diff options
author | gbalykov <g.balykov@samsung.com> | 2018-02-22 20:47:46 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2018-02-22 09:47:46 -0800 |
commit | 34247df6ccb1bcc54363807f047e67c8d43c03cb (patch) | |
tree | f74c65cf73c5e677046cc17e6c9ea6d9f839421c | |
parent | 9e7ec667bd2871970b127fda856b0c6cf3eb2060 (diff) | |
download | coreclr-34247df6ccb1bcc54363807f047e67c8d43c03cb.tar.gz coreclr-34247df6ccb1bcc54363807f047e67c8d43c03cb.tar.bz2 coreclr-34247df6ccb1bcc54363807f047e67c8d43c03cb.zip |
Remove relocations for MethodTable::m_pParentMethodTable for Linux ARM (#15915)
-rw-r--r-- | src/debug/daccess/nidump.cpp | 4 | ||||
-rw-r--r-- | src/inc/fixuppointer.h | 208 | ||||
-rw-r--r-- | src/vm/class.cpp | 10 | ||||
-rw-r--r-- | src/vm/generics.cpp | 1 | ||||
-rw-r--r-- | src/vm/methodtable.cpp | 35 | ||||
-rw-r--r-- | src/vm/methodtable.h | 69 | ||||
-rw-r--r-- | src/vm/proftoeeinterfaceimpl.cpp | 2 |
7 files changed, 299 insertions, 30 deletions
diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index 274b1e7ddf..45320dca7f 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -5987,7 +5987,7 @@ PTR_MethodTable NativeImageDumper::GetParent( PTR_MethodTable mt ) /* REVISIT_TODO Thu 12/01/2005 * Handle fixups */ - PTR_MethodTable parent( mt->m_pParentMethodTable ); + PTR_MethodTable parent( ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent()) ); _ASSERTE(!CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(parent))); return parent; } @@ -6961,7 +6961,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name, - PTR_MethodTable parent = mt->m_pParentMethodTable; + PTR_MethodTable parent = ReadPointerMaybeNull((MethodTable*) mt, &MethodTable::m_pParentMethodTable, mt->GetFlagHasIndirectParent()); if( parent == NULL ) { DisplayWriteFieldPointer( m_pParentMethodTable, NULL, MethodTable, diff --git a/src/inc/fixuppointer.h b/src/inc/fixuppointer.h index a711418bd4..5a897e44ea 100644 --- a/src/inc/fixuppointer.h +++ b/src/inc/fixuppointer.h @@ -319,6 +319,14 @@ public: return FALSE; } + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + // Ignores isIndirect and offset values. + FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsTagged(base); + } + #ifndef DACCESS_COMPILE // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. // Does not need explicit base and thus can be used in non-DAC builds only. @@ -358,6 +366,14 @@ public: return dac_cast<DPTR(RelativeFixupPointer<PTR_TYPE>)>(base)->GetValue(base); } + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + // Ignores isIndirect and offset values. + FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValueAtPtr(base); + } + // Returns value of the encoded pointer. The pointer can be NULL. PTR_TYPE GetValueMaybeNull(TADDR base) const { @@ -393,6 +409,14 @@ public: return dac_cast<DPTR(RelativeFixupPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base); } + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + // Ignores isIndirect and offset values. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValueMaybeNullAtPtr(base); + } + #ifndef DACCESS_COMPILE // Set encoded value of the pointer. Assumes that the value is not NULL. FORCEINLINE void SetValue(PTR_TYPE addr) @@ -429,6 +453,14 @@ public: _ASSERTE((addr & FIXUP_POINTER_INDIRECTION) != 0); return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION); } + + // Returns the pointer to the indirection cell. + // Ignores isIndirect and offset values. + PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + return GetValuePtr(); + } #endif // !DACCESS_COMPILE // Returns value of the encoded pointer. Assumes that the pointer is not NULL. @@ -462,6 +494,14 @@ public: LIMITED_METHOD_CONTRACT; return IsIndirectPtr((TADDR)this); } + + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Ignores isIndirect and offset values. + bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsIndirectPtr(); + } #endif // Returns whether pointer is indirect. The value can be NULL. @@ -483,6 +523,14 @@ public: LIMITED_METHOD_CONTRACT; return IsIndirectPtrMaybeNull((TADDR)this); } + + // Returns whether pointer is indirect. The value can be NULL. + // Ignores isIndirect and offset values. + bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsIndirectPtrMaybeNull(); + } #endif private: @@ -765,6 +813,130 @@ private: INT32 m_delta; }; +//---------------------------------------------------------------------------- +// IndirectPointer is pointer with optional indirection, similar to FixupPointer and RelativeFixupPointer. +// +// In comparison to FixupPointer, IndirectPointer's indirection is handled from outside by isIndirect flag. +// In comparison to RelativeFixupPointer, IndirectPointer's offset is a constant, +// while RelativeFixupPointer's offset is an address. +// +// IndirectPointer can contain NULL only if it is not indirect. +// +template<typename PTR_TYPE> +class IndirectPointer +{ +public: + + static constexpr bool isRelative = false; + typedef PTR_TYPE type; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_addr == (TADDR)NULL; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if (isIndirect) + { + _ASSERTE(!IsNull()); + return (*PTR_TADDR(addr + offset) & 1) != 0; + } + return FALSE; + } + + // Returns value of the encoded pointer. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE PTR_TYPE GetValueIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if (isIndirect) + { + _ASSERTE(!IsNull()); + addr = *PTR_TADDR(addr + offset); + } + return dac_cast<PTR_TYPE>(addr); + } + +#ifndef DACCESS_COMPILE + // Returns the pointer to the indirection cell. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + TADDR addr = m_addr; + if (isIndirect) + { + _ASSERTE(!IsNull()); + return (PTR_TYPE *)(addr + offset); + } + return (PTR_TYPE *)&m_addr; + } +#endif // !DACCESS_COMPILE + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<DPTR(IndirectPointer<PTR_TYPE>)>(base)->GetValueIndirect(isIndirect, offset); + } + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValueAtPtrIndirect(base, isIndirect, offset); + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + if (isIndirect) + _ASSERTE(!IsNull()); + return isIndirect; + } + + // Returns whether pointer is indirect. The value can be NULL. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtrIndirect(isIndirect, offset); + } +#endif // !DACCESS_COMPILE + +#ifndef DACCESS_COMPILE + // Set encoded value of the pointer. Assumes that the value is not NULL. + void SetValue(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + m_addr = dac_cast<TADDR>(addr); + } + + // Set encoded value of the pointer. The value can be NULL. + void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValue(addr); + } +#endif // !DACCESS_COMPILE + +private: + TADDR m_addr; +}; + template<bool isMaybeNull, typename T, typename PT> typename PT::type ReadPointer(const T *base, const PT T::* pPointerFieldMember) @@ -783,6 +955,24 @@ ReadPointer(const T *base, const PT T::* pPointerFieldMember) } } +template<bool isMaybeNull, typename T, typename PT> +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect) +{ + LIMITED_METHOD_DAC_CONTRACT; + + uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base; + + if (isMaybeNull) + { + return PT::GetValueMaybeNullAtPtrIndirect(dac_cast<TADDR>(base) + offset, isIndirect, offset); + } + else + { + return PT::GetValueAtPtrIndirect(dac_cast<TADDR>(base) + offset, isIndirect, offset); + } +} + template<typename T, typename PT> typename PT::type ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember) @@ -794,6 +984,15 @@ ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember) template<typename T, typename PT> typename PT::type +ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember, bool isIndirect) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer<true>(base, pPointerFieldMember, isIndirect); +} + +template<typename T, typename PT> +typename PT::type ReadPointer(const T *base, const PT T::* pPointerFieldMember) { LIMITED_METHOD_DAC_CONTRACT; @@ -801,6 +1000,15 @@ ReadPointer(const T *base, const PT T::* pPointerFieldMember) return ReadPointer<false>(base, pPointerFieldMember); } +template<typename T, typename PT> +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer<false>(base, pPointerFieldMember, isIndirect); +} + template<bool isMaybeNull, typename T, typename C, typename PT> typename PT::type ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember) diff --git a/src/vm/class.cpp b/src/vm/class.cpp index d0b07f0896..cd2bbbae47 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -883,7 +883,15 @@ ClassLoader::LoadExactParentAndInterfacesTransitively(MethodTable *pMT) LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Replaced approximate parent %s with exact parent %s from token %x\n", pParentMT->GetDebugClassName(), pNewParentMT->GetDebugClassName(), crExtends)); // SetParentMethodTable is not used here since we want to update the indirection cell in the NGen case - *EnsureWritablePages(pMT->GetParentMethodTablePtr()) = pNewParentMT; + if (pMT->IsParentMethodTableIndirectPointerMaybeNull()) + { + *EnsureWritablePages(pMT->GetParentMethodTableValuePtr()) = pNewParentMT; + } + else + { + EnsureWritablePages(pMT->GetParentMethodTablePointerPtr()); + pMT->GetParentMethodTablePointerPtr()->SetValueMaybeNull(pNewParentMT); + } pParentMT = pNewParentMT; } diff --git a/src/vm/generics.cpp b/src/vm/generics.cpp index 83bcd86f84..4ff877ed43 100644 --- a/src/vm/generics.cpp +++ b/src/vm/generics.cpp @@ -365,6 +365,7 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( pMT->ClearFlag(MethodTable::enum_flag_IsPreRestored); pMT->ClearFlag(MethodTable::enum_flag_HasIndirectParent); + pMT->m_pParentMethodTable.SetValueMaybeNull(NULL); // Non non-virtual slots pMT->ClearFlag(MethodTable::enum_flag_HasSingleNonVirtualSlot); diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index e8f9dccdc3..710a81abf4 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -4816,7 +4816,17 @@ void MethodTable::Fixup(DataImage *image) #endif // _DEBUG MethodTable * pParentMT = GetParentMethodTable(); - _ASSERTE(!pNewMT->GetFlag(enum_flag_HasIndirectParent)); + _ASSERTE(!pNewMT->IsParentMethodTableIndirectPointerMaybeNull()); + + ZapRelocationType relocType; + if (decltype(MethodTable::m_pParentMethodTable)::isRelative) + { + relocType = IMAGE_REL_BASED_RELPTR; + } + else + { + relocType = IMAGE_REL_BASED_PTR; + } if (pParentMT != NULL) { @@ -4828,7 +4838,8 @@ void MethodTable::Fixup(DataImage *image) { if (image->CanHardBindToZapModule(pParentMT->GetLoaderModule())) { - image->FixupPointerField(this, offsetof(MethodTable, m_pParentMethodTable)); + _ASSERTE(!IsParentMethodTableIndirectPointer()); + image->FixupField(this, offsetof(MethodTable, m_pParentMethodTable), pParentMT, 0, relocType); } else { @@ -4864,7 +4875,7 @@ void MethodTable::Fixup(DataImage *image) if (pImport != NULL) { - image->FixupFieldToNode(this, offsetof(MethodTable, m_pParentMethodTable), pImport, -(SSIZE_T)offsetof(MethodTable, m_pParentMethodTable)); + image->FixupFieldToNode(this, offsetof(MethodTable, m_pParentMethodTable), pImport, -PARENT_MT_FIXUP_OFFSET, relocType); pNewMT->SetFlag(enum_flag_HasIndirectParent); } } @@ -6128,7 +6139,15 @@ void MethodTable::Restore() // // Restore parent method table // - Module::RestoreMethodTablePointerRaw(GetParentMethodTablePtr(), GetLoaderModule(), CLASS_LOAD_APPROXPARENTS); + if (IsParentMethodTableIndirectPointerMaybeNull()) + { + Module::RestoreMethodTablePointerRaw(GetParentMethodTableValuePtr(), GetLoaderModule(), CLASS_LOAD_APPROXPARENTS); + } + else + { + ClassLoader::EnsureLoaded(ReadPointer(this, &MethodTable::m_pParentMethodTable, GetFlagHasIndirectParent()), + CLASS_LOAD_APPROXPARENTS); + } // // Restore interface classes @@ -8183,13 +8202,7 @@ BOOL MethodTable::IsParentMethodTablePointerValid() if (!GetWriteableData_NoLogging()->IsParentMethodTablePointerValid()) return FALSE; - if (!GetFlag(enum_flag_HasIndirectParent)) - { - return TRUE; - } - TADDR pMT; - pMT = *PTR_TADDR(m_pParentMethodTable + offsetof(MethodTable, m_pParentMethodTable)); - return !CORCOMPILE_IS_POINTER_TAGGED(pMT); + return !IsParentMethodTableTagged(dac_cast<PTR_MethodTable>(this)); } #endif diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h index 0073a18dde..29d36d1dce 100644 --- a/src/vm/methodtable.h +++ b/src/vm/methodtable.h @@ -2177,6 +2177,14 @@ public: // THE METHOD TABLE PARENT (SUPERCLASS/BASE CLASS) // +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) +#define PARENT_MT_FIXUP_OFFSET (-FIXUP_POINTER_INDIRECTION) + typedef RelativeFixupPointer<PTR_MethodTable> ParentMT_t; +#else +#define PARENT_MT_FIXUP_OFFSET ((SSIZE_T)offsetof(MethodTable, m_pParentMethodTable)) + typedef IndirectPointer<PTR_MethodTable> ParentMT_t; +#endif + BOOL HasApproxParent() { LIMITED_METHOD_DAC_CONTRACT; @@ -2195,33 +2203,63 @@ public: LIMITED_METHOD_DAC_CONTRACT; PRECONDITION(IsParentMethodTablePointerValid()); - - TADDR pMT = m_pParentMethodTable; -#ifdef FEATURE_PREJIT - if (GetFlag(enum_flag_HasIndirectParent)) - pMT = *PTR_TADDR(m_pParentMethodTable + offsetof(MethodTable, m_pParentMethodTable)); -#endif - return PTR_MethodTable(pMT); + return ReadPointerMaybeNull(this, &MethodTable::m_pParentMethodTable, GetFlagHasIndirectParent()); } inline static PTR_VOID GetParentMethodTableOrIndirection(PTR_VOID pMT) { WRAPPER_NO_CONTRACT; +#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_) + PTR_MethodTable pMethodTable = dac_cast<PTR_MethodTable>(pMT); + PTR_MethodTable pParentMT = ReadPointerMaybeNull((MethodTable*) pMethodTable, &MethodTable::m_pParentMethodTable); + return dac_cast<PTR_VOID>(pParentMT); +#else return PTR_VOID(*PTR_TADDR(dac_cast<TADDR>(pMT) + offsetof(MethodTable, m_pParentMethodTable))); +#endif } - inline MethodTable ** GetParentMethodTablePtr() + inline static bool IsParentMethodTableTagged(PTR_MethodTable pMT) { - WRAPPER_NO_CONTRACT; + LIMITED_METHOD_CONTRACT; + TADDR base = dac_cast<TADDR>(pMT) + offsetof(MethodTable, m_pParentMethodTable); + return pMT->m_pParentMethodTable.IsTaggedIndirect(base, pMT->GetFlagHasIndirectParent(), PARENT_MT_FIXUP_OFFSET); + } + bool GetFlagHasIndirectParent() + { #ifdef FEATURE_PREJIT - return GetFlag(enum_flag_HasIndirectParent) ? - (MethodTable **)(m_pParentMethodTable + offsetof(MethodTable, m_pParentMethodTable)) :(MethodTable **)&m_pParentMethodTable; + return GetFlag(enum_flag_HasIndirectParent); #else - return (MethodTable **)&m_pParentMethodTable; + return FALSE; #endif } +#ifndef DACCESS_COMPILE + inline ParentMT_t * GetParentMethodTablePointerPtr() + { + LIMITED_METHOD_CONTRACT; + return &m_pParentMethodTable; + } + + inline bool IsParentMethodTableIndirectPointerMaybeNull() + { + LIMITED_METHOD_CONTRACT; + return m_pParentMethodTable.IsIndirectPtrMaybeNullIndirect(GetFlagHasIndirectParent(), PARENT_MT_FIXUP_OFFSET); + } + + inline bool IsParentMethodTableIndirectPointer() + { + LIMITED_METHOD_CONTRACT; + return m_pParentMethodTable.IsIndirectPtrIndirect(GetFlagHasIndirectParent(), PARENT_MT_FIXUP_OFFSET); + } + + inline MethodTable ** GetParentMethodTableValuePtr() + { + LIMITED_METHOD_CONTRACT; + return m_pParentMethodTable.GetValuePtrIndirect(GetFlagHasIndirectParent(), PARENT_MT_FIXUP_OFFSET); + } +#endif // !DACCESS_COMPILE + // Is the parent method table pointer equal to the given argument? BOOL ParentEquals(PTR_MethodTable pMT) { @@ -2239,8 +2277,8 @@ public: void SetParentMethodTable (MethodTable *pParentMethodTable) { LIMITED_METHOD_CONTRACT; - PRECONDITION(!GetFlag(enum_flag_HasIndirectParent)); - m_pParentMethodTable = (TADDR)pParentMethodTable; + PRECONDITION(!IsParentMethodTableIndirectPointerMaybeNull()); + m_pParentMethodTable.SetValueMaybeNull(pParentMethodTable); #ifdef _DEBUG GetWriteableDataForWrite_NoLogging()->SetParentMethodTablePointerValid(); #endif @@ -4139,11 +4177,12 @@ private: LPCUTF8 debug_m_szClassName; #endif //_DEBUG + // On Linux ARM is a RelativeFixupPointer. Otherwise, // Parent PTR_MethodTable if enum_flag_HasIndirectParent is not set. Pointer to indirection cell // if enum_flag_enum_flag_HasIndirectParent is set. The indirection is offset by offsetof(MethodTable, m_pParentMethodTable). // It allows casting helpers to go through parent chain natually. Casting helper do not need need the explicit check // for enum_flag_HasIndirectParentMethodTable. - TADDR m_pParentMethodTable; + ParentMT_t m_pParentMethodTable; RelativePointer<PTR_Module> m_pLoaderModule; // LoaderModule. It is equal to the ZapModule in ngened images diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp index 5daf127387..04330a26e0 100644 --- a/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/vm/proftoeeinterfaceimpl.cpp @@ -7091,7 +7091,7 @@ HRESULT ProfToEEInterfaceImpl::GetClassLayout(ClassID classID, // running into - attempting to get the class layout for all types at module load time. // If we don't detect this the runtime will AV during the field iteration below. Feel // free to eliminate this check when a more complete solution is available. - if (CORCOMPILE_IS_POINTER_TAGGED(*(typeHandle.AsMethodTable()->GetParentMethodTablePtr()))) + if (MethodTable::IsParentMethodTableTagged(typeHandle.AsMethodTable())) { return CORPROF_E_DATAINCOMPLETE; } |