in src/Microsoft.Diagnostics.Runtime/ClrRuntime.cs [269:341]
public IEnumerable<ClrNativeHeapInfo> EnumerateClrNativeHeaps()
{
// Enumerate the JIT code heaps.
foreach (ClrJitManager jitMgr in EnumerateJitManagers())
foreach (ClrNativeHeapInfo heap in jitMgr.EnumerateNativeHeaps())
yield return heap;
HashSet<ulong> visited = new();
// Ensure we are working on a consistent set of domains/modules
DomainAndModules domainData = GetAppDomainData();
// Walk domains
if (domainData.SystemDomain is not null)
{
visited.Add(domainData.SystemDomain.LoaderAllocator);
foreach (ClrNativeHeapInfo heap in domainData.SystemDomain.EnumerateLoaderAllocatorHeaps())
yield return heap;
}
if (domainData.SharedDomain is not null)
{
visited.Add(domainData.SharedDomain.LoaderAllocator);
foreach (ClrNativeHeapInfo heap in domainData.SharedDomain.EnumerateLoaderAllocatorHeaps())
yield return heap;
}
foreach (ClrAppDomain domain in domainData.AppDomains)
{
if (domain.LoaderAllocator == 0 || visited.Add(domain.LoaderAllocator))
foreach (ClrNativeHeapInfo heap in domain.EnumerateLoaderAllocatorHeaps())
yield return heap;
}
// Walk modules. We do this after domains to ensure we don't enumerate
// previously enumerated LoaderAllocators.
foreach (ClrModule module in domainData.Modules)
{
// We don't want to skip modules with no address, as we might have
// multiple of those with unique heaps.
if (module.Address == 0 || visited.Add(module.Address))
{
if (module.ThunkHeap != 0 && visited.Add(module.ThunkHeap))
foreach (ClrNativeHeapInfo heap in module.EnumerateThunkHeap())
yield return heap;
// LoaderAllocator may be shared with its parent domain. We only have a
// unique LoaderAllocator in the case of collectable assemblies.
if (module.LoaderAllocator != 0 && visited.Add(module.LoaderAllocator))
foreach (ClrNativeHeapInfo heap in module.EnumerateLoaderAllocatorHeaps())
yield return heap;
}
}
IAbstractClrNativeHeaps? nativeHeaps = GetService<IAbstractClrNativeHeaps>();
if (nativeHeaps is not null)
{
foreach (ClrNativeHeapInfo gcFreeRegion in nativeHeaps.EnumerateGCFreeRegions())
{
yield return gcFreeRegion;
}
foreach (ClrNativeHeapInfo handleHeap in nativeHeaps.EnumerateHandleTableRegions())
{
yield return handleHeap;
}
foreach (ClrNativeHeapInfo bkRegions in nativeHeaps.EnumerateGCBookkeepingRegions())
{
yield return bkRegions;
}
}
}