Skip to content

Commit

Permalink
Move pinned heap handle table from BaseDomain to AppDomain and ma…
Browse files Browse the repository at this point in the history
…ke callers go through the `AppDomain` (dotnet#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`
  • Loading branch information
elinor-fung authored and jtschuster committed Sep 17, 2024
1 parent c01f48b commit 4854ffe
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 92 deletions.
2 changes: 1 addition & 1 deletion src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3672,7 +3672,7 @@ HRESULT DacDbiInterfaceImpl::GetLoaderHeapMemoryRanges(DacDbiArrayList<COR_MEMOR
// it's own LoaderAllocator, but there's no easy way of getting a hand at them other than going through
// the heap, getting a managed LoaderAllocators, from there getting a Scout, and from there getting a native
// pointer to the LoaderAllocator tos enumerate.
PTR_LoaderAllocator pGlobalAllocator = SystemDomain::System()->GetLoaderAllocator();
PTR_LoaderAllocator pGlobalAllocator = SystemDomain::GetGlobalLoaderAllocator();
_ASSERTE(pGlobalAllocator);
EnumerateMemRangesForLoaderAllocator(pGlobalAllocator, &memoryRanges);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 4 additions & 5 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
93 changes: 31 additions & 62 deletions src/coreclr/vm/appdomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -661,7 +640,7 @@ OBJECTREF AppDomain::GetMissingObject()
#ifndef DACCESS_COMPILE


STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString)
STRINGREF* AppDomain::IsStringInterned(STRINGREF *pString)
{
CONTRACTL
{
Expand All @@ -676,7 +655,7 @@ STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString)
return GetLoaderAllocator()->IsStringInterned(pString);
}

STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString)
STRINGREF* AppDomain::GetOrInternString(STRINGREF *pString)
{
CONTRACTL
{
Expand All @@ -691,7 +670,7 @@ STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString)
return GetLoaderAllocator()->GetOrInternString(pString);
}

void BaseDomain::InitPinnedHeapHandleTable()
void AppDomain::InitPinnedHeapHandleTable()
{
CONTRACTL
{
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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
Expand All @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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())
{
Expand Down
43 changes: 22 additions & 21 deletions src/coreclr/vm/appdomain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,37 +457,18 @@ 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;
_ASSERTE(!"Not an AppDomain");
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;
Expand Down Expand Up @@ -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<PTR_AppDomain>(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; }

Expand Down Expand Up @@ -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)
{
Expand All @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/loaderallocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 4854ffe

Please sign in to comment.