diff options
Diffstat (limited to 'src/vm')
-rw-r--r-- | src/vm/array.cpp | 11 | ||||
-rw-r--r-- | src/vm/ceeload.cpp | 80 | ||||
-rw-r--r-- | src/vm/ceeload.h | 30 | ||||
-rw-r--r-- | src/vm/class.cpp | 17 | ||||
-rw-r--r-- | src/vm/dataimage.cpp | 6 | ||||
-rw-r--r-- | src/vm/dataimage.h | 78 | ||||
-rw-r--r-- | src/vm/debughelp.cpp | 2 | ||||
-rw-r--r-- | src/vm/genericdict.cpp | 2 | ||||
-rw-r--r-- | src/vm/generics.cpp | 11 | ||||
-rw-r--r-- | src/vm/jithelpers.cpp | 8 | ||||
-rw-r--r-- | src/vm/jitinterface.cpp | 19 | ||||
-rw-r--r-- | src/vm/jitinterface.h | 4 | ||||
-rw-r--r-- | src/vm/method.cpp | 18 | ||||
-rw-r--r-- | src/vm/methodtable.cpp | 206 | ||||
-rw-r--r-- | src/vm/methodtable.h | 161 | ||||
-rw-r--r-- | src/vm/methodtable.inl | 76 | ||||
-rw-r--r-- | src/vm/methodtablebuilder.cpp | 21 | ||||
-rw-r--r-- | src/vm/prestub.cpp | 13 | ||||
-rw-r--r-- | src/vm/proftoeeinterfaceimpl.cpp | 2 |
19 files changed, 526 insertions, 239 deletions
diff --git a/src/vm/array.cpp b/src/vm/array.cpp index d6792942e7..3a33aff43a 100644 --- a/src/vm/array.cpp +++ b/src/vm/array.cpp @@ -310,7 +310,7 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy DWORD numNonVirtualSlots = numCtors + 3; // 3 for the proper rank Get, Set, Address size_t cbMT = sizeof(MethodTable); - cbMT += MethodTable::GetNumVtableIndirections(numVirtuals) * sizeof(PTR_PCODE); + cbMT += MethodTable::GetNumVtableIndirections(numVirtuals) * sizeof(MethodTable::VTableIndir_t); // GC info size_t cbCGCDescData = 0; @@ -509,8 +509,11 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy #endif // !defined(_WIN64) && (DATA_ALIGNMENT > 4) pMT->SetBaseSize(baseSize); // Because of array method table persisting, we need to copy the map - memcpy(pMTHead + imapOffset, pParentClass->GetInterfaceMap(), - pParentClass->GetNumInterfaces() * sizeof(InterfaceInfo_t)); + for (unsigned index = 0; index < pParentClass->GetNumInterfaces(); ++index) + { + InterfaceInfo_t *pIntInfo = (InterfaceInfo_t *) (pMTHead + imapOffset + index * sizeof(InterfaceInfo_t)); + pIntInfo->SetMethodTable((pParentClass->GetInterfaceMap() + index)->GetMethodTable()); + } pMT->SetInterfaceMap(pParentClass->GetNumInterfaces(), (InterfaceInfo_t *)(pMTHead + imapOffset)); // Copy down flags for these interfaces as well. This is simplified a bit since we know that System.Array @@ -536,7 +539,7 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy if (canShareVtableChunks) { // Share the parent chunk - it.SetIndirectionSlot(pParentClass->GetVtableIndirections()[it.GetIndex()]); + it.SetIndirectionSlot(pParentClass->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull()); } else { diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index bec7372bd1..c64d9e9042 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -2803,7 +2803,7 @@ BOOL Module::IsPreV4Assembly() } -ArrayDPTR(FixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index) +ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index) { LIMITED_METHOD_CONTRACT; @@ -8100,6 +8100,8 @@ void Module::SaveTypeHandle(DataImage * image, #endif // _DEBUG } +#ifndef DACCESS_COMPILE + void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) { STANDARD_VM_CONTRACT; @@ -8121,7 +8123,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) // items numElementsHot...i-1 are cold for (i = 0; i < numElements; i++) { - MethodTable *ppMTTemp = ppMT[i]; + MethodTable *ppMTTemp = ppMT[i].GetValue(); // Count the number of boxed statics along the way totalBoxedStatics += ppMTTemp->GetNumBoxedRegularStatics(); @@ -8135,8 +8137,8 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) if (hot) { // swap ppMT[i] and ppMT[numElementsHot] to maintain the loop invariant - ppMT[i] = ppMT[numElementsHot]; - ppMT[numElementsHot] = ppMTTemp; + ppMT[i].SetValue(ppMT[numElementsHot].GetValue()); + ppMT[numElementsHot].SetValue(ppMTTemp); numElementsHot++; } @@ -8161,11 +8163,11 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) for (i = 0; i < numElementsHot; i++) { - hashArray[i] = GenerateHash(ppMT[i], HOT); + hashArray[i] = GenerateHash(ppMT[i].GetValue(), HOT); } for (i = numElementsHot; i < numElements; i++) { - hashArray[i] = GenerateHash(ppMT[i], COLD); + hashArray[i] = GenerateHash(ppMT[i].GetValue(), COLD); } // Sort the two arrays by hash values to create regions with the same hash values. @@ -8228,7 +8230,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) // make cctorInfoCold point to the first cold element cctorInfoCold = cctorInfoHot + numElementsHot; - ppHotGCStaticsMTs = (totalBoxedStatics != 0) ? new FixupPointer<PTR_MethodTable>[totalBoxedStatics] : NULL; + ppHotGCStaticsMTs = (totalBoxedStatics != 0) ? new RelativeFixupPointer<PTR_MethodTable>[totalBoxedStatics] : NULL; numHotGCStaticsMTs = totalBoxedStatics; DWORD iGCStaticMT = 0; @@ -8244,7 +8246,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) ppColdGCStaticsMTs = ppHotGCStaticsMTs + numHotGCStaticsMTs; } - MethodTable* pMT = ppMT[i]; + MethodTable* pMT = ppMT[i].GetValue(); ClassCtorInfoEntry* pEntry = &cctorInfoHot[i]; WORD numBoxedStatics = pMT->GetNumBoxedRegularStatics(); @@ -8274,7 +8276,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) == (iGCStaticMT - pEntry->firstBoxedStaticMTIndex) * sizeof(MethodTable*)); TypeHandle th = pField->GetFieldTypeHandleThrowing(); - ppHotGCStaticsMTs[iGCStaticMT++].SetValue(th.GetMethodTable()); + ppHotGCStaticsMTs[iGCStaticMT++].SetValueMaybeNull(th.GetMethodTable()); numFoundBoxedStatics++; } @@ -8297,7 +8299,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) if (numElements > 0) image->StoreStructure(ppMT, - sizeof(MethodTable *) * numElements, + sizeof(RelativePointer<MethodTable *>) * numElements, DataImage::ITEM_MODULE_CCTOR_INFO_HOT); if (numElements > numElementsHot) @@ -8314,7 +8316,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) if ( numHotGCStaticsMTs ) { // Save the mt templates - image->StoreStructure( ppHotGCStaticsMTs, numHotGCStaticsMTs * sizeof(MethodTable*), + image->StoreStructure( ppHotGCStaticsMTs, numHotGCStaticsMTs * sizeof(RelativeFixupPointer<MethodTable*>), DataImage::ITEM_GC_STATIC_HANDLES_HOT); } else @@ -8325,7 +8327,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) if ( numColdGCStaticsMTs ) { // Save the hot mt templates - image->StoreStructure( ppColdGCStaticsMTs, numColdGCStaticsMTs * sizeof(MethodTable*), + image->StoreStructure( ppColdGCStaticsMTs, numColdGCStaticsMTs * sizeof(RelativeFixupPointer<MethodTable*>), DataImage::ITEM_GC_STATIC_HANDLES_COLD); } else @@ -8334,6 +8336,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData) } } +#endif // !DACCESS_COMPILE bool Module::AreAllClassesFullyLoaded() { @@ -9134,13 +9137,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 { @@ -9470,7 +9480,7 @@ void ModuleCtorInfo::Fixup(DataImage *image) for (DWORD i=0; i<numElements; i++) { - image->FixupPointerField(ppMT, i * sizeof(ppMT[0])); + image->FixupRelativePointerField(ppMT, i * sizeof(ppMT[0])); } } else @@ -10092,11 +10102,37 @@ void Module::RestoreMethodTablePointer(RelativeFixupPointer<PTR_MethodTable> * p if (ppMT->IsTagged((TADDR)ppMT)) { - RestoreMethodTablePointerRaw(ppMT->GetValuePtr((TADDR)ppMT), pContainingModule, level); + RestoreMethodTablePointerRaw(ppMT->GetValuePtr(), pContainingModule, level); } else { - ClassLoader::EnsureLoaded(ppMT->GetValue((TADDR)ppMT), level); + ClassLoader::EnsureLoaded(ppMT->GetValue(), level); + } +} + +/*static*/ +void Module::RestoreMethodTablePointer(PlainPointer<PTR_MethodTable> * ppMT, + Module *pContainingModule, + ClassLoadLevel level) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + if (ppMT->IsNull()) + return; + + if (ppMT->IsTagged()) + { + RestoreMethodTablePointerRaw(ppMT->GetValuePtr(), pContainingModule, level); + } + else + { + ClassLoader::EnsureLoaded(ppMT->GetValue(), level); } } @@ -10231,7 +10267,7 @@ PTR_Module Module::RestoreModulePointerIfLoaded(DPTR(RelativeFixupPointer<PTR_Mo return ppModule->GetValue(dac_cast<TADDR>(ppModule)); #ifndef DACCESS_COMPILE - PTR_Module * ppValue = ppModule->GetValuePtr(dac_cast<TADDR>(ppModule)); + PTR_Module * ppValue = ppModule->GetValuePtr(); // Ensure that the compiler won't fetch the value twice TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue); @@ -10284,7 +10320,7 @@ void Module::RestoreModulePointer(RelativeFixupPointer<PTR_Module> * ppModule, M if (!ppModule->IsTagged((TADDR)ppModule)) return; - PTR_Module * ppValue = ppModule->GetValuePtr((TADDR)ppModule); + PTR_Module * ppValue = ppModule->GetValuePtr(); // Ensure that the compiler won't fetch the value twice TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue); @@ -10438,7 +10474,7 @@ void Module::RestoreTypeHandlePointer(RelativeFixupPointer<TypeHandle> * pHandle if (pHandle->IsTagged((TADDR)pHandle)) { - RestoreTypeHandlePointerRaw(pHandle->GetValuePtr((TADDR)pHandle), pContainingModule, level); + RestoreTypeHandlePointerRaw(pHandle->GetValuePtr(), pContainingModule, level); } else { @@ -10540,7 +10576,7 @@ void Module::RestoreMethodDescPointer(RelativeFixupPointer<PTR_MethodDesc> * ppM if (ppMD->IsTagged((TADDR)ppMD)) { - RestoreMethodDescPointerRaw(ppMD->GetValuePtr((TADDR)ppMD), pContainingModule, level); + RestoreMethodDescPointerRaw(ppMD->GetValuePtr(), pContainingModule, level); } else { @@ -13865,7 +13901,7 @@ ModuleCtorInfo::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) // This class is contained so do not enumerate 'this'. DacEnumMemoryRegion(dac_cast<TADDR>(ppMT), numElements * - sizeof(TADDR)); + sizeof(RelativePointer<MethodTable *>)); DacEnumMemoryRegion(dac_cast<TADDR>(cctorInfoHot), numElementsHot * sizeof(ClassCtorInfoEntry)); DacEnumMemoryRegion(dac_cast<TADDR>(cctorInfoCold), diff --git a/src/vm/ceeload.h b/src/vm/ceeload.h index 987ace0ae2..b70ea51feb 100644 --- a/src/vm/ceeload.h +++ b/src/vm/ceeload.h @@ -622,7 +622,7 @@ struct ModuleCtorInfo DWORD numElements; DWORD numLastAllocated; DWORD numElementsHot; - DPTR(PTR_MethodTable) ppMT; // size is numElements + DPTR(RelativePointer<PTR_MethodTable>) ppMT; // size is numElements PTR_ClassCtorInfoEntry cctorInfoHot; // size is numElementsHot PTR_ClassCtorInfoEntry cctorInfoCold; // size is numElements-numElementsHot @@ -631,8 +631,8 @@ struct ModuleCtorInfo DWORD numHotHashes; DWORD numColdHashes; - ArrayDPTR(FixupPointer<PTR_MethodTable>) ppHotGCStaticsMTs; // hot table - ArrayDPTR(FixupPointer<PTR_MethodTable>) ppColdGCStaticsMTs; // cold table + ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) ppHotGCStaticsMTs; // hot table + ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) ppColdGCStaticsMTs; // cold table DWORD numHotGCStaticsMTs; DWORD numColdGCStaticsMTs; @@ -668,7 +668,13 @@ struct ModuleCtorInfo return hashVal; }; - ArrayDPTR(FixupPointer<PTR_MethodTable>) GetGCStaticMTs(DWORD index); + ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) GetGCStaticMTs(DWORD index); + + PTR_MethodTable GetMT(DWORD i) + { + LIMITED_METHOD_DAC_CONTRACT; + return ppMT[i].GetValue(dac_cast<TADDR>(ppMT) + i * sizeof(RelativePointer<PTR_MethodTable>)); + } #ifdef FEATURE_PREJIT @@ -679,11 +685,11 @@ struct ModuleCtorInfo class ClassCtorInfoEntryArraySort : public CQuickSort<DWORD> { private: - PTR_MethodTable *m_pBase1; + DPTR(RelativePointer<PTR_MethodTable>) m_pBase1; public: //Constructor - ClassCtorInfoEntryArraySort(DWORD *base, PTR_MethodTable *base1, int count) + ClassCtorInfoEntryArraySort(DWORD *base, DPTR(RelativePointer<PTR_MethodTable>) base1, int count) : CQuickSort<DWORD>(base, count) { WRAPPER_NO_CONTRACT; @@ -704,6 +710,7 @@ struct ModuleCtorInfo return 1; } +#ifndef DACCESS_COMPILE // Swap is overwriten so that we can sort both the MethodTable pointer // array and the ClassCtorInfoEntry array in parrallel. FORCEINLINE void Swap(SSIZE_T iFirst, SSIZE_T iSecond) @@ -719,10 +726,11 @@ struct ModuleCtorInfo m_pBase[iFirst] = m_pBase[iSecond]; m_pBase[iSecond] = sTemp; - sTemp1 = m_pBase1[iFirst]; - m_pBase1[iFirst] = m_pBase1[iSecond]; - m_pBase1[iSecond] = sTemp1; + sTemp1 = m_pBase1[iFirst].GetValueMaybeNull(); + m_pBase1[iFirst].SetValueMaybeNull(m_pBase1[iSecond].GetValueMaybeNull()); + m_pBase1[iSecond].SetValueMaybeNull(sTemp1); } +#endif // !DACCESS_COMPILE }; #endif // FEATURE_PREJIT }; @@ -2808,6 +2816,10 @@ public: ClassLoadLevel level = CLASS_LOADED); static void RestoreFieldDescPointer(RelativeFixupPointer<PTR_FieldDesc> * ppFD); + static void RestoreMethodTablePointer(PlainPointer<PTR_MethodTable> * ppMT, + Module *pContainingModule = NULL, + ClassLoadLevel level = CLASS_LOADED); + static void RestoreModulePointer(RelativeFixupPointer<PTR_Module> * ppModule, Module *pContainingModule); static PTR_Module RestoreModulePointerIfLoaded(DPTR(RelativeFixupPointer<PTR_Module>) ppModule, Module *pContainingModule); diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 2210a14620..464d604781 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -883,7 +883,15 @@ ClassLoader::LoadExactParentAndInterfacesTransitively(MethodTable *pMT) LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Replaced approximate parent %s with exact parent %s from token %x\n", pParentMT->GetDebugClassName(), pNewParentMT->GetDebugClassName(), crExtends)); // SetParentMethodTable is not used here since we want to update the indirection cell in the NGen case - *EnsureWritablePages(pMT->GetParentMethodTablePtr()) = pNewParentMT; + if (pMT->GetParentMethodTablePlainOrRelativePointerPtr()->IsIndirectPtrMaybeNull()) + { + *EnsureWritablePages(pMT->GetParentMethodTablePlainOrRelativePointerPtr()->GetValuePtr()) = pNewParentMT; + } + else + { + EnsureWritablePages(pMT->GetParentMethodTablePlainOrRelativePointerPtr()); + pMT->GetParentMethodTablePlainOrRelativePointerPtr()->SetValueMaybeNull(pNewParentMT); + } pParentMT = pNewParentMT; } @@ -902,8 +910,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/dataimage.cpp b/src/vm/dataimage.cpp index fc584d7b39..4e276fe460 100644 --- a/src/vm/dataimage.cpp +++ b/src/vm/dataimage.cpp @@ -738,9 +738,7 @@ FORCEINLINE static CorCompileSection GetSectionForNodeType(ZapNodeType type) // SECTION_READONLY_WARM case NodeTypeForItemKind(DataImage::ITEM_METHOD_TABLE): - case NodeTypeForItemKind(DataImage::ITEM_VTABLE_CHUNK): case NodeTypeForItemKind(DataImage::ITEM_INTERFACE_MAP): - case NodeTypeForItemKind(DataImage::ITEM_DICTIONARY): case NodeTypeForItemKind(DataImage::ITEM_DISPATCH_MAP): case NodeTypeForItemKind(DataImage::ITEM_GENERICS_STATIC_FIELDDESCS): case NodeTypeForItemKind(DataImage::ITEM_GC_STATIC_HANDLES_COLD): @@ -750,6 +748,10 @@ FORCEINLINE static CorCompileSection GetSectionForNodeType(ZapNodeType type) case NodeTypeForItemKind(DataImage::ITEM_STORED_METHOD_SIG_READONLY_WARM): return CORCOMPILE_SECTION_READONLY_WARM; + case NodeTypeForItemKind(DataImage::ITEM_DICTIONARY): + case NodeTypeForItemKind(DataImage::ITEM_VTABLE_CHUNK): + return CORCOMPILE_SECTION_READONLY_VCHUNKS_AND_DICTIONARY; + // SECTION_CLASS_COLD case NodeTypeForItemKind(DataImage::ITEM_PARAM_TYPEDESC): case NodeTypeForItemKind(DataImage::ITEM_ARRAY_TYPEDESC): diff --git a/src/vm/dataimage.h b/src/vm/dataimage.h index 5d48a710e7..0167ec5762 100644 --- a/src/vm/dataimage.h +++ b/src/vm/dataimage.h @@ -309,8 +309,58 @@ public: void FixupPointerField(PVOID p, SSIZE_T offset); void FixupRelativePointerField(PVOID p, SSIZE_T offset); + template<typename T, typename PT> + void FixupPlainOrRelativePointerField(const T *base, const RelativePointer<PT> T::* pPointerFieldMember) + { + STANDARD_VM_CONTRACT; + SSIZE_T offset = (SSIZE_T) &(base->*pPointerFieldMember) - (SSIZE_T) base; + FixupRelativePointerField((PVOID)base, offset); + } + + template<typename T, typename C, typename PT> + void FixupPlainOrRelativePointerField(const T *base, const C T::* pFirstPointerFieldMember, const RelativePointer<PT> C::* pSecondPointerFieldMember) + { + STANDARD_VM_CONTRACT; + const RelativePointer<PT> *ptr = &(base->*pFirstPointerFieldMember.*pSecondPointerFieldMember); + SSIZE_T offset = (SSIZE_T) ptr - (SSIZE_T) base; + FixupRelativePointerField((PVOID)base, offset); + } + + template<typename T, typename PT> + void FixupPlainOrRelativePointerField(const T *base, const PlainPointer<PT> T::* pPointerFieldMember) + { + STANDARD_VM_CONTRACT; + SSIZE_T offset = (SSIZE_T) &(base->*pPointerFieldMember) - (SSIZE_T) base; + FixupPointerField((PVOID)base, offset); + } + + template<typename T, typename C, typename PT> + void FixupPlainOrRelativePointerField(const T *base, const C T::* pFirstPointerFieldMember, const PlainPointer<PT> C::* pSecondPointerFieldMember) + { + STANDARD_VM_CONTRACT; + const PlainPointer<PT> *ptr = &(base->*pFirstPointerFieldMember.*pSecondPointerFieldMember); + SSIZE_T offset = (SSIZE_T) ptr - (SSIZE_T) base; + FixupPointerField((PVOID)base, offset); + } + void FixupField(PVOID p, SSIZE_T offset, PVOID pTarget, SSIZE_T targetOffset = 0, ZapRelocationType type = IMAGE_REL_BASED_PTR); + template<typename T, typename PT> + void FixupPlainOrRelativeField(const T *base, const RelativePointer<PT> T::* pPointerFieldMember, PVOID pTarget, SSIZE_T targetOffset = 0) + { + STANDARD_VM_CONTRACT; + SSIZE_T offset = (SSIZE_T) &(base->*pPointerFieldMember) - (SSIZE_T) base; + FixupField((PVOID)base, offset, pTarget, targetOffset, IMAGE_REL_BASED_RELPTR); + } + + template<typename T, typename PT> + void FixupPlainOrRelativeField(const T *base, const PlainPointer<PT> T::* pPointerFieldMember, PVOID pTarget, SSIZE_T targetOffset = 0) + { + STANDARD_VM_CONTRACT; + SSIZE_T offset = (SSIZE_T) &(base->*pPointerFieldMember) - (SSIZE_T) base; + FixupField((PVOID)base, offset, pTarget, targetOffset, IMAGE_REL_BASED_PTR); + } + void FixupFieldToNode(PVOID p, SSIZE_T offset, ZapNode * pTarget, SSIZE_T targetOffset = 0, ZapRelocationType type = IMAGE_REL_BASED_PTR); void FixupFieldToNode(PVOID p, SSIZE_T offset, ZapStoredStructure * pTarget, SSIZE_T targetOffset = 0, ZapRelocationType type = IMAGE_REL_BASED_PTR) @@ -318,6 +368,34 @@ public: return FixupFieldToNode(p, offset, (ZapNode *)pTarget, targetOffset, type); } + template<typename T, typename PT> + void FixupPlainOrRelativeFieldToNode(const T *base, const RelativePointer<PT> T::* pPointerFieldMember, ZapNode * pTarget, SSIZE_T targetOffset = 0) + { + STANDARD_VM_CONTRACT; + SSIZE_T offset = (SSIZE_T) &(base->*pPointerFieldMember) - (SSIZE_T) base; + FixupFieldToNode((PVOID)base, offset, pTarget, targetOffset, IMAGE_REL_BASED_RELPTR); + } + + template<typename T, typename PT> + void FixupPlainOrRelativeFieldToNode(const T *base, const RelativePointer<PT> T::* pPointerFieldMember, ZapStoredStructure * pTarget, SSIZE_T targetOffset = 0) + { + return FixupPlainOrRelativeFieldToNode(base, pPointerFieldMember, (ZapNode *)pTarget, targetOffset); + } + + template<typename T, typename PT> + void FixupPlainOrRelativeFieldToNode(const T *base, const PlainPointer<PT> T::* pPointerFieldMember, ZapNode * pTarget, SSIZE_T targetOffset = 0) + { + STANDARD_VM_CONTRACT; + SSIZE_T offset = (SSIZE_T) &(base->*pPointerFieldMember) - (SSIZE_T) base; + FixupFieldToNode((PVOID)base, offset, pTarget, targetOffset, IMAGE_REL_BASED_PTR); + } + + template<typename T, typename PT> + void FixupPlainOrRelativeFieldToNode(const T *base, const PlainPointer<PT> T::* pPointerFieldMember, ZapStoredStructure * pTarget, SSIZE_T targetOffset = 0) + { + return FixupPlainOrRelativeFieldToNode(base, pPointerFieldMember, (ZapNode *)pTarget, targetOffset); + } + BOOL IsStored(const void *data) { WRAPPER_NO_CONTRACT; return m_structures.LookupPtr(data) != NULL; } diff --git a/src/vm/debughelp.cpp b/src/vm/debughelp.cpp index 376b88cd42..23443ceece 100644 --- a/src/vm/debughelp.cpp +++ b/src/vm/debughelp.cpp @@ -318,7 +318,7 @@ MethodDesc* AsMethodDesc(size_t addr) // extra indirection if the address is tagged (the low bit is set). // That could AV if we don't check it first. - if (!ppMT->IsTagged((TADDR)ppMT) || isMemoryReadable((TADDR)ppMT->GetValuePtr((TADDR)ppMT), sizeof(MethodTable*))) + if (!ppMT->IsTagged((TADDR)ppMT) || isMemoryReadable((TADDR)ppMT->GetValuePtr(), sizeof(MethodTable*))) { if (AsMethodTable((size_t)RelativeFixupPointer<PTR_MethodTable>::GetValueAtPtr((TADDR)ppMT)) != 0) { diff --git a/src/vm/genericdict.cpp b/src/vm/genericdict.cpp index c93e583345..5fad30f4b8 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 51e6d7bbac..ed5313263f 100644 --- a/src/vm/generics.cpp +++ b/src/vm/generics.cpp @@ -255,7 +255,7 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( // Bytes are required for the vtable itself S_SIZE_T safe_cbMT = S_SIZE_T( cbGC ) + S_SIZE_T( sizeof(MethodTable) ); - safe_cbMT += MethodTable::GetNumVtableIndirections(cSlots) * sizeof(PTR_PCODE); + safe_cbMT += MethodTable::GetNumVtableIndirections(cSlots) * sizeof(MethodTable::VTableIndir_t); if (safe_cbMT.IsOverflow()) { ThrowHR(COR_E_OVERFLOW); @@ -364,7 +364,7 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( pMT->ClearFlag(MethodTable::enum_flag_IsZapped); pMT->ClearFlag(MethodTable::enum_flag_IsPreRestored); - pMT->ClearFlag(MethodTable::enum_flag_HasIndirectParent); + pMT->m_pParentMethodTable.SetValueMaybeNull(NULL); // Non non-virtual slots pMT->ClearFlag(MethodTable::enum_flag_HasSingleNonVirtualSlot); @@ -440,7 +440,7 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( if (canShareVtableChunks) { // Share the canonical chunk - it.SetIndirectionSlot(pOldMT->GetVtableIndirections()[it.GetIndex()]); + it.SetIndirectionSlot(pOldMT->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull()); } else { @@ -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/jithelpers.cpp b/src/vm/jithelpers.cpp index 96c2cf6e97..32be77823c 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -2396,7 +2396,7 @@ HCIMPL2(Object*, JIT_ChkCastClass_Portable, MethodTable* pTargetMT, Object* pObj if (pMT == pTargetMT) return pObject; - pMT = MethodTable::GetParentMethodTableOrIndirection(pMT); + pMT = MethodTable::GetParentMethodTable(pMT); } while (pMT); ENDFORBIDGC(); @@ -2416,14 +2416,14 @@ HCIMPL2(Object*, JIT_ChkCastClassSpecial_Portable, MethodTable* pTargetMT, Objec PRECONDITION(pObject->GetMethodTable() != pTargetMT); } CONTRACTL_END; - PTR_VOID pMT = MethodTable::GetParentMethodTableOrIndirection(pObject->GetMethodTable()); + PTR_VOID pMT = MethodTable::GetParentMethodTable(pObject->GetMethodTable()); while (pMT) { if (pMT == pTargetMT) return pObject; - pMT = MethodTable::GetParentMethodTableOrIndirection(pMT); + pMT = MethodTable::GetParentMethodTable(pMT); } ENDFORBIDGC(); @@ -2450,7 +2450,7 @@ HCIMPL2(Object*, JIT_IsInstanceOfClass_Portable, MethodTable* pTargetMT, Object* if (pMT == pTargetMT) return pObject; - pMT = MethodTable::GetParentMethodTableOrIndirection(pMT); + pMT = MethodTable::GetParentMethodTable(pMT); } while (pMT); if (!pObject->GetMethodTable()->HasTypeEquivalence()) diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 97fe3e8262..efffa8d9f7 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -3085,6 +3085,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; @@ -3299,6 +3300,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 && @@ -3546,6 +3553,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; + } } } } @@ -8434,7 +8447,8 @@ CONTRACTL { /*********************************************************************/ void CEEInfo::getMethodVTableOffset (CORINFO_METHOD_HANDLE methodHnd, unsigned * pOffsetOfIndirection, - unsigned * pOffsetAfterIndirection) + unsigned * pOffsetAfterIndirection, + bool * isRelative) { CONTRACTL { SO_TOLERANT; @@ -8455,8 +8469,9 @@ void CEEInfo::getMethodVTableOffset (CORINFO_METHOD_HANDLE methodHnd, // better be in the vtable _ASSERTE(method->GetSlot() < method->GetMethodTable()->GetNumVirtuals()); - *pOffsetOfIndirection = MethodTable::GetVtableOffset() + MethodTable::GetIndexOfVtableIndirection(method->GetSlot()) * sizeof(PTR_PCODE); + *pOffsetOfIndirection = MethodTable::GetVtableOffset() + MethodTable::GetIndexOfVtableIndirection(method->GetSlot()) * sizeof(MethodTable::VTableIndir_t); *pOffsetAfterIndirection = MethodTable::GetIndexAfterVtableIndirection(method->GetSlot()) * sizeof(PCODE); + *isRelative = MethodTable::VTableIndir_t::isRelative ? 1 : 0; EE_TO_JIT_TRANSITION_LEAF(); } diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index 8df6b72ea4..141c812280 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -727,8 +727,8 @@ public: void getMethodVTableOffset ( CORINFO_METHOD_HANDLE methodHnd, unsigned * pOffsetOfIndirection, - unsigned * pOffsetAfterIndirection - ); + unsigned * pOffsetAfterIndirection, + bool * isRelative); CORINFO_METHOD_HANDLE resolveVirtualMethod( CORINFO_METHOD_HANDLE virtualMethod, diff --git a/src/vm/method.cpp b/src/vm/method.cpp index 63777e8ac1..4bae82a61d 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -3341,14 +3341,7 @@ MethodDesc::Fixup( } } - if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative) - { - image->FixupRelativePointerField(this, offsetof(InstantiatedMethodDesc, m_pPerInstInfo)); - } - else - { - image->FixupPointerField(this, offsetof(InstantiatedMethodDesc, m_pPerInstInfo)); - } + image->FixupPlainOrRelativePointerField((InstantiatedMethodDesc*) this, &InstantiatedMethodDesc::m_pPerInstInfo); // Generic methods are dealt with specially to avoid encoding the formal method type parameters if (IsTypicalMethodDefinition()) @@ -3427,14 +3420,7 @@ MethodDesc::Fixup( NDirectMethodDesc *pNMD = (NDirectMethodDesc *)this; - if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative) - { - image->FixupRelativePointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pWriteableData)); - } - else - { - image->FixupPointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pWriteableData)); - } + image->FixupPlainOrRelativePointerField(pNMD, &NDirectMethodDesc::ndirect, &decltype(NDirectMethodDesc::ndirect)::m_pWriteableData); NDirectWriteableData *pWriteableData = pNMD->GetWriteableData(); NDirectImportThunkGlue *pImportThunkGlue = pNMD->GetNDirectImportThunkGlue(); diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index 1088082c84..32d55d303e 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -1011,7 +1011,7 @@ void MethodTable::SetInterfaceMap(WORD wNumInterfaces, InterfaceInfo_t* iMap) m_wNumInterfaces = wNumInterfaces; CONSISTENCY_CHECK(IS_ALIGNED(iMap, sizeof(void*))); - m_pInterfaceMap = iMap; + m_pInterfaceMap.SetValue(iMap); } //========================================================================================== @@ -1234,7 +1234,12 @@ void MethodTable::AddDynamicInterface(MethodTable *pItfMT) if (TotalNumInterfaces > 0) { InterfaceInfo_t *pInterfaceMap = GetInterfaceMap(); PREFIX_ASSUME(pInterfaceMap != NULL); - memcpy(pNewItfMap, pInterfaceMap, TotalNumInterfaces * sizeof(InterfaceInfo_t)); + + for (unsigned index = 0; index < TotalNumInterfaces; ++index) + { + InterfaceInfo_t *pIntInfo = (InterfaceInfo_t *) (pNewItfMap + index); + pIntInfo->SetMethodTable((pInterfaceMap + index)->GetMethodTable()); + } } // Add the new interface at the end of the map. @@ -1244,7 +1249,8 @@ void MethodTable::AddDynamicInterface(MethodTable *pItfMT) *(((DWORD_PTR *)pNewItfMap) - 1) = NumDynAddedInterfaces + 1; // Switch the old interface map with the new one. - VolatileStore(EnsureWritablePages(&m_pInterfaceMap), pNewItfMap); + EnsureWritablePages(&m_pInterfaceMap); + m_pInterfaceMap.SetValueVolatile(pNewItfMap); // Log the fact that we leaked the interface vtable map. #ifdef _DEBUG @@ -1285,7 +1291,7 @@ void MethodTable::SetupGenericsStaticsInfo(FieldDesc* pStaticFieldDescs) pInfo->m_DynamicTypeID = (SIZE_T)-1; } - pInfo->m_pFieldDescs = pStaticFieldDescs; + pInfo->m_pFieldDescs.SetValueMaybeNull(pStaticFieldDescs); } #endif // !DACCESS_COMPILE @@ -1782,7 +1788,7 @@ TypeHandle::CastResult MethodTable::CanCastToClassNoGC(MethodTable *pTargetMT) if (pMT == pTargetMT) return TypeHandle::CanCast; - pMT = MethodTable::GetParentMethodTableOrIndirection(pMT); + pMT = MethodTable::GetParentMethodTable(pMT); } while (pMT); } @@ -3145,7 +3151,7 @@ void MethodTable::AllocateRegularStaticBoxes() OBJECTREF* pStaticSlots = (OBJECTREF*)(pStaticBase + pClassCtorInfoEntry->firstBoxedStaticOffset); GCPROTECT_BEGININTERIOR(pStaticSlots); - ArrayDPTR(FixupPointer<PTR_MethodTable>) ppMTs = GetLoaderModule()->GetZapModuleCtorInfo()-> + ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) ppMTs = GetLoaderModule()->GetZapModuleCtorInfo()-> GetGCStaticMTs(pClassCtorInfoEntry->firstBoxedStaticMTIndex); DWORD numBoxedStatics = pClassCtorInfoEntry->numBoxedStatics; @@ -4120,7 +4126,7 @@ void ModuleCtorInfo::AddElement(MethodTable *pMethodTable) { _ASSERTE(numElements == numLastAllocated); - MethodTable ** ppOldMTEntries = ppMT; + RelativePointer<MethodTable *> *ppOldMTEntries = ppMT; #ifdef _PREFAST_ #pragma warning(push) @@ -4131,12 +4137,19 @@ void ModuleCtorInfo::AddElement(MethodTable *pMethodTable) #pragma warning(pop) #endif // _PREFAST_ - ppMT = new MethodTable* [numNewAllocated]; + ppMT = new RelativePointer<MethodTable *> [numNewAllocated]; _ASSERTE(ppMT); - memcpy(ppMT, ppOldMTEntries, sizeof(MethodTable *) * numLastAllocated); - memset(ppMT + numLastAllocated, 0, sizeof(MethodTable *) * (numNewAllocated - numLastAllocated)); + for (unsigned index = 0; index < numLastAllocated; ++index) + { + ppMT[index].SetValueMaybeNull(ppOldMTEntries[index].GetValueMaybeNull()); + } + + for (unsigned index = numLastAllocated; index < numNewAllocated; ++index) + { + ppMT[index].SetValueMaybeNull(NULL); + } delete[] ppOldMTEntries; @@ -4148,7 +4161,7 @@ void ModuleCtorInfo::AddElement(MethodTable *pMethodTable) // Note the use of two "parallel" arrays. We do this to keep the workingset smaller since we // often search (in GetClassCtorInfoIfExists) for a methodtable pointer but never actually find it. - ppMT[numElements] = pMethodTable; + ppMT[numElements].SetValue(pMethodTable); numElements++; } @@ -4274,16 +4287,32 @@ void MethodTable::Save(DataImage *image, DWORD profilingFlags) // Dynamic interface maps have an additional DWORD_PTR preceding the InterfaceInfo_t array if (HasDynamicInterfaceMap()) { - ZapStoredStructure * pInterfaceMapNode = image->StoreInternedStructure(((DWORD_PTR *)GetInterfaceMap()) - 1, - GetInterfaceMapSize(), - DataImage::ITEM_INTERFACE_MAP); - + ZapStoredStructure * pInterfaceMapNode; + if (decltype(InterfaceInfo_t::m_pMethodTable)::isRelative) + { + pInterfaceMapNode = image->StoreStructure(((DWORD_PTR *)GetInterfaceMap()) - 1, + GetInterfaceMapSize(), + DataImage::ITEM_INTERFACE_MAP); + } + else + { + pInterfaceMapNode = image->StoreInternedStructure(((DWORD_PTR *)GetInterfaceMap()) - 1, + GetInterfaceMapSize(), + DataImage::ITEM_INTERFACE_MAP); + } image->BindPointer(GetInterfaceMap(), pInterfaceMapNode, sizeof(DWORD_PTR)); } else #endif // FEATURE_COMINTEROP { - image->StoreInternedStructure(GetInterfaceMap(), GetInterfaceMapSize(), DataImage::ITEM_INTERFACE_MAP); + if (decltype(InterfaceInfo_t::m_pMethodTable)::isRelative) + { + image->StoreStructure(GetInterfaceMap(), GetInterfaceMapSize(), DataImage::ITEM_INTERFACE_MAP); + } + else + { + image->StoreInternedStructure(GetInterfaceMap(), GetInterfaceMapSize(), DataImage::ITEM_INTERFACE_MAP); + } } SaveExtraInterfaceInfo(image); @@ -4300,7 +4329,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 { @@ -4647,14 +4683,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 { @@ -4692,7 +4735,7 @@ void MethodTable::Fixup(DataImage *image) if (IsCanonicalMethodTable()) { // Pointer to EEClass - image->FixupPointerField(this, offsetof(MethodTable, m_pEEClass)); + image->FixupPlainOrRelativePointerField(this, &MethodTable::m_pEEClass); } else { @@ -4707,7 +4750,7 @@ void MethodTable::Fixup(DataImage *image) if (image->CanHardBindToZapModule(pCanonMT->GetLoaderModule())) { // Pointer to canonical methodtable - image->FixupField(this, offsetof(MethodTable, m_pCanonMT), pCanonMT, UNION_METHODTABLE); + image->FixupPlainOrRelativeField(this, &MethodTable::m_pCanonMT, pCanonMT, UNION_METHODTABLE); } else { @@ -4725,18 +4768,28 @@ void MethodTable::Fixup(DataImage *image) if (pImport != NULL) { - image->FixupFieldToNode(this, offsetof(MethodTable, m_pCanonMT), pImport, UNION_INDIRECTION); + image->FixupPlainOrRelativeFieldToNode(this, &MethodTable::m_pCanonMT, pImport, UNION_INDIRECTION); } } - image->FixupField(this, offsetof(MethodTable, m_pLoaderModule), pZapModule); + image->FixupField(this, offsetof(MethodTable, m_pLoaderModule), pZapModule, 0, IMAGE_REL_BASED_RELPTR); #ifdef _DEBUG image->FixupPointerField(this, offsetof(MethodTable, debug_m_szClassName)); #endif // _DEBUG MethodTable * pParentMT = GetParentMethodTable(); - _ASSERTE(!pNewMT->GetFlag(enum_flag_HasIndirectParent)); + _ASSERTE(!pNewMT->m_pParentMethodTable.IsIndirectPtrMaybeNull()); + + ZapRelocationType relocType; + if (decltype(MethodTable::m_pParentMethodTable)::isRelative) + { + relocType = IMAGE_REL_BASED_RELPTR; + } + else + { + relocType = IMAGE_REL_BASED_PTR; + } if (pParentMT != NULL) { @@ -4748,7 +4801,8 @@ void MethodTable::Fixup(DataImage *image) { if (image->CanHardBindToZapModule(pParentMT->GetLoaderModule())) { - image->FixupPointerField(this, offsetof(MethodTable, m_pParentMethodTable)); + _ASSERTE(!m_pParentMethodTable.IsIndirectPtr()); + image->FixupField(this, offsetof(MethodTable, m_pParentMethodTable), pParentMT, 0, relocType); } else { @@ -4784,8 +4838,7 @@ void MethodTable::Fixup(DataImage *image) if (pImport != NULL) { - image->FixupFieldToNode(this, offsetof(MethodTable, m_pParentMethodTable), pImport, -(SSIZE_T)offsetof(MethodTable, m_pParentMethodTable)); - pNewMT->SetFlag(enum_flag_HasIndirectParent); + image->FixupFieldToNode(this, offsetof(MethodTable, m_pParentMethodTable), pImport, FIXUP_POINTER_INDIRECTION, relocType); } } @@ -4798,14 +4851,14 @@ void MethodTable::Fixup(DataImage *image) if (HasInterfaceMap()) { - image->FixupPointerField(this, offsetof(MethodTable, m_pMultipurposeSlot2)); + image->FixupPlainOrRelativePointerField(this, &MethodTable::m_pInterfaceMap); FixupExtraInterfaceInfo(image); } _ASSERTE(GetWriteableData()); - image->FixupPointerField(this, offsetof(MethodTable, m_pWriteableData)); - m_pWriteableData->Fixup(image, this, needsRestore); + image->FixupPlainOrRelativePointerField(this, &MethodTable::m_pWriteableData); + m_pWriteableData.GetValue()->Fixup(image, this, needsRestore); #ifdef FEATURE_COMINTEROP if (HasGuidInfo()) @@ -4873,7 +4926,14 @@ void MethodTable::Fixup(DataImage *image) VtableIndirectionSlotIterator it = IterateVtableIndirectionSlots(); while (it.Next()) { - image->FixupPointerField(this, it.GetOffsetFromMethodTable()); + if (VTableIndir_t::isRelative) + { + image->FixupRelativePointerField(this, it.GetOffsetFromMethodTable()); + } + else + { + image->FixupPointerField(this, it.GetOffsetFromMethodTable()); + } } } @@ -4894,7 +4954,7 @@ void MethodTable::Fixup(DataImage *image) { // Virtual slots live in chunks pointed to by vtable indirections - slotBase = (PVOID) GetVtableIndirections()[GetIndexOfVtableIndirection(slotNumber)]; + slotBase = (PVOID) GetVtableIndirections()[GetIndexOfVtableIndirection(slotNumber)].GetValueMaybeNull(); slotOffset = GetIndexAfterVtableIndirection(slotNumber) * sizeof(PCODE); } else if (HasSingleNonVirtualSlot()) @@ -4989,7 +5049,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()) { @@ -5002,10 +5062,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); + } } } } @@ -5034,7 +5107,7 @@ void MethodTable::Fixup(DataImage *image) { GenericsStaticsInfo *pInfo = GetGenericsStaticsInfo(); - image->FixupPointerField(this, (BYTE *)&pInfo->m_pFieldDescs - (BYTE *)this); + image->FixupRelativePointerField(this, (BYTE *)&pInfo->m_pFieldDescs - (BYTE *)this); if (!isCanonical) { for (DWORD i = 0; i < GetClass()->GetNumStaticFields(); i++) @@ -5046,12 +5119,12 @@ void MethodTable::Fixup(DataImage *image) if (NeedsCrossModuleGenericsStaticsInfo()) { - MethodTableWriteableData * pNewWriteableData = (MethodTableWriteableData *)image->GetImagePointer(m_pWriteableData); + MethodTableWriteableData * pNewWriteableData = (MethodTableWriteableData *)image->GetImagePointer(m_pWriteableData.GetValue()); CrossModuleGenericsStaticsInfo * pNewCrossModuleGenericsStaticsInfo = pNewWriteableData->GetCrossModuleGenericsStaticsInfo(); pNewCrossModuleGenericsStaticsInfo->m_DynamicTypeID = pInfo->m_DynamicTypeID; - image->ZeroPointerField(m_pWriteableData, sizeof(MethodTableWriteableData) + offsetof(CrossModuleGenericsStaticsInfo, m_pModuleForStatics)); + image->ZeroPointerField(m_pWriteableData.GetValue(), sizeof(MethodTableWriteableData) + offsetof(CrossModuleGenericsStaticsInfo, m_pModuleForStatics)); pNewMT->SetFlag(enum_flag_StaticsMask_IfGenericsThenCrossModule); } @@ -5950,9 +6023,9 @@ void MethodTable::DoRestoreTypeKey() // If we have an indirection cell then restore the m_pCanonMT and its module pointer // - if (union_getLowBits(m_pCanonMT) == UNION_INDIRECTION) + if (union_getLowBits(m_pCanonMT.GetValue()) == UNION_INDIRECTION) { - Module::RestoreMethodTablePointerRaw((MethodTable **)(union_getPointer(m_pCanonMT)), + Module::RestoreMethodTablePointerRaw((MethodTable **)(union_getPointer(m_pCanonMT.GetValue())), GetLoaderModule(), CLASS_LOAD_UNRESTORED); } @@ -6028,7 +6101,7 @@ void MethodTable::Restore() // // Restore parent method table // - Module::RestoreMethodTablePointerRaw(GetParentMethodTablePtr(), GetLoaderModule(), CLASS_LOAD_APPROXPARENTS); + Module::RestoreMethodTablePointer(&m_pParentMethodTable, GetLoaderModule(), CLASS_LOAD_APPROXPARENTS); // // Restore interface classes @@ -6189,7 +6262,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; @@ -6197,7 +6270,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 { @@ -6214,7 +6288,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 { @@ -7593,7 +7668,7 @@ BOOL MethodTable::SanityCheck() // strings have component size2, all other non-arrays should have 0 _ASSERTE((GetComponentSize() <= 2) || IsArray()); - if (m_pEEClass == NULL) + if (m_pEEClass.IsNull()) { if (IsAsyncPinType()) { @@ -7733,7 +7808,7 @@ ClassCtorInfoEntry* MethodTable::GetClassCtorInfoIfExists() if (HasBoxedRegularStatics()) { ModuleCtorInfo *pModuleCtorInfo = GetZapModule()->GetZapModuleCtorInfo(); - DPTR(PTR_MethodTable) ppMT = pModuleCtorInfo->ppMT; + DPTR(RelativePointer<PTR_MethodTable>) ppMT = pModuleCtorInfo->ppMT; PTR_DWORD hotHashOffsets = pModuleCtorInfo->hotHashOffsets; PTR_DWORD coldHashOffsets = pModuleCtorInfo->coldHashOffsets; @@ -7744,8 +7819,8 @@ ClassCtorInfoEntry* MethodTable::GetClassCtorInfoIfExists() for (DWORD i = hotHashOffsets[hash]; i != hotHashOffsets[hash + 1]; i++) { - _ASSERTE(ppMT[i]); - if (dac_cast<TADDR>(ppMT[i]) == dac_cast<TADDR>(this)) + _ASSERTE(!ppMT[i].IsNull()); + if (dac_cast<TADDR>(pModuleCtorInfo->GetMT(i)) == dac_cast<TADDR>(this)) { return pModuleCtorInfo->cctorInfoHot + i; } @@ -7759,8 +7834,8 @@ ClassCtorInfoEntry* MethodTable::GetClassCtorInfoIfExists() for (DWORD i = coldHashOffsets[hash]; i != coldHashOffsets[hash + 1]; i++) { - _ASSERTE(ppMT[i]); - if (dac_cast<TADDR>(ppMT[i]) == dac_cast<TADDR>(this)) + _ASSERTE(!ppMT[i].IsNull()); + if (dac_cast<TADDR>(pModuleCtorInfo->GetMT(i)) == dac_cast<TADDR>(this)) { return pModuleCtorInfo->cctorInfoCold + (i - pModuleCtorInfo->numElementsHot); } @@ -7784,13 +7859,8 @@ BOOL MethodTable::IsParentMethodTablePointerValid() if (!GetWriteableData_NoLogging()->IsParentMethodTablePointerValid()) return FALSE; - if (!GetFlag(enum_flag_HasIndirectParent)) - { - return TRUE; - } - TADDR pMT; - pMT = *PTR_TADDR(m_pParentMethodTable + offsetof(MethodTable, m_pParentMethodTable)); - return !CORCOMPILE_IS_POINTER_TAGGED(pMT); + TADDR base = dac_cast<TADDR>(this) + offsetof(MethodTable, m_pParentMethodTable); + return !m_pParentMethodTable.IsTagged(base); } #endif @@ -9165,9 +9235,10 @@ MethodTable::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) DacEnumMemoryRegion(dac_cast<TADDR>(it.GetIndirectionSlot()), it.GetSize()); } - if (m_pWriteableData.IsValid()) + PTR_MethodTableWriteableData pWriteableData = ReadPointer(this, &MethodTable::m_pWriteableData); + if (pWriteableData.IsValid()) { - m_pWriteableData.EnumMem(); + pWriteableData.EnumMem(); } if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE) @@ -9355,13 +9426,13 @@ void MethodTable::SetSlot(UINT32 slotNumber, PCODE slotCode) if (!IsCanonicalMethodTable()) { - if (GetVtableIndirections()[indirectionIndex] == GetCanonicalMethodTable()->GetVtableIndirections()[indirectionIndex]) + if (GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == GetCanonicalMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull()) fSharedVtableChunk = TRUE; } if (slotNumber < GetNumParentVirtuals()) { - if (GetVtableIndirections()[indirectionIndex] == GetParentMethodTable()->GetVtableIndirections()[indirectionIndex]) + if (GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull()) fSharedVtableChunk = TRUE; } @@ -9627,8 +9698,6 @@ bool MethodTable::ClassRequiresUnmanagedCodeCheck() return false; } -#endif // !DACCESS_COMPILE - BOOL MethodTable::Validate() @@ -9638,13 +9707,14 @@ BOOL MethodTable::Validate() ASSERT_AND_CHECK(SanityCheck()); #ifdef _DEBUG - if (m_pWriteableData == NULL) + if (m_pWriteableData.IsNull()) { _ASSERTE(IsAsyncPinType()); return TRUE; } - DWORD dwLastVerifiedGCCnt = m_pWriteableData->m_dwLastVerifedGCCnt; + MethodTableWriteableData *pWriteableData = m_pWriteableData.GetValue(); + DWORD dwLastVerifiedGCCnt = pWriteableData->m_dwLastVerifedGCCnt; // Here we used to assert that (dwLastVerifiedGCCnt <= GCHeapUtilities::GetGCHeap()->GetGcCount()) but // this is no longer true because with background gc. Since the purpose of having // m_dwLastVerifedGCCnt is just to only verify the same method table once for each GC @@ -9675,13 +9745,15 @@ BOOL MethodTable::Validate() #ifdef _DEBUG // It is not a fatal error to fail the update the counter. We will run slower and retry next time, // but the system will function properly. - if (EnsureWritablePagesNoThrow(m_pWriteableData, sizeof(MethodTableWriteableData))) - m_pWriteableData->m_dwLastVerifedGCCnt = GCHeapUtilities::GetGCHeap()->GetGcCount(); + if (EnsureWritablePagesNoThrow(pWriteableData, sizeof(MethodTableWriteableData))) + pWriteableData->m_dwLastVerifedGCCnt = GCHeapUtilities::GetGCHeap()->GetGcCount(); #endif //_DEBUG return TRUE; } +#endif // !DACCESS_COMPILE + NOINLINE BYTE *MethodTable::GetLoaderAllocatorObjectForGC() { WRAPPER_NO_CONTRACT; diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h index d3eb0ce9b5..77ec9f51ea 100644 --- a/src/vm/methodtable.h +++ b/src/vm/methodtable.h @@ -110,25 +110,40 @@ struct InterfaceInfo_t friend class NativeImageDumper; #endif - FixupPointer<PTR_MethodTable> m_pMethodTable; // Method table of the interface + // Method table of the interface +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + RelativeFixupPointer<PTR_MethodTable> m_pMethodTable; +#else + FixupPointer<PTR_MethodTable> m_pMethodTable; +#endif public: FORCEINLINE PTR_MethodTable GetMethodTable() { LIMITED_METHOD_CONTRACT; - return m_pMethodTable.GetValue(); + return ReadPointerMaybeNull(this, &InterfaceInfo_t::m_pMethodTable); } #ifndef DACCESS_COMPILE void SetMethodTable(MethodTable * pMT) { LIMITED_METHOD_CONTRACT; - m_pMethodTable.SetValue(pMT); + m_pMethodTable.SetValueMaybeNull(pMT); } // Get approximate method table. This is used by the type loader before the type is fully loaded. PTR_MethodTable GetApproxMethodTable(Module * pContainingModule); -#endif +#endif // !DACCESS_COMPILE + +#ifndef DACCESS_COMPILE + InterfaceInfo_t(InterfaceInfo_t &right) + { + m_pMethodTable.SetValueMaybeNull(right.m_pMethodTable.GetValueMaybeNull()); + } +#else // !DACCESS_COMPILE +private: + InterfaceInfo_t(InterfaceInfo_t &right); +#endif // !DACCESS_COMPILE }; // struct InterfaceInfo_t typedef DPTR(InterfaceInfo_t) PTR_InterfaceInfo; @@ -247,7 +262,7 @@ typedef DPTR(GenericsDictInfo) PTR_GenericsDictInfo; struct GenericsStaticsInfo { // Pointer to field descs for statics - PTR_FieldDesc m_pFieldDescs; + RelativePointer<PTR_FieldDesc> m_pFieldDescs; // Method table ID for statics SIZE_T m_DynamicTypeID; @@ -1498,7 +1513,10 @@ public: CONSISTENCY_CHECK(slotNum < GetNumVirtuals()); // Virtual slots live in chunks pointed to by vtable indirections - return *(GetVtableIndirections()[GetIndexOfVtableIndirection(slotNum)] + GetIndexAfterVtableIndirection(slotNum)); + + DWORD index = GetIndexOfVtableIndirection(slotNum); + TADDR base = dac_cast<TADDR>(&(GetVtableIndirections()[index])); + return *(VTableIndir_t::GetValueMaybeNullAtPtr(base) + GetIndexAfterVtableIndirection(slotNum)); } PTR_PCODE GetSlotPtrRaw(UINT32 slotNum) @@ -1510,7 +1528,9 @@ public: if (slotNum < GetNumVirtuals()) { // Virtual slots live in chunks pointed to by vtable indirections - return GetVtableIndirections()[GetIndexOfVtableIndirection(slotNum)] + GetIndexAfterVtableIndirection(slotNum); + DWORD index = GetIndexOfVtableIndirection(slotNum); + TADDR base = dac_cast<TADDR>(&(GetVtableIndirections()[index])); + return VTableIndir_t::GetValueMaybeNullAtPtr(base) + GetIndexAfterVtableIndirection(slotNum); } else if (HasSingleNonVirtualSlot()) { @@ -1594,12 +1614,18 @@ public: #define VTABLE_SLOTS_PER_CHUNK 8 #define VTABLE_SLOTS_PER_CHUNK_LOG2 3 +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + typedef RelativePointer<PTR_PCODE> VTableIndir_t; +#else + typedef PlainPointer<PTR_PCODE> VTableIndir_t; +#endif + static DWORD GetIndexOfVtableIndirection(DWORD slotNum); static DWORD GetStartSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals); static DWORD GetEndSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals); static UINT32 GetIndexAfterVtableIndirection(UINT32 slotNum); static DWORD GetNumVtableIndirections(DWORD wNumVirtuals); - PTR_PTR_PCODE GetVtableIndirections(); + DPTR(VTableIndir_t) GetVtableIndirections(); DWORD GetNumVtableIndirections(); class VtableIndirectionSlotIterator @@ -1607,7 +1633,7 @@ public: friend class MethodTable; private: - PTR_PTR_PCODE m_pSlot; + DPTR(VTableIndir_t) m_pSlot; DWORD m_i; DWORD m_count; PTR_MethodTable m_pMT; @@ -2100,6 +2126,12 @@ public: // THE METHOD TABLE PARENT (SUPERCLASS/BASE CLASS) // +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + typedef RelativeFixupPointer<PTR_MethodTable> ParentMT_t; +#else + typedef PlainPointer<PTR_MethodTable> ParentMT_t; +#endif + BOOL HasApproxParent() { LIMITED_METHOD_DAC_CONTRACT; @@ -2118,32 +2150,24 @@ public: LIMITED_METHOD_DAC_CONTRACT; PRECONDITION(IsParentMethodTablePointerValid()); - - TADDR pMT = m_pParentMethodTable; -#ifdef FEATURE_PREJIT - if (GetFlag(enum_flag_HasIndirectParent)) - pMT = *PTR_TADDR(m_pParentMethodTable + offsetof(MethodTable, m_pParentMethodTable)); -#endif - return PTR_MethodTable(pMT); + return ReadPointerMaybeNull(this, &MethodTable::m_pParentMethodTable); } - inline static PTR_VOID GetParentMethodTableOrIndirection(PTR_VOID pMT) + inline static PTR_VOID GetParentMethodTable(PTR_VOID pMT) { - WRAPPER_NO_CONTRACT; - return PTR_VOID(*PTR_TADDR(dac_cast<TADDR>(pMT) + offsetof(MethodTable, m_pParentMethodTable))); + LIMITED_METHOD_DAC_CONTRACT; + + PTR_MethodTable pMethodTable = dac_cast<PTR_MethodTable>(pMT); + return pMethodTable->GetParentMethodTable(); } - inline MethodTable ** GetParentMethodTablePtr() +#ifndef DACCESS_COMPILE + inline ParentMT_t * GetParentMethodTablePlainOrRelativePointerPtr() { - WRAPPER_NO_CONTRACT; - -#ifdef FEATURE_PREJIT - return GetFlag(enum_flag_HasIndirectParent) ? - (MethodTable **)(m_pParentMethodTable + offsetof(MethodTable, m_pParentMethodTable)) :(MethodTable **)&m_pParentMethodTable; -#else - return (MethodTable **)&m_pParentMethodTable; -#endif + LIMITED_METHOD_CONTRACT; + return &m_pParentMethodTable; } +#endif // !DACCESS_COMPILE // Is the parent method table pointer equal to the given argument? BOOL ParentEquals(PTR_MethodTable pMT) @@ -2162,8 +2186,8 @@ public: void SetParentMethodTable (MethodTable *pParentMethodTable) { LIMITED_METHOD_CONTRACT; - PRECONDITION(!GetFlag(enum_flag_HasIndirectParent)); - m_pParentMethodTable = (TADDR)pParentMethodTable; + PRECONDITION(!m_pParentMethodTable.IsIndirectPtrMaybeNull()); + m_pParentMethodTable.SetValueMaybeNull(pParentMethodTable); #ifdef _DEBUG GetWriteableDataForWrite_NoLogging()->SetParentMethodTablePointerValid(); #endif @@ -2209,12 +2233,12 @@ public: inline void SetClass(EEClass *pClass) { LIMITED_METHOD_CONTRACT; - m_pEEClass = pClass; + m_pEEClass.SetValue(pClass); } inline void SetCanonicalMethodTable(MethodTable * pMT) { - m_pCanonMT = (TADDR)pMT | MethodTable::UNION_METHODTABLE; + m_pCanonMT.SetValue((TADDR)pMT | MethodTable::UNION_METHODTABLE); } #endif @@ -2639,7 +2663,7 @@ public: { WRAPPER_NO_CONTRACT; _ASSERTE(HasGenericsStaticsInfo()); - return GetGenericsStaticsInfo()->m_pFieldDescs; + return ReadPointerMaybeNull((GenericsStaticsInfo *)GetGenericsStaticsInfo(), &GenericsStaticsInfo::m_pFieldDescs); } BOOL HasCrossModuleGenericStaticsInfo() @@ -2992,12 +3016,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() { @@ -3005,15 +3037,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) { @@ -3033,7 +3070,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 // @@ -3119,36 +3156,39 @@ public: // Private part of MethodTable // ------------------------------------------------------------------ +#ifndef DACCESS_COMPILE inline void SetWriteableData(PTR_MethodTableWriteableData pMTWriteableData) { LIMITED_METHOD_CONTRACT; _ASSERTE(pMTWriteableData); - m_pWriteableData = pMTWriteableData; + m_pWriteableData.SetValue(pMTWriteableData); } - +#endif + inline PTR_Const_MethodTableWriteableData GetWriteableData() const { LIMITED_METHOD_DAC_CONTRACT; g_IBCLogger.LogMethodTableWriteableDataAccess(this); - return m_pWriteableData; + return GetWriteableData_NoLogging(); } inline PTR_Const_MethodTableWriteableData GetWriteableData_NoLogging() const { LIMITED_METHOD_DAC_CONTRACT; - return m_pWriteableData; + return ReadPointer(this, &MethodTable::m_pWriteableData); } inline PTR_MethodTableWriteableData GetWriteableDataForWrite() { - LIMITED_METHOD_CONTRACT; + LIMITED_METHOD_DAC_CONTRACT; g_IBCLogger.LogMethodTableWriteableDataWriteAccess(this); - return m_pWriteableData; + return GetWriteableDataForWrite_NoLogging(); } inline PTR_MethodTableWriteableData GetWriteableDataForWrite_NoLogging() { - return m_pWriteableData; + LIMITED_METHOD_DAC_CONTRACT; + return ReadPointer(this, &MethodTable::m_pWriteableData); } //------------------------------------------------------------------- @@ -4042,11 +4082,15 @@ private: // if enum_flag_enum_flag_HasIndirectParent is set. The indirection is offset by offsetof(MethodTable, m_pParentMethodTable). // It allows casting helpers to go through parent chain natually. Casting helper do not need need the explicit check // for enum_flag_HasIndirectParentMethodTable. - TADDR m_pParentMethodTable; + ParentMT_t m_pParentMethodTable; - PTR_Module m_pLoaderModule; // LoaderModule. It is equal to the ZapModule in ngened images + RelativePointer<PTR_Module> m_pLoaderModule; // LoaderModule. It is equal to the ZapModule in ngened images - PTR_MethodTableWriteableData m_pWriteableData; +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + RelativePointer<PTR_MethodTableWriteableData> m_pWriteableData; +#else + PlainPointer<PTR_MethodTableWriteableData> m_pWriteableData; +#endif // The value of lowest two bits describe what the union contains enum LowBits { @@ -4058,8 +4102,13 @@ private: static const TADDR UNION_MASK = 3; union { - EEClass * m_pEEClass; - TADDR m_pCanonMT; +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + RelativePointer<DPTR(EEClass)> m_pEEClass; + RelativePointer<TADDR> m_pCanonMT; +#else + PlainPointer<DPTR(EEClass)> m_pEEClass; + PlainPointer<TADDR> m_pCanonMT; +#endif }; __forceinline static LowBits union_getLowBits(TADDR pCanonMT) @@ -4081,14 +4130,18 @@ private: union { - PTR_Dictionary * m_pPerInstInfo; - TADDR m_ElementTypeHnd; - TADDR m_pMultipurposeSlot1; + PerInstInfo_t m_pPerInstInfo; + TADDR m_ElementTypeHnd; + TADDR m_pMultipurposeSlot1; }; public: union { - InterfaceInfo_t * m_pInterfaceMap; +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + RelativePointer<PTR_InterfaceInfo> m_pInterfaceMap; +#else + PlainPointer<PTR_InterfaceInfo> m_pInterfaceMap; +#endif TADDR m_pMultipurposeSlot2; }; diff --git a/src/vm/methodtable.inl b/src/vm/methodtable.inl index 9b72d24d0f..0d0acda885 100644 --- a/src/vm/methodtable.inl +++ b/src/vm/methodtable.inl @@ -23,24 +23,26 @@ inline PTR_EEClass MethodTable::GetClass_NoLogging() { LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT); + #ifdef _DEBUG - LowBits lowBits = union_getLowBits(m_pCanonMT); + LowBits lowBits = union_getLowBits(addr); if (lowBits == UNION_EECLASS) { - return PTR_EEClass(m_pCanonMT); + return PTR_EEClass(addr); } else if (lowBits == UNION_METHODTABLE) { // pointer to canonical MethodTable. - TADDR canonicalMethodTable = union_getPointer(m_pCanonMT); - return PTR_EEClass(PTR_MethodTable(canonicalMethodTable)->m_pCanonMT); + TADDR canonicalMethodTable = union_getPointer(addr); + return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(canonicalMethodTable), &MethodTable::m_pCanonMT)); } #ifdef FEATURE_PREJIT else if (lowBits == UNION_INDIRECTION) { // pointer to indirection cell that points to canonical MethodTable - TADDR canonicalMethodTable = *PTR_TADDR(union_getPointer(m_pCanonMT)); - return PTR_EEClass(PTR_MethodTable(canonicalMethodTable)->m_pCanonMT); + TADDR canonicalMethodTable = *PTR_TADDR(union_getPointer(addr)); + return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(canonicalMethodTable), &MethodTable::m_pCanonMT)); } #endif #ifdef DACCESS_COMPILE @@ -52,8 +54,6 @@ inline PTR_EEClass MethodTable::GetClass_NoLogging() #else - TADDR addr = m_pCanonMT; - if ((addr & 2) == 0) { // pointer to EEClass @@ -65,12 +65,12 @@ inline PTR_EEClass MethodTable::GetClass_NoLogging() { // pointer to indirection cell that points to canonical MethodTable TADDR canonicalMethodTable = *PTR_TADDR(addr - 3); - return PTR_EEClass(PTR_MethodTable(canonicalMethodTable)->m_pCanonMT); + return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(canonicalMethodTable), &MethodTable::m_pCanonMT)); } #endif // pointer to canonical MethodTable. - return PTR_EEClass(PTR_MethodTable(addr - 2)->m_pCanonMT); + return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(addr - 2), &MethodTable::m_pCanonMT)); #endif } @@ -113,25 +113,27 @@ inline BOOL MethodTable::IsClassPointerValid() WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - LowBits lowBits = union_getLowBits(m_pCanonMT); + TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT); + + LowBits lowBits = union_getLowBits(addr); if (lowBits == UNION_EECLASS) { - return (m_pEEClass != NULL); + return !m_pEEClass.IsNull(); } else if (lowBits == UNION_METHODTABLE) { // pointer to canonical MethodTable. - TADDR canonicalMethodTable = union_getPointer(m_pCanonMT); - return (PTR_MethodTable(canonicalMethodTable)->m_pEEClass != NULL); + TADDR canonicalMethodTable = union_getPointer(addr); + return !PTR_MethodTable(canonicalMethodTable)->m_pEEClass.IsNull(); } #ifdef FEATURE_PREJIT else if (lowBits == UNION_INDIRECTION) { // pointer to indirection cell that points to canonical MethodTable - TADDR canonicalMethodTable = *PTR_TADDR(union_getPointer(m_pCanonMT)); + TADDR canonicalMethodTable = *PTR_TADDR(union_getPointer(addr)); if (CORCOMPILE_IS_POINTER_TAGGED(canonicalMethodTable)) return FALSE; - return (PTR_MethodTable(canonicalMethodTable)->m_pEEClass != NULL); + return !PTR_MethodTable(canonicalMethodTable)->m_pEEClass.IsNull(); } #endif _ASSERTE(!"Malformed m_pEEClass in MethodTable"); @@ -161,7 +163,7 @@ inline PTR_Module MethodTable::GetZapModule() PTR_Module zapModule = NULL; if (IsZapped()) { - zapModule = m_pLoaderModule; + zapModule = ReadPointer(this, &MethodTable::m_pLoaderModule); } return zapModule; @@ -171,7 +173,7 @@ inline PTR_Module MethodTable::GetZapModule() inline PTR_Module MethodTable::GetLoaderModule() { LIMITED_METHOD_DAC_CONTRACT; - return m_pLoaderModule; + return ReadPointer(this, &MethodTable::m_pLoaderModule); } inline PTR_LoaderAllocator MethodTable::GetLoaderAllocator() @@ -187,7 +189,7 @@ inline PTR_LoaderAllocator MethodTable::GetLoaderAllocator() inline void MethodTable::SetLoaderModule(Module* pModule) { WRAPPER_NO_CONTRACT; - m_pLoaderModule = pModule; + m_pLoaderModule.SetValue(pModule); } inline void MethodTable::SetLoaderAllocator(LoaderAllocator* pAllocator) @@ -885,10 +887,10 @@ inline DWORD MethodTable::GetNumVtableIndirections(DWORD wNumVirtuals) } //========================================================================================== -inline PTR_PTR_PCODE MethodTable::GetVtableIndirections() +inline DPTR(MethodTable::VTableIndir_t) MethodTable::GetVtableIndirections() { LIMITED_METHOD_DAC_CONTRACT; - return dac_cast<PTR_PTR_PCODE>(dac_cast<TADDR>(this) + sizeof(MethodTable)); + return dac_cast<DPTR(VTableIndir_t)>(dac_cast<TADDR>(this) + sizeof(MethodTable)); } //========================================================================================== @@ -950,7 +952,7 @@ inline DWORD MethodTable::VtableIndirectionSlotIterator::GetOffsetFromMethodTabl WRAPPER_NO_CONTRACT; PRECONDITION(m_i != (DWORD) -1 && m_i < m_count); - return GetVtableOffset() + sizeof(PTR_PCODE) * m_i; + return GetVtableOffset() + sizeof(VTableIndir_t) * m_i; } //========================================================================================== @@ -959,7 +961,7 @@ inline PTR_PCODE MethodTable::VtableIndirectionSlotIterator::GetIndirectionSlot( LIMITED_METHOD_DAC_CONTRACT; PRECONDITION(m_i != (DWORD) -1 && m_i < m_count); - return *m_pSlot; + return m_pSlot->GetValueMaybeNull(dac_cast<TADDR>(m_pSlot)); } //========================================================================================== @@ -967,7 +969,7 @@ inline PTR_PCODE MethodTable::VtableIndirectionSlotIterator::GetIndirectionSlot( inline void MethodTable::VtableIndirectionSlotIterator::SetIndirectionSlot(PTR_PCODE pChunk) { LIMITED_METHOD_CONTRACT; - *m_pSlot = pChunk; + m_pSlot->SetValueMaybeNull(pChunk); } #endif @@ -1145,8 +1147,10 @@ inline PTR_MethodTable MethodTable::GetCanonicalMethodTable() { LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT); + #ifdef _DEBUG - LowBits lowBits = union_getLowBits(m_pCanonMT); + LowBits lowBits = union_getLowBits(addr); if (lowBits == UNION_EECLASS) { return dac_cast<PTR_MethodTable>(this); @@ -1154,18 +1158,17 @@ inline PTR_MethodTable MethodTable::GetCanonicalMethodTable() else if (lowBits == UNION_METHODTABLE) { // pointer to canonical MethodTable. - return PTR_MethodTable(union_getPointer(m_pCanonMT)); + return PTR_MethodTable(union_getPointer(addr)); } #ifdef FEATURE_PREJIT else if (lowBits == UNION_INDIRECTION) { - return PTR_MethodTable(*PTR_TADDR(union_getPointer(m_pCanonMT))); + return PTR_MethodTable(*PTR_TADDR(union_getPointer(addr))); } #endif _ASSERTE(!"Malformed m_pCanonMT in MethodTable"); return NULL; #else - TADDR addr = m_pCanonMT; if ((addr & 2) == 0) return dac_cast<PTR_MethodTable>(this); @@ -1185,11 +1188,12 @@ inline TADDR MethodTable::GetCanonicalMethodTableFixup() LIMITED_METHOD_DAC_CONTRACT; #ifdef FEATURE_PREJIT - LowBits lowBits = union_getLowBits(m_pCanonMT); + TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT); + LowBits lowBits = union_getLowBits(addr); if (lowBits == UNION_INDIRECTION) { // pointer to canonical MethodTable. - return *PTR_TADDR(union_getPointer(m_pCanonMT)); + return *PTR_TADDR(union_getPointer(addr)); } else #endif @@ -1252,7 +1256,7 @@ inline BOOL MethodTable::HasExplicitSize() inline DWORD MethodTable::GetPerInstInfoSize() { LIMITED_METHOD_DAC_CONTRACT; - return GetNumDicts() * sizeof(TypeHandle*); + return GetNumDicts() * sizeof(PerInstInfoElem_t); } //========================================================================================== @@ -1304,7 +1308,7 @@ inline BOOL MethodTable::IsCanonicalMethodTable() { LIMITED_METHOD_DAC_CONTRACT; - return (union_getLowBits(m_pCanonMT) == UNION_EECLASS); + return (union_getLowBits(ReadPointer(this, &MethodTable::m_pCanonMT)) == UNION_EECLASS); } //========================================================================================== @@ -1338,7 +1342,7 @@ inline PTR_InterfaceInfo MethodTable::GetInterfaceMap() { LIMITED_METHOD_DAC_CONTRACT; - return dac_cast<PTR_InterfaceInfo>(m_pMultipurposeSlot2); // m_pInterfaceMap + return ReadPointer(this, &MethodTable::m_pInterfaceMap); } //========================================================================================== @@ -1351,7 +1355,7 @@ FORCEINLINE TADDR MethodTable::GetMultipurposeSlotPtr(WFLAGS2_ENUM flag, const B DWORD offset = offsets[GetFlag((WFLAGS2_ENUM)(flag - 1))]; if (offset >= sizeof(MethodTable)) { - offset += GetNumVtableIndirections() * sizeof(PTR_PCODE); + offset += GetNumVtableIndirections() * sizeof(VTableIndir_t); } return dac_cast<TADDR>(this) + offset; @@ -1366,7 +1370,7 @@ FORCEINLINE DWORD MethodTable::GetOffsetOfOptionalMember(OptionalMemberId id) DWORD offset = c_OptionalMembersStartOffsets[GetFlag(enum_flag_MultipurposeSlotsMask)]; - offset += GetNumVtableIndirections() * sizeof(PTR_PCODE); + offset += GetNumVtableIndirections() * sizeof(VTableIndir_t); #undef METHODTABLE_OPTIONAL_MEMBER #define METHODTABLE_OPTIONAL_MEMBER(NAME, TYPE, GETTER) \ @@ -1733,7 +1737,7 @@ FORCEINLINE PTR_Module MethodTable::GetGenericsStaticsModuleAndID(DWORD * pID) _ASSERTE(!IsStringOrArray()); if (m_dwFlags & enum_flag_StaticsMask_IfGenericsThenCrossModule) { - CrossModuleGenericsStaticsInfo *pInfo = m_pWriteableData->GetCrossModuleGenericsStaticsInfo(); + CrossModuleGenericsStaticsInfo *pInfo = ReadPointer(this, &MethodTable::m_pWriteableData)->GetCrossModuleGenericsStaticsInfo(); _ASSERTE(FitsIn<DWORD>(pInfo->m_DynamicTypeID) || pInfo->m_DynamicTypeID == (SIZE_T)-1); *pID = static_cast<DWORD>(pInfo->m_DynamicTypeID); return pInfo->m_pModuleForStatics; diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index 888dd7fb6f..6cf75ed247 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -8851,7 +8851,7 @@ void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pAp // // Non-canonical method tables either share everything or nothing so it is sufficient to check // just the first indirection to detect sharing. - if (pMT->GetVtableIndirections()[0] != pCanonMT->GetVtableIndirections()[0]) + if (pMT->GetVtableIndirections()[0].GetValueMaybeNull() != pCanonMT->GetVtableIndirections()[0].GetValueMaybeNull()) { for (DWORD i = 0; i < nParentVirtuals; i++) { @@ -8878,7 +8878,7 @@ void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pAp // We need to re-inherit this slot from the exact parent. DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i); - if (pMT->GetVtableIndirections()[indirectionIndex] == pApproxParentMT->GetVtableIndirections()[indirectionIndex]) + if (pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == pApproxParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull()) { // The slot lives in a chunk shared from the approximate parent MT // If so, we need to change to share the chunk from the exact parent MT @@ -8889,7 +8889,7 @@ void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pAp _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule())); #endif - pMT->GetVtableIndirections()[indirectionIndex] = pParentMT->GetVtableIndirections()[indirectionIndex]; + pMT->GetVtableIndirections()[indirectionIndex].SetValueMaybeNull(pParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull()); i = MethodTable::GetEndSlotForVtableIndirection(indirectionIndex, nParentVirtuals) - 1; continue; @@ -9746,7 +9746,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule, S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable)); // vtable - cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(PTR_PCODE); + cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t); DWORD dwMultipurposeSlotsMask = 0; @@ -9790,7 +9790,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; } @@ -9895,7 +9895,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule, { // Share the parent chunk _ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals()); - it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()]); + it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull()); } else { @@ -9943,19 +9943,20 @@ 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)); } } #ifdef _DEBUG - pMT->m_pWriteableData->m_dwLastVerifedGCCnt = (DWORD)-1; + pMT->m_pWriteableData.GetValue()->m_dwLastVerifedGCCnt = (DWORD)-1; #endif // _DEBUG RETURN(pMT); @@ -10444,7 +10445,7 @@ MethodTableBuilder::SetupMethodTable2( // with code:MethodDesc::SetStableEntryPointInterlocked. // DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot); - if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex] != pMT->GetVtableIndirections()[indirectionIndex]) + if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() != pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull()) pMT->SetSlot(iCurSlot, pMD->GetMethodEntryPoint()); } else diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 84d27943f5..ee8cae7c1e 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -2540,6 +2540,7 @@ void ProcessDynamicDictionaryLookup(TransitionBlock * pTransitionBlock pResult->signature = NULL; pResult->indirectFirstOffset = 0; + pResult->indirectSecondOffset = 0; pResult->indirections = CORINFO_USEHELPER; @@ -2612,6 +2613,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; } } @@ -2657,6 +2664,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; } } diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp index 0493163287..8b55f06bd8 100644 --- a/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/vm/proftoeeinterfaceimpl.cpp @@ -6843,7 +6843,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassLayout(ClassID classID, // running into - attempting to get the class layout for all types at module load time. // If we don't detect this the runtime will AV during the field iteration below. Feel // free to eliminate this check when a more complete solution is available. - if (CORCOMPILE_IS_POINTER_TAGGED(*(typeHandle.AsMethodTable()->GetParentMethodTablePtr()))) + if (typeHandle.AsMethodTable()->GetParentMethodTablePlainOrRelativePointerPtr()->IsTagged()) { return CORPROF_E_DATAINCOMPLETE; } |