Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

[CppCodeGen] Enable reflection support #6700

Merged
merged 8 commits into from
Jan 10, 2019
Merged

Conversation

kbaladurin
Copy link
Member

With this change and #6695 reflection tests are passed with following constraints:

  • Some tests are skipped due to missing exceptions support
  • TestByRefLikeTypeMethod is skipped (it's necessary to implement RhGetCodeTarget for CppCodeGen)
  • TestByRefReturnInvoke is skipped (it's necessary to implement Nullable box/unbox)

Also #6405 and #6423 should be fixed.

@@ -439,6 +446,11 @@ public sealed override MethodInvoker TryGetMethodInvoker(RuntimeTypeHandle decla
// Now have the type loader build or locate a dictionary for this method
uint index = cookie >> 1;

if (!RuntimeAugments.SupportsRelativePointers)
{
index = (uint)(IntPtr.Size * index) / sizeof(uint);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indexing into pBlob is becoming kind of awkward after this change. I think we should just change the type of pBlob to void* and cast to the right type before each use.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thank you!

}
else
{
// .NET Native uses RVAs
dynamicInvokeMethod = TypeLoaderEnvironment.RvaToFunctionPointer(module.Handle, pBlob[index + 1]);
dynamicInvokeMethod = TypeLoaderEnvironment.RvaToFunctionPointer(module.Handle, pBlob[index + IntPtr.Size / sizeof(uint)]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unnecessary

@@ -279,7 +279,8 @@ private string GetStackValueKindCPPTypeName(StackValueKind kind, TypeDesc type =
case StackValueKind.Int64: return "int64_t";
case StackValueKind.NativeInt: return "intptr_t";
case StackValueKind.ObjRef: return "void*";
case StackValueKind.Float: return "double";
case StackValueKind.Float:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? It would be nice to add a comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem occurs when we use reflection to get float fields. Compiler generates following code to unbox float value:

double unboxed = *(double*)(float*)((void**)boxed + 1)

that produce incorrect result.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be rather fixed in the implementation of unbox instead of here.

I think that the same problem will happen for other types too. For example, if the type is sbyte and the boxed value is -1, we will end up with 0xFF pushed on the IL stack today. Instead, we should end up with -1 on the IL stack.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for suggestion!

return typeName.Replace("::", "_") + "_" + name;
string res = typeName.Replace("::", "_") + "_" + name;

if (isGCStatic && !isThreadStatic && dataNameNeeded)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the __data suffix for? I am not able to figure it out by just looking at the code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__data is used for naming variables of structure type:

_System_Private_CoreLib_System_Boolean_GCStatics _System_Private_CoreLib_System_Boolean_gcStatics__data;
_System_Private_CoreLib_System_Boolean_GCStatics *_System_Private_CoreLib_System_Boolean_gcStatics__data__ptr = &_System_Private_CoreLib_System_Boolean_gcStatics__data;
_System_Private_CoreLib_System_Boolean_GCStatics **_System_Private_CoreLib_System_Boolean_gcStatics = &_System_Private_CoreLib_System_Boolean_gcStatics__data__ptr;

symbolNode.Target is GenericTypesHashtableNode ||
symbolNode.Target is TypeMetadataMapNode ||
if ((!(symbolNode.Target is EmbeddedDataContainerNode) &&
!(symbolNode.Target is StackTraceMethodMappingNode) ||
isEagerCctorTable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isEagerCctorTable condition does not seem to be necessary now that the logic is flipped.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isEagerCctorTable is needed because !(symbolNode.Target is EmbeddedDataContainerNode) filters all ArrayOfEmbeddedPointersNode nodes.


// Method generic dictionaries get prefixed by the hash code of the owning method
if (node is MethodGenericDictionaryNode)
offset -= _compilation.TypeSystemContext.Target.PointerSize;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MethodGenericDictionaryNode.HeaderSize ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even better - would an unconditional call to ISymbolDefinitionNode.Offset work ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISymbolDefinitionNode.Offset points to the part of data after header but we doesn't know header size. I think using MethodGenericDictionaryNode.HeaderSize is more suitable, but it's necessary to make it public.

Konstantin Baladurin added 2 commits December 25, 2018 14:52
Konstantin Baladurin added 2 commits December 27, 2018 10:35
As we use double for float and int32_t for sbyte and int16 we should
use exact type for boxing/unboxing otherwise we will get incorrect
results.

This patch fixes float box/unbox issues in reflection tests
@jkotas
Copy link
Member

jkotas commented Jan 10, 2019

@dotnet-bot test this please

@jkotas
Copy link
Member

jkotas commented Jan 10, 2019

Thanks

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants