diff options
author | Fadi Hanna <fadim@microsoft.com> | 2017-08-16 21:51:27 +0300 |
---|---|---|
committer | Fadi Hanna <fadim@microsoft.com> | 2017-08-16 21:51:27 +0300 |
commit | 9098fbfe1660fe26539f60439ed3242fbb9aba5a (patch) | |
tree | 24cfaced3dc183797b5532df35867ee358e41a3b /src/System.Private.TypeLoader | |
parent | 0f701216d41eb039490d9bca21840bc3ee9ae7d3 (diff) |
• Fix native layout encoding for USG vtable methods requiring a calling convention converter
• Fix binder/ILCompiler/typeloader to correctly handle vtable entries for dynamic types in the partial canonical case where a call converter thunk is not needed, or where it's needed but need to use the generic context of a base type.
• Add new tests to PX dynamic generics
• Minor refactoring to genericdictinoarycell.cs to make log easier to read (grouping logging of dictionary cells together)
[tfs-changeset: 1670506]
Diffstat (limited to 'src/System.Private.TypeLoader')
-rw-r--r-- | src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs | 30 | ||||
-rw-r--r-- | src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/genericdictionarycell.cs | 18 |
2 files changed, 36 insertions, 12 deletions
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index 1bd8b2035..a1da52d2c 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -998,6 +998,20 @@ namespace Internal.Runtime.TypeLoader TypeLoaderLogger.WriteLine("Allocated new method dictionary for method " + method.ToString() + " @ " + rmd.LowLevelToString()); } + private RuntimeTypeHandle[] GetGenericContextOfBaseType(DefType type, int vtableMethodSlot) + { + DefType baseType = type.BaseType; + Debug.Assert(baseType == null || !GetRuntimeTypeHandle(baseType).IsNull()); + Debug.Assert(vtableMethodSlot < GetRuntimeTypeHandle(type).GetNumVtableSlots()); + + int numBaseTypeVtableSlots = baseType == null ? 0 : GetRuntimeTypeHandle(baseType).GetNumVtableSlots(); + + if (vtableMethodSlot < numBaseTypeVtableSlots) + return GetGenericContextOfBaseType(baseType, vtableMethodSlot); + else + return GetRuntimeTypeHandles(type.Instantiation); + } + private unsafe void FinishVTableCallingConverterThunks(TypeDesc type, TypeBuilderState state) { Debug.Assert(state.TemplateType.IsCanonicalSubtype(CanonicalFormKind.Universal)); @@ -1009,9 +1023,11 @@ namespace Internal.Runtime.TypeLoader IntPtr* vtableCells = (IntPtr*)((byte*)GetRuntimeTypeHandle(type).ToIntPtr() + sizeof(EEType)); Debug.Assert((state.VTableMethodSignatures.Length - state.NumSealedVTableMethodSignatures) <= numVtableSlots); + TypeDesc baseType = type.BaseType; + int numBaseTypeVtableSlots = GetRuntimeTypeHandle(baseType).GetNumVtableSlots(); + // Generic context RuntimeTypeHandle[] typeArgs = Empty<RuntimeTypeHandle>.Array; - RuntimeTypeHandle[] methodArgs = Empty<RuntimeTypeHandle>.Array; // No GVMs in vtables if (type is DefType) typeArgs = GetRuntimeTypeHandles(((DefType)type).Instantiation); @@ -1020,11 +1036,21 @@ namespace Internal.Runtime.TypeLoader for (int i = 0; i < state.VTableMethodSignatures.Length; i++) { + RuntimeTypeHandle[] typeArgsToUse = typeArgs; + int vtableSlotInDynamicType = -1; if (!state.VTableMethodSignatures[i].IsSealedVTableSlot) { vtableSlotInDynamicType = state.VTableSlotsMapping.GetVTableSlotInTargetType((int)state.VTableMethodSignatures[i].VTableSlot); Debug.Assert(vtableSlotInDynamicType != -1); + + if (vtableSlotInDynamicType < numBaseTypeVtableSlots) + { + // Vtable method from the vtable portion of a base type. Use generic context of the basetype defining the vtable slot. + // We should never reach here for array types (the vtable entries of the System.Array basetype should never need a converter). + Debug.Assert(type is DefType); + typeArgsToUse = GetGenericContextOfBaseType((DefType)type, vtableSlotInDynamicType); + } } IntPtr originalFunctionPointerFromVTable = state.VTableMethodSignatures[i].IsSealedVTableSlot ? @@ -1036,7 +1062,7 @@ namespace Internal.Runtime.TypeLoader originalFunctionPointerFromVTable, state.VTableMethodSignatures[i].MethodSignature, IntPtr.Zero, // No instantiating arg for non-generic instance methods - typeArgs, + typeArgsToUse, Empty<RuntimeTypeHandle>.Array); // No GVMs in vtables, no no method args if (state.VTableMethodSignatures[i].IsSealedVTableSlot) diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/genericdictionarycell.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/genericdictionarycell.cs index 05b4daaf3..a07d6dad8 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/genericdictionarycell.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/genericdictionarycell.cs @@ -1071,11 +1071,15 @@ namespace Internal.Runtime.TypeLoader for (uint i = 0; i < count; i++) { + TypeLoaderLogger.WriteLine(" -> DictionaryCell[" + i.LowLevelToString() + "] = "); + GenericDictionaryCell cell = ParseAndCreateCell(nativeLayoutInfoLoadContext, ref parser); - cell.Prepare(typeBuilder); dictionary[i] = cell; } + for (uint i = 0; i < count; i++) + dictionary[i].Prepare(typeBuilder); + return dictionary; } @@ -1815,15 +1819,7 @@ namespace Internal.Runtime.TypeLoader NativeParser sigParser = parser.GetParserFromRelativeOffset(); RuntimeSignature signature = RuntimeSignature.CreateFromNativeLayoutSignature(nativeLayoutInfoLoadContext._module.Handle, sigParser.Offset); -#if TYPE_LOADER_TRACE - TypeLoaderLogger.WriteLine("CallingConventionConverter on: "); - TypeLoaderLogger.WriteLine(" -> Flags: " + ((int)flags).LowLevelToString()); - TypeLoaderLogger.WriteLine(" -> Signature: " + signature.NativeLayoutSignature().LowLevelToString()); - for (int i = 0; !nativeLayoutInfoLoadContext._typeArgumentHandles.IsNull && i < nativeLayoutInfoLoadContext._typeArgumentHandles.Length; i++) - TypeLoaderLogger.WriteLine(" -> TypeArg[" + i.LowLevelToString() + "]: " + nativeLayoutInfoLoadContext._typeArgumentHandles[i]); - for (int i = 0; !nativeLayoutInfoLoadContext._methodArgumentHandles.IsNull && i < nativeLayoutInfoLoadContext._methodArgumentHandles.Length; i++) - TypeLoaderLogger.WriteLine(" -> MethodArg[" + i.LowLevelToString() + "]: " + nativeLayoutInfoLoadContext._methodArgumentHandles[i]); -#endif + TypeLoaderLogger.WriteLine("CallingConventionConverter: Flags=" + ((int)flags).LowLevelToString() + " Signature=" + signature.NativeLayoutSignature().LowLevelToString()); cell = new CallingConventionConverterCell { @@ -1844,6 +1840,7 @@ namespace Internal.Runtime.TypeLoader { OtherDictionarySlot = parser.GetUnsigned() }; + TypeLoaderLogger.WriteLine("PointerToOtherSlot: " + ((PointerToOtherDictionarySlotCell)cell).OtherDictionarySlot.LowLevelToString()); break; case FixupSignatureKind.IntValue: @@ -1851,6 +1848,7 @@ namespace Internal.Runtime.TypeLoader { Value = new IntPtr((int)parser.GetUnsigned()) }; + TypeLoaderLogger.WriteLine("IntValue: " + ((IntPtrCell)cell).Value.LowLevelToString()); break; default: |