diff options
Diffstat (limited to 'packaging/0009-Remove-relocations-from-SECTION_MethodDesc-for-ngene.patch')
-rw-r--r-- | packaging/0009-Remove-relocations-from-SECTION_MethodDesc-for-ngene.patch | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/packaging/0009-Remove-relocations-from-SECTION_MethodDesc-for-ngene.patch b/packaging/0009-Remove-relocations-from-SECTION_MethodDesc-for-ngene.patch new file mode 100644 index 0000000000..d348274583 --- /dev/null +++ b/packaging/0009-Remove-relocations-from-SECTION_MethodDesc-for-ngene.patch @@ -0,0 +1,595 @@ +From 37436d59134e8beea0fcb4a7bb2b9c3e1e5e9714 Mon Sep 17 00:00:00 2001 +From: gbalykov <g.balykov@samsung.com> +Date: Sat, 3 Jun 2017 06:31:28 +0300 +Subject: [PATCH 09/32] Remove relocations from SECTION_MethodDesc for ngened + images for fields accessed from jit code for Linux ARM (#11963) + +--- + .../superpmi/superpmi-shared/methodcontext.cpp | 6 ++ + .../superpmi/superpmi-shared/methodcontext.h | 1 + + src/debug/daccess/nidump.cpp | 4 +- + src/inc/corinfo.h | 7 ++ + src/inc/fixuppointer.h | 99 +++++++++++++++++++++- + src/jit/importer.cpp | 14 +++ + src/vm/dllimport.cpp | 12 +++ + src/vm/genmeth.cpp | 10 +-- + src/vm/jitinterface.cpp | 12 +++ + src/vm/method.cpp | 18 +++- + src/vm/method.hpp | 32 +++++-- + src/vm/methodtablebuilder.cpp | 4 +- + src/vm/prestub.cpp | 13 +++ + 13 files changed, 211 insertions(+), 21 deletions(-) + +diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +index e60ef83..4c5fb61 100644 +--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp ++++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +@@ -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]; + } +diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +index f7c0e16..4887522 100644 +--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h ++++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +@@ -240,6 +240,7 @@ public: + DWORD testForNull; + DWORD testForFixup; + DWORDLONG offsets[CORINFO_MAXINDIRECTIONS]; ++ DWORD indirectFirstOffset; + }; + struct Agnostic_CORINFO_CONST_LOOKUP + { +diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp +index 5e8302f..d1e69f6 100644 +--- a/src/debug/daccess/nidump.cpp ++++ b/src/debug/daccess/nidump.cpp +@@ -7947,7 +7947,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), +@@ -8103,7 +8103,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 ) + { +diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h +index 2495de2..f6a136c 100644 +--- a/src/inc/corinfo.h ++++ b/src/inc/corinfo.h +@@ -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 +diff --git a/src/inc/fixuppointer.h b/src/inc/fixuppointer.h +index 549023a..38ae348 100644 +--- a/src/inc/fixuppointer.h ++++ b/src/inc/fixuppointer.h +@@ -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 +diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp +index 2d50741..80c0b75 100644 +--- a/src/jit/importer.cpp ++++ b/src/jit/importer.cpp +@@ -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 = +diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp +index cf546cd..3ec8b5f 100644 +--- a/src/vm/dllimport.cpp ++++ b/src/vm/dllimport.cpp +@@ -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(); + } + } +diff --git a/src/vm/genmeth.cpp b/src/vm/genmeth.cpp +index d5b435b..dc55221 100644 +--- a/src/vm/genmeth.cpp ++++ b/src/vm/genmeth.cpp +@@ -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); +diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp +index f7617ad..08965a7 100644 +--- a/src/vm/jitinterface.cpp ++++ b/src/vm/jitinterface.cpp +@@ -3141,6 +3141,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; + +@@ -3264,6 +3266,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; +@@ -3568,6 +3575,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; ++ } + } + } + +diff --git a/src/vm/method.cpp b/src/vm/method.cpp +index c8c1b9f..1407264 100644 +--- a/src/vm/method.cpp ++++ b/src/vm/method.cpp +@@ -3651,7 +3651,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()) +@@ -3730,7 +3737,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(); +diff --git a/src/vm/method.hpp b/src/vm/method.hpp +index ae65f30..9023a1b 100644 +--- a/src/vm/method.hpp ++++ b/src/vm/method.hpp +@@ -2590,7 +2590,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; +@@ -2812,11 +2816,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() +@@ -3221,7 +3225,7 @@ public: + if (IMD_IsGenericMethodDefinition()) + return TRUE; + else +- return m_pPerInstInfo != NULL; ++ return !m_pPerInstInfo.IsNull(); + } + + // All varieties of InstantiatedMethodDesc's support this method. +@@ -3229,13 +3233,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() +@@ -3394,7 +3406,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; +diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp +index 3162f7c..fdf4f48 100644 +--- a/src/vm/methodtablebuilder.cpp ++++ b/src/vm/methodtablebuilder.cpp +@@ -6121,8 +6121,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, +diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp +index 88bd9de..af3f190 100644 +--- a/src/vm/prestub.cpp ++++ b/src/vm/prestub.cpp +@@ -2405,6 +2405,9 @@ void ProcessDynamicDictionaryLookup(TransitionBlock * pTransitionBlock + + pResult->testForFixup = pResult->testForNull = false; + pResult->signature = NULL; ++ ++ pResult->indirectFirstOffset = 0; ++ + pResult->indirections = CORINFO_USEHELPER; + + DWORD numGenericArgs = 0; +@@ -2455,6 +2458,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; +@@ -2494,6 +2502,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; + } + } +-- +2.7.4 + |