in ClrMemDiag/Desktop/runtimebase.cs [384:521]
public override IEnumerable<ClrMemoryRegion> EnumerateMemoryRegions()
{
// Enumerate GC Segment regions.
IHeapDetails[] heaps;
if (ServerGC)
{
heaps = new IHeapDetails[HeapCount];
int i = 0;
Address[] heapList = GetServerHeapList();
if (heapList != null)
{
foreach (ulong addr in heapList)
{
heaps[i++] = GetSvrHeapDetails(addr);
if (i == heaps.Length)
break;
}
}
else
{
heaps = new IHeapDetails[0];
}
}
else
{
Debug.Assert(HeapCount == 1);
heaps = new IHeapDetails[1];
heaps[0] = GetWksHeapDetails();
}
int max = 2048; // Max number of segments in case of inconsistent data.
for (int i = 0; i < heaps.Length; ++i)
{
// Small heap
ISegmentData segment = GetSegmentData(heaps[i].FirstHeapSegment);
while (segment != null && max-- > 0)
{
Debug.Assert(segment.Start < segment.Committed);
Debug.Assert(segment.Committed <= segment.Reserved);
GCSegmentType type = (segment.Address == heaps[i].EphemeralSegment) ? GCSegmentType.Ephemeral : GCSegmentType.Regular;
yield return new MemoryRegion(this, segment.Start, segment.Committed - segment.Start, ClrMemoryRegionType.GCSegment, (uint)i, type);
yield return new MemoryRegion(this, segment.Committed, segment.Reserved - segment.Committed, ClrMemoryRegionType.ReservedGCSegment, (uint)i, type);
if (segment.Address == segment.Next || segment.Address == 0)
segment = null;
else
segment = GetSegmentData(segment.Next);
}
segment = GetSegmentData(heaps[i].FirstLargeHeapSegment);
while (segment != null && max-- > 0)
{
Debug.Assert(segment.Start < segment.Committed);
Debug.Assert(segment.Committed <= segment.Reserved);
yield return new MemoryRegion(this, segment.Start, segment.Committed - segment.Start, ClrMemoryRegionType.GCSegment, (uint)i, GCSegmentType.LargeObject);
yield return new MemoryRegion(this, segment.Committed, segment.Reserved - segment.Committed, ClrMemoryRegionType.ReservedGCSegment, (uint)i, GCSegmentType.LargeObject);
if (segment.Address == segment.Next || segment.Address == 0)
segment = null;
else
segment = GetSegmentData(segment.Next);
}
}
// Enumerate handle table regions.
HashSet<ulong> regions = new HashSet<ulong>();
foreach (ClrHandle handle in EnumerateHandles())
{
VirtualQueryData vq;
if (!_dataReader.VirtualQuery(handle.Address, out vq))
continue;
if (regions.Contains(vq.BaseAddress))
continue;
regions.Add(vq.BaseAddress);
yield return new MemoryRegion(this, vq.BaseAddress, vq.Size, ClrMemoryRegionType.HandleTableChunk, handle.AppDomain);
}
// Enumerate each AppDomain and Module specific heap.
AppDomainHeapWalker adhw = new AppDomainHeapWalker(this);
IAppDomainData ad = GetAppDomainData(SystemDomainAddress);
foreach (MemoryRegion region in adhw.EnumerateHeaps(ad))
yield return region;
foreach (ulong module in EnumerateModules(ad))
foreach (MemoryRegion region in adhw.EnumerateModuleHeaps(ad, module))
yield return region;
ad = GetAppDomainData(SharedDomainAddress);
foreach (MemoryRegion region in adhw.EnumerateHeaps(ad))
yield return region;
foreach (ulong module in EnumerateModules(ad))
foreach (MemoryRegion region in adhw.EnumerateModuleHeaps(ad, module))
yield return region;
IAppDomainStoreData ads = GetAppDomainStoreData();
if (ads != null)
{
IList<ulong> appDomains = GetAppDomainList(ads.Count);
if (appDomains != null)
{
foreach (ulong addr in appDomains)
{
ad = GetAppDomainData(addr);
foreach (MemoryRegion region in adhw.EnumerateHeaps(ad))
yield return region;
foreach (ulong module in EnumerateModules(ad))
foreach (MemoryRegion region in adhw.EnumerateModuleHeaps(ad, module))
yield return region;
}
}
}
// Enumerate each JIT code heap.
regions.Clear();
foreach (ICodeHeap jitHeap in EnumerateJitHeaps())
{
if (jitHeap.Type == CodeHeapType.Host)
{
VirtualQueryData vq;
if (_dataReader.VirtualQuery(jitHeap.Address, out vq))
yield return new MemoryRegion(this, vq.BaseAddress, vq.Size, ClrMemoryRegionType.JitHostCodeHeap);
else
yield return new MemoryRegion(this, jitHeap.Address, 0, ClrMemoryRegionType.JitHostCodeHeap);
}
else if (jitHeap.Type == CodeHeapType.Loader)
{
foreach (MemoryRegion region in adhw.EnumerateJitHeap(jitHeap.Address))
yield return region;
}
}
}