diff options
author | Konstantin Baladurin <k.baladurin@partner.samsung.com> | 2018-04-26 17:34:58 +0300 |
---|---|---|
committer | Vladislav Andresov <v.andresov@partner.samsung.com> | 2018-04-26 20:04:15 +0300 |
commit | 371df401e4d8c9639035d164710d1246e0cb8548 (patch) | |
tree | b550f3433a68c80a1ff952413b7b7a0e3ab97995 /packaging/0024-Remove-relocations-for-MethodTable-m_pPerInstInfo-fo.patch | |
parent | 5e7a310b1a251937154d05cd52637ac62b6d5edc (diff) | |
download | coreclr-accepted/tizen_4.0_unified.tar.gz coreclr-accepted/tizen_4.0_unified.tar.bz2 coreclr-accepted/tizen_4.0_unified.zip |
Add memory optimization patches from upstreamsubmit/tizen_4.0/20180427.011218accepted/tizen/4.0/unified/20180427.062437accepted/tizen_4.0_unified
Change-Id: Ie8ea75fa60184b77135289c8fdc0f49d40b49d87
Diffstat (limited to 'packaging/0024-Remove-relocations-for-MethodTable-m_pPerInstInfo-fo.patch')
-rw-r--r-- | packaging/0024-Remove-relocations-for-MethodTable-m_pPerInstInfo-fo.patch | 541 |
1 files changed, 541 insertions, 0 deletions
diff --git a/packaging/0024-Remove-relocations-for-MethodTable-m_pPerInstInfo-fo.patch b/packaging/0024-Remove-relocations-for-MethodTable-m_pPerInstInfo-fo.patch new file mode 100644 index 0000000000..4bc117b4ed --- /dev/null +++ b/packaging/0024-Remove-relocations-for-MethodTable-m_pPerInstInfo-fo.patch @@ -0,0 +1,541 @@ +From ca3a3d9695301697d9011f4187eefaa05595f9e7 Mon Sep 17 00:00:00 2001 +From: Gleb Balykov <g.balykov@samsung.com> +Date: Thu, 12 Apr 2018 12:49:39 +0300 +Subject: [PATCH 24/32] Remove relocations for MethodTable::m_pPerInstInfo for + Linux ARM + +FIX: fix No.4, manually applied patch due to code differencies +--- + .../superpmi/superpmi-shared/methodcontext.cpp | 6 +++ + .../superpmi/superpmi-shared/methodcontext.h | 1 + + src/debug/daccess/nidump.cpp | 6 ++- + src/inc/corinfo.h | 7 ++++ + src/jit/importer.cpp | 6 +-- + src/vm/ceeload.cpp | 11 ++++- + src/vm/class.cpp | 7 +++- + src/vm/genericdict.cpp | 2 +- + src/vm/generics.cpp | 5 ++- + src/vm/jitinterface.cpp | 13 ++++++ + src/vm/methodtable.cpp | 47 +++++++++++++++++----- + src/vm/methodtable.h | 29 +++++++++---- + src/vm/methodtable.inl | 2 +- + src/vm/methodtablebuilder.cpp | 7 ++-- + src/vm/prestub.cpp | 13 ++++++ + 15 files changed, 129 insertions(+), 33 deletions(-) + +diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +index 4c5fb61..4406b85 100644 +--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp ++++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +@@ -1574,6 +1574,7 @@ void MethodContext::recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, + 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; ++ value.stubLookup.runtimeLookup.indirectSecondOffset = (DWORD)pResult->stubLookup.runtimeLookup.indirectSecondOffset; + for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) + value.stubLookup.runtimeLookup.offsets[i] = (DWORDLONG)pResult->stubLookup.runtimeLookup.offsets[i]; + } +@@ -1585,6 +1586,7 @@ void MethodContext::recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, + value.stubLookup.runtimeLookup.testForNull = (DWORD)0; + value.stubLookup.runtimeLookup.testForFixup = (DWORD)0; + value.stubLookup.runtimeLookup.indirectFirstOffset = (DWORD)0; ++ value.stubLookup.runtimeLookup.indirectSecondOffset = (DWORD)0; + for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) + value.stubLookup.runtimeLookup.offsets[i] = (DWORDLONG)0; + +@@ -1764,6 +1766,7 @@ void MethodContext::repGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, + 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; ++ pResult->stubLookup.runtimeLookup.indirectSecondOffset = value.stubLookup.runtimeLookup.indirectSecondOffset != 0; + for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) + pResult->stubLookup.runtimeLookup.offsets[i] = (SIZE_T)value.stubLookup.runtimeLookup.offsets[i]; + } +@@ -3222,6 +3225,7 @@ void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolve + 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; ++ value.lookup.runtimeLookup.indirectSecondOffset = (DWORD)pResult->lookup.runtimeLookup.indirectSecondOffset; + for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) + value.lookup.runtimeLookup.offsets[i] = (DWORDLONG)pResult->lookup.runtimeLookup.offsets[i]; + } +@@ -3233,6 +3237,7 @@ void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolve + value.lookup.runtimeLookup.testForNull = (DWORD)0; + value.lookup.runtimeLookup.testForFixup = (DWORD)0; + value.lookup.runtimeLookup.indirectFirstOffset = (DWORD)0; ++ value.lookup.runtimeLookup.indirectSecondOffset = (DWORD)0; + for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) + value.lookup.runtimeLookup.offsets[i] = (DWORDLONG)0; + // copy the constLookup view of the union +@@ -3311,6 +3316,7 @@ void MethodContext::repEmbedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolve + 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; ++ pResult->lookup.runtimeLookup.indirectSecondOffset = value.lookup.runtimeLookup.indirectSecondOffset != 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 4887522..53227e4 100644 +--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h ++++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +@@ -241,6 +241,7 @@ public: + DWORD testForFixup; + DWORDLONG offsets[CORINFO_MAXINDIRECTIONS]; + DWORD indirectFirstOffset; ++ DWORD indirectSecondOffset; + }; + struct Agnostic_CORINFO_CONST_LOOKUP + { +diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp +index 04d610e..d43e9f9 100644 +--- a/src/debug/daccess/nidump.cpp ++++ b/src/debug/daccess/nidump.cpp +@@ -5106,7 +5106,9 @@ void NativeImageDumper::MethodTableToString( PTR_MethodTable mt, SString& buf ) + { + numDicts = (DWORD)CountDictionariesInClass(token, dependency->pImport); + } +- PTR_Dictionary dictionary( mt->GetPerInstInfo()[numDicts-1] ); ++ ++ TADDR base = dac_cast<TADDR>(&(mt->GetPerInstInfo()[numDicts-1])); ++ PTR_Dictionary dictionary( MethodTable::PerInstInfoElem_t::GetValueAtPtr(base) ); + unsigned numArgs = mt->GetNumGenericArgs(); + + DictionaryToArgString( dictionary, numArgs, buf ); +@@ -7092,7 +7094,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, + DisplayEndStructure( METHODTABLES ); //GenericsDictInfo + + +- DPTR(PTR_Dictionary) perInstInfo = mt->GetPerInstInfo(); ++ DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo(); + + DisplayStartStructure( "PerInstInfo", + DPtrToPreferredAddr(perInstInfo), +diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h +index a6acd71..58fcdf4 100644 +--- a/src/inc/corinfo.h ++++ b/src/inc/corinfo.h +@@ -1331,6 +1331,13 @@ struct CORINFO_RUNTIME_LOOKUP + // 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; ++ ++ // If set, second offset is indirect. ++ // 0 means that value stored at second offset (offsets[1]) from pointer is next pointer, to which the next offset ++ // (offsets[2]) is added and so on. ++ // 1 means that value stored at second offset (offsets[1]) from pointer is offset2, and the next pointer is ++ // stored at pointer+offsets[1]+offset2. ++ bool indirectSecondOffset; + } ; + + // Result of calling embedGenericHandle +diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp +index c5f2970..62f1c13 100644 +--- a/src/jit/importer.cpp ++++ b/src/jit/importer.cpp +@@ -1980,10 +1980,10 @@ GenTreePtr Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedTok + // Applied repeated indirections + for (WORD i = 0; i < pRuntimeLookup->indirections; i++) + { +- if (i == 1 && pRuntimeLookup->indirectFirstOffset) ++ if ((i == 1 && pRuntimeLookup->indirectFirstOffset) || (i == 2 && pRuntimeLookup->indirectSecondOffset)) + { + indOffTree = impCloneExpr(slotPtrTree, &slotPtrTree, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL, +- nullptr DEBUGARG("impRuntimeLookup indirectFirstOffset")); ++ nullptr DEBUGARG("impRuntimeLookup indirectOffset")); + } + + if (i != 0) +@@ -1993,7 +1993,7 @@ GenTreePtr Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedTok + slotPtrTree->gtFlags |= GTF_IND_INVARIANT; + } + +- if (i == 1 && pRuntimeLookup->indirectFirstOffset) ++ if ((i == 1 && pRuntimeLookup->indirectFirstOffset) || (i == 2 && pRuntimeLookup->indirectSecondOffset)) + { + slotPtrTree = gtNewOperNode(GT_ADD, TYP_I_IMPL, indOffTree, slotPtrTree); + } +diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp +index 43e2c14..9e5a525 100644 +--- a/src/vm/ceeload.cpp ++++ b/src/vm/ceeload.cpp +@@ -9325,13 +9325,20 @@ void Module::PlaceType(DataImage *image, TypeHandle th, DWORD profilingFlags) + { + if (pMT->HasPerInstInfo()) + { +- Dictionary ** pPerInstInfo = pMT->GetPerInstInfo(); ++ DPTR(MethodTable::PerInstInfoElem_t) pPerInstInfo = pMT->GetPerInstInfo(); + + BOOL fIsEagerBound = pMT->CanEagerBindToParentDictionaries(image, NULL); + + if (fIsEagerBound) + { +- image->PlaceInternedStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT); ++ if (MethodTable::PerInstInfoElem_t::isRelative) ++ { ++ image->PlaceStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_HOT); ++ } ++ else ++ { ++ image->PlaceInternedStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT); ++ } + } + else + { +diff --git a/src/vm/class.cpp b/src/vm/class.cpp +index 6697b23..c1519a2 100644 +--- a/src/vm/class.cpp ++++ b/src/vm/class.cpp +@@ -908,8 +908,11 @@ ClassLoader::LoadExactParentAndInterfacesTransitively(MethodTable *pMT) + DWORD nDicts = pParentMT->GetNumDicts(); + for (DWORD iDict = 0; iDict < nDicts; iDict++) + { +- if (pMT->GetPerInstInfo()[iDict] != pParentMT->GetPerInstInfo()[iDict]) +- *EnsureWritablePages(&pMT->GetPerInstInfo()[iDict]) = pParentMT->GetPerInstInfo()[iDict]; ++ if (pMT->GetPerInstInfo()[iDict].GetValueMaybeNull() != pParentMT->GetPerInstInfo()[iDict].GetValueMaybeNull()) ++ { ++ EnsureWritablePages(&pMT->GetPerInstInfo()[iDict]); ++ pMT->GetPerInstInfo()[iDict].SetValueMaybeNull(pParentMT->GetPerInstInfo()[iDict].GetValueMaybeNull()); ++ } + } + } + +diff --git a/src/vm/genericdict.cpp b/src/vm/genericdict.cpp +index c93e583..5fad30f 100644 +--- a/src/vm/genericdict.cpp ++++ b/src/vm/genericdict.cpp +@@ -742,7 +742,7 @@ Dictionary::PopulateEntry( + } + + // MethodTable is expected to be normalized +- _ASSERTE(pDictionary == pMT->GetPerInstInfo()[dictionaryIndex]); ++ _ASSERTE(pDictionary == pMT->GetPerInstInfo()[dictionaryIndex].GetValueMaybeNull()); + } + else + { +diff --git a/src/vm/generics.cpp b/src/vm/generics.cpp +index 63d95a0..650caef 100644 +--- a/src/vm/generics.cpp ++++ b/src/vm/generics.cpp +@@ -499,7 +499,7 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( + _ASSERTE(pOldMT->HasPerInstInfo()); + + // Fill in per-inst map pointer (which points to the array of generic dictionary pointers) +- pMT->SetPerInstInfo ((Dictionary**) (pMemory + cbMT + cbOptional + cbIMap + sizeof(GenericsDictInfo))); ++ pMT->SetPerInstInfo((MethodTable::PerInstInfoElem_t *) (pMemory + cbMT + cbOptional + cbIMap + sizeof(GenericsDictInfo))); + _ASSERTE(FitsIn<WORD>(pOldMT->GetNumDicts())); + _ASSERTE(FitsIn<WORD>(pOldMT->GetNumGenericArgs())); + pMT->SetDictInfo(static_cast<WORD>(pOldMT->GetNumDicts()), static_cast<WORD>(pOldMT->GetNumGenericArgs())); +@@ -508,7 +508,8 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( + // The others are filled in by LoadExactParents which copied down any inherited generic + // dictionary pointers. + Dictionary * pDict = (Dictionary*) (pMemory + cbMT + cbOptional + cbIMap + cbPerInst); +- *(pMT->GetPerInstInfo() + (pOldMT->GetNumDicts()-1)) = pDict; ++ MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *) (pMT->GetPerInstInfo() + (pOldMT->GetNumDicts()-1)); ++ pPInstInfo->SetValueMaybeNull(pDict); + + // Fill in the instantiation section of the generic dictionary. The remainder of the + // generic dictionary will be zeroed, which is the correct initial state. +diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp +index 52db7c5..e0adf87 100644 +--- a/src/vm/jitinterface.cpp ++++ b/src/vm/jitinterface.cpp +@@ -3149,6 +3149,7 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr + pResult->signature = NULL; + + pResult->indirectFirstOffset = 0; ++ pResult->indirectSecondOffset = 0; + + // Unless we decide otherwise, just do the lookup via a helper function + pResult->indirections = CORINFO_USEHELPER; +@@ -3363,6 +3364,12 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr + IfFailThrow(sigptr.GetData(&data)); + pResult->offsets[2] = sizeof(TypeHandle) * data; + ++ if (MethodTable::IsPerInstInfoRelative()) ++ { ++ pResult->indirectFirstOffset = 1; ++ pResult->indirectSecondOffset = 1; ++ } ++ + return; + } + else if (type == ELEMENT_TYPE_GENERICINST && +@@ -3610,6 +3617,12 @@ NoSpecialCase: + + // Next indirect through the dictionary appropriate to this instantiated type + pResult->offsets[1] = sizeof(TypeHandle*) * (pContextMT->GetNumDicts() - 1); ++ ++ if (MethodTable::IsPerInstInfoRelative()) ++ { ++ pResult->indirectFirstOffset = 1; ++ pResult->indirectSecondOffset = 1; ++ } + } + } + } +diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp +index e93f63d..4c1746e 100644 +--- a/src/vm/methodtable.cpp ++++ b/src/vm/methodtable.cpp +@@ -4332,7 +4332,14 @@ void MethodTable::Save(DataImage *image, DWORD profilingFlags) + ZapStoredStructure * pPerInstInfoNode; + if (CanEagerBindToParentDictionaries(image, NULL)) + { +- pPerInstInfoNode = image->StoreInternedStructure((BYTE *)GetPerInstInfo() - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo), DataImage::ITEM_DICTIONARY); ++ if (PerInstInfoElem_t::isRelative) ++ { ++ pPerInstInfoNode = image->StoreStructure((BYTE *)GetPerInstInfo() - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo), DataImage::ITEM_DICTIONARY); ++ } ++ else ++ { ++ pPerInstInfoNode = image->StoreInternedStructure((BYTE *)GetPerInstInfo() - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo), DataImage::ITEM_DICTIONARY); ++ } + } + else + { +@@ -4675,14 +4682,21 @@ BOOL MethodTable::IsWriteable() + // target module. Thus we want to call CanEagerBindToMethodTable + // to check we can hardbind to the containing structure. + static +-void HardBindOrClearDictionaryPointer(DataImage *image, MethodTable *pMT, void * p, SSIZE_T offset) ++void HardBindOrClearDictionaryPointer(DataImage *image, MethodTable *pMT, void * p, SSIZE_T offset, bool isRelative) + { + WRAPPER_NO_CONTRACT; + + if (image->CanEagerBindToMethodTable(pMT) && + image->CanHardBindToZapModule(pMT->GetLoaderModule())) + { +- image->FixupPointerField(p, offset); ++ if (isRelative) ++ { ++ image->FixupRelativePointerField(p, offset); ++ } ++ else ++ { ++ image->FixupPointerField(p, offset); ++ } + } + else + { +@@ -5017,7 +5031,7 @@ void MethodTable::Fixup(DataImage *image) + if (HasPerInstInfo()) + { + // Fixup the pointer to the per-inst table +- image->FixupPointerField(this, offsetof(MethodTable, m_pPerInstInfo)); ++ image->FixupPlainOrRelativePointerField(this, &MethodTable::m_pPerInstInfo); + + for (MethodTable *pChain = this; pChain != NULL; pChain = pChain->GetParentMethodTable()) + { +@@ -5030,10 +5044,23 @@ void MethodTable::Fixup(DataImage *image) + + // We special-case the dictionary for this method table because we must always + // hard bind to it even if it's not in its preferred zap module ++ size_t sizeDict = sizeof(PerInstInfoElem_t); ++ + if (pChain == this) +- image->FixupPointerField(GetPerInstInfo(), dictNum * sizeof(Dictionary *)); ++ { ++ if (PerInstInfoElem_t::isRelative) ++ { ++ image->FixupRelativePointerField(GetPerInstInfo(), dictNum * sizeDict); ++ } ++ else ++ { ++ image->FixupPointerField(GetPerInstInfo(), dictNum * sizeDict); ++ } ++ } + else +- HardBindOrClearDictionaryPointer(image, pChain, GetPerInstInfo(), dictNum * sizeof(Dictionary *)); ++ { ++ HardBindOrClearDictionaryPointer(image, pChain, GetPerInstInfo(), dictNum * sizeDict, PerInstInfoElem_t::isRelative); ++ } + } + } + } +@@ -6218,7 +6245,7 @@ BOOL MethodTable::IsWinRTObjectType() + //========================================================================================== + // Return a pointer to the dictionary for an instantiated type + // Return NULL if not instantiated +-Dictionary* MethodTable::GetDictionary() ++PTR_Dictionary MethodTable::GetDictionary() + { + LIMITED_METHOD_DAC_CONTRACT; + +@@ -6226,7 +6253,8 @@ Dictionary* MethodTable::GetDictionary() + { + // The instantiation for this class is stored in the type slots table + // *after* any inherited slots +- return GetPerInstInfo()[GetNumDicts()-1]; ++ TADDR base = dac_cast<TADDR>(&(GetPerInstInfo()[GetNumDicts()-1])); ++ return PerInstInfoElem_t::GetValueMaybeNullAtPtr(base); + } + else + { +@@ -6243,7 +6271,8 @@ Instantiation MethodTable::GetInstantiation() + if (HasInstantiation()) + { + PTR_GenericsDictInfo pDictInfo = GetGenericsDictInfo(); +- return Instantiation(GetPerInstInfo()[pDictInfo->m_wNumDicts-1]->GetInstantiation(), pDictInfo->m_wNumTyPars); ++ TADDR base = dac_cast<TADDR>(&(GetPerInstInfo()[pDictInfo->m_wNumDicts-1])); ++ return Instantiation(PerInstInfoElem_t::GetValueMaybeNullAtPtr(base)->GetInstantiation(), pDictInfo->m_wNumTyPars); + } + else + { +diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h +index 63d35e6..81a9186 100644 +--- a/src/vm/methodtable.h ++++ b/src/vm/methodtable.h +@@ -3008,12 +3008,20 @@ public: + // must have a dictionary entry. On the other hand, for instantiations shared with Dict<string,double> the opposite holds. + // + ++#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) ++ typedef RelativePointer<PTR_Dictionary> PerInstInfoElem_t; ++ typedef RelativePointer<DPTR(PerInstInfoElem_t)> PerInstInfo_t; ++#else ++ typedef PlainPointer<PTR_Dictionary> PerInstInfoElem_t; ++ typedef PlainPointer<DPTR(PerInstInfoElem_t)> PerInstInfo_t; ++#endif ++ + // Return a pointer to the per-instantiation information. See field itself for comments. +- DPTR(PTR_Dictionary) GetPerInstInfo() ++ DPTR(PerInstInfoElem_t) GetPerInstInfo() + { + LIMITED_METHOD_DAC_CONTRACT; + _ASSERTE(HasPerInstInfo()); +- return dac_cast<DPTR(PTR_Dictionary)>(m_pMultipurposeSlot1); ++ return ReadPointer(this, &MethodTable::m_pPerInstInfo); + } + BOOL HasPerInstInfo() + { +@@ -3021,15 +3029,20 @@ public: + return GetFlag(enum_flag_HasPerInstInfo) && !IsArray(); + } + #ifndef DACCESS_COMPILE ++ static inline bool IsPerInstInfoRelative() ++ { ++ LIMITED_METHOD_CONTRACT; ++ return decltype(m_pPerInstInfo)::isRelative; ++ } + static inline DWORD GetOffsetOfPerInstInfo() + { + LIMITED_METHOD_CONTRACT; + return offsetof(MethodTable, m_pPerInstInfo); + } +- void SetPerInstInfo(Dictionary** pPerInstInfo) ++ void SetPerInstInfo(PerInstInfoElem_t *pPerInstInfo) + { + LIMITED_METHOD_CONTRACT; +- m_pPerInstInfo = pPerInstInfo; ++ m_pPerInstInfo.SetValue(pPerInstInfo); + } + void SetDictInfo(WORD numDicts, WORD numTyPars) + { +@@ -3049,7 +3062,7 @@ public: + // Get a pointer to the dictionary for this instantiated type + // (The instantiation is stored in the initial slots of the dictionary) + // If not instantiated, return NULL +- Dictionary* GetDictionary(); ++ PTR_Dictionary GetDictionary(); + + #ifdef FEATURE_PREJIT + // +@@ -4123,9 +4136,9 @@ private: + + union + { +- PTR_Dictionary * m_pPerInstInfo; +- TADDR m_ElementTypeHnd; +- TADDR m_pMultipurposeSlot1; ++ PerInstInfo_t m_pPerInstInfo; ++ TADDR m_ElementTypeHnd; ++ TADDR m_pMultipurposeSlot1; + }; + public: + union +diff --git a/src/vm/methodtable.inl b/src/vm/methodtable.inl +index 4c808ee..b69513d 100644 +--- a/src/vm/methodtable.inl ++++ b/src/vm/methodtable.inl +@@ -1256,7 +1256,7 @@ inline BOOL MethodTable::HasExplicitSize() + inline DWORD MethodTable::GetPerInstInfoSize() + { + LIMITED_METHOD_DAC_CONTRACT; +- return GetNumDicts() * sizeof(TypeHandle*); ++ return GetNumDicts() * sizeof(PerInstInfoElem_t); + } + + //========================================================================================== +diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp +index 5d77463..792a19c 100644 +--- a/src/vm/methodtablebuilder.cpp ++++ b/src/vm/methodtablebuilder.cpp +@@ -10050,7 +10050,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule, + if (dwNumDicts != 0) + { + cbTotalSize += sizeof(GenericsDictInfo); +- cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(TypeHandle*)); ++ cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t)); + cbTotalSize += cbInstAndDict; + } + +@@ -10203,14 +10203,15 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule, + // the dictionary pointers follow the interface map + if (dwNumDicts) + { +- Dictionary** pPerInstInfo = (Dictionary**)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo)); ++ MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo)); + + pMT->SetPerInstInfo ( pPerInstInfo); + + // Fill in the dictionary for this type, if it's instantiated + if (cbInstAndDict) + { +- *(pPerInstInfo + (dwNumDicts-1)) = (Dictionary*) (pPerInstInfo + dwNumDicts); ++ MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1)); ++ pPInstInfo->SetValueMaybeNull((Dictionary*) (pPerInstInfo + dwNumDicts)); + } + } + +diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp +index 746e415..b31e8f7 100644 +--- a/src/vm/prestub.cpp ++++ b/src/vm/prestub.cpp +@@ -2407,6 +2407,7 @@ void ProcessDynamicDictionaryLookup(TransitionBlock * pTransitionBlock + pResult->signature = NULL; + + pResult->indirectFirstOffset = 0; ++ pResult->indirectSecondOffset = 0; + + pResult->indirections = CORINFO_USEHELPER; + +@@ -2479,6 +2480,12 @@ void ProcessDynamicDictionaryLookup(TransitionBlock * pTransitionBlock + IfFailThrow(sigptr.GetData(&data)); + pResult->offsets[2] = sizeof(TypeHandle) * data; + ++ if (MethodTable::IsPerInstInfoRelative()) ++ { ++ pResult->indirectFirstOffset = 1; ++ pResult->indirectSecondOffset = 1; ++ } ++ + return; + } + } +@@ -2524,6 +2531,12 @@ void ProcessDynamicDictionaryLookup(TransitionBlock * pTransitionBlock + // Next indirect through the dictionary appropriate to this instantiated type + pResult->offsets[1] = sizeof(TypeHandle*) * (pContextMT->GetNumDicts() - 1); + ++ if (MethodTable::IsPerInstInfoRelative()) ++ { ++ pResult->indirectFirstOffset = 1; ++ pResult->indirectSecondOffset = 1; ++ } ++ + *pDictionaryIndexAndSlot |= dictionarySlot; + } + } +-- +2.7.4 + |