From bff5b16365fbee52f0322962ffbed65aad9726fe Mon Sep 17 00:00:00 2001 From: dotnet-bot Date: Tue, 12 Dec 2017 11:35:48 -0800 Subject: [PATCH] ProjectX Changes to the UpdateTypeFloatingDictionary API While updating the floating dictionary for a EEtype at runtime, the type loader looks for the exact base type that owns the dictionary first. This is because we may be having a virtual method run on a derived type and the generic lookup are performed on the base type's dictionary. Since in multifile scenario, the base type's dictionary may end up having a copy in each module, therefore the lookup of the right base type should be based on the dictionary pointer offset in the EEtype, instead of the real dictionary pointer. [tfs-changeset: 1683620] --- .../Runtime/TypeLoader/EETypeCreator.cs | 33 +++++++++++++++++-- .../TypeLoader/TypeLoaderEnvironment.cs | 14 ++------ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs index c2f02dcc629..ae9c31a8100 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs @@ -1105,13 +1105,23 @@ public static RuntimeTypeHandle CreateEEType(TypeDesc type, TypeBuilderState sta return state.HalfBakedRuntimeTypeHandle; } - public static IntPtr GetDictionary(EEType* pEEType) + public static int GetDictionaryOffsetInEEtype(EEType* pEEType) { // Dictionary slot is the first vtable slot EEType* pBaseType = pEEType->BaseType; int dictionarySlot = (pBaseType == null ? 0 : pBaseType->NumVtableSlots); - return *(IntPtr*)((byte*)pEEType + sizeof(EEType) + dictionarySlot * IntPtr.Size); + return sizeof(EEType) + dictionarySlot * IntPtr.Size; + } + + public static IntPtr GetDictionaryAtOffset(EEType* pEEType, int offset) + { + return *(IntPtr*)((byte*)pEEType + offset); + } + + public static IntPtr GetDictionary(EEType* pEEType) + { + return GetDictionaryAtOffset(pEEType, GetDictionaryOffsetInEEtype(pEEType)); } public static int GetDictionarySlotInVTable(TypeDesc type) @@ -1140,5 +1150,24 @@ private static int GetMostDerivedDictionarySlot(ref TypeDesc nextTypeToExamineFo typeWithDictionary = null; return -1; } + + public static EEType* GetBaseEETypeForDictionaryPtr(EEType* pEEType, IntPtr dictionaryPtr) + { + // Look for the exact base type that owns the dictionary + IntPtr curDictPtr = GetDictionary(pEEType); + EEType* pBaseEEType = pEEType; + + while (curDictPtr != dictionaryPtr) + { + pBaseEEType = pBaseEEType->BaseType; + Debug.Assert(pBaseEEType != null); + // Since in multifile scenario, the base type's dictionary may end up having + // a copy in each module, therefore the lookup of the right base type should be + // based on the dictionary pointer in the current EEtype, instead of the base EEtype. + curDictPtr = GetDictionaryAtOffset(pEEType, EETypeCreator.GetDictionaryOffsetInEEtype(pBaseEEType)); + } + + return pBaseEEType; + } } } diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index 42dc86eabe4..30f13e5d041 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -526,21 +526,11 @@ public unsafe IntPtr UpdateFloatingDictionary(IntPtr context, IntPtr dictionaryP if (isTypeContext) { - EEType* pEEType = (EEType*)context.ToPointer(); - IntPtr curDictPtr = EETypeCreator.GetDictionary(pEEType); - // Look for the exact base type that owns the dictionary. We may be having // a virtual method run on a derived type and the generic lookup are performed // on the base type's dictionary. - while (curDictPtr != dictionaryPtr) - { - pEEType = pEEType->BaseType; - Debug.Assert(pEEType != null); - curDictPtr = EETypeCreator.GetDictionary(pEEType); - Debug.Assert(curDictPtr != IntPtr.Zero); - } - - context = (IntPtr)pEEType; + EEType* pEEType = (EEType*)context.ToPointer(); + context = (IntPtr)EETypeCreator.GetBaseEETypeForDictionaryPtr(pEEType, dictionaryPtr); } using (LockHolder.Hold(_typeLoaderLock))