public IEnumerable EnumerateClrNativeHeaps()

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;
                }
            }
        }