summaryrefslogtreecommitdiff
path: root/packaging/0019-Remove-relocations-from-SECTION_Readonly-for-fields-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/0019-Remove-relocations-from-SECTION_Readonly-for-fields-.patch')
-rw-r--r--packaging/0019-Remove-relocations-from-SECTION_Readonly-for-fields-.patch903
1 files changed, 903 insertions, 0 deletions
diff --git a/packaging/0019-Remove-relocations-from-SECTION_Readonly-for-fields-.patch b/packaging/0019-Remove-relocations-from-SECTION_Readonly-for-fields-.patch
new file mode 100644
index 0000000..2b4e53c
--- /dev/null
+++ b/packaging/0019-Remove-relocations-from-SECTION_Readonly-for-fields-.patch
@@ -0,0 +1,903 @@
+From 9440822ceb7b6e58b840cfa4f4118e6410375df5 Mon Sep 17 00:00:00 2001
+From: Gleb Balykov <g.balykov@samsung.com>
+Date: Wed, 21 Jun 2017 19:48:49 +0300
+Subject: [PATCH 19/32] Remove relocations from SECTION_Readonly for fields not
+ accessed from jit code on ARM
+
+---
+ src/debug/daccess/nidump.cpp | 6 ++--
+ src/inc/fixuppointer.h | 28 +++++++++++++---
+ src/vm/ceeload.cpp | 31 ++++++++++--------
+ src/vm/ceeload.h | 26 ++++++++++-----
+ src/vm/dataimage.h | 78 ++++++++++++++++++++++++++++++++++++++++++++
+ src/vm/methodtable.cpp | 54 +++++++++++++++++-------------
+ src/vm/methodtable.h | 25 +++++++++-----
+ src/vm/methodtable.inl | 58 +++++++++++++++++---------------
+ 8 files changed, 218 insertions(+), 88 deletions(-)
+
+diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp
+index 2ec5d9a..673aa39 100644
+--- a/src/debug/daccess/nidump.cpp
++++ b/src/debug/daccess/nidump.cpp
+@@ -3959,7 +3959,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
+@@ -7301,7 +7301,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 )
+@@ -7335,7 +7335,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/fixuppointer.h b/src/inc/fixuppointer.h
+index 83ff20e..20eb9d8 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
+@@ -264,6 +270,9 @@ public:
+ RelativeFixupPointer<PTR_TYPE>& operator = (const RelativeFixupPointer<PTR_TYPE> &) =delete;
+ RelativeFixupPointer<PTR_TYPE>& operator = (RelativeFixupPointer<PTR_TYPE> &&) =delete;
+
++ // Default constructor
++ RelativeFixupPointer<PTR_TYPE>() {}
++
+ // Returns whether the encoded pointer is NULL.
+ BOOL IsNull() const
+ {
+@@ -468,7 +477,6 @@ public:
+ PTR_TYPE GetValue(TADDR base) const
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+- PRECONDITION(!IsNull());
+ return dac_cast<PTR_TYPE>(m_ptr);
+ }
+
+@@ -480,6 +488,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 +508,7 @@ public:
+ return dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
+ }
+
++#ifndef DACCESS_COMPILE
+ void SetValue(PTR_TYPE addr)
+ {
+ LIMITED_METHOD_CONTRACT;
+@@ -503,7 +519,6 @@ public:
+ void SetValue(TADDR base, PTR_TYPE addr)
+ {
+ LIMITED_METHOD_CONTRACT;
+- PRECONDITION(addr != NULL);
+ m_ptr = dac_cast<TADDR>(addr);
+ }
+
+@@ -521,7 +536,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 +543,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 +551,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/vm/ceeload.cpp b/src/vm/ceeload.cpp
+index cd40ad7..3a85a52 100644
+--- a/src/vm/ceeload.cpp
++++ b/src/vm/ceeload.cpp
+@@ -2892,7 +2892,7 @@ BOOL Module::IsPreV4Assembly()
+ }
+
+
+-ArrayDPTR(FixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index)
++ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+@@ -8282,6 +8282,8 @@ void Module::SaveTypeHandle(DataImage * image,
+ #endif // _DEBUG
+ }
+
++#ifndef DACCESS_COMPILE
++
+ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData)
+ {
+ STANDARD_VM_CONTRACT;
+@@ -8303,7 +8305,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();
+@@ -8317,8 +8319,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++;
+ }
+@@ -8343,11 +8345,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.
+@@ -8410,7 +8412,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;
+@@ -8426,7 +8428,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();
+@@ -8456,7 +8458,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++;
+ }
+@@ -8479,7 +8481,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)
+@@ -8496,7 +8498,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
+@@ -8507,7 +8509,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
+@@ -8516,6 +8518,7 @@ void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData)
+ }
+ }
+
++#endif // !DACCESS_COMPILE
+
+ bool Module::AreAllClassesFullyLoaded()
+ {
+@@ -9658,7 +9661,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
+@@ -14064,7 +14067,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 fa61089..e82f279 100644
+--- a/src/vm/ceeload.h
++++ b/src/vm/ceeload.h
+@@ -620,7 +620,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
+
+@@ -629,8 +629,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;
+@@ -666,7 +666,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
+
+@@ -677,11 +683,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;
+@@ -702,6 +708,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)
+@@ -717,10 +724,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
+ };
+diff --git a/src/vm/dataimage.h b/src/vm/dataimage.h
+index 5d48a71..0167ec5 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/methodtable.cpp b/src/vm/methodtable.cpp
+index 598759a..e219bb7 100644
+--- a/src/vm/methodtable.cpp
++++ b/src/vm/methodtable.cpp
+@@ -1014,7 +1014,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);
+ }
+
+ //==========================================================================================
+@@ -1247,7 +1247,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
+@@ -1288,7 +1289,7 @@ void MethodTable::SetupGenericsStaticsInfo(FieldDesc* pStaticFieldDescs)
+ pInfo->m_DynamicTypeID = (SIZE_T)-1;
+ }
+
+- pInfo->m_pFieldDescs = pStaticFieldDescs;
++ pInfo->m_pFieldDescs.SetValueMaybeNull(pStaticFieldDescs);
+ }
+
+ #endif // !DACCESS_COMPILE
+@@ -3148,7 +3149,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;
+@@ -4123,7 +4124,7 @@ void ModuleCtorInfo::AddElement(MethodTable *pMethodTable)
+ {
+ _ASSERTE(numElements == numLastAllocated);
+
+- MethodTable ** ppOldMTEntries = ppMT;
++ RelativePointer<MethodTable *> *ppOldMTEntries = ppMT;
+
+ #ifdef _PREFAST_
+ #pragma warning(push)
+@@ -4134,12 +4135,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;
+
+@@ -4151,7 +4159,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++;
+ }
+
+@@ -4691,7 +4699,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
+ {
+@@ -4706,7 +4714,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
+ {
+@@ -4724,11 +4732,11 @@ 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));
+@@ -4797,7 +4805,7 @@ void MethodTable::Fixup(DataImage *image)
+
+ if (HasInterfaceMap())
+ {
+- image->FixupPointerField(this, offsetof(MethodTable, m_pMultipurposeSlot2));
++ image->FixupPlainOrRelativePointerField(this, &MethodTable::m_pInterfaceMap);
+
+ FixupExtraInterfaceInfo(image);
+ }
+@@ -5033,7 +5041,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++)
+@@ -5950,9 +5958,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);
+ }
+
+@@ -7593,7 +7601,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 +7741,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 +7752,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 +7767,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);
+ }
+diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h
+index 93a9ae2..f8b34ae 100644
+--- a/src/vm/methodtable.h
++++ b/src/vm/methodtable.h
+@@ -248,7 +248,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;
+@@ -2210,12 +2210,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
+
+@@ -2640,7 +2640,7 @@ public:
+ {
+ WRAPPER_NO_CONTRACT;
+ _ASSERTE(HasGenericsStaticsInfo());
+- return GetGenericsStaticsInfo()->m_pFieldDescs;
++ return ReadPointerMaybeNull((GenericsStaticsInfo *)GetGenericsStaticsInfo(), &GenericsStaticsInfo::m_pFieldDescs);
+ }
+
+ BOOL HasCrossModuleGenericStaticsInfo()
+@@ -4059,7 +4059,7 @@ private:
+ // for enum_flag_HasIndirectParentMethodTable.
+ TADDR 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;
+
+@@ -4073,8 +4073,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)
+@@ -4103,7 +4108,11 @@ private:
+ 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 9b72d24..eb1abb0 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)
+@@ -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
+@@ -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);
+ }
+
+ //==========================================================================================
+--
+2.7.4
+