Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 107 additions & 32 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6468,7 +6468,10 @@ HRESULT DacHeapWalker::MoveToNextObject()
mCurrObj += mCurrSize;

// Check to see if we are in the correct bounds.
if (mHeaps[mCurrHeap].Gen0Start <= mCurrObj && mHeaps[mCurrHeap].Gen0End > mCurrObj)
bool isGen0 = IsRegion() ? (mHeaps[mCurrHeap].Segments[mCurrSeg].Generation == 0) :
(mHeaps[mCurrHeap].Gen0Start <= mCurrObj && mHeaps[mCurrHeap].Gen0End > mCurrObj);

if (isGen0)
CheckAllocAndSegmentRange();

// Check to see if we've moved off the end of a segment
Expand Down Expand Up @@ -6557,7 +6560,10 @@ HRESULT DacHeapWalker::NextSegment()

mCurrObj = mHeaps[mCurrHeap].Segments[mCurrSeg].Start;

if (mHeaps[mCurrHeap].Gen0Start <= mCurrObj && mHeaps[mCurrHeap].Gen0End > mCurrObj)
bool isGen0 = IsRegion() ? (mHeaps[mCurrHeap].Segments[mCurrSeg].Generation == 0) :
(mHeaps[mCurrHeap].Gen0Start <= mCurrObj && mHeaps[mCurrHeap].Gen0End > mCurrObj);

if (isGen0)
CheckAllocAndSegmentRange();

if (!mCache.ReadMT(mCurrObj, &mCurrMT))
Expand Down Expand Up @@ -6739,54 +6745,107 @@ HRESULT DacHeapWalker::ListNearObjects(CORDB_ADDRESS obj, CORDB_ADDRESS *pPrev,

HRESULT DacHeapWalker::InitHeapDataWks(HeapData *&pHeaps, size_t &pCount)
{
bool regions = IsRegion();

// Scrape basic heap details
pCount = 1;
pHeaps = new (nothrow) HeapData[1];
if (pHeaps == NULL)
return E_OUTOFMEMORY;

dac_generation gen0 = *GenerationTableIndex(g_gcDacGlobals->generation_table, 0);
dac_generation gen1 = *GenerationTableIndex(g_gcDacGlobals->generation_table, 1);
dac_generation gen2 = *GenerationTableIndex(g_gcDacGlobals->generation_table, 2);
dac_generation loh = *GenerationTableIndex(g_gcDacGlobals->generation_table, 3);
dac_generation poh = *GenerationTableIndex(g_gcDacGlobals->generation_table, 4);
dac_generation gen0 = GenerationTableIndex(g_gcDacGlobals->generation_table, 0);
dac_generation gen1 = GenerationTableIndex(g_gcDacGlobals->generation_table, 1);
dac_generation gen2 = GenerationTableIndex(g_gcDacGlobals->generation_table, 2);
dac_generation loh = GenerationTableIndex(g_gcDacGlobals->generation_table, 3);
dac_generation poh = GenerationTableIndex(g_gcDacGlobals->generation_table, 4);

pHeaps[0].YoungestGenPtr = (CORDB_ADDRESS)gen0.allocation_context.alloc_ptr;
pHeaps[0].YoungestGenLimit = (CORDB_ADDRESS)gen0.allocation_context.alloc_limit;

pHeaps[0].Gen0Start = (CORDB_ADDRESS)gen0.allocation_start;
pHeaps[0].Gen0End = (CORDB_ADDRESS)*g_gcDacGlobals->alloc_allocated;
pHeaps[0].Gen1Start = (CORDB_ADDRESS)gen1.allocation_start;
if (!regions)
{
pHeaps[0].Gen0Start = (CORDB_ADDRESS)gen0.allocation_start;
pHeaps[0].Gen0End = (CORDB_ADDRESS)*g_gcDacGlobals->alloc_allocated;
pHeaps[0].Gen1Start = (CORDB_ADDRESS)gen1.allocation_start;
}

// Segments
int count = GetSegmentCount(loh.start_segment);
count += GetSegmentCount(poh.start_segment);
count += GetSegmentCount(gen2.start_segment);
if (regions)
{
count += GetSegmentCount(gen1.start_segment);
count += GetSegmentCount(gen0.start_segment);
}

pHeaps[0].SegmentCount = count;
pHeaps[0].Segments = new (nothrow) SegmentData[count];
if (pHeaps[0].Segments == NULL)
return E_OUTOFMEMORY;

// Small object heap segments
DPTR(dac_heap_segment) seg = gen2.start_segment;
DPTR(dac_heap_segment) seg;
int i = 0;
for (; seg && (i < count); ++i)

// Small object heap segments
if (regions)
{
pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
if (seg.GetAddr() == (TADDR)*g_gcDacGlobals->ephemeral_heap_segment)
seg = gen2.start_segment;
for (; seg && (i < count); ++i)
{
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)*g_gcDacGlobals->alloc_allocated;
pHeaps[0].Segments[i].Generation = 1;
pHeaps[0].EphemeralSegment = i;
pHeaps[0].Segments[i].Generation = 2;
pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)seg->allocated;

seg = seg->next;
}
else
seg = gen1.start_segment;
for (; seg && (i < count); ++i)
{
pHeaps[0].Segments[i].Generation = 1;
pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)seg->allocated;
pHeaps[0].Segments[i].Generation = 2;

seg = seg->next;
}
seg = gen0.start_segment;
for (; seg && (i < count); ++i)
{
pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
if (seg.GetAddr() == (TADDR)*g_gcDacGlobals->ephemeral_heap_segment)
{
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)*g_gcDacGlobals->alloc_allocated;
pHeaps[0].EphemeralSegment = i;
}
else
{
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)seg->allocated;
}
pHeaps[0].Segments[i].Generation = 0;

seg = seg->next;
seg = seg->next;
}
}
else
{
DPTR(dac_heap_segment) seg = gen2.start_segment;
for (; seg && (i < count); ++i)
{
pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
if (seg.GetAddr() == (TADDR)*g_gcDacGlobals->ephemeral_heap_segment)
{
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)*g_gcDacGlobals->alloc_allocated;
pHeaps[0].Segments[i].Generation = 1;
pHeaps[0].EphemeralSegment = i;
}
else
{
pHeaps[0].Segments[i].End = (CORDB_ADDRESS)seg->allocated;
pHeaps[0].Segments[i].Generation = 2;
}

seg = seg->next;
}
}

// Large object heap segments
Expand Down Expand Up @@ -6896,6 +6955,8 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *p
size_t heapCount = 0;
HeapData *heaps = 0;

bool region = IsRegion();

#ifdef FEATURE_SVR_GC
HRESULT hr = GCHeapUtilities::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount);
#else
Expand All @@ -6908,16 +6969,20 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *p
int total = 0;
for (size_t i = 0; i < heapCount; ++i)
{
// SegmentCount is +1 due to the ephemeral segment containing more than one
// generation (Gen1 + Gen0, and sometimes part of Gen2).
total += (int)heaps[i].SegmentCount + 1;

// It's possible that part of Gen2 lives on the ephemeral segment. If so,
// we need to add one more to the output.
const size_t eph = heaps[i].EphemeralSegment;
_ASSERTE(eph < heaps[i].SegmentCount);
if (heaps[i].Segments[eph].Start != heaps[i].Gen1Start)
total += (int)heaps[i].SegmentCount;
if (!region)
{
// SegmentCount is +1 due to the ephemeral segment containing more than one
// generation (Gen1 + Gen0, and sometimes part of Gen2).
total++;

// It's possible that part of Gen2 lives on the ephemeral segment. If so,
// we need to add one more to the output.
const size_t eph = heaps[i].EphemeralSegment;
_ASSERTE(eph < heaps[i].SegmentCount);
if (heaps[i].Segments[eph].Start != heaps[i].Gen1Start)
total++;
}
}

pSegments->Alloc(total);
Expand All @@ -6926,9 +6991,10 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *p
int curr = 0;
for (size_t i = 0; i < heapCount; ++i)
{
// Generation 0 is not in the segment list.
_ASSERTE(curr < total);
if (!region)
{
// Generation 0 is not in the segment list.
COR_SEGMENT &seg = (*pSegments)[curr++];
seg.start = heaps[i].Gen0Start;
seg.end = heaps[i].Gen0End;
Expand All @@ -6938,7 +7004,16 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *p

for (size_t j = 0; j < heaps[i].SegmentCount; ++j)
{
if (heaps[i].Segments[j].Generation == 1)
if (region)
{
_ASSERTE(curr < total);
COR_SEGMENT &seg = (*pSegments)[curr++];
seg.start = heaps[i].Segments[j].Start;
seg.end = heaps[i].Segments[j].End;
seg.type = (CorDebugGenerationTypes)heaps[i].Segments[j].Generation;
seg.heap = (ULONG)i;
}
else if (heaps[i].Segments[j].Generation == 1)
{
// This is the ephemeral segment. We have already written Gen0,
// now write Gen1.
Expand Down
48 changes: 24 additions & 24 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,10 @@ ClrDataAccess::GetHeapAllocData(unsigned int count, struct DacpGenerationAllocDa

if (data && count >= 1)
{
DPTR(dac_generation) table = g_gcDacGlobals->generation_table;
DPTR(unused_generation) table = g_gcDacGlobals->generation_table;
for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++)
{
dac_generation entry = *GenerationTableIndex(table, i);
dac_generation entry = GenerationTableIndex(table, i);
data[0].allocData[i].allocBytes = (CLRDATA_ADDRESS)(ULONG_PTR) entry.allocation_context.alloc_bytes;
data[0].allocData[i].allocBytesLoh = (CLRDATA_ADDRESS)(ULONG_PTR) entry.allocation_context.alloc_bytes_uoh;
}
Expand Down Expand Up @@ -2809,12 +2809,12 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData)
// get bounds for the different generations
for (unsigned int i=0; i < DAC_NUMBERGENERATIONS; i++)
{
DPTR(dac_generation) generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS) dac_cast<TADDR>(generation->start_segment);
detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS) generation->allocation_start;
DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context);
detailsData->generation_table[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context->alloc_ptr;
detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context->alloc_limit;
dac_generation generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS) dac_cast<TADDR>(generation.start_segment);
detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS) generation.allocation_start;
gc_alloc_context alloc_context = generation.allocation_context;
detailsData->generation_table[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context.alloc_ptr;
detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context.alloc_limit;
}

if (g_gcDacGlobals->finalize_queue.IsValid())
Expand Down Expand Up @@ -3790,12 +3790,12 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags)
// this is the convention in the GC so it is repeated here
for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++)
{
dac_generation *gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
__DPtr<dac_heap_segment> seg = dac_cast<TADDR>(gen->start_segment);
dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
__DPtr<dac_heap_segment> seg = dac_cast<TADDR>(gen.start_segment);
while (seg)
{
DacEnumMemoryRegion(dac_cast<TADDR>(seg), sizeof(dac_heap_segment));
seg = seg->next;
DacEnumMemoryRegion(dac_cast<TADDR>(seg), sizeof(dac_heap_segment));
seg = seg->next;
}
}
}
Expand Down Expand Up @@ -4619,14 +4619,14 @@ HRESULT ClrDataAccess::GetGenerationTable(unsigned int cGenerations, struct Dacp
{
for (unsigned int i = 0; i < numGenerationTableEntries; i++)
{
DPTR(dac_generation) generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
pGenerationData[i].start_segment = (CLRDATA_ADDRESS) dac_cast<TADDR>(generation->start_segment);
dac_generation generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
pGenerationData[i].start_segment = (CLRDATA_ADDRESS) dac_cast<TADDR>(generation.start_segment);

pGenerationData[i].allocation_start = (CLRDATA_ADDRESS) generation->allocation_start;
pGenerationData[i].allocation_start = (CLRDATA_ADDRESS) generation.allocation_start;

DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context);
pGenerationData[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context->alloc_ptr;
pGenerationData[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context->alloc_limit;
gc_alloc_context alloc_context = generation.allocation_context;
pGenerationData[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context.alloc_ptr;
pGenerationData[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context.alloc_limit;
}
}
else
Expand Down Expand Up @@ -4709,12 +4709,12 @@ HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned
{
for (unsigned int i = 0; i < numGenerationTableEntries; ++i)
{
DPTR(dac_generation) generation = ServerGenerationTableIndex(heapAddress, i);
pGenerationData[i].start_segment = (CLRDATA_ADDRESS)dac_cast<TADDR>(generation->start_segment);
pGenerationData[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start;
DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context);
pGenerationData[i].allocContextPtr = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_ptr;
pGenerationData[i].allocContextLimit = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_limit;
dac_generation generation = ServerGenerationTableIndex(heapAddress, i);
pGenerationData[i].start_segment = (CLRDATA_ADDRESS)dac_cast<TADDR>(generation.start_segment);
pGenerationData[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation.allocation_start;
gc_alloc_context alloc_context = generation.allocation_context;
pGenerationData[i].allocContextPtr = (CLRDATA_ADDRESS)(ULONG_PTR)alloc_context.alloc_ptr;
pGenerationData[i].allocContextLimit = (CLRDATA_ADDRESS)(ULONG_PTR)alloc_context.alloc_limit;
}
}
else
Expand Down
Loading