Partially remove relocations from Class section of NGEN-ed images (dotnet/coreclr...
authorRuben Ayrapetyan <ruben-ayrapetyan@users.noreply.github.com>
Wed, 28 Jun 2017 06:16:01 +0000 (09:16 +0300)
committerJan Kotas <jkotas@microsoft.com>
Wed, 28 Jun 2017 06:16:01 +0000 (23:16 -0700)
* Remove relocations for ParamTypeDesc::m_TemplateMT.

* Remove relocations for LayoutEEClass::m_LayoutInfo.m_pFieldMarshalers.

* Prepare RelativeFixupPointer.

* Remove relocations for FieldMarshaler::m_pFD and FieldMarshaler_*::m_*.

Commit migrated from https://github.com/dotnet/coreclr/commit/44f57065649af5f8bcbb7c71d827221a7bc1bf7a

12 files changed:
src/coreclr/src/debug/daccess/nidump.cpp
src/coreclr/src/inc/fixuppointer.h
src/coreclr/src/vm/ceeload.cpp
src/coreclr/src/vm/ceeload.h
src/coreclr/src/vm/class.cpp
src/coreclr/src/vm/class.h
src/coreclr/src/vm/fieldmarshaler.cpp
src/coreclr/src/vm/fieldmarshaler.h
src/coreclr/src/vm/methodtablebuilder.cpp
src/coreclr/src/vm/typedesc.cpp
src/coreclr/src/vm/typedesc.h
src/coreclr/src/vm/typedesc.inl

index a878c7c..cd5ba83 100644 (file)
@@ -4745,7 +4745,7 @@ void NativeImageDumper::TraverseTypeHashEntry(void *pContext, PTR_EETypeHashEntr
              * all that much harm here (bloats m_discoveredMTs though,
              * but not by a huge amount.
              */
-            PTR_MethodTable mt(ptd->m_TemplateMT.GetValue());
+            PTR_MethodTable mt(ptd->GetTemplateMethodTableInternal());
             if (isInRange(PTR_TO_TADDR(mt)))
             {
                 m_discoveredMTs.AppendEx(mt);
@@ -6201,7 +6201,7 @@ void NativeImageDumper::TypeDescToString( PTR_TypeDesc td, SString& buf )
         if( td->IsArray()  )
         {
             //td->HasTypeParam() may also be true.
-            PTR_MethodTable mt = ptd->m_TemplateMT.GetValue();
+            PTR_MethodTable mt = ptd->GetTemplateMethodTableInternal();
             _ASSERTE( PTR_TO_TADDR(mt) );
             if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(mt)) )
             {
@@ -8451,7 +8451,7 @@ NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
                                      VERBOSE_TYPES );
         DisplayWriteFieldInt( m_numCTMFields, eecli->m_numCTMFields,
                               EEClassLayoutInfo, VERBOSE_TYPES );
-        PTR_FieldMarshaler fmArray( TO_TADDR(eecli->m_pFieldMarshalers) );
+        PTR_FieldMarshaler fmArray = eecli->GetFieldMarshalers();
         DisplayWriteFieldAddress( m_pFieldMarshalers,
                                   DPtrToPreferredAddr(fmArray),
                                   eecli->m_numCTMFields
@@ -8793,7 +8793,7 @@ void NativeImageDumper::DumpTypeDesc( PTR_TypeDesc td )
     {
         PTR_ParamTypeDesc ptd(td);
         DisplayStartVStructure( "ParamTypeDesc", TYPEDESCS );
-        WriteFieldMethodTable( m_TemplateMT, ptd->m_TemplateMT.GetValue(), 
+        WriteFieldMethodTable( m_TemplateMT, ptd->GetTemplateMethodTableInternal(),
                                ParamTypeDesc, TYPEDESCS );
         WriteFieldTypeHandle( m_Arg, ptd->m_Arg, 
                               ParamTypeDesc, TYPEDESCS );
index 38ae348..83ff20e 100644 (file)
@@ -249,6 +249,15 @@ public:
     static constexpr bool isRelative = true;
     typedef PTR_TYPE type;
 
+#ifndef DACCESS_COMPILE
+    RelativeFixupPointer()
+    {
+        SetValueMaybeNull(NULL);
+    }
+#else // DACCESS_COMPILE
+    RelativeFixupPointer() =delete;
+#endif // DACCESS_COMPILE
+
     // Implicit copy/move is not allowed
     RelativeFixupPointer<PTR_TYPE>(const RelativeFixupPointer<PTR_TYPE> &) =delete;
     RelativeFixupPointer<PTR_TYPE>(RelativeFixupPointer<PTR_TYPE> &&) =delete;
@@ -273,6 +282,15 @@ public:
         return FALSE;
     }
 
+#ifndef DACCESS_COMPILE
+    FORCEINLINE BOOL IsTagged() const
+    {
+        LIMITED_METHOD_CONTRACT;
+        TADDR base = (TADDR) this;
+        return IsTagged(base);
+    }
+#endif // !DACCESS_COMPILE
+
     // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
     FORCEINLINE PTR_TYPE GetValue(TADDR base) const
     {
@@ -343,7 +361,7 @@ public:
     {
         LIMITED_METHOD_CONTRACT;
         PRECONDITION(addr != NULL);
-        m_delta = (TADDR)addr - (TADDR)this;
+        m_delta = dac_cast<TADDR>(addr) - (TADDR)this;
     }
 
     // Set encoded value of the pointer. The value can be NULL.
@@ -353,7 +371,7 @@ public:
         if (addr == NULL)
             m_delta = NULL;
         else
-            m_delta = (TADDR)addr - (TADDR)base;
+            m_delta = dac_cast<TADDR>(addr) - (TADDR)base;
     }
 
     // Set encoded value of the pointer. The value can be NULL.
@@ -373,6 +391,15 @@ public:
         return dac_cast<DPTR(PTR_TYPE)>(addr - FIXUP_POINTER_INDIRECTION);
     }
 
+#ifndef DACCESS_COMPILE
+    PTR_TYPE * GetValuePtr() const
+    {
+        LIMITED_METHOD_CONTRACT;
+        TADDR base = (TADDR) this;
+        return GetValuePtr(base);
+    }
+#endif // !DACCESS_COMPILE
+
     // Returns value of the encoded pointer. Assumes that the pointer is not NULL. 
     // Allows the value to be tagged.
     FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const
index 47810b7..49068fc 100644 (file)
@@ -10702,7 +10702,7 @@ void Module::RestoreMethodDescPointer(RelativeFixupPointer<PTR_MethodDesc> * ppM
 }
 
 /*static*/
-void Module::RestoreFieldDescPointer(FixupPointer<PTR_FieldDesc> * ppFD)
+void Module::RestoreFieldDescPointer(RelativeFixupPointer<PTR_FieldDesc> * ppFD)
 {
     CONTRACTL
     {
@@ -10712,6 +10712,9 @@ void Module::RestoreFieldDescPointer(FixupPointer<PTR_FieldDesc> * ppFD)
     }
     CONTRACTL_END;
 
+    if (!ppFD->IsTagged())
+        return;
+
     PTR_FieldDesc * ppValue = ppFD->GetValuePtr();
 
     // Ensure that the compiler won't fetch the value twice
@@ -10723,7 +10726,7 @@ void Module::RestoreFieldDescPointer(FixupPointer<PTR_FieldDesc> * ppFD)
         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
 #endif
 
-        Module * pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppValue));
+        Module * pContainingModule = ExecutionManager::FindZapModule((TADDR)ppValue);
         PREFIX_ASSUME(pContainingModule != NULL);
 
         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
index 7fa125d..0896c9b 100644 (file)
@@ -2901,8 +2901,7 @@ public:
     static void RestoreMethodDescPointer(RelativeFixupPointer<PTR_MethodDesc> * ppMD,
                                          Module *pContainingModule = NULL,
                                          ClassLoadLevel level = CLASS_LOADED);
-
-    static void RestoreFieldDescPointer(FixupPointer<PTR_FieldDesc> * ppFD);
+    static void RestoreFieldDescPointer(RelativeFixupPointer<PTR_FieldDesc> * ppFD);
 
     static void RestoreModulePointer(RelativeFixupPointer<PTR_Module> * ppModule, Module *pContainingModule);
 
index 0259b1e..6697b23 100644 (file)
@@ -2818,13 +2818,13 @@ void EEClass::Save(DataImage *image, MethodTable *pMT)
 
         if (pInfo->m_numCTMFields > 0)
         {
-            ZapStoredStructure * pNode = image->StoreStructure(pInfo->m_pFieldMarshalers,
+            ZapStoredStructure * pNode = image->StoreStructure(pInfo->GetFieldMarshalers(),
                                             pInfo->m_numCTMFields * MAXFIELDMARSHALERSIZE,
                                             DataImage::ITEM_FIELD_MARSHALERS);
 
             for (UINT iField = 0; iField < pInfo->m_numCTMFields; iField++)
             {
-                FieldMarshaler *pFM = (FieldMarshaler*)((BYTE *)pInfo->m_pFieldMarshalers + iField * MAXFIELDMARSHALERSIZE);
+                FieldMarshaler *pFM = (FieldMarshaler*)((BYTE *)pInfo->GetFieldMarshalers() + iField * MAXFIELDMARSHALERSIZE);
                 pFM->Save(image);
 
                 if (iField > 0)
@@ -3029,11 +3029,11 @@ void EEClass::Fixup(DataImage *image, MethodTable *pMT)
 
     if (HasLayout())
     {
-        image->FixupPointerField(this, offsetof(LayoutEEClass, m_LayoutInfo.m_pFieldMarshalers));
+        image->FixupRelativePointerField(this, offsetof(LayoutEEClass, m_LayoutInfo.m_pFieldMarshalers));
 
         EEClassLayoutInfo *pInfo = &((LayoutEEClass*)this)->m_LayoutInfo;
 
-        FieldMarshaler *pFM = pInfo->m_pFieldMarshalers;
+        FieldMarshaler *pFM = pInfo->GetFieldMarshalers();
         FieldMarshaler *pFMEnd = (FieldMarshaler*) ((BYTE *)pFM + pInfo->m_numCTMFields*MAXFIELDMARSHALERSIZE);
         while (pFM < pFMEnd)
         {
index d1f10d4..60cab67 100644 (file)
@@ -109,6 +109,7 @@ class LoaderAllocator;
 class ComCallWrapperTemplate;
 
 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
+typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
 
 
 //---------------------------------------------------------------------------------
@@ -439,7 +440,7 @@ class EEClassLayoutInfo
         // An array of FieldMarshaler data blocks, used to drive call-time
         // marshaling of NStruct reference parameters. The number of elements
         // equals m_numCTMFields.
-        FieldMarshaler *m_pFieldMarshalers;
+        RelativePointer<PTR_FieldMarshaler> m_pFieldMarshalers;
 
 
     public:
@@ -468,12 +469,20 @@ class EEClassLayoutInfo
             return m_numCTMFields;
         }
 
-        FieldMarshaler *GetFieldMarshalers() const
+        PTR_FieldMarshaler GetFieldMarshalers() const
         {
             LIMITED_METHOD_CONTRACT;
-            return m_pFieldMarshalers;
+            return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
         }
 
+#ifndef DACCESS_COMPILE
+        void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
+        {
+            LIMITED_METHOD_CONTRACT;
+            m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
+        }
+#endif // DACCESS_COMPILE
+
         BOOL IsBlittable() const
         {
             LIMITED_METHOD_CONTRACT;
index 0de71b5..9415b94 100644 (file)
@@ -1318,7 +1318,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
     }
 
     pEEClassLayoutInfoOut->m_numCTMFields        = fHasNonTrivialParent ? pParentMT->GetLayoutInfo()->m_numCTMFields : 0;
-    pEEClassLayoutInfoOut->m_pFieldMarshalers    = NULL;
+    pEEClassLayoutInfoOut->SetFieldMarshalers(NULL);
     pEEClassLayoutInfoOut->SetIsBlittable(TRUE);
     if (fHasNonTrivialParent)
         pEEClassLayoutInfoOut->SetIsBlittable(pParentMT->IsBlittable());
@@ -1599,7 +1599,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
 
     if (pEEClassLayoutInfoOut->m_numCTMFields)
     {
-        pEEClassLayoutInfoOut->m_pFieldMarshalers = (FieldMarshaler*)(pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(MAXFIELDMARSHALERSIZE) * S_SIZE_T(pEEClassLayoutInfoOut->m_numCTMFields))));
+        pEEClassLayoutInfoOut->SetFieldMarshalers((FieldMarshaler*)(pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(MAXFIELDMARSHALERSIZE) * S_SIZE_T(pEEClassLayoutInfoOut->m_numCTMFields)))));
 
         // Bring in the parent's fieldmarshalers
         if (fHasNonTrivialParent)
@@ -1608,8 +1608,8 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
             PREFAST_ASSUME(pParentLayoutInfo != NULL);  // See if (fParentHasLayout) branch above
             
             UINT numChildCTMFields = pEEClassLayoutInfoOut->m_numCTMFields - pParentLayoutInfo->m_numCTMFields;
-            memcpyNoGCRefs( ((BYTE*)pEEClassLayoutInfoOut->m_pFieldMarshalers) + MAXFIELDMARSHALERSIZE*numChildCTMFields,
-                            pParentLayoutInfo->m_pFieldMarshalers,
+            memcpyNoGCRefs( ((BYTE*)pEEClassLayoutInfoOut->GetFieldMarshalers()) + MAXFIELDMARSHALERSIZE*numChildCTMFields,
+                            pParentLayoutInfo->GetFieldMarshalers(),
                             MAXFIELDMARSHALERSIZE * (pParentLayoutInfo->m_numCTMFields) );
         }
 
@@ -3726,7 +3726,7 @@ VOID FieldMarshaler_SafeArray::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNa
     pSafeArray = (LPSAFEARRAY*)pNativeValue;
 
     VARTYPE vt = m_vt;
-    MethodTable* pMT = m_pMT.GetValue();
+    MethodTable* pMT = m_pMT.GetValueMaybeNull();
 
     GCPROTECT_BEGIN(pArray)
     {
@@ -3771,7 +3771,7 @@ VOID FieldMarshaler_SafeArray::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF
     }
 
     VARTYPE vt = m_vt;
-    MethodTable* pMT = m_pMT.GetValue();
+    MethodTable* pMT = m_pMT.GetValueMaybeNull();
 
     // If we have an empty vartype, get it from the safearray vartype
     if (vt == VT_EMPTY)
@@ -4868,3 +4868,10 @@ IMPLEMENT_FieldMarshaler_METHOD(void, Restore,
     (),
     ,
     ())
+
+#ifndef DACCESS_COMPILE
+IMPLEMENT_FieldMarshaler_METHOD(VOID, CopyTo,
+    (VOID *pDest, SIZE_T destSize) const,
+    ,
+    (pDest, destSize))
+#endif // !DACCESS_COMPILE
index 287da41..f11c81b 100644 (file)
@@ -253,6 +253,28 @@ VOID FmtValueTypeUpdateCLR(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE
     }                                                   \
     ELEMENT_SIZE_IMPL(NativeSize, AlignmentReq)
 
+#define COPY_TO_IMPL_BASE_STRUCT_ONLY() \
+    VOID CopyToImpl(VOID *pDest, SIZE_T destSize) \
+    { \
+        static_assert(sizeof(*this) == sizeof(FieldMarshaler), \
+                      "Please, implement CopyToImpl for correct copy of field values"); \
+        \
+        FieldMarshaler::CopyToImpl(pDest, destSize); \
+    }
+
+#define START_COPY_TO_IMPL(CLASS_NAME) \
+    VOID CopyToImpl(VOID *pDest, SIZE_T destSize) const \
+    { \
+        FieldMarshaler::CopyToImpl(pDest, destSize); \
+    \
+        CLASS_NAME *pDestFieldMarshaller = (std::remove_const<std::remove_pointer<decltype(this)>::type>::type *) pDest; \
+        _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize); \
+
+#define END_COPY_TO_IMPL(CLASS_NAME) \
+        static_assert(std::is_same<CLASS_NAME *, decltype(pDestFieldMarshaller)>::value, \
+                      "Structure's name is required"); \
+    }
+
 
 //=======================================================================
 //
@@ -278,6 +300,7 @@ public:
     VOID ScalarUpdateCLR(const VOID *pNative, LPVOID pCLR) const;
     VOID NestedValueClassUpdateNative(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const;
     VOID NestedValueClassUpdateCLR(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const;
+    VOID CopyTo(VOID *pDest, SIZE_T destSize) const;
 #ifdef FEATURE_PREJIT
     void Save(DataImage *image);
     void Fixup(DataImage *image);
@@ -351,10 +374,21 @@ public:
 #endif // FEATURE_PREJIT
     }
 
+    void CopyToImpl(VOID *pDest, SIZE_T destSize) const
+    {
+        FieldMarshaler *pDestFieldMarshaller = (FieldMarshaler *) pDest;
+
+        _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize);
+
+        pDestFieldMarshaller->SetFieldDesc(GetFieldDesc());
+        pDestFieldMarshaller->SetExternalOffset(GetExternalOffset());
+        pDestFieldMarshaller->SetNStructFieldType(GetNStructFieldType());
+    }
+
     void SetFieldDesc(FieldDesc* pFD)
     {
         LIMITED_METHOD_CONTRACT;
-        m_pFD.SetValue(pFD);
+        m_pFD.SetValueMaybeNull(pFD);
     }
 
     FieldDesc* GetFieldDesc() const
@@ -369,7 +403,7 @@ public:
         }
         CONTRACT_END;
 
-        RETURN m_pFD.GetValue();
+        RETURN m_pFD.GetValueMaybeNull();
     }
 
     void SetExternalOffset(UINT32 dwExternalOffset)
@@ -394,7 +428,7 @@ protected:
 #endif
     }
 
-    static inline void RestoreHelper(FixupPointer<PTR_MethodTable> *ppMT)
+    static inline void RestoreHelper(RelativeFixupPointer<PTR_MethodTable> *ppMT)
     {
         CONTRACTL
         {
@@ -414,7 +448,7 @@ protected:
     }
 
 #ifdef _DEBUG
-    static inline BOOL IsRestoredHelper(FixupPointer<PTR_MethodTable> pMT)
+    static inline BOOL IsRestoredHelper(const RelativeFixupPointer<PTR_MethodTable> &pMT)
     {
         WRAPPER_NO_CONTRACT;
 
@@ -428,7 +462,7 @@ protected:
 #endif // _DEBUG
 
 
-    FixupPointer<PTR_FieldDesc> m_pFD;      // FieldDesc
+    RelativeFixupPointer<PTR_FieldDesc> m_pFD;      // FieldDesc
     UINT32           m_dwExternalOffset;    // offset of field in the fixed portion
     NStructFieldType m_nft;
 };
@@ -449,6 +483,7 @@ public:
     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
 
     ELEMENT_SIZE_IMPL(sizeof(BSTR), sizeof(BSTR))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 //=======================================================================
@@ -462,6 +497,7 @@ public:
     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
 
     ELEMENT_SIZE_IMPL(sizeof(HSTRING), sizeof(HSTRING))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 //=======================================================================
@@ -473,7 +509,7 @@ public:
 
     FieldMarshaler_Nullable(MethodTable* pMT)
     {
-        m_pNullableTypeMT.SetValue(pMT);
+        m_pNullableTypeMT.SetValueMaybeNull(pMT);
     }
 
     BOOL IsNullableMarshalerImpl() const
@@ -526,6 +562,12 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_Nullable)
+    {
+        pDestFieldMarshaller->m_pNullableTypeMT.SetValueMaybeNull(GetMethodTable());
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_Nullable)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -550,7 +592,7 @@ public:
     }
 
 private:
-    FixupPointer<PTR_MethodTable> m_pNullableTypeMT;
+    RelativeFixupPointer<PTR_MethodTable> m_pNullableTypeMT;
 };
 
 
@@ -565,6 +607,7 @@ public:
     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
     
     ELEMENT_SIZE_IMPL(sizeof(HSTRING), sizeof(HSTRING))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 //=======================================================================
@@ -578,6 +621,7 @@ public:
     VOID UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const;
     
     ELEMENT_SIZE_IMPL(sizeof(HRESULT), sizeof(HRESULT))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 #endif // FEATURE_COMINTEROP
@@ -593,7 +637,7 @@ public:
     FieldMarshaler_NestedLayoutClass(MethodTable *pMT)
     {
         WRAPPER_NO_CONTRACT;
-        m_pNestedMethodTable.SetValue(pMT);
+        m_pNestedMethodTable.SetValueMaybeNull(pMT);
     }
 
     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
@@ -629,6 +673,12 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_NestedLayoutClass)
+    {
+        pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(GetMethodTable());
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_NestedLayoutClass)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -649,12 +699,12 @@ public:
         }
         CONTRACTL_END;
 
-        return m_pNestedMethodTable.GetValue();
+        return m_pNestedMethodTable.GetValueMaybeNull();
     }
 
 private:
     // MethodTable of nested FieldMarshaler.
-    FixupPointer<PTR_MethodTable> m_pNestedMethodTable;
+    RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
 };
 
 
@@ -667,7 +717,7 @@ public:
     FieldMarshaler_NestedValueClass(MethodTable *pMT)
     {
         WRAPPER_NO_CONTRACT;
-        m_pNestedMethodTable.SetValue(pMT);
+        m_pNestedMethodTable.SetValueMaybeNull(pMT);
     }
 
     BOOL IsNestedValueClassMarshalerImpl() const
@@ -712,6 +762,12 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_NestedValueClass)
+    {
+        pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(GetMethodTable());
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_NestedValueClass)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -738,13 +794,13 @@ public:
         }
         CONTRACTL_END;
 
-        return m_pNestedMethodTable.GetValue();
+        return m_pNestedMethodTable.GetValueMaybeNull();
     }
 
 
 private:
     // MethodTable of nested NStruct.
-    FixupPointer<PTR_MethodTable> m_pNestedMethodTable;
+    RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
 };
 
 
@@ -760,6 +816,7 @@ public:
     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
 
     ELEMENT_SIZE_IMPL(sizeof(LPWSTR), sizeof(LPWSTR))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 //=======================================================================
@@ -774,6 +831,7 @@ public:
        VOID DestroyNativeImpl(LPVOID pNativeValue) const;
 
        ELEMENT_SIZE_IMPL(sizeof(LPSTR), sizeof(LPSTR))
+        COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 //=======================================================================
@@ -806,6 +864,13 @@ public:
         return m_ThrowOnUnmappableChar;
     }
     
+    START_COPY_TO_IMPL(FieldMarshaler_StringAnsi)
+    {
+        pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
+        pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_StringAnsi)
+
 private:
     bool m_BestFitMap:1;
     bool m_ThrowOnUnmappableChar:1;
@@ -829,6 +894,12 @@ public:
         m_numchar = numChar;
     }
     
+    START_COPY_TO_IMPL(FieldMarshaler_FixedStringUni)
+    {
+        pDestFieldMarshaller->m_numchar = m_numchar;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_FixedStringUni)
+
 private:
     // # of characters for fixed strings
     UINT32           m_numchar;
@@ -864,6 +935,14 @@ public:
         return m_ThrowOnUnmappableChar;
     }
     
+    START_COPY_TO_IMPL(FieldMarshaler_FixedStringAnsi)
+    {
+        pDestFieldMarshaller->m_numchar = m_numchar;
+        pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
+        pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_FixedStringAnsi)
+
 private:
     // # of characters for fixed strings
     UINT32           m_numchar;
@@ -901,6 +980,14 @@ public:
         return m_ThrowOnUnmappableChar;
     }
     
+    START_COPY_TO_IMPL(FieldMarshaler_FixedCharArrayAnsi)
+    {
+        pDestFieldMarshaller->m_numElems = m_numElems;
+        pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
+        pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_FixedCharArrayAnsi)
+
 private:
     // # of elements for fixedchararray
     UINT32           m_numElems;
@@ -980,6 +1067,16 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_FixedArray)
+    {
+        pDestFieldMarshaller->m_arrayType.SetValueMaybeNull(m_arrayType.GetValueMaybeNull());
+        pDestFieldMarshaller->m_numElems = m_numElems;
+        pDestFieldMarshaller->m_vt = m_vt;
+        pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
+        pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_FixedArray)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -994,7 +1091,7 @@ public:
 #endif
    
 private:
-    FixupPointer<TypeHandle> m_arrayType;
+    RelativeFixupPointer<TypeHandle> m_arrayType;
     UINT32           m_numElems;
     VARTYPE          m_vt;
     bool             m_BestFitMap:1; // Note: deliberately use small bools to save on working set - this is the largest FieldMarshaler and dominates the cost of the FieldMarshaler array
@@ -1020,7 +1117,7 @@ public:
     {
         WRAPPER_NO_CONTRACT;
         m_vt = vt;
-        m_pMT.SetValue(pMT);
+        m_pMT.SetValueMaybeNull(pMT);
     }
 
 #ifdef FEATURE_PREJIT
@@ -1049,6 +1146,13 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_SafeArray)
+    {
+        pDestFieldMarshaller->m_pMT.SetValueMaybeNull(m_pMT.GetValueMaybeNull());
+        pDestFieldMarshaller->m_vt = m_vt;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_SafeArray)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -1079,7 +1183,7 @@ public:
     }
 
 private:
-    FixupPointer<PTR_MethodTable> m_pMT;
+    RelativeFixupPointer<PTR_MethodTable> m_pMT;
     VARTYPE          m_vt;
 };
 #endif //FEATURE_CLASSIC_COMINTEROP
@@ -1094,7 +1198,7 @@ public:
     FieldMarshaler_Delegate(MethodTable* pMT)
     {
         WRAPPER_NO_CONTRACT;
-        m_pNestedMethodTable.SetValue(pMT);
+        m_pNestedMethodTable.SetValueMaybeNull(pMT);
     }
 
     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
@@ -1128,6 +1232,12 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_Delegate)
+    {
+        pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(m_pNestedMethodTable.GetValueMaybeNull());
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_Delegate)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -1148,10 +1258,10 @@ public:
         }
         CONTRACTL_END;
 
-        return m_pNestedMethodTable.GetValue();
+        return m_pNestedMethodTable.GetValueMaybeNull();
     }
 
-    FixupPointer<PTR_MethodTable> m_pNestedMethodTable;
+    RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
 };
 
 
@@ -1168,6 +1278,7 @@ public:
     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
 
     ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 
@@ -1184,6 +1295,7 @@ public:
     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
 
     ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 #ifdef FEATURE_COMINTEROP
@@ -1204,8 +1316,8 @@ public:
     FieldMarshaler_Interface(MethodTable *pClassMT, MethodTable *pItfMT, DWORD dwFlags)
     {
         WRAPPER_NO_CONTRACT;
-        m_pClassMT.SetValue(pClassMT);
-        m_pItfMT.SetValue(pItfMT);
+        m_pClassMT.SetValueMaybeNull(pClassMT);
+        m_pItfMT.SetValueMaybeNull(pItfMT);
         m_dwFlags = dwFlags;
     }
 
@@ -1237,6 +1349,14 @@ public:
         FieldMarshaler::RestoreImpl();
     }
 
+    START_COPY_TO_IMPL(FieldMarshaler_Interface)
+    {
+        pDestFieldMarshaller->m_pClassMT.SetValueMaybeNull(m_pClassMT.GetValueMaybeNull());
+        pDestFieldMarshaller->m_pItfMT.SetValueMaybeNull(m_pItfMT.GetValueMaybeNull());
+        pDestFieldMarshaller->m_dwFlags = m_dwFlags;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_Interface)
+
 #ifdef _DEBUG
     BOOL IsRestored() const
     {
@@ -1275,7 +1395,7 @@ public:
         }
         CONTRACTL_END;
 
-        return m_pClassMT.GetValue();
+        return m_pClassMT.GetValueMaybeNull();
     }
 
     MethodTable *GetInterfaceMethodTable() const
@@ -1289,12 +1409,12 @@ public:
         }
         CONTRACTL_END;
 
-        return m_pItfMT.GetValue();
+        return m_pItfMT.GetValueMaybeNull();
     }
 
 private:
-    FixupPointer<PTR_MethodTable> m_pClassMT;
-    FixupPointer<PTR_MethodTable> m_pItfMT;
+    RelativeFixupPointer<PTR_MethodTable> m_pClassMT;
+    RelativeFixupPointer<PTR_MethodTable> m_pItfMT;
     DWORD           m_dwFlags;
 };
 
@@ -1328,6 +1448,7 @@ public:
     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
 
     ELEMENT_SIZE_IMPL(sizeof(VARIANT), 8)
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 };
 
 #endif // FEATURE_COMINTEROP
@@ -1352,7 +1473,13 @@ public:
     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
 
     SCALAR_MARSHALER_IMPL(1, 1)
-    
+
+    START_COPY_TO_IMPL(FieldMarshaler_Illegal)
+    {
+        pDestFieldMarshaller->m_resIDWhy = m_resIDWhy;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_Illegal)
+
 private:
     UINT m_resIDWhy;
 };
@@ -1369,6 +1496,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(1, 1)
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1413,6 +1541,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(2, 2)
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1456,6 +1585,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(4, 4)
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1499,6 +1629,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(8, 8)
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1599,6 +1730,13 @@ public:
         return m_ThrowOnUnmappableChar;
     }
     
+    START_COPY_TO_IMPL(FieldMarshaler_Ansi)
+    {
+        pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
+        pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
+    }
+    END_COPY_TO_IMPL(FieldMarshaler_Ansi)
+
 private:
     bool             m_BestFitMap:1;
     bool             m_ThrowOnUnmappableChar:1;
@@ -1614,6 +1752,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(sizeof(BOOL), sizeof(BOOL))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1661,6 +1800,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(sizeof(VARIANT_BOOL), sizeof(VARIANT_BOOL))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1711,6 +1851,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(1, 1)
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1752,6 +1893,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(sizeof(DECIMAL), 8);
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
     {
@@ -1793,6 +1935,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(sizeof(DATE), sizeof(DATE))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
@@ -1811,6 +1954,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(sizeof(CURRENCY), sizeof(CURRENCY))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
@@ -1825,6 +1969,7 @@ public:
     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
 
     SCALAR_MARSHALER_IMPL(sizeof(INT64), sizeof(INT64))
+    COPY_TO_IMPL_BASE_STRUCT_ONLY()
 
     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
index f5a256a..bd9dd24 100644 (file)
@@ -4142,11 +4142,11 @@ VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
             {
                 if (pwalk->m_MD == bmtMetaData->pFields[i])
                 {
-
                     pLayoutFieldInfo = pwalk;
-                    CopyMemory(pNextFieldMarshaler,
-                               &(pwalk->m_FieldMarshaler),
-                               MAXFIELDMARSHALERSIZE);
+
+                    const FieldMarshaler *pSrcFieldMarshaler = (const FieldMarshaler *) &pwalk->m_FieldMarshaler;
+
+                    pSrcFieldMarshaler->CopyTo(pNextFieldMarshaler, MAXFIELDMARSHALERSIZE);
 
                     pNextFieldMarshaler->SetFieldDesc(pFD);
                     pNextFieldMarshaler->SetExternalOffset(pwalk->m_offset);
index 6718068..7da1c84 100644 (file)
@@ -40,7 +40,7 @@ BOOL ParamTypeDesc::Verify() {
     STATIC_CONTRACT_DEBUG_ONLY;
     STATIC_CONTRACT_SUPPORTS_DAC;
 
-    _ASSERTE(m_TemplateMT.IsNull() || m_TemplateMT.GetValue()->SanityCheck());
+    _ASSERTE(m_TemplateMT.IsNull() || GetTemplateMethodTableInternal()->SanityCheck());
     _ASSERTE(!GetTypeParam().IsNull());
     BAD_FORMAT_NOTHROW_ASSERT(GetTypeParam().IsTypeDesc() || !GetTypeParam().AsMethodTable()->IsArray());
     BAD_FORMAT_NOTHROW_ASSERT(CorTypeInfo::IsModifier_NoThrow(GetInternalCorElementType()) ||
@@ -59,7 +59,7 @@ BOOL ArrayTypeDesc::Verify() {
     STATIC_CONTRACT_SUPPORTS_DAC;
 
     // m_TemplateMT == 0 may be null when building types involving TypeVarTypeDesc's
-    BAD_FORMAT_NOTHROW_ASSERT(m_TemplateMT.IsNull() || m_TemplateMT.GetValue()->IsArray());
+    BAD_FORMAT_NOTHROW_ASSERT(m_TemplateMT.IsNull() || GetTemplateMethodTable()->IsArray());
     BAD_FORMAT_NOTHROW_ASSERT(CorTypeInfo::IsArray_NoThrow(GetInternalCorElementType()));
     ParamTypeDesc::Verify();
     return(true);
@@ -844,7 +844,7 @@ OBJECTREF ParamTypeDesc::GetManagedClassObject()
         if (OwnsTemplateMethodTable())
         {
             // Set the handle on template methodtable as well to make Object.GetType for arrays take the fast path
-            EnsureWritablePages(m_TemplateMT.GetValue()->GetWriteableDataForWrite())->m_hExposedClassObject = m_hExposedClassObject;
+            EnsureWritablePages(GetTemplateMethodTableInternal()->GetWriteableDataForWrite())->m_hExposedClassObject = m_hExposedClassObject;
         }
 
         // Log the TypeVarTypeDesc access
@@ -1011,7 +1011,7 @@ void TypeDesc::DoFullyLoad(Generics::RecursionGraph *pVisited, ClassLoadLevel le
         // Fully load the template method table
         if (!pPTD->m_TemplateMT.IsNull())
         {
-            pPTD->m_TemplateMT.GetValue()->DoFullyLoad(&newVisited, level, pPending, &fBailed, pInstContext);
+            pPTD->GetTemplateMethodTableInternal()->DoFullyLoad(&newVisited, level, pPending, &fBailed, pInstContext);
         }
     }
 
@@ -1189,8 +1189,8 @@ void ParamTypeDesc::Save(DataImage *image)
     if (OwnsTemplateMethodTable())
     {
         // This TypeDesc should be the only one saving this MT
-        _ASSERTE(!image->IsStored(m_TemplateMT.GetValue()));
-        Module::SaveMethodTable(image, m_TemplateMT.GetValue(), 0);
+        _ASSERTE(!image->IsStored(GetTemplateMethodTableInternal()));
+        Module::SaveMethodTable(image, GetTemplateMethodTableInternal(), 0);
     }
 
 }
@@ -1219,8 +1219,8 @@ void ParamTypeDesc::Fixup(DataImage *image)
             // TypeDesc and the MT are "tightly-knit") In other words if one is present in
             // an NGEN image then then other will be, and if one is "used" at runtime then
             // the other will be too.
-            image->FixupPointerField(this, offsetof(ParamTypeDesc, m_TemplateMT));
-            m_TemplateMT.GetValue()->Fixup(image);
+            image->FixupMethodTablePointer(this, &m_TemplateMT);
+            GetTemplateMethodTableInternal()->Fixup(image);
         }
         else
         {
@@ -1275,14 +1275,14 @@ BOOL ParamTypeDesc::ComputeNeedsRestore(DataImage *image, TypeHandleList *pVisit
     { 
         if (OwnsTemplateMethodTable())
         {
-            if (m_TemplateMT.GetValue()->ComputeNeedsRestore(image, pVisited))
+            if (GetTemplateMethodTableInternal()->ComputeNeedsRestore(image, pVisited))
             {
                 res = TRUE;
             }
         }
         else
         {
-            if (!image->CanPrerestoreEagerBindToMethodTable(m_TemplateMT.GetValue(), pVisited))
+            if (!image->CanPrerestoreEagerBindToMethodTable(GetTemplateMethodTableInternal(), pVisited))
             {
                 res = TRUE;
             }
@@ -2419,7 +2419,7 @@ ParamTypeDesc::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
     SUPPORTS_DAC;
     DAC_ENUM_DTHIS();
 
-    PTR_MethodTable pTemplateMT = m_TemplateMT.GetValue();
+    PTR_MethodTable pTemplateMT = GetTemplateMethodTableInternal();
     if (pTemplateMT.IsValid())
     {
         pTemplateMT->EnumMemoryRegions(flags);
index a8b1c25..3e8b0e6 100644 (file)
@@ -254,7 +254,7 @@ public:
 
         LIMITED_METHOD_CONTRACT;
 
-        m_TemplateMT.SetValue(pMT);
+        m_TemplateMT.SetValueMaybeNull(pMT);
 
         // ParamTypeDescs start out life not fully loaded
         m_typeAndFlags |= TypeDesc::enum_flag_IsNotFullyLoaded;
@@ -323,8 +323,13 @@ public:
     friend class ArrayOpLinker;
 #endif
 protected:
+    PTR_MethodTable GetTemplateMethodTableInternal() {
+        WRAPPER_NO_CONTRACT;
+        return ReadPointerMaybeNull(this, &ParamTypeDesc::m_TemplateMT);
+    }
+
     // the m_typeAndFlags field in TypeDesc tell what kind of parameterized type we have
-    FixupPointer<PTR_MethodTable> m_TemplateMT; // The shared method table, some variants do not use this field (it is null)
+    RelativeFixupPointer<PTR_MethodTable> m_TemplateMT; // The shared method table, some variants do not use this field (it is null)
     TypeHandle      m_Arg;              // The type that is being modified
     LOADERHANDLE    m_hExposedClassObject;  // handle back to the internal reflection Type object
 };
@@ -380,8 +385,8 @@ public:
         WRAPPER_NO_CONTRACT;
 
         _ASSERTE(!m_TemplateMT.IsNull());
-        _ASSERTE(m_TemplateMT.GetValue()->IsArray());
-        _ASSERTE(m_TemplateMT.GetValue()->ParentEquals(g_pArrayClass));
+        _ASSERTE(GetTemplateMethodTableInternal()->IsArray());
+        _ASSERTE(GetTemplateMethodTableInternal()->ParentEquals(g_pArrayClass));
 
         return g_pArrayClass;
     }
@@ -416,16 +421,16 @@ public:
     void Fixup(DataImage *image);
 #endif
 
-    MethodTable * GetTemplateMethodTable() {
+    PTR_MethodTable GetTemplateMethodTable() {
         WRAPPER_NO_CONTRACT;
-        MethodTable * pTemplateMT = m_TemplateMT.GetValue();
-        _ASSERTE(pTemplateMT->IsArray());
-        return pTemplateMT;
+        PTR_MethodTable ptrTemplateMT = GetTemplateMethodTableInternal();
+        _ASSERTE(ptrTemplateMT->IsArray());
+        return ptrTemplateMT;
     }
 
     TADDR GetTemplateMethodTableMaybeTagged() {
         WRAPPER_NO_CONTRACT;
-        return m_TemplateMT.GetValueMaybeTagged();
+        return m_TemplateMT.GetValueMaybeTagged(dac_cast<TADDR>(this) + offsetof(ArrayTypeDesc, m_TemplateMT));
     }
 
 #ifdef FEATURE_COMINTEROP
index 4d7416e..312270e 100644 (file)
@@ -31,7 +31,7 @@ inline PTR_MethodTable  TypeDesc::GetMethodTable() {
     if (GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE)
         return dac_cast<PTR_MethodTable>(asParam->m_Arg.AsMethodTable());
     else
-        return(asParam->m_TemplateMT.GetValue());
+        return(asParam->GetTemplateMethodTableInternal());
 }
 
 inline TypeHandle TypeDesc::GetTypeParam() {