Remove relocations from SECTION_MethodDesc for ngened images for fields accessed...
authorgbalykov <g.balykov@samsung.com>
Sat, 3 Jun 2017 03:31:28 +0000 (06:31 +0300)
committerJan Kotas <jkotas@microsoft.com>
Sat, 3 Jun 2017 03:31:28 +0000 (20:31 -0700)
13 files changed:
src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
src/ToolBox/superpmi/superpmi-shared/methodcontext.h
src/debug/daccess/nidump.cpp
src/inc/corinfo.h
src/inc/fixuppointer.h
src/jit/importer.cpp
src/vm/dllimport.cpp
src/vm/genmeth.cpp
src/vm/jitinterface.cpp
src/vm/method.cpp
src/vm/method.hpp
src/vm/methodtablebuilder.cpp
src/vm/prestub.cpp

index e60ef83..4c5fb61 100644 (file)
@@ -1573,6 +1573,7 @@ void MethodContext::recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
             value.stubLookup.runtimeLookup.indirections = (DWORD)pResult->stubLookup.runtimeLookup.indirections;
             value.stubLookup.runtimeLookup.testForNull  = (DWORD)pResult->stubLookup.runtimeLookup.testForNull;
             value.stubLookup.runtimeLookup.testForFixup = (DWORD)pResult->stubLookup.runtimeLookup.testForFixup;
+            value.stubLookup.runtimeLookup.indirectFirstOffset = (DWORD)pResult->stubLookup.runtimeLookup.indirectFirstOffset;
             for (int i                                    = 0; i < CORINFO_MAXINDIRECTIONS; i++)
                 value.stubLookup.runtimeLookup.offsets[i] = (DWORDLONG)pResult->stubLookup.runtimeLookup.offsets[i];
         }
@@ -1583,6 +1584,7 @@ void MethodContext::recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
             value.stubLookup.runtimeLookup.indirections = (DWORD)0;
             value.stubLookup.runtimeLookup.testForNull  = (DWORD)0;
             value.stubLookup.runtimeLookup.testForFixup = (DWORD)0;
+            value.stubLookup.runtimeLookup.indirectFirstOffset = (DWORD)0;
             for (int i                                    = 0; i < CORINFO_MAXINDIRECTIONS; i++)
                 value.stubLookup.runtimeLookup.offsets[i] = (DWORDLONG)0;
 
@@ -1761,6 +1763,7 @@ void MethodContext::repGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
         pResult->stubLookup.runtimeLookup.indirections = (WORD)value.stubLookup.runtimeLookup.indirections;
         pResult->stubLookup.runtimeLookup.testForNull  = value.stubLookup.runtimeLookup.testForNull != 0;
         pResult->stubLookup.runtimeLookup.testForFixup = value.stubLookup.runtimeLookup.testForFixup != 0;
+        pResult->stubLookup.runtimeLookup.indirectFirstOffset = value.stubLookup.runtimeLookup.indirectFirstOffset != 0;
         for (int i                                       = 0; i < CORINFO_MAXINDIRECTIONS; i++)
             pResult->stubLookup.runtimeLookup.offsets[i] = (SIZE_T)value.stubLookup.runtimeLookup.offsets[i];
     }
@@ -3218,6 +3221,7 @@ void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN*       pResolve
         value.lookup.runtimeLookup.indirections = (DWORD)pResult->lookup.runtimeLookup.indirections;
         value.lookup.runtimeLookup.testForNull  = (DWORD)pResult->lookup.runtimeLookup.testForNull;
         value.lookup.runtimeLookup.testForFixup = (DWORD)pResult->lookup.runtimeLookup.testForFixup;
+        value.lookup.runtimeLookup.indirectFirstOffset = (DWORD)pResult->lookup.runtimeLookup.indirectFirstOffset;
         for (int i                                = 0; i < CORINFO_MAXINDIRECTIONS; i++)
             value.lookup.runtimeLookup.offsets[i] = (DWORDLONG)pResult->lookup.runtimeLookup.offsets[i];
     }
@@ -3228,6 +3232,7 @@ void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN*       pResolve
         value.lookup.runtimeLookup.indirections = (DWORD)0;
         value.lookup.runtimeLookup.testForNull  = (DWORD)0;
         value.lookup.runtimeLookup.testForFixup = (DWORD)0;
+        value.lookup.runtimeLookup.indirectFirstOffset = (DWORD)0;
         for (int i                                = 0; i < CORINFO_MAXINDIRECTIONS; i++)
             value.lookup.runtimeLookup.offsets[i] = (DWORDLONG)0;
         // copy the constLookup view of the union
@@ -3305,6 +3310,7 @@ void MethodContext::repEmbedGenericHandle(CORINFO_RESOLVED_TOKEN*       pResolve
         pResult->lookup.runtimeLookup.indirections = (WORD)value.lookup.runtimeLookup.indirections;
         pResult->lookup.runtimeLookup.testForNull  = value.lookup.runtimeLookup.testForNull != 0;
         pResult->lookup.runtimeLookup.testForFixup = value.lookup.runtimeLookup.testForFixup != 0;
+        pResult->lookup.runtimeLookup.indirectFirstOffset = value.lookup.runtimeLookup.indirectFirstOffset != 0;
         for (int i                                   = 0; i < CORINFO_MAXINDIRECTIONS; i++)
             pResult->lookup.runtimeLookup.offsets[i] = (size_t)value.lookup.runtimeLookup.offsets[i];
     }
index f7c0e16..4887522 100644 (file)
@@ -240,6 +240,7 @@ public:
         DWORD     testForNull;
         DWORD     testForFixup;
         DWORDLONG offsets[CORINFO_MAXINDIRECTIONS];
+        DWORD     indirectFirstOffset;
     };
     struct Agnostic_CORINFO_CONST_LOOKUP
     {
index 6e73708..62b68ef 100644 (file)
@@ -7905,7 +7905,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module )
         if( !CHECK_OPT(METHODDESCS) )
             CoverageReadString( dac_cast<TADDR>(ndmd->GetLibNameRaw()) );
 
-        PTR_NDirectWriteableData wnd( nd->m_pWriteableData );
+        PTR_NDirectWriteableData wnd( ndmd->GetWriteableData() );
         DisplayStartStructureWithOffset( m_pWriteableData,
                                          DPtrToPreferredAddr(wnd),
                                          sizeof(*wnd),
@@ -8061,7 +8061,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module )
         }
         //now handle the contents of the m_pMethInst/m_pPerInstInfo union.
         unsigned numSlots = imd->m_wNumGenericArgs;
-        PTR_Dictionary inst(imd->m_pPerInstInfo);
+        PTR_Dictionary inst(imd->IMD_GetMethodDictionary());
         unsigned dictSize;
         if( kind == InstantiatedMethodDesc::SharedMethodInstantiation )
         {
index 2117d4e..0620994 100644 (file)
@@ -1323,6 +1323,13 @@ struct CORINFO_RUNTIME_LOOKUP
     bool                    testForFixup;
 
     SIZE_T                  offsets[CORINFO_MAXINDIRECTIONS];
+
+    // If set, first offset is indirect.
+    // 0 means that value stored at first offset (offsets[0]) from pointer is next pointer, to which the next offset
+    // (offsets[1]) is added and so on.
+    // 1 means that value stored at first offset (offsets[0]) from pointer is offset1, and the next pointer is
+    // stored at pointer+offsets[0]+offset1.
+    bool                indirectFirstOffset;
 } ;
 
 // Result of calling embedGenericHandle
index 549023a..38ae348 100644 (file)
@@ -30,6 +30,10 @@ template<typename PTR_TYPE>
 class RelativePointer
 {
 public:
+
+    static constexpr bool isRelative = true;
+    typedef PTR_TYPE type;
+
 #ifndef DACCESS_COMPILE
     RelativePointer()
     {
@@ -173,6 +177,10 @@ template<typename PTR_TYPE>
 class FixupPointer
 {
 public:
+
+    static constexpr bool isRelative = false;
+    typedef PTR_TYPE type;
+
     // Returns whether the encoded pointer is NULL.
     BOOL IsNull() const
     {
@@ -237,6 +245,10 @@ template<typename PTR_TYPE>
 class RelativeFixupPointer
 {
 public:
+
+    static constexpr bool isRelative = true;
+    typedef PTR_TYPE type;
+
     // Implicit copy/move is not allowed
     RelativeFixupPointer<PTR_TYPE>(const RelativeFixupPointer<PTR_TYPE> &) =delete;
     RelativeFixupPointer<PTR_TYPE>(RelativeFixupPointer<PTR_TYPE> &&) =delete;
@@ -384,7 +396,7 @@ private:
 // Fixup used for RelativePointer
 #define IMAGE_REL_BASED_RelativePointer IMAGE_REL_BASED_RELPTR
 
-#else // FEATURE_PREJIT
+#endif // FEATURE_PREJIT
 
 //----------------------------------------------------------------------------
 // PlainPointer is simple pointer wrapper to support compilation without indirections
@@ -393,6 +405,10 @@ template<typename PTR_TYPE>
 class PlainPointer
 {
 public:
+
+    static constexpr bool isRelative = false;
+    typedef PTR_TYPE type;
+
     // Returns whether the encoded pointer is NULL.
     BOOL IsNull() const
     {
@@ -499,11 +515,13 @@ private:
     TADDR m_ptr;
 };
 
+#ifndef FEATURE_PREJIT
+
 #define FixupPointer PlainPointer
 #define RelativePointer PlainPointer
 #define RelativeFixupPointer PlainPointer
 
-#endif // FEATURE_PREJIT
+#endif // !FEATURE_PREJIT
 
 //----------------------------------------------------------------------------
 // RelativePointer32 is pointer encoded as relative 32-bit offset. It is used
@@ -513,6 +531,10 @@ template<typename PTR_TYPE>
 class RelativePointer32
 {
 public:
+
+    static constexpr bool isRelative = true;
+    typedef PTR_TYPE type;
+
     // Returns whether the encoded pointer is NULL.
     BOOL IsNull() const
     {
@@ -581,4 +603,77 @@ private:
     INT32 m_delta;
 };
 
+template<bool isMaybeNull, typename T, typename PT>
+typename PT::type
+ReadPointer(const T *base, const PT T::* pPointerFieldMember)
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base;
+
+    if (isMaybeNull)
+    {
+        return PT::GetValueMaybeNullAtPtr(dac_cast<TADDR>(base) + offset);
+    }
+    else
+    {
+        return PT::GetValueAtPtr(dac_cast<TADDR>(base) + offset);
+    }
+}
+
+template<typename T, typename PT>
+typename PT::type
+ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember)
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    return ReadPointer<true>(base, pPointerFieldMember);
+}
+
+template<typename T, typename PT>
+typename PT::type
+ReadPointer(const T *base, const PT T::* pPointerFieldMember)
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    return ReadPointer<false>(base, pPointerFieldMember);
+}
+
+template<bool isMaybeNull, typename T, typename C, typename PT>
+typename PT::type
+ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    const PT *ptr = &(base->*pFirstPointerFieldMember.*pSecondPointerFieldMember);
+    uintptr_t offset = (uintptr_t) ptr - (uintptr_t) base;
+
+    if (isMaybeNull)
+    {
+        return PT::GetValueMaybeNullAtPtr(dac_cast<TADDR>(base) + offset);
+    }
+    else
+    {
+        return PT::GetValueAtPtr(dac_cast<TADDR>(base) + offset);
+    }
+}
+
+template<typename T, typename C, typename PT>
+typename PT::type
+ReadPointerMaybeNull(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    return ReadPointer<true>(base, pFirstPointerFieldMember, pSecondPointerFieldMember);
+}
+
+template<typename T, typename C, typename PT>
+typename PT::type
+ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    return ReadPointer<false>(base, pFirstPointerFieldMember, pSecondPointerFieldMember);
+}
+
 #endif //_FIXUPPOINTER_H
index 361d102..5cc5e4e 100644 (file)
@@ -1975,15 +1975,29 @@ GenTreePtr Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedTok
                                    nullptr DEBUGARG("impRuntimeLookup slot"));
     }
 
+    GenTreePtr indOffTree = nullptr;
+
     // Applied repeated indirections
     for (WORD i = 0; i < pRuntimeLookup->indirections; i++)
     {
+        if (i == 1 && pRuntimeLookup->indirectFirstOffset)
+        {
+            indOffTree = impCloneExpr(slotPtrTree, &slotPtrTree, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL,
+                                      nullptr DEBUGARG("impRuntimeLookup indirectFirstOffset"));
+        }
+
         if (i != 0)
         {
             slotPtrTree = gtNewOperNode(GT_IND, TYP_I_IMPL, slotPtrTree);
             slotPtrTree->gtFlags |= GTF_IND_NONFAULTING;
             slotPtrTree->gtFlags |= GTF_IND_INVARIANT;
         }
+
+        if (i == 1 && pRuntimeLookup->indirectFirstOffset)
+        {
+            slotPtrTree = gtNewOperNode(GT_ADD, TYP_I_IMPL, indOffTree, slotPtrTree);
+        }
+
         if (pRuntimeLookup->offsets[i] != 0)
         {
             slotPtrTree =
index b780711..49c7d7a 100644 (file)
@@ -2294,7 +2294,19 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
                     //pcsEmit->EmitCALL(METHOD__STUBHELPERS__GET_NDIRECT_TARGET, 1, 1);
                     pcsEmit->EmitLDC(offsetof(NDirectMethodDesc, ndirect.m_pWriteableData));
                     pcsEmit->EmitADD();
+
+                    if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
+                    {
+                        pcsEmit->EmitDUP();
+                    }
+
                     pcsEmit->EmitLDIND_I();
+
+                    if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
+                    {
+                        pcsEmit->EmitADD();
+                    }
+
                     pcsEmit->EmitLDIND_I();
                 }
             }
index d5b435b..dc55221 100644 (file)
@@ -1518,9 +1518,9 @@ void InstantiatedMethodDesc::SetupGenericMethodDefinition(IMDInternalImport *pIM
     S_SIZE_T dwAllocSize = S_SIZE_T(numTyPars) * S_SIZE_T(sizeof(TypeHandle));
 
     // the memory allocated for m_pMethInst will be freed if the declaring type fails to load
-    m_pPerInstInfo = (Dictionary *) pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(dwAllocSize));
+    m_pPerInstInfo.SetValue((Dictionary *) pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(dwAllocSize)));
 
-    TypeHandle * pInstDest = (TypeHandle *)m_pPerInstInfo;
+    TypeHandle * pInstDest = (TypeHandle *) IMD_GetMethodDictionaryNonNull();
     for(unsigned int i = 0; i < numTyPars; i++)
     {
         hEnumTyPars.EnumNext(&tkTyPar);
@@ -1553,7 +1553,7 @@ void InstantiatedMethodDesc::SetupWrapperStubWithInstantiations(MethodDesc* wrap
 
     m_pWrappedMethodDesc.SetValue(wrappedMD);
     m_wFlags2 = WrapperStubWithInstantiations | (m_wFlags2 & ~KindMask);
-    m_pPerInstInfo = (Dictionary*)pInst;
+    m_pPerInstInfo.SetValueMaybeNull((Dictionary*)pInst);
 
     _ASSERTE(FitsIn<WORD>(numGenericArgs));
     m_wNumGenericArgs = static_cast<WORD>(numGenericArgs);
@@ -1571,7 +1571,7 @@ void InstantiatedMethodDesc::SetupSharedMethodInstantiation(DWORD numGenericArgs
     _ASSERTE(numGenericArgs != 0);
     // Initially the dictionary layout is empty
     m_wFlags2 = SharedMethodInstantiation | (m_wFlags2 & ~KindMask);
-    m_pPerInstInfo = (Dictionary *)pPerInstInfo;
+    m_pPerInstInfo.SetValueMaybeNull((Dictionary *)pPerInstInfo);
 
     _ASSERTE(FitsIn<WORD>(numGenericArgs));
     m_wNumGenericArgs = static_cast<WORD>(numGenericArgs);
@@ -1589,7 +1589,7 @@ void InstantiatedMethodDesc::SetupUnsharedMethodInstantiation(DWORD numGenericAr
 
     // The first field is never used
     m_wFlags2 = UnsharedMethodInstantiation | (m_wFlags2 & ~KindMask);
-    m_pPerInstInfo = (Dictionary *)pInst;
+    m_pPerInstInfo.SetValueMaybeNull((Dictionary *)pInst);
 
     _ASSERTE(FitsIn<WORD>(numGenericArgs));
     m_wNumGenericArgs = static_cast<WORD>(numGenericArgs);
index ef0e87f..c28d6e1 100644 (file)
@@ -3085,6 +3085,8 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr
     CORINFO_RUNTIME_LOOKUP *pResult = &pResultLookup->runtimeLookup;
     pResult->signature = NULL;
 
+    pResult->indirectFirstOffset = 0;
+
     // Unless we decide otherwise, just do the lookup via a helper function
     pResult->indirections = CORINFO_USEHELPER;
 
@@ -3208,6 +3210,11 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr
 #endif
                 pResult->offsets[0] = offsetof(InstantiatedMethodDesc, m_pPerInstInfo);
 
+                if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
+                {
+                    pResult->indirectFirstOffset = 1;
+                }
+
                 ULONG data;
                 IfFailThrow(sigptr.GetData(&data));
                 pResult->offsets[1] = sizeof(TypeHandle) * data;
@@ -3512,6 +3519,11 @@ NoSpecialCase:
 
             // Indirect through dictionary table pointer in InstantiatedMethodDesc
             pResult->offsets[0] = offsetof(InstantiatedMethodDesc, m_pPerInstInfo);
+
+            if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
+            {
+                pResult->indirectFirstOffset = 1;
+            }
         }
     }
 
index ca0ecc1..241a0cc 100644 (file)
@@ -3496,7 +3496,14 @@ MethodDesc::Fixup(
             }
         }
 
-        image->FixupPointerField(this, offsetof(InstantiatedMethodDesc, m_pPerInstInfo));
+        if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
+        {
+            image->FixupRelativePointerField(this, offsetof(InstantiatedMethodDesc, m_pPerInstInfo));
+        }
+        else
+        {
+            image->FixupPointerField(this, offsetof(InstantiatedMethodDesc, m_pPerInstInfo));
+        }
 
         // Generic methods are dealt with specially to avoid encoding the formal method type parameters
         if (IsTypicalMethodDefinition())
@@ -3575,7 +3582,14 @@ MethodDesc::Fixup(
 
         NDirectMethodDesc *pNMD = (NDirectMethodDesc *)this;
 
-        image->FixupPointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pWriteableData));
+        if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
+        {
+            image->FixupRelativePointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pWriteableData));
+        }
+        else
+        {
+            image->FixupPointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pWriteableData));
+        }
 
         NDirectWriteableData *pWriteableData = pNMD->GetWriteableData();
         NDirectImportThunkGlue *pImportThunkGlue = pNMD->GetNDirectImportThunkGlue();
index 4b85357..71e838a 100644 (file)
@@ -2586,7 +2586,11 @@ public:
         };
 
         // The writeable part of the methoddesc.
-        PTR_NDirectWriteableData    m_pWriteableData;
+#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_)
+        RelativePointer<PTR_NDirectWriteableData>    m_pWriteableData;
+#else
+        PlainPointer<PTR_NDirectWriteableData>    m_pWriteableData;
+#endif
 
 #ifdef HAS_NDIRECT_IMPORT_PRECODE
         RelativePointer<PTR_NDirectImportThunkGlue> m_pImportThunkGlue;
@@ -2808,11 +2812,11 @@ public:
         return (ndirect.m_wFlags & kStdCallWithRetBuf) != 0;
     }
 
-    NDirectWriteableData* GetWriteableData() const
+    PTR_NDirectWriteableData GetWriteableData() const
     {
-        LIMITED_METHOD_CONTRACT;
+        LIMITED_METHOD_DAC_CONTRACT;
 
-        return ndirect.m_pWriteableData;
+        return ReadPointer(this, &NDirectMethodDesc::ndirect, &decltype(NDirectMethodDesc::ndirect)::m_pWriteableData);
     }
 
     PTR_NDirectImportThunkGlue GetNDirectImportThunkGlue()
@@ -3217,7 +3221,7 @@ public:
         if (IMD_IsGenericMethodDefinition())
             return TRUE;
         else
-            return m_pPerInstInfo != NULL;
+            return !m_pPerInstInfo.IsNull();
     }
 
     // All varieties of InstantiatedMethodDesc's support this method.
@@ -3225,13 +3229,21 @@ public:
     {
         LIMITED_METHOD_DAC_CONTRACT;
 
-        return Instantiation(m_pPerInstInfo->GetInstantiation(), m_wNumGenericArgs);
+        return Instantiation(IMD_GetMethodDictionary()->GetInstantiation(), m_wNumGenericArgs);
     }
 
     PTR_Dictionary IMD_GetMethodDictionary()
     {
         LIMITED_METHOD_DAC_CONTRACT;
-        return m_pPerInstInfo;
+
+        return ReadPointerMaybeNull(this, &InstantiatedMethodDesc::m_pPerInstInfo);
+    }
+
+    PTR_Dictionary IMD_GetMethodDictionaryNonNull()
+    {
+        LIMITED_METHOD_DAC_CONTRACT;
+
+        return ReadPointer(this, &InstantiatedMethodDesc::m_pPerInstInfo);
     }
 
     BOOL IMD_IsGenericMethodDefinition()
@@ -3390,7 +3402,11 @@ public: // <TODO>make private: JITinterface.cpp accesses through this </TODO>
         //
         // For generic method definitions that are not the typical method definition (e.g. C<int>.m<U>)
         // this field is null; to obtain the instantiation use LoadMethodInstantiation
-    PTR_Dictionary m_pPerInstInfo;  //SHARED
+#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_)
+    RelativePointer<PTR_Dictionary> m_pPerInstInfo;  //SHARED
+#else
+    PlainPointer<PTR_Dictionary> m_pPerInstInfo;  //SHARED
+#endif
 
 private:
     WORD          m_wFlags2;
index 01c7ce9..1b3d775 100644 (file)
@@ -5913,8 +5913,8 @@ MethodTableBuilder::InitMethodDesc(
             NDirectMethodDesc *pNewNMD = (NDirectMethodDesc*)pNewMD;
 
             // Allocate writeable data
-            pNewNMD->ndirect.m_pWriteableData = (NDirectWriteableData*)
-                AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData)));
+            pNewNMD->ndirect.m_pWriteableData.SetValue((NDirectWriteableData*)
+                AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData))));
 
 #ifdef HAS_NDIRECT_IMPORT_PRECODE 
             pNewNMD->ndirect.m_pImportThunkGlue.SetValue(Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD,
index 921d376..1ebcdc4 100644 (file)
@@ -2383,6 +2383,9 @@ void ProcessDynamicDictionaryLookup(TransitionBlock *           pTransitionBlock
 
     pResult->testForFixup = pResult->testForNull = false;
     pResult->signature = NULL;
+
+    pResult->indirectFirstOffset = 0;
+
     pResult->indirections = CORINFO_USEHELPER;
 
     DWORD numGenericArgs = 0;
@@ -2433,6 +2436,11 @@ void ProcessDynamicDictionaryLookup(TransitionBlock *           pTransitionBlock
             pResult->indirections = 2;
             pResult->offsets[0] = offsetof(InstantiatedMethodDesc, m_pPerInstInfo);
 
+            if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
+            {
+                pResult->indirectFirstOffset = 1;
+            }
+
             ULONG data;
             IfFailThrow(sigptr.GetData(&data));
             pResult->offsets[1] = sizeof(TypeHandle) * data;
@@ -2472,6 +2480,11 @@ void ProcessDynamicDictionaryLookup(TransitionBlock *           pTransitionBlock
             // Indirect through dictionary table pointer in InstantiatedMethodDesc
             pResult->offsets[0] = offsetof(InstantiatedMethodDesc, m_pPerInstInfo);
 
+            if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
+            {
+                pResult->indirectFirstOffset = 1;
+            }
+
             *pDictionaryIndexAndSlot |= dictionarySlot;
         }
     }