summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Forstall <brucefo@microsoft.com>2017-08-08 11:28:27 -0700
committerGitHub <noreply@github.com>2017-08-08 11:28:27 -0700
commit7590378d8a00d7c29ade23fada2ce79f4495b889 (patch)
tree2f621550b98e22430354d815e9a261671cddf50b
parent488d562052e61dde32ff0593835acc2713e9a0d1 (diff)
parent76a572a65026f277c5c42b25fcb01cce4625b10f (diff)
downloadcoreclr-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
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h3
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/lwmlist.h2
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp19
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontext.h15
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h2
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp7
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp5
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp5
-rw-r--r--src/ToolBox/superpmi/superpmi/icorjitinfo.cpp5
-rw-r--r--src/debug/daccess/nidump.cpp29
-rw-r--r--src/inc/corcompile.h1
-rw-r--r--src/inc/corinfo.h20
-rw-r--r--src/inc/fixuppointer.h177
-rw-r--r--src/jit/ICorJitInfo_API_wrapper.hpp5
-rw-r--r--src/jit/codegenlegacy.cpp78
-rw-r--r--src/jit/emitarm.cpp10
-rw-r--r--src/jit/importer.cpp6
-rw-r--r--src/jit/lower.cpp61
-rw-r--r--src/jit/lower.h6
-rw-r--r--src/jit/morph.cpp20
-rw-r--r--src/vm/array.cpp11
-rw-r--r--src/vm/ceeload.cpp80
-rw-r--r--src/vm/ceeload.h30
-rw-r--r--src/vm/class.cpp17
-rw-r--r--src/vm/dataimage.cpp6
-rw-r--r--src/vm/dataimage.h78
-rw-r--r--src/vm/debughelp.cpp2
-rw-r--r--src/vm/genericdict.cpp2
-rw-r--r--src/vm/generics.cpp11
-rw-r--r--src/vm/jithelpers.cpp8
-rw-r--r--src/vm/jitinterface.cpp19
-rw-r--r--src/vm/jitinterface.h4
-rw-r--r--src/vm/method.cpp18
-rw-r--r--src/vm/methodtable.cpp206
-rw-r--r--src/vm/methodtable.h161
-rw-r--r--src/vm/methodtable.inl76
-rw-r--r--src/vm/methodtablebuilder.cpp21
-rw-r--r--src/vm/prestub.cpp13
-rw-r--r--src/vm/proftoeeinterfaceimpl.cpp2
-rw-r--r--src/zap/zapimage.cpp1
-rw-r--r--src/zap/zapinfo.cpp7
-rw-r--r--src/zap/zapinfo.h3
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,