-
Notifications
You must be signed in to change notification settings - Fork 508
[CppCodeGen] Enable reflection support #6700
Conversation
5c454e4
to
2d53b84
Compare
@@ -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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unnecessary
This patch fixes attribute reflection tests that fails due to missing type metadata.
@@ -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: |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MethodGenericDictionaryNode.HeaderSize
?
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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.
We should take into account delta for reloc node
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
@dotnet-bot test this please |
Thanks |
With this change and #6695 reflection tests are passed with following constraints:
TestByRefLikeTypeMethod
is skipped (it's necessary to implementRhGetCodeTarget
for CppCodeGen)TestByRefReturnInvoke
is skipped (it's necessary to implement Nullable box/unbox)Also #6405 and #6423 should be fixed.