diff options
author | Bruce Forstall <brucefo@microsoft.com> | 2017-08-08 11:28:27 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-08 11:28:27 -0700 |
commit | 7590378d8a00d7c29ade23fada2ce79f4495b889 (patch) | |
tree | 2f621550b98e22430354d815e9a261671cddf50b | |
parent | 488d562052e61dde32ff0593835acc2713e9a0d1 (diff) | |
parent | 76a572a65026f277c5c42b25fcb01cce4625b10f (diff) | |
download | coreclr-7590378d8a00d7c29ade23fada2ce79f4495b889.tar.gz coreclr-7590378d8a00d7c29ade23fada2ce79f4495b889.tar.bz2 coreclr-7590378d8a00d7c29ade23fada2ce79f4495b889.zip |
Merge pull request #12168 from gbalykov/remove-relocations-readonly
Partially remove relocations from SECTION_Readonly
42 files changed, 921 insertions, 331 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h index 00b5c1b965..ad6b269041 100644 --- a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h +++ b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h @@ -109,7 +109,8 @@ CORINFO_MODULE_HANDLE getMethodModule(CORINFO_METHOD_HANDLE method); // vtable of it's owning class or interface. void getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */ + unsigned* offsetAfterIndirection,/* OUT */ + bool* isRelative /* OUT */ ); // Find the virtual method in implementingClass that overrides virtualMethod. diff --git a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h index 23cdf70922..349b6bf105 100644 --- a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h +++ b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h @@ -102,7 +102,7 @@ LWM(GetMethodInfo, DWORDLONG, Agnostic_GetMethodInfo) LWM(GetMethodName, DLD, DD) LWM(GetMethodSig, DLDL, Agnostic_CORINFO_SIG_INFO) LWM(GetMethodSync, DWORDLONG, DLDL) -LWM(GetMethodVTableOffset, DWORDLONG, DD) +LWM(GetMethodVTableOffset, DWORDLONG, DDD) LWM(GetNewArrHelper, DWORDLONG, DWORD) LWM(GetNewHelper, Agnostic_GetNewHelper, DWORD) LWM(GetParentType, DWORDLONG, DWORDLONG) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index f522265e11..b33e0318b5 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -1504,6 +1504,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]; } @@ -2970,26 +2971,29 @@ void MethodContext::repGetEHinfo(CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, C void MethodContext::recGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, - unsigned* offsetAfterIndirection) + unsigned* offsetAfterIndirection, + bool* isRelative) { if (GetMethodVTableOffset == nullptr) - GetMethodVTableOffset = new LightWeightMap<DWORDLONG, DD>(); + GetMethodVTableOffset = new LightWeightMap<DWORDLONG, DDD>(); - DD value; + DDD value; value.A = (DWORD)*offsetOfIndirection; value.B = (DWORD)*offsetAfterIndirection; + value.C = *isRelative; GetMethodVTableOffset->Add((DWORDLONG)method, value); DEBUG_REC(dmpGetMethodVTableOffset((DWORDLONG)method, value)); } -void MethodContext::dmpGetMethodVTableOffset(DWORDLONG key, DD value) +void MethodContext::dmpGetMethodVTableOffset(DWORDLONG key, DDD value) { - printf("GetMethodVTableOffset key ftn-%016llX, value offi-%u, offa-%u", key, value.A, value.B); + printf("GetMethodVTableOffset key ftn-%016llX, value offi-%u, offa-%u. offr-%d", key, value.A, value.B, value.C); } void MethodContext::repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, - unsigned* offsetAfterIndirection) + unsigned* offsetAfterIndirection, + bool* isRelative) { - DD value; + DDD value; AssertCodeMsg(GetMethodVTableOffset != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)method); @@ -2999,6 +3003,7 @@ void MethodContext::repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, *offsetOfIndirection = (unsigned)value.A; *offsetAfterIndirection = (unsigned)value.B; + *isRelative = value.C; DEBUG_REP(dmpGetMethodVTableOffset((DWORDLONG)method, value)); } diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index 4b42fa7be4..d2f43b477a 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -211,6 +211,7 @@ public: DWORD testForFixup; DWORDLONG offsets[CORINFO_MAXINDIRECTIONS]; DWORD indirectFirstOffset; + DWORD indirectSecondOffset; }; struct Agnostic_CORINFO_LOOKUP { @@ -236,6 +237,12 @@ public: DWORD A; DWORD B; }; + struct DDD + { + DWORD A; + DWORD B; + bool C; + }; struct Agnostic_CanTailCall { DWORDLONG callerHnd; @@ -843,11 +850,13 @@ public: void recGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, - unsigned* offsetAfterIndirection); - void dmpGetMethodVTableOffset(DWORDLONG key, DD value); + unsigned* offsetAfterIndirection, + bool* isRelative); + void dmpGetMethodVTableOffset(DWORDLONG key, DDD value); void repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, - unsigned* offsetAfterIndirection); + unsigned* offsetAfterIndirection, + bool* isRelative); void recResolveVirtualMethod(CORINFO_METHOD_HANDLE virtMethod, CORINFO_CLASS_HANDLE implClass, diff --git a/src/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h b/src/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h index 0030a2bbd5..c3988f8487 100644 --- a/src/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h +++ b/src/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h @@ -297,6 +297,7 @@ inline MethodContext::Agnostic_CORINFO_RUNTIME_LOOKUP SpmiRecordsHelper::StoreAg runtimeLookup.testForNull = (DWORD)pLookup->testForNull; runtimeLookup.testForFixup = (DWORD)pLookup->testForFixup; runtimeLookup.indirectFirstOffset = (DWORD)pLookup->indirectFirstOffset; + runtimeLookup.indirectSecondOffset = (DWORD)pLookup->indirectSecondOffset; for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) runtimeLookup.offsets[i] = (DWORDLONG)pLookup->offsets[i]; return runtimeLookup; @@ -312,6 +313,7 @@ inline CORINFO_RUNTIME_LOOKUP SpmiRecordsHelper::RestoreCORINFO_RUNTIME_LOOKUP( runtimeLookup.testForNull = lookup.testForNull != 0; runtimeLookup.testForFixup = lookup.testForFixup != 0; runtimeLookup.indirectFirstOffset = lookup.indirectFirstOffset != 0; + runtimeLookup.indirectSecondOffset = lookup.indirectSecondOffset != 0; for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++) runtimeLookup.offsets[i] = (size_t)lookup.offsets[i]; return CORINFO_RUNTIME_LOOKUP(); diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 1ba0ed2a65..d79e4ee51a 100644 --- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -214,12 +214,13 @@ CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule(CORINFO_METHOD_HANDLE me // vtable of it's owning class or interface. void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */ + unsigned* offsetAfterIndirection,/* OUT */ + bool* isRelative /* OUT */ ) { mc->cr->AddCall("getMethodVTableOffset"); - original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); - mc->recGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); + original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); + mc->recGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); } // Find the virtual method in implementingClass that overrides virtualMethod. diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 6760800d59..d731a773f0 100644 --- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -145,11 +145,12 @@ CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule(CORINFO_METHOD_HANDLE me // vtable of it's owning class or interface. void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */ + unsigned* offsetAfterIndirection,/* OUT */ + bool* isRelative /* OUT */ ) { mcs->AddCall("getMethodVTableOffset"); - original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); + original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); } // Find the virtual method in implementingClass that overrides virtualMethod. diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index b098eb6b46..fd45a3c2dc 100644 --- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -134,10 +134,11 @@ CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule(CORINFO_METHOD_HANDLE me // vtable of it's owning class or interface. void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */ + unsigned* offsetAfterIndirection,/* OUT */ + bool* isRelative /* OUT */ ) { - original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); + original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); } // Find the virtual method in implementingClass that overrides virtualMethod. diff --git a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index d88e35299a..e8b4187a99 100644 --- a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -165,11 +165,12 @@ CORINFO_MODULE_HANDLE MyICJI::getMethodModule(CORINFO_METHOD_HANDLE method) // vtable of it's owning class or interface. void MyICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */ + unsigned* offsetAfterIndirection,/* OUT */ + bool* isRelative /* OUT */ ) { jitInstance->mc->cr->AddCall("getMethodVTableOffset"); - jitInstance->mc->repGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); + jitInstance->mc->repGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); } // Find the virtual method in implementingClass that overrides virtualMethod. diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index c2ec84fba0..f1ee6f151e 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -3947,7 +3947,7 @@ void NativeImageDumper::DumpModule( PTR_Module module ) DisplayWriteFieldInt( numElementsHot, ctorInfo->numElementsHot, ModuleCtorInfo, SLIM_MODULE_TBLS ); DisplayWriteFieldAddress( ppMT, DPtrToPreferredAddr(ctorInfo->ppMT), - ctorInfo->numElements * sizeof(MethodTable*), + ctorInfo->numElements * sizeof(RelativePointer<MethodTable*>), ModuleCtorInfo, SLIM_MODULE_TBLS ); /* REVISIT_TODO Tue 03/21/2006 * is cctorInfoHot and cctorInfoCold actually have anything interesting @@ -5084,7 +5084,10 @@ 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 ); @@ -5983,7 +5986,7 @@ PTR_MethodTable NativeImageDumper::GetParent( PTR_MethodTable mt ) /* REVISIT_TODO Thu 12/01/2005 * Handle fixups */ - PTR_MethodTable parent( mt->m_pParentMethodTable ); + PTR_MethodTable parent( ReadPointerMaybeNull((MethodTable *) mt, &MethodTable::m_pParentMethodTable) ); _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(parent))); return parent; } @@ -6957,7 +6960,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, - PTR_MethodTable parent = mt->m_pParentMethodTable; + PTR_MethodTable parent = ReadPointerMaybeNull((MethodTable *) mt, &MethodTable::m_pParentMethodTable); if( parent == NULL ) { DisplayWriteFieldPointer( m_pParentMethodTable, NULL, MethodTable, @@ -6977,7 +6980,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, DPtrToPreferredAddr(mt->GetLoaderModule()), MethodTable, METHODTABLES ); - PTR_MethodTableWriteableData wd = mt->m_pWriteableData; + PTR_MethodTableWriteableData wd = ReadPointer((MethodTable *)mt, &MethodTable::m_pWriteableData); _ASSERTE(wd != NULL); DisplayStartStructureWithOffset( m_pWriteableData, DPtrToPreferredAddr(wd), sizeof(*wd), MethodTable, METHODTABLES ); @@ -7023,8 +7026,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, GenericsDictInfo, METHODTABLES); DisplayEndStructure( METHODTABLES ); //GenericsDictInfo - - DPTR(PTR_Dictionary) perInstInfo = mt->GetPerInstInfo(); + DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo(); DisplayStartStructure( "PerInstInfo", DPtrToPreferredAddr(perInstInfo), @@ -7160,9 +7162,9 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, { m_display->StartStructureWithOffset("Vtable", mt->GetVtableOffset(), - mt->GetNumVtableIndirections() * sizeof(PTR_PCODE), + mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t), DataPtrToDisplay(PTR_TO_TADDR(mt) + mt->GetVtableOffset()), - mt->GetNumVtableIndirections() * sizeof(PTR_PCODE)); + mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t)); MethodTable::VtableIndirectionSlotIterator itIndirect = mt->IterateVtableIndirectionSlots(); @@ -7181,7 +7183,8 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, { DisplayStartElement( "Slot", ALWAYS ); DisplayWriteElementInt( "Index", i, ALWAYS ); - PTR_PCODE tgt = mt->GetVtableIndirections()[i]; + TADDR base = dac_cast<TADDR>(&(mt->GetVtableIndirections()[i])); + PTR_PCODE tgt = MethodTable::VTableIndir_t::GetValueMaybeNullAtPtr(base); DisplayWriteElementPointer( "Pointer", DataPtrToDisplay(dac_cast<TADDR>(tgt)), ALWAYS ); @@ -7217,7 +7220,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, else { CoverageRead( PTR_TO_TADDR(mt) + mt->GetVtableOffset(), - mt->GetNumVtableIndirections() * sizeof(PTR_PCODE) ); + mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t) ); if (mt->HasNonVirtualSlotsArray()) { @@ -7233,7 +7236,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, { PTR_InterfaceInfo ifMap = mt->GetInterfaceMap(); m_display->StartArrayWithOffset( "InterfaceMap", - offsetof(MethodTable, m_pMultipurposeSlot2), + offsetof(MethodTable, m_pInterfaceMap), sizeof(void*), NULL ); for( unsigned i = 0; i < mt->GetNumInterfaces(); ++i ) @@ -7267,7 +7270,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, DPtrToPreferredAddr(genStatics), sizeof(*genStatics) ); - PTR_FieldDesc fieldDescs = genStatics->m_pFieldDescs; + PTR_FieldDesc fieldDescs = ReadPointerMaybeNull((GenericsStaticsInfo *) genStatics, &GenericsStaticsInfo::m_pFieldDescs); if( fieldDescs == NULL ) { DisplayWriteFieldPointer( m_pFieldDescs, NULL, GenericsStaticsInfo, diff --git a/src/inc/corcompile.h b/src/inc/corcompile.h index 31bf213d41..3403e2254b 100644 --- a/src/inc/corcompile.h +++ b/src/inc/corcompile.h @@ -1331,6 +1331,7 @@ class ICorCompilePreloader CORCOMPILE_SECTION(READONLY_HOT) \ CORCOMPILE_SECTION(READONLY_WARM) \ CORCOMPILE_SECTION(READONLY_COLD) \ + CORCOMPILE_SECTION(READONLY_VCHUNKS_AND_DICTIONARY) \ CORCOMPILE_SECTION(CLASS_COLD) \ CORCOMPILE_SECTION(CROSS_DOMAIN_INFO) \ CORCOMPILE_SECTION(METHOD_PRECODE_COLD) \ diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index 4af22e53f4..084b9841bb 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -213,11 +213,11 @@ TODO: Talk about initializing strutures before use #define SELECTANY extern __declspec(selectany) #endif -SELECTANY const GUID JITEEVersionIdentifier = { /* 28eb875f-b6a9-4a04-9ba7-69ba59deed46 */ - 0x28eb875f, - 0xb6a9, - 0x4a04, - { 0x9b, 0xa7, 0x69, 0xba, 0x59, 0xde, 0xed, 0x46 } +SELECTANY const GUID JITEEVersionIdentifier = { /* 5a1cfc89-a84a-4642-b01d-ead88e60c1ee */ + 0x5a1cfc89, + 0xa84a, + 0x4642, + { 0xb0, 0x1d, 0xea, 0xd8, 0x8e, 0x60, 0xc1, 0xee } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1332,6 +1332,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 @@ -2062,7 +2069,8 @@ public: virtual void getMethodVTableOffset ( CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */ + unsigned* offsetAfterIndirection, /* OUT */ + bool* isRelative /* OUT */ ) = 0; // Find the virtual method in implementingClass that overrides virtualMethod, diff --git a/src/inc/fixuppointer.h b/src/inc/fixuppointer.h index 83ff20e04f..a711418bd4 100644 --- a/src/inc/fixuppointer.h +++ b/src/inc/fixuppointer.h @@ -141,6 +141,12 @@ public: LIMITED_METHOD_CONTRACT; SetValueMaybeNull((TADDR)this, addr); } + + FORCEINLINE void SetValueVolatile(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValue(addr); + } #endif #ifndef DACCESS_COMPILE @@ -208,15 +214,38 @@ public: return dac_cast<PTR_TYPE>(addr); } + // Returns value of the encoded pointer. + FORCEINLINE PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValue(); + } + +#ifndef DACCESS_COMPILE // Returns the pointer to the indirection cell. PTR_TYPE * GetValuePtr() const { - LIMITED_METHOD_DAC_CONTRACT; + LIMITED_METHOD_CONTRACT; TADDR addr = m_addr; if ((addr & FIXUP_POINTER_INDIRECTION) != 0) - return dac_cast<DPTR(PTR_TYPE)>(addr - FIXUP_POINTER_INDIRECTION); + return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION); return (PTR_TYPE *)&m_addr; } +#endif // !DACCESS_COMPILE + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<DPTR(FixupPointer<PTR_TYPE>)>(base)->GetValue(); + } + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<DPTR(FixupPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(); + } // Returns value of the encoded pointer. // Allows the value to be tagged. @@ -229,12 +258,20 @@ public: return addr; } +#ifndef DACCESS_COMPILE void SetValue(PTR_TYPE addr) { LIMITED_METHOD_CONTRACT; m_addr = dac_cast<TADDR>(addr); } + void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValue(addr); + } +#endif // !DACCESS_COMPILE + private: TADDR m_addr; }; @@ -283,11 +320,12 @@ public: } #ifndef DACCESS_COMPILE + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + // Does not need explicit base and thus can be used in non-DAC builds only. FORCEINLINE BOOL IsTagged() const { LIMITED_METHOD_CONTRACT; - TADDR base = (TADDR) this; - return IsTagged(base); + return IsTagged((TADDR)this); } #endif // !DACCESS_COMPILE @@ -382,21 +420,14 @@ public: } #endif - // Returns the pointer to the indirection cell. - PTR_TYPE * GetValuePtr(TADDR base) const - { - LIMITED_METHOD_CONTRACT; - TADDR addr = base + m_delta; - _ASSERTE((addr & FIXUP_POINTER_INDIRECTION) != 0); - return dac_cast<DPTR(PTR_TYPE)>(addr - FIXUP_POINTER_INDIRECTION); - } - #ifndef DACCESS_COMPILE + // Returns the pointer to the indirection cell. PTR_TYPE * GetValuePtr() const { LIMITED_METHOD_CONTRACT; - TADDR base = (TADDR) this; - return GetValuePtr(base); + TADDR addr = ((TADDR)this) + m_delta; + _ASSERTE((addr & FIXUP_POINTER_INDIRECTION) != 0); + return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION); } #endif // !DACCESS_COMPILE @@ -412,6 +443,48 @@ public: return addr; } + // Returns whether pointer is indirect. Assumes that the value is not NULL. + bool IsIndirectPtr(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsNull()); + + TADDR addr = base + m_delta; + + return (addr & FIXUP_POINTER_INDIRECTION) != 0; + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtr() const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtr((TADDR)this); + } +#endif + + // Returns whether pointer is indirect. The value can be NULL. + bool IsIndirectPtrMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + + if (m_delta == 0) + return false; + + return IsIndirectPtr(base); + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. The value can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtrMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtrMaybeNull((TADDR)this); + } +#endif + private: #ifndef DACCESS_COMPILE Volatile<TADDR> m_delta; @@ -444,10 +517,20 @@ public: } // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + BOOL IsTagged(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsTagged(); + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. BOOL IsTagged() const { LIMITED_METHOD_DAC_CONTRACT; - return m_ptr & 1; + TADDR addr = m_ptr; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0; + return FALSE; } // Returns value of the encoded pointer. @@ -457,18 +540,22 @@ public: return dac_cast<PTR_TYPE>(m_ptr); } +#ifndef DACCESS_COMPILE // Returns the pointer to the indirection cell. PTR_TYPE * GetValuePtr() const { - LIMITED_METHOD_DAC_CONTRACT; + LIMITED_METHOD_CONTRACT; + TADDR addr = m_ptr; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION); return (PTR_TYPE *)&m_ptr; } +#endif // !DACCESS_COMPILE // Returns value of the encoded pointer. Assumes that the pointer is not NULL. PTR_TYPE GetValue(TADDR base) const { LIMITED_METHOD_DAC_CONTRACT; - PRECONDITION(!IsNull()); return dac_cast<PTR_TYPE>(m_ptr); } @@ -480,6 +567,13 @@ public: } // Returns value of the encoded pointer. The pointer can be NULL. + PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<PTR_TYPE>(m_ptr); + } + + // Returns value of the encoded pointer. The pointer can be NULL. PTR_TYPE GetValueMaybeNull(TADDR base) const { LIMITED_METHOD_DAC_CONTRACT; @@ -493,6 +587,43 @@ public: return dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base); } + // Returns whether pointer is indirect. Assumes that the value is not NULL. + bool IsIndirectPtr(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + + return (m_ptr & FIXUP_POINTER_INDIRECTION) != 0; + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtr() const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtr((TADDR)this); + } +#endif + + // Returns whether pointer is indirect. The value can be NULL. + bool IsIndirectPtrMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + + return IsIndirectPtr(base); + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. The value can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtrMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtrMaybeNull((TADDR)this); + } +#endif + +#ifndef DACCESS_COMPILE void SetValue(PTR_TYPE addr) { LIMITED_METHOD_CONTRACT; @@ -503,7 +634,6 @@ public: void SetValue(TADDR base, PTR_TYPE addr) { LIMITED_METHOD_CONTRACT; - PRECONDITION(addr != NULL); m_ptr = dac_cast<TADDR>(addr); } @@ -521,7 +651,6 @@ public: m_ptr = dac_cast<TADDR>(addr); } -#ifndef DACCESS_COMPILE // Set encoded value of the pointer. The value can be NULL. // Does not need explicit base and thus can be used in non-DAC builds only. FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr) @@ -529,7 +658,6 @@ public: LIMITED_METHOD_CONTRACT; return SetValueMaybeNull((TADDR)this, addr); } -#endif // Static version of SetValueMaybeNull. It is meant to simplify access to arrays of pointers. FORCEINLINE static void SetValueMaybeNullAtPtr(TADDR base, PTR_TYPE addr) @@ -538,6 +666,13 @@ public: dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->SetValueMaybeNull(base, addr); } + FORCEINLINE void SetValueVolatile(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + VolatileStore((PTR_TYPE *)(&m_ptr), addr); + } +#endif + private: TADDR m_ptr; }; diff --git a/src/jit/ICorJitInfo_API_wrapper.hpp b/src/jit/ICorJitInfo_API_wrapper.hpp index b9fd876995..1d30e0096e 100644 --- a/src/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/jit/ICorJitInfo_API_wrapper.hpp @@ -122,10 +122,11 @@ CORINFO_MODULE_HANDLE WrapICorJitInfo::getMethodModule( void WrapICorJitInfo::getMethodVTableOffset( CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ - unsigned* offsetAfterIndirection /* OUT */) + unsigned* offsetAfterIndirection, /* OUT */ + bool* isRelative /* OUT */) { API_ENTER(getMethodVTableOffset); - wrapHnd->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection); + wrapHnd->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); API_LEAVE(getMethodVTableOffset); } diff --git a/src/jit/codegenlegacy.cpp b/src/jit/codegenlegacy.cpp index 26982345e5..71bd62a3d1 100644 --- a/src/jit/codegenlegacy.cpp +++ b/src/jit/codegenlegacy.cpp @@ -18904,29 +18904,48 @@ regMaskTP CodeGen::genCodeForCall(GenTreeCall* call, bool valUsed) // stub dispatching is off or this is not a virtual call (could be a tailcall) { regNumber vptrReg; + regNumber vptrReg1; + regMaskTP vptrMask1; unsigned vtabOffsOfIndirection; unsigned vtabOffsAfterIndirection; + bool isRelative; noway_assert(callType == CT_USER_FUNC); + /* Get hold of the vtable offset (note: this might be expensive) */ + + compiler->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, + &vtabOffsAfterIndirection, &isRelative); + vptrReg = regSet.rsGrabReg(RBM_ALLINT); // Grab an available register to use for the CALL indirection vptrMask = genRegMask(vptrReg); + if (isRelative) + { + vptrReg1 = regSet.rsGrabReg(RBM_ALLINT & ~vptrMask); + vptrMask1 = genRegMask(vptrReg1); + } + /* The register no longer holds a live pointer value */ gcInfo.gcMarkRegSetNpt(vptrMask); + if (isRelative) + { + gcInfo.gcMarkRegSetNpt(vptrMask1); + } + // MOV vptrReg, [REG_CALL_THIS + offs] getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, genGetThisArgReg(call), VPTR_OFFS); regTracker.rsTrackRegTrash(vptrReg); - noway_assert(vptrMask & ~call->gtCallRegUsedMask); - - /* Get hold of the vtable offset (note: this might be expensive) */ + if (isRelative) + { + regTracker.rsTrackRegTrash(vptrReg1); + } - compiler->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, - &vtabOffsAfterIndirection); + noway_assert(vptrMask & ~call->gtCallRegUsedMask); /* The register no longer holds a live pointer value */ gcInfo.gcMarkRegSetNpt(vptrMask); @@ -18935,25 +18954,61 @@ regMaskTP CodeGen::genCodeForCall(GenTreeCall* call, bool valUsed) if (vtabOffsOfIndirection != CORINFO_VIRTUALCALL_NO_CHUNK) { + if (isRelative) + { +#if defined(_TARGET_ARM_) + unsigned offset = vtabOffsOfIndirection + vtabOffsAfterIndirection; + + // ADD vptrReg1, REG_CALL_IND_SCRATCH, vtabOffsOfIndirection + vtabOffsAfterIndirection + getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, vptrReg1, vptrReg, offset); +#else + unreached(); +#endif + } + // MOV vptrReg, [REG_CALL_IND_SCRATCH + vtabOffsOfIndirection] getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg, vtabOffsOfIndirection); } + else + { + assert(!isRelative); + } /* Call through the appropriate vtable slot */ if (fTailCall) { - /* Load the function address: "[vptrReg+vtabOffs] -> reg_intret" */ - - getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_TAILCALL_ADDR, vptrReg, - vtabOffsAfterIndirection); + if (isRelative) + { +#if defined(_TARGET_ARM_) + /* Load the function address: "[vptrReg1 + vptrReg] -> reg_intret" */ + getEmitter()->emitIns_R_ARR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_TAILCALL_ADDR, vptrReg1, + vptrReg, 0); +#else + unreached(); +#endif + } + else + { + /* Load the function address: "[vptrReg+vtabOffs] -> reg_intret" */ + getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_TAILCALL_ADDR, vptrReg, + vtabOffsAfterIndirection); + } } else { #if CPU_LOAD_STORE_ARCH - getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg, - vtabOffsAfterIndirection); + if (isRelative) + { + getEmitter()->emitIns_R_ARR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg1, vptrReg, + 0); + } + else + { + getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg, + vtabOffsAfterIndirection); + } getEmitter()->emitIns_Call(emitter::EC_INDIR_R, call->gtCallMethHnd, INDEBUG_LDISASM_COMMA(sigInfo) NULL, // addr @@ -18961,6 +19016,7 @@ regMaskTP CodeGen::genCodeForCall(GenTreeCall* call, bool valUsed) gcInfo.gcRegByrefSetCur, ilOffset, vptrReg); // ireg #else + assert(!isRelative); getEmitter()->emitIns_Call(emitter::EC_FUNC_VIRTUAL, call->gtCallMethHnd, INDEBUG_LDISASM_COMMA(sigInfo) NULL, // addr args, retSize, gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp index a0c7196ecb..0126b13b1e 100644 --- a/src/jit/emitarm.cpp +++ b/src/jit/emitarm.cpp @@ -2459,6 +2459,16 @@ void emitter::emitIns_R_R_I(instruction ins, fmt = IF_T2_M0; sf = INS_FLAGS_NOT_SET; } + else if (insDoesNotSetFlags(flags) && (reg1 != REG_SP) && (reg1 != REG_PC)) + { + // movw,movt reg1, imm + codeGen->instGen_Set_Reg_To_Imm(attr, reg1, (ins == INS_sub ? -1 : 1) * imm); + + // ins reg1, reg2 + emitIns_R_R(INS_add, attr, reg1, reg2); + + return; + } else { assert(!"Instruction cannot be encoded"); diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index c2c491a35e..d529bb2fe9 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/jit/lower.cpp b/src/jit/lower.cpp index 8644aca209..1d23349d29 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -3446,6 +3446,13 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call) // We'll introduce another use of this local so increase its ref count. comp->lvaTable[lclNum].incRefCnts(comp->compCurBB->getBBWeight(comp), comp); + // Get hold of the vtable offset (note: this might be expensive) + unsigned vtabOffsOfIndirection; + unsigned vtabOffsAfterIndirection; + bool isRelative; + comp->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, + &vtabOffsAfterIndirection, &isRelative); + // If the thisPtr is a local field, then construct a local field type node GenTree* local; if (thisPtr->isLclField()) @@ -3461,22 +3468,58 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call) // pointer to virtual table = [REG_CALL_THIS + offs] GenTree* result = Ind(Offset(local, VPTR_OFFS)); - // Get hold of the vtable offset (note: this might be expensive) - unsigned vtabOffsOfIndirection; - unsigned vtabOffsAfterIndirection; - comp->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, - &vtabOffsAfterIndirection); - // Get the appropriate vtable chunk if (vtabOffsOfIndirection != CORINFO_VIRTUALCALL_NO_CHUNK) { - // result = [REG_CALL_IND_SCRATCH + vtabOffsOfIndirection] - result = Ind(Offset(result, vtabOffsOfIndirection)); + if (isRelative) + { + // MethodTable offset is a relative pointer. + // + // Additional temporary variable is used to store virtual table pointer. + // Address of method is obtained by the next computations: + // + // Save relative offset to tmp (vtab is virtual table pointer, vtabOffsOfIndirection is offset of + // vtable-1st-level-indirection): + // tmp = [vtab + vtabOffsOfIndirection] + // + // Save address of method to result (vtabOffsAfterIndirection is offset of vtable-2nd-level-indirection): + // result = [vtab + vtabOffsOfIndirection + vtabOffsAfterIndirection + tmp] + unsigned lclNumTmp = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp")); + + comp->lvaTable[lclNumTmp].incRefCnts(comp->compCurBB->getBBWeight(comp), comp); + GenTree* lclvNodeStore = comp->gtNewTempAssign(lclNumTmp, result); + + LIR::Range range = LIR::SeqTree(comp, lclvNodeStore); + JITDUMP("result of obtaining pointer to virtual table:\n"); + DISPRANGE(range); + BlockRange().InsertBefore(call, std::move(range)); + + GenTree* tmpTree = comp->gtNewLclvNode(lclNumTmp, result->TypeGet()); + tmpTree = Offset(tmpTree, vtabOffsOfIndirection); + + tmpTree = comp->gtNewOperNode(GT_IND, TYP_I_IMPL, tmpTree, false); + GenTree* offs = comp->gtNewIconNode(vtabOffsOfIndirection + vtabOffsAfterIndirection, TYP_INT); + result = comp->gtNewOperNode(GT_ADD, TYP_I_IMPL, comp->gtNewLclvNode(lclNumTmp, result->TypeGet()), offs); + + result = Ind(OffsetByIndex(result, tmpTree)); + } + else + { + // result = [REG_CALL_IND_SCRATCH + vtabOffsOfIndirection] + result = Ind(Offset(result, vtabOffsOfIndirection)); + } + } + else + { + assert(!isRelative); } // Load the function address // result = [reg+vtabOffs] - result = Ind(Offset(result, vtabOffsAfterIndirection)); + if (!isRelative) + { + result = Ind(Offset(result, vtabOffsAfterIndirection)); + } return result; } diff --git a/src/jit/lower.h b/src/jit/lower.h index 39b61ef667..f09df7a836 100644 --- a/src/jit/lower.h +++ b/src/jit/lower.h @@ -147,6 +147,12 @@ private: return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, nullptr, 0, offset); } + GenTree* OffsetByIndex(GenTree* base, GenTree* index) + { + var_types resultType = (base->TypeGet() == TYP_REF) ? TYP_BYREF : base->TypeGet(); + return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, index, 0, 0); + } + // returns true if the tree can use the read-modify-write memory instruction form bool isRMWRegOper(GenTreePtr tree); diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 4b76e804bf..91b92064fd 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -7231,14 +7231,30 @@ void Compiler::fgMorphTailCall(GenTreeCall* call) unsigned vtabOffsOfIndirection; unsigned vtabOffsAfterIndirection; - info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, &vtabOffsAfterIndirection); + bool isRelative; + info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, &vtabOffsAfterIndirection, + &isRelative); /* Get the appropriate vtable chunk */ if (vtabOffsOfIndirection != CORINFO_VIRTUALCALL_NO_CHUNK) { - add = gtNewOperNode(GT_ADD, TYP_I_IMPL, vtbl, gtNewIconNode(vtabOffsOfIndirection, TYP_I_IMPL)); + add = gtNewOperNode(GT_ADD, TYP_I_IMPL, vtbl, gtNewIconNode(vtabOffsOfIndirection, TYP_I_IMPL)); + + GenTreePtr indOffTree; + + if (isRelative) + { + indOffTree = impCloneExpr(add, &add, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL, + nullptr DEBUGARG("virtual table call")); + } + vtbl = gtNewOperNode(GT_IND, TYP_I_IMPL, add); + + if (isRelative) + { + vtbl = gtNewOperNode(GT_ADD, TYP_I_IMPL, vtbl, indOffTree); + } } /* Now the appropriate vtable slot */ 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; } diff --git a/src/zap/zapimage.cpp b/src/zap/zapimage.cpp index 2b38eaf107..60a48a81fb 100644 --- a/src/zap/zapimage.cpp +++ b/src/zap/zapimage.cpp @@ -572,6 +572,7 @@ void ZapImage::AllocateVirtualSections() #endif // defined(WIN64EXCEPTIONS) m_pPreloadSections[CORCOMPILE_SECTION_READONLY_WARM] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, sizeof(TADDR)); + m_pPreloadSections[CORCOMPILE_SECTION_READONLY_VCHUNKS_AND_DICTIONARY] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, sizeof(TADDR)); // // GC Info for methods which were not touched in profiling diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index 4f06d94615..5683f4f3e1 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -3683,10 +3683,11 @@ CORINFO_MODULE_HANDLE ZapInfo::getMethodModule(CORINFO_METHOD_HANDLE method) } void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, - unsigned * pOffsetOfIndirection, - unsigned * pOffsetAfterIndirection) + unsigned * pOffsetOfIndirection, + unsigned * pOffsetAfterIndirection, + bool * isRelative) { - m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection); + m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative); } CORINFO_METHOD_HANDLE ZapInfo::resolveVirtualMethod( diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h index 44ad5de52d..88f095bc2d 100644 --- a/src/zap/zapinfo.h +++ b/src/zap/zapinfo.h @@ -662,7 +662,8 @@ public: void getMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsigned * pOffsetOfIndirection, - unsigned * pOffsetAfterIndirection); + unsigned * pOffsetAfterIndirection, + bool * isRelative); CORINFO_METHOD_HANDLE resolveVirtualMethod( CORINFO_METHOD_HANDLE virtualMethod, |