From 4854ffedfc2e51d4071f2b4a8152a6662288b2de Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Fri, 6 Sep 2024 10:13:12 -0700 Subject: [PATCH] Move pinned heap handle table from `BaseDomain` to `AppDomain` and make callers go through the `AppDomain` (#107420) - Move the pinned heap handle table to `AppDomain` - This does make the current use in the `GlobalLoaderAllocator` (went through `SystemDomain`) and in EnC adding a static field (went through `AppDomain`) use the same table. They have the same lifetime. - Move `GetLoaderAllocator` (it already always returns the global one), `IsStringInterned`, `GetOrInternString` functions from `BaseDomain` to `AppDomain` --- src/coreclr/debug/daccess/dacdbiimpl.cpp | 2 +- src/coreclr/debug/daccess/enummem.cpp | 2 +- src/coreclr/debug/daccess/request.cpp | 9 +-- src/coreclr/vm/appdomain.cpp | 93 ++++++++---------------- src/coreclr/vm/appdomain.hpp | 43 +++++------ src/coreclr/vm/loaderallocator.cpp | 4 +- 6 files changed, 61 insertions(+), 92 deletions(-) diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index be5ee49e10b69a..6309533648bb20 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -3672,7 +3672,7 @@ HRESULT DacDbiInterfaceImpl::GetLoaderHeapMemoryRanges(DacDbiArrayListGetLoaderAllocator(); + PTR_LoaderAllocator pGlobalAllocator = SystemDomain::GetGlobalLoaderAllocator(); _ASSERTE(pGlobalAllocator); EnumerateMemRangesForLoaderAllocator(pGlobalAllocator, &memoryRanges); diff --git a/src/coreclr/debug/daccess/enummem.cpp b/src/coreclr/debug/daccess/enummem.cpp index be3c1123ea4165..7840bb29070cd0 100644 --- a/src/coreclr/debug/daccess/enummem.cpp +++ b/src/coreclr/debug/daccess/enummem.cpp @@ -743,7 +743,7 @@ HRESULT ClrDataAccess::EnumMemDumpAppDomainInfo(CLRDataEnumMemoryFlags flags) if (flags == CLRDATA_ENUM_MEM_HEAP2) { - SystemDomain::System()->GetLoaderAllocator()->EnumMemoryRegions(flags); + SystemDomain::GetGlobalLoaderAllocator()->EnumMemoryRegions(flags); } AppDomain* appDomain = AppDomain::GetCurrentDomain(); diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index bbd2b96c9ba370..2be13b91e98aa9 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2838,7 +2838,7 @@ ClrDataAccess::GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData * ZeroMemory(appdomainData, sizeof(DacpAppDomainData)); appdomainData->AppDomainPtr = PTR_CDADDR(pBaseDomain); - PTR_LoaderAllocator pLoaderAllocator = pBaseDomain->GetLoaderAllocator(); + PTR_LoaderAllocator pLoaderAllocator = SystemDomain::GetGlobalLoaderAllocator(); appdomainData->pHighFrequencyHeap = HOST_CDADDR(pLoaderAllocator->GetHighFrequencyHeap()); appdomainData->pLowFrequencyHeap = HOST_CDADDR(pLoaderAllocator->GetLowFrequencyHeap()); appdomainData->pStubHeap = HOST_CDADDR(pLoaderAllocator->GetStubHeap()); @@ -4065,8 +4065,7 @@ ClrDataAccess::TraverseVirtCallStubHeap(CLRDATA_ADDRESS pAppDomain, VCSHeapType SOSDacEnter(); - BaseDomain* pBaseDomain = PTR_BaseDomain(TO_TADDR(pAppDomain)); - VirtualCallStubManager *pVcsMgr = pBaseDomain->GetLoaderAllocator()->GetVirtualCallStubManager(); + VirtualCallStubManager *pVcsMgr = SystemDomain::GetGlobalLoaderAllocator()->GetVirtualCallStubManager(); if (!pVcsMgr) { hr = E_POINTER; @@ -4111,8 +4110,8 @@ HRESULT ClrDataAccess::GetDomainLoaderAllocator(CLRDATA_ADDRESS domainAddress, C SOSDacEnter(); - PTR_BaseDomain pDomain = PTR_BaseDomain(TO_TADDR(domainAddress)); - *pLoaderAllocator = pDomain != nullptr ? HOST_CDADDR(pDomain->GetLoaderAllocator()) : 0; + // The one and only app domain uses the global loader allocator + *pLoaderAllocator = HOST_CDADDR(SystemDomain::GetGlobalLoaderAllocator()); SOSDacLeave(); return hr; diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index cd03be337899bb..8d3395cd8ebbd2 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -430,27 +430,6 @@ void PinnedHeapHandleTable::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) } } -//***************************************************************************** -// BaseDomain -//***************************************************************************** - -BaseDomain::BaseDomain() -{ - // initialize fields so the domain can be safely destructed - // shouldn't call anything that can fail here - use ::Init instead - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - FORBID_FAULT; - } - CONTRACTL_END; - - // Make sure the container is set to NULL so that it gets loaded when it is used. - m_pPinnedHeapHandleTable = NULL; -} //BaseDomain::BaseDomain - #undef LOADERHEAP_PROFILE_COUNTER void AppDomain::ClearBinderContext() @@ -573,7 +552,7 @@ void AppDomain::SetNativeDllSearchDirectories(LPCWSTR wszNativeDllSearchDirector } } -OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo, MethodTable *pMTToFillWithStaticBoxes, bool isClassInitdeByUpdatingStaticPointer) +OBJECTREF* AppDomain::AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo, MethodTable *pMTToFillWithStaticBoxes, bool isClassInitdeByUpdatingStaticPointer) { CONTRACTL { @@ -661,7 +640,7 @@ OBJECTREF AppDomain::GetMissingObject() #ifndef DACCESS_COMPILE -STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString) +STRINGREF* AppDomain::IsStringInterned(STRINGREF *pString) { CONTRACTL { @@ -676,7 +655,7 @@ STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString) return GetLoaderAllocator()->IsStringInterned(pString); } -STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString) +STRINGREF* AppDomain::GetOrInternString(STRINGREF *pString) { CONTRACTL { @@ -691,7 +670,7 @@ STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString) return GetLoaderAllocator()->GetOrInternString(pString); } -void BaseDomain::InitPinnedHeapHandleTable() +void AppDomain::InitPinnedHeapHandleTable() { CONTRACTL { @@ -1622,6 +1601,30 @@ HRESULT SystemDomain::NotifyProfilerShutdown() #endif // PROFILING_SUPPORTED AppDomain::AppDomain() + : m_handleStore{NULL} + , m_pPinnedHeapHandleTable{NULL} + , m_pDefaultBinder{NULL} + , m_pRefClassFactHash{NULL} +#ifdef FEATURE_COMINTEROP + , m_pRefDispIDCache{NULL} + , m_hndMissing{NULL} +#endif //FEATURE_COMINTEROP + , m_pDelayedLoaderAllocatorUnloadList{NULL} + , m_pRootAssembly{NULL} + , m_dwFlags{0} + , m_cRef{1} +#ifdef FEATURE_COMINTEROP + , m_pRCWCache{NULL} +#endif //FEATURE_COMINTEROP +#ifdef FEATURE_COMWRAPPERS + , m_pRCWRefCache{NULL} +#endif // FEATURE_COMWRAPPERS + , m_Stage{STAGE_CREATING} + , m_MemoryPressure{0} + , m_ForceTrivialWaitOperations{false} +#ifdef FEATURE_TYPEEQUIVALENCE + , m_pTypeEquivalenceTable{NULL} +#endif // FEATURE_TYPEEQUIVALENCE { // initialize fields so the appdomain can be safely destructed // shouldn't call anything that can fail here - use ::Init instead @@ -1634,45 +1637,16 @@ AppDomain::AppDomain() } CONTRACTL_END; - m_cRef=1; - m_JITLock.PreInit(); m_ClassInitLock.PreInit(); m_ILStubGenLock.PreInit(); m_NativeTypeLoadLock.PreInit(); m_FileLoadLock.PreInit(); - m_pDefaultBinder = NULL; - m_pRootAssembly = NULL; - - m_dwFlags = 0; -#ifdef FEATURE_COMINTEROP - m_pRCWCache = NULL; -#endif //FEATURE_COMINTEROP -#ifdef FEATURE_COMWRAPPERS - m_pRCWRefCache = NULL; -#endif // FEATURE_COMWRAPPERS - - m_handleStore = NULL; - #ifdef _DEBUG m_Assemblies.Debug_SetAppDomain(this); #endif // _DEBUG -#ifdef FEATURE_COMINTEROP - m_pRefDispIDCache = NULL; - m_hndMissing = NULL; -#endif - - m_pRefClassFactHash = NULL; - - m_ForceTrivialWaitOperations = false; - m_Stage=STAGE_CREATING; - -#ifdef FEATURE_TYPEEQUIVALENCE - m_pTypeEquivalenceTable = NULL; -#endif // FEATURE_TYPEEQUIVALENCE - } // AppDomain::AppDomain AppDomain::~AppDomain() @@ -1696,13 +1670,10 @@ void AppDomain::Init() CONTRACTL { STANDARD_VM_CHECK; + PRECONDITION(m_Stage == STAGE_CREATING); } CONTRACTL_END; - m_pDelayedLoaderAllocatorUnloadList = NULL; - - SetStage( STAGE_CREATING); - // // The JIT lock and the CCtor locks are at the same level (and marked as // UNSAFE_SAME_LEVEL) because they are all part of the same deadlock detection mechanism. We @@ -1729,8 +1700,6 @@ void AppDomain::Init() // Set up the binding caches m_AssemblyCache.Init(&m_DomainCacheCrst, GetHighFrequencyHeap()); - m_MemoryPressure = 0; - m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore(); if (!m_handleStore) { @@ -4057,7 +4026,7 @@ void AppDomain::EnumStaticGCRefs(promote_func* fn, ScanContext* sc) #endif // !DACCESS_COMPILE //------------------------------------------------------------------------ -PTR_LoaderAllocator BaseDomain::GetLoaderAllocator() +PTR_LoaderAllocator AppDomain::GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return SystemDomain::GetGlobalLoaderAllocator(); // The one and only domain is not unloadable @@ -4536,7 +4505,7 @@ SystemDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis) if (flags == CLRDATA_ENUM_MEM_HEAP2) { - GetLoaderAllocator()->EnumMemoryRegions(flags); + GetGlobalLoaderAllocator()->EnumMemoryRegions(flags); } if (m_pSystemPEAssembly.IsValid()) { diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index b2fcc9d58696ca..b357f6e1a512a9 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -457,12 +457,11 @@ class BaseDomain // // Initialization/shutdown routines for every instance of an BaseDomain. - BaseDomain(); + BaseDomain() = default; virtual ~BaseDomain() {} virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; } - PTR_LoaderAllocator GetLoaderAllocator(); virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; @@ -470,24 +469,6 @@ class BaseDomain return NULL; } - STRINGREF *IsStringInterned(STRINGREF *pString); - STRINGREF *GetOrInternString(STRINGREF *pString); - - // Returns an array of OBJECTREF* that can be used to store domain specific data. - // Statics and reflection info (Types, MemberInfo,..) are stored this way - // If pStaticsInfo != 0, allocation will only take place if GC statics in the DynamicStaticsInfo are NULL (and the allocation - // will be properly serialized) - OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo = NULL, MethodTable *pMTToFillWithStaticBoxes = NULL, bool isClassInitdeByUpdatingStaticPointer = false); - -protected: - - //**************************************************************************************** - // Helper method to initialize the large heap handle table. - void InitPinnedHeapHandleTable(); - - // The pinned heap handle table. - PinnedHeapHandleTable *m_pPinnedHeapHandleTable; - #ifdef DACCESS_COMPILE public: virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis) = 0; @@ -752,6 +733,11 @@ class AppDomain : public BaseDomain virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; } virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast(this); } + PTR_LoaderAllocator GetLoaderAllocator(); + + STRINGREF *IsStringInterned(STRINGREF *pString); + STRINGREF *GetOrInternString(STRINGREF *pString); + OBJECTREF GetRawExposedObject() { LIMITED_METHOD_CONTRACT; return NULL; } OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return (OBJECTHANDLE)NULL; } @@ -1256,6 +1242,12 @@ class AppDomain : public BaseDomain void NotifyDebuggerUnload(); #endif // DEBUGGING_SUPPORTED +public: + // Returns an array of OBJECTREF* that can be used to store domain specific data. + // Statics and reflection info (Types, MemberInfo,..) are stored this way + // If pStaticsInfo != 0, allocation will only take place if GC statics in the DynamicStaticsInfo are NULL (and the allocation + // will be properly serialized) + OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo = NULL, MethodTable *pMTToFillWithStaticBoxes = NULL, bool isClassInitdeByUpdatingStaticPointer = false); #ifndef DACCESS_COMPILE OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested) { @@ -1265,7 +1257,16 @@ class AppDomain : public BaseDomain } #endif // DACCESS_COMPILE - void EnumStaticGCRefs(promote_func* fn, ScanContext* sc); +private: + // Helper method to initialize the large heap handle table. + void InitPinnedHeapHandleTable(); + +private: + // The pinned heap handle table. + PinnedHeapHandleTable *m_pPinnedHeapHandleTable; + +public: + void EnumStaticGCRefs(promote_func* fn, ScanContext* sc); void SetupSharedStatics(); diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index cd5ca66f660fa4..ff6506b76292a6 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -844,7 +844,7 @@ LOADERHANDLE LoaderAllocator::AllocateHandle(OBJECTREF value) } else { - OBJECTREF* pRef = GetDomain()->AllocateObjRefPtrsInLargeTable(1); + OBJECTREF* pRef = AppDomain::GetCurrentDomain()->AllocateObjRefPtrsInLargeTable(1); SetObjectReference(pRef, gc.value); retVal = (((UINT_PTR)pRef) + 1); } @@ -2384,7 +2384,7 @@ void LoaderAllocator::AllocateGCHandlesBytesForStaticVariables(DynamicStaticsInf } else { - GetDomain()->AllocateObjRefPtrsInLargeTable(cSlots, pStaticsInfo, pMTToFillWithStaticBoxes, isClassInitedByUpdatingStaticPointer); + AppDomain::GetCurrentDomain()->AllocateObjRefPtrsInLargeTable(cSlots, pStaticsInfo, pMTToFillWithStaticBoxes, isClassInitedByUpdatingStaticPointer); } } #endif // !DACCESS_COMPILE