From 44f57065649af5f8bcbb7c71d827221a7bc1bf7a Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 28 Jun 2017 09:16:01 +0300 Subject: [PATCH] Partially remove relocations from Class section of NGEN-ed images (#11962) * 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_*. --- src/debug/daccess/nidump.cpp | 8 +- src/inc/fixuppointer.h | 31 ++++++- src/vm/ceeload.cpp | 7 +- src/vm/ceeload.h | 3 +- src/vm/class.cpp | 8 +- src/vm/class.h | 15 +++- src/vm/fieldmarshaler.cpp | 19 ++-- src/vm/fieldmarshaler.h | 197 ++++++++++++++++++++++++++++++++++++------ src/vm/methodtablebuilder.cpp | 8 +- src/vm/typedesc.cpp | 22 ++--- src/vm/typedesc.h | 23 +++-- src/vm/typedesc.inl | 2 +- 12 files changed, 269 insertions(+), 74 deletions(-) diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index a878c7c..cd5ba83 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -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 ); diff --git a/src/inc/fixuppointer.h b/src/inc/fixuppointer.h index 38ae348..83ff20e 100644 --- a/src/inc/fixuppointer.h +++ b/src/inc/fixuppointer.h @@ -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(const RelativeFixupPointer &) =delete; RelativeFixupPointer(RelativeFixupPointer &&) =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(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(addr) - (TADDR)base; } // Set encoded value of the pointer. The value can be NULL. @@ -373,6 +391,15 @@ public: return dac_cast(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 diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index 47810b7..49068fc 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -10702,7 +10702,7 @@ void Module::RestoreMethodDescPointer(RelativeFixupPointer * ppM } /*static*/ -void Module::RestoreFieldDescPointer(FixupPointer * ppFD) +void Module::RestoreFieldDescPointer(RelativeFixupPointer * ppFD) { CONTRACTL { @@ -10712,6 +10712,9 @@ void Module::RestoreFieldDescPointer(FixupPointer * 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 * ppFD) CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0); #endif - Module * pContainingModule = ExecutionManager::FindZapModule(dac_cast(ppValue)); + Module * pContainingModule = ExecutionManager::FindZapModule((TADDR)ppValue); PREFIX_ASSUME(pContainingModule != NULL); RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup); diff --git a/src/vm/ceeload.h b/src/vm/ceeload.h index 7fa125d..0896c9b 100644 --- a/src/vm/ceeload.h +++ b/src/vm/ceeload.h @@ -2901,8 +2901,7 @@ public: static void RestoreMethodDescPointer(RelativeFixupPointer * ppMD, Module *pContainingModule = NULL, ClassLoadLevel level = CLASS_LOADED); - - static void RestoreFieldDescPointer(FixupPointer * ppFD); + static void RestoreFieldDescPointer(RelativeFixupPointer * ppFD); static void RestoreModulePointer(RelativeFixupPointer * ppModule, Module *pContainingModule); diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 0259b1e..6697b23 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -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) { diff --git a/src/vm/class.h b/src/vm/class.h index d1f10d4..60cab67 100644 --- a/src/vm/class.h +++ b/src/vm/class.h @@ -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 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; diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp index 0de71b5..9415b94 100644 --- a/src/vm/fieldmarshaler.cpp +++ b/src/vm/fieldmarshaler.cpp @@ -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 diff --git a/src/vm/fieldmarshaler.h b/src/vm/fieldmarshaler.h index 287da41..f11c81b 100644 --- a/src/vm/fieldmarshaler.h +++ b/src/vm/fieldmarshaler.h @@ -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::type>::type *) pDest; \ + _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize); \ + +#define END_COPY_TO_IMPL(CLASS_NAME) \ + static_assert(std::is_same::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 *ppMT) + static inline void RestoreHelper(RelativeFixupPointer *ppMT) { CONTRACTL { @@ -414,7 +448,7 @@ protected: } #ifdef _DEBUG - static inline BOOL IsRestoredHelper(FixupPointer pMT) + static inline BOOL IsRestoredHelper(const RelativeFixupPointer &pMT) { WRAPPER_NO_CONTRACT; @@ -428,7 +462,7 @@ protected: #endif // _DEBUG - FixupPointer m_pFD; // FieldDesc + RelativeFixupPointer 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 m_pNullableTypeMT; + RelativeFixupPointer 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 m_pNestedMethodTable; + RelativeFixupPointer 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 m_pNestedMethodTable; + RelativeFixupPointer 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 m_arrayType; + RelativeFixupPointer 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 m_pMT; + RelativeFixupPointer 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 m_pNestedMethodTable; + RelativeFixupPointer 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 m_pClassMT; - FixupPointer m_pItfMT; + RelativeFixupPointer m_pClassMT; + RelativeFixupPointer 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; diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index f5a256a..bd9dd24 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -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); diff --git a/src/vm/typedesc.cpp b/src/vm/typedesc.cpp index 6718068..7da1c84 100644 --- a/src/vm/typedesc.cpp +++ b/src/vm/typedesc.cpp @@ -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); diff --git a/src/vm/typedesc.h b/src/vm/typedesc.h index a8b1c25..3e8b0e6 100644 --- a/src/vm/typedesc.h +++ b/src/vm/typedesc.h @@ -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 m_TemplateMT; // The shared method table, some variants do not use this field (it is null) + RelativeFixupPointer 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(this) + offsetof(ArrayTypeDesc, m_TemplateMT)); } #ifdef FEATURE_COMINTEROP diff --git a/src/vm/typedesc.inl b/src/vm/typedesc.inl index 4d7416e..312270e 100644 --- a/src/vm/typedesc.inl +++ b/src/vm/typedesc.inl @@ -31,7 +31,7 @@ inline PTR_MethodTable TypeDesc::GetMethodTable() { if (GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE) return dac_cast(asParam->m_Arg.AsMethodTable()); else - return(asParam->m_TemplateMT.GetValue()); + return(asParam->GetTemplateMethodTableInternal()); } inline TypeHandle TypeDesc::GetTypeParam() { -- 2.7.4