From 37436d59134e8beea0fcb4a7bb2b9c3e1e5e9714 Mon Sep 17 00:00:00 2001 From: gbalykov 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(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 class RelativePointer { public: + + static constexpr bool isRelative = true; + typedef PTR_TYPE type; + #ifndef DACCESS_COMPILE RelativePointer() { @@ -173,6 +177,10 @@ template 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 class RelativeFixupPointer { public: + + static constexpr bool isRelative = true; + typedef PTR_TYPE type; + // Implicit copy/move is not allowed RelativeFixupPointer(const RelativeFixupPointer &) =delete; RelativeFixupPointer(RelativeFixupPointer &&) =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 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 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 +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(base) + offset); + } + else + { + return PT::GetValueAtPtr(dac_cast(base) + offset); + } +} + +template +typename PT::type +ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pPointerFieldMember); +} + +template +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pPointerFieldMember); +} + +template +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(base) + offset); + } + else + { + return PT::GetValueAtPtr(dac_cast(base) + offset); + } +} + +template +typename PT::type +ReadPointerMaybeNull(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pFirstPointerFieldMember, pSecondPointerFieldMember); +} + +template +typename PT::type +ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(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(numGenericArgs)); m_wNumGenericArgs = static_cast(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(numGenericArgs)); m_wNumGenericArgs = static_cast(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(numGenericArgs)); m_wNumGenericArgs = static_cast(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 m_pWriteableData; +#else + PlainPointer m_pWriteableData; +#endif #ifdef HAS_NDIRECT_IMPORT_PRECODE RelativePointer 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: // make private: JITinterface.cpp accesses through this // // For generic method definitions that are not the typical method definition (e.g. C.m) // this field is null; to obtain the instantiation use LoadMethodInstantiation - PTR_Dictionary m_pPerInstInfo; //SHARED +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + RelativePointer m_pPerInstInfo; //SHARED +#else + PlainPointer 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