From 53ec75f90fc77f7d03309a6aaeae182d875148d4 Mon Sep 17 00:00:00 2001 From: Gleb Balykov Date: Thu, 22 Jun 2017 20:24:54 +0300 Subject: [PATCH 22/32] Remove relocations for InterfaceInfo_t::m_pMethodTable for Linux ARM --- src/vm/array.cpp | 7 +++++-- src/vm/methodtable.cpp | 33 +++++++++++++++++++++++++++------ src/vm/methodtable.h | 23 +++++++++++++++++++---- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/vm/array.cpp b/src/vm/array.cpp index d679294..3f5a8aa 100644 --- a/src/vm/array.cpp +++ b/src/vm/array.cpp @@ -509,8 +509,11 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy #endif // !defined(_WIN64) && (DATA_ALIGNMENT > 4) pMT->SetBaseSize(baseSize); // Because of array method table persisting, we need to copy the map - memcpy(pMTHead + imapOffset, pParentClass->GetInterfaceMap(), - pParentClass->GetNumInterfaces() * sizeof(InterfaceInfo_t)); + for (unsigned index = 0; index < pParentClass->GetNumInterfaces(); ++index) + { + InterfaceInfo_t *pIntInfo = (InterfaceInfo_t *) (pMTHead + imapOffset + index * sizeof(InterfaceInfo_t)); + pIntInfo->SetMethodTable((pParentClass->GetInterfaceMap() + index)->GetMethodTable()); + } pMT->SetInterfaceMap(pParentClass->GetNumInterfaces(), (InterfaceInfo_t *)(pMTHead + imapOffset)); // Copy down flags for these interfaces as well. This is simplified a bit since we know that System.Array diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index e219bb7..b849746 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -1237,7 +1237,12 @@ void MethodTable::AddDynamicInterface(MethodTable *pItfMT) if (TotalNumInterfaces > 0) { InterfaceInfo_t *pInterfaceMap = GetInterfaceMap(); PREFIX_ASSUME(pInterfaceMap != NULL); - memcpy(pNewItfMap, pInterfaceMap, TotalNumInterfaces * sizeof(InterfaceInfo_t)); + + for (unsigned index = 0; index < TotalNumInterfaces; ++index) + { + InterfaceInfo_t *pIntInfo = (InterfaceInfo_t *) (pNewItfMap + index); + pIntInfo->SetMethodTable((pInterfaceMap + index)->GetMethodTable()); + } } // Add the new interface at the end of the map. @@ -4285,16 +4290,32 @@ void MethodTable::Save(DataImage *image, DWORD profilingFlags) // Dynamic interface maps have an additional DWORD_PTR preceding the InterfaceInfo_t array if (HasDynamicInterfaceMap()) { - ZapStoredStructure * pInterfaceMapNode = image->StoreInternedStructure(((DWORD_PTR *)GetInterfaceMap()) - 1, - GetInterfaceMapSize(), - DataImage::ITEM_INTERFACE_MAP); - + ZapStoredStructure * pInterfaceMapNode; + if (decltype(InterfaceInfo_t::m_pMethodTable)::isRelative) + { + pInterfaceMapNode = image->StoreStructure(((DWORD_PTR *)GetInterfaceMap()) - 1, + GetInterfaceMapSize(), + DataImage::ITEM_INTERFACE_MAP); + } + else + { + pInterfaceMapNode = image->StoreInternedStructure(((DWORD_PTR *)GetInterfaceMap()) - 1, + GetInterfaceMapSize(), + DataImage::ITEM_INTERFACE_MAP); + } image->BindPointer(GetInterfaceMap(), pInterfaceMapNode, sizeof(DWORD_PTR)); } else #endif // FEATURE_COMINTEROP { - image->StoreInternedStructure(GetInterfaceMap(), GetInterfaceMapSize(), DataImage::ITEM_INTERFACE_MAP); + if (decltype(InterfaceInfo_t::m_pMethodTable)::isRelative) + { + image->StoreStructure(GetInterfaceMap(), GetInterfaceMapSize(), DataImage::ITEM_INTERFACE_MAP); + } + else + { + image->StoreInternedStructure(GetInterfaceMap(), GetInterfaceMapSize(), DataImage::ITEM_INTERFACE_MAP); + } } SaveExtraInterfaceInfo(image); diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h index f8b34ae..ef0cb44 100644 --- a/src/vm/methodtable.h +++ b/src/vm/methodtable.h @@ -111,25 +111,40 @@ struct InterfaceInfo_t friend class NativeImageDumper; #endif - FixupPointer m_pMethodTable; // Method table of the interface + // Method table of the interface +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + RelativeFixupPointer m_pMethodTable; +#else + FixupPointer m_pMethodTable; +#endif public: FORCEINLINE PTR_MethodTable GetMethodTable() { LIMITED_METHOD_CONTRACT; - return m_pMethodTable.GetValue(); + return ReadPointerMaybeNull(this, &InterfaceInfo_t::m_pMethodTable); } #ifndef DACCESS_COMPILE void SetMethodTable(MethodTable * pMT) { LIMITED_METHOD_CONTRACT; - m_pMethodTable.SetValue(pMT); + m_pMethodTable.SetValueMaybeNull(pMT); } // Get approximate method table. This is used by the type loader before the type is fully loaded. PTR_MethodTable GetApproxMethodTable(Module * pContainingModule); -#endif +#endif // !DACCESS_COMPILE + +#ifndef DACCESS_COMPILE + InterfaceInfo_t(InterfaceInfo_t &right) + { + m_pMethodTable.SetValueMaybeNull(right.m_pMethodTable.GetValueMaybeNull()); + } +#else // !DACCESS_COMPILE +private: + InterfaceInfo_t(InterfaceInfo_t &right); +#endif // !DACCESS_COMPILE }; // struct InterfaceInfo_t typedef DPTR(InterfaceInfo_t) PTR_InterfaceInfo; -- 2.7.4