Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Fix DacHeapWalker for USE_REGIONS
  • Loading branch information
cshung committed Aug 3, 2021
commit 46475d2fbb019d7bd981e682b40f32087c18a51c
127 changes: 100 additions & 27 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6468,7 +6468,9 @@ 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 +6559,9 @@ 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,6 +6743,8 @@ 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];
Expand All @@ -6754,39 +6760,90 @@ HRESULT DacHeapWalker::InitHeapDataWks(HeapData *&pHeaps, size_t &pCount)
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 +6953,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 +6967,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 +6989,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 +7002,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
14 changes: 14 additions & 0 deletions src/coreclr/debug/daccess/request_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index)
} \
}

inline bool IsRegion()
{
if (GCHeapUtilities::IsServerHeap())
{
// TODO, avoid hard coding constant
int saved_sweep_ephemeral_start_index = 17;
return g_gcDacGlobals->gc_heap_field_offsets[saved_sweep_ephemeral_start_index] == -1;
}
else
{
return g_gcDacGlobals->saved_sweep_ephemeral_start == nullptr;
}
}

// Indexes into a heap's generation table, given the heap instance
// and the desired index. Returns a DPTR to the requested element.
inline DPTR(dac_generation)
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/gc/gc_typefields.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ DEFINE_FIELD (background_saved_lowest_address, uint8_t*)
DEFINE_FIELD (background_saved_highest_address, uint8_t*)
#if defined(ALL_FIELDS) || !defined(USE_REGIONS)
DEFINE_DPTR_FIELD (saved_sweep_ephemeral_seg, dac_heap_segment)
DEFINE_FIELD (saved_sweep_ephemeral_start, uint8_t*)
// Do not add fields before this one. It's index is currently hard coded in the DAC to detect regions build
DEFINE_FIELD (saved_sweep_ephemeral_start, uint8_t*)
#else
DEFINE_MISSING_FIELD
DEFINE_MISSING_FIELD
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ class generation
static_assert(offsetof(dac_generation, allocation_context) == offsetof(generation, allocation_context), "DAC generation offset mismatch");
static_assert(offsetof(dac_generation, start_segment) == offsetof(generation, start_segment), "DAC generation offset mismatch");
#ifndef USE_REGIONS
// REGIONS TODO: make sure the debugger handles this correctly in all cases.
static_assert(offsetof(dac_generation, allocation_start) == offsetof(generation, allocation_start), "DAC generation offset mismatch");
#endif //!USE_REGIONS

Expand Down