From 2e58dc6f59bed4ec1b17053eb8e7f5d6c4721378 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Tue, 20 Jul 2021 16:05:24 -0700 Subject: [PATCH 1/4] Make sure ServerGCHeapDetails is up to date --- src/coreclr/debug/daccess/request.cpp | 27 ++--- src/coreclr/debug/daccess/request_common.h | 110 ++++++++++++++++++--- src/coreclr/debug/daccess/request_svr.cpp | 83 +++++++++++----- src/coreclr/gc/gc.cpp | 41 +++++++- src/coreclr/gc/gcinterface.dac.h | 7 ++ src/coreclr/gc/gcinterface.dacvars.def | 1 + src/coreclr/gc/gcpriv.h | 26 ----- 7 files changed, 222 insertions(+), 73 deletions(-) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 968664489d8909..82d0f940d32bdc 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2772,19 +2772,24 @@ ClrDataAccess::GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails * HRESULT ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) { + // Make sure ClrDataAccess::ServerGCHeapDetails() is updated as well. if (detailsData == NULL) + { return E_INVALIDARG; + } SOSDacEnter(); + detailsData->heapAddr = NULL; + detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->card_table = PTR_CDADDR(g_card_table); - detailsData->heapAddr = NULL; + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; + detailsData->alloc_allocated = (CLRDATA_ADDRESS)*g_gcDacGlobals->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)*g_gcDacGlobals->ephemeral_heap_segment; + detailsData->card_table = PTR_CDADDR(g_card_table); detailsData->mark_array = (CLRDATA_ADDRESS)*g_gcDacGlobals->mark_array; - detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; detailsData->next_sweep_obj = (CLRDATA_ADDRESS)*g_gcDacGlobals->next_sweep_obj; if (g_gcDacGlobals->saved_sweep_ephemeral_seg != nullptr) { @@ -2801,13 +2806,12 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) detailsData->background_saved_lowest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_lowest_address; detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_highest_address; + // get bounds for the different generations for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++) { DPTR(dac_generation) generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i); detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS) dac_cast(generation->start_segment); - detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS) generation->allocation_start; - DPTR(gc_alloc_context) alloc_context = dac_cast(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; @@ -4699,13 +4703,13 @@ HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned } else { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); + TADDR heapAddress = TO_TADDR(heapAddr); - if (pHeap.IsValid()) + if (heapAddress != 0) { for (unsigned int i = 0; i < numGenerationTableEntries; ++i) { - DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i); + DPTR(dac_generation) generation = ServerGenerationTableIndex(heapAddress, i); pGenerationData[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); pGenerationData[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); @@ -4749,10 +4753,11 @@ HRESULT ClrDataAccess::GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, } else { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); - - if (pHeap.IsValid()) + TADDR heapAddress = TO_TADDR(heapAddr); + if (heapAddress != 0) { + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; DPTR(uint8_t*) pFillPointerArray= dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); for (unsigned int i = 0; i < numFillPointers; ++i) diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index d5f60df957c8bc..a7ce71517aa87d 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -26,6 +26,16 @@ DPTR(T) Dereference(DPTR(T*) ptr) return __DPtr(ptr_base); } +// Indexes into the global heap table, returning a TADDR to the requested +// heap instance. +inline TADDR +HeapTableIndex(DPTR(dac_gc_heap**) heaps, size_t index) +{ + DPTR(dac_gc_heap*) heap_table = Dereference(heaps); + DPTR(dac_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(dac_gc_heap*)); + return Dereference(ptr).GetAddr(); +} + // Indexes into a given generation table, returning a DPTR to the // requested element (the element at the given index) of the table. inline DPTR(dac_generation) @@ -34,24 +44,102 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index) return TableIndex(base, index, g_gcDacGlobals->generation_size); } +// Starting .NET 6, it is possible for the gc_heap object to have different layouts +// for coreclr.dll and clrgc.dll. Instead of using assuming dac_gc_heap and gc_heap +// have identical layout, we have the gc exported an array of field offsets instead. +// These offsets could be -1, indicating the field does not exist in the current +// gc_heap being used. + +// field_offset = g_gcDacGlobals->gc_heap_field_offsets +// p_field_offset = field_offset[field_index] +// p_field = heap + p_field_offset +#define LOAD_BASE(field_name, field_index, field_type) \ + DPTR(int) p_##field_name##_offset = TableIndex(field_offsets, field_index, sizeof(int)); \ + int field_name##_offset = *p_##field_name##_offset; \ + DPTR(field_type) p_##field_name = heap + field_name##_offset; + +// if (field_offset != -1) +// result.field = *p_field +#define LOAD(field_name, field_index, field_type) \ + LOAD_BASE(field_name, field_index, field_type) \ + if (field_name##_offset != -1) \ + { \ + field_type field_name = *p_##field_name; \ + result.field_name = field_name; \ + } + +// if (field_offset != -1) +// result.field = DPTR(field_type)field_name +#define LOAD_DPTR(field_name, field_index, field_type) \ + LOAD_BASE(field_name, field_index, field_type*) \ + if (field_name##_offset != -1) \ + { \ + field_type* field_name = *p_##field_name; \ + result.field_name = DPTR(field_type)((TADDR)field_name); \ + } + +// if (field_offset != -1) +// for i from 0 to array_length - 1 +// result.field[i] = *p_field +// p_field = p_field + 1 +#define LOAD_ARRAY(field_name, field_index, field_type, array_length) \ + LOAD_BASE(field_name, field_index, field_type) \ + if (field_name##_offset != -1) \ + { \ + for (int i = 0; i < array_length; i++) \ + { \ + result.field_name[i] = *p_##field_name; \ + p_##field_name = p_##field_name + 1; \ + } \ + } + // 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) -ServerGenerationTableIndex(DPTR(dac_gc_heap) heap, size_t index) +ServerGenerationTableIndex(TADDR heap, size_t index) { - TADDR base_addr = dac_cast(heap) + offsetof(dac_gc_heap, generation_table); - DPTR(dac_generation) base = __DPtr(base_addr); - return TableIndex(base, index, g_gcDacGlobals->generation_size); + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + LOAD_BASE (generation_table, 18, dac_generation); + assert (generation_table_offset != -1); + return TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size); } -// Indexes into the global heap table, returning a DPTR to the requested -// heap instance. -inline DPTR(dac_gc_heap) -HeapTableIndex(DPTR(dac_gc_heap**) heaps, size_t index) +// Load an instance of dac_gc_heap for the heap pointed by heap. +// Fields that does not exist in the current gc_heap instance is zero initialized. +// Return the dac_gc_heap object. +inline dac_gc_heap +LoadGcHeapData(TADDR heap) { - DPTR(dac_gc_heap*) heap_table = Dereference(heaps); - DPTR(dac_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(dac_gc_heap*)); - return Dereference(ptr); + dac_gc_heap result; + memset(&result, 0, sizeof(dac_gc_heap)); + + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + + LOAD (alloc_allocated, 0, uint8_t*); + LOAD_DPTR (ephemeral_heap_segment, 1, dac_heap_segment); + LOAD_DPTR (finalize_queue, 2, dac_finalize_queue); + LOAD (oom_info, 3, oom_history); + LOAD_ARRAY(interesting_data_per_heap, 4, size_t, NUM_GC_DATA_POINTS); + LOAD_ARRAY(compact_reasons_per_heap, 5, size_t, MAX_COMPACT_REASONS_COUNT); + LOAD_ARRAY(expand_mechanisms_per_heap, 6, size_t, MAX_EXPAND_MECHANISMS_COUNT); + LOAD_ARRAY(interesting_mechanism_bits_per_heap,7, size_t, MAX_GC_MECHANISM_BITS_COUNT); + LOAD (internal_root_array, 8, uint8_t*); + LOAD (internal_root_array_index, 9, size_t); + LOAD (heap_analyze_success, 10, BOOL); + LOAD (card_table, 11, uint32_t*); + LOAD (mark_array, 12, uint32_t*); + LOAD (next_sweep_obj, 13, uint8_t*); + LOAD (background_saved_lowest_address, 14, uint8_t*); + LOAD (background_saved_highest_address, 15, uint8_t*); + LOAD_DPTR (saved_sweep_ephemeral_seg, 16, dac_heap_segment); + LOAD (saved_sweep_ephemeral_start, 17, uint8_t*); + + return result; } +#undef LOAD_ARRAY +#undef LOAD_DPTR +#undef LOAD +#undef LOAD_BASE + #endif // _REQUEST_COMMON_H_ diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index 558ac0c33471b3..e34e7e643b4e2f 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -64,7 +64,7 @@ HRESULT GetServerHeaps(CLRDATA_ADDRESS pGCHeaps[], ICorDebugDataTarget * pTarget // heap addresses. for (int i = 0; i < GCHeapCount(); i++) { - pGCHeaps[i] = (CLRDATA_ADDRESS)HeapTableIndex(g_gcDacGlobals->g_heaps, i).GetAddr(); + pGCHeaps[i] = (CLRDATA_ADDRESS)HeapTableIndex(g_gcDacGlobals->g_heaps, i); } return S_OK; @@ -86,7 +86,7 @@ HRESULT ClrDataAccess::GetServerAllocData(unsigned int count, struct DacpGenerat for (unsigned int n=0; n < heaps; n++) { - DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); + TADDR pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); for (int i=0;i(TO_TADDR(heapAddr)); - int i; + TADDR heapAddress = TO_TADDR(heapAddr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; //get global information first detailsData->heapAddr = heapAddr; detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->card_table = PTR_CDADDR(g_card_table); + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; // now get information specific to this heap (server mode gives us several heaps; we're getting // information about only one of them. detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)dac_cast(pHeap->ephemeral_heap_segment); + detailsData->card_table = (CLRDATA_ADDRESS)pHeap->card_table; + detailsData->mark_array = (CLRDATA_ADDRESS)pHeap->mark_array; + detailsData->next_sweep_obj = (CLRDATA_ADDRESS)pHeap->next_sweep_obj; + if (pHeap->saved_sweep_ephemeral_seg.IsValid()) + { + detailsData->saved_sweep_ephemeral_seg = (CLRDATA_ADDRESS)dac_cast(pHeap->saved_sweep_ephemeral_seg); + detailsData->saved_sweep_ephemeral_start = (CLRDATA_ADDRESS)*pHeap->saved_sweep_ephemeral_start; + } + else + { + // with regions, we don't have these variables anymore + // use special value -1 in saved_sweep_ephemeral_seg to signal the region case + detailsData->saved_sweep_ephemeral_seg = (CLRDATA_ADDRESS)-1; + detailsData->saved_sweep_ephemeral_start = 0; + } + detailsData->background_saved_lowest_address = (CLRDATA_ADDRESS)pHeap->background_saved_lowest_address; + detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)pHeap->background_saved_highest_address; // get bounds for the different generations - for (i=0; imax_gen + 2; i++) { - DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i); + DPTR(dac_generation) generation = ServerGenerationTableIndex(heapAddress, i); detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); @@ -134,10 +158,13 @@ HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapD } DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; - DPTR(uint8_t*) pFillPointerArray= dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for(i=0; i<(NUMBERGENERATIONS+dac_finalize_queue::ExtraSegCount); i++) + if (fq.IsValid()) { - detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS) pFillPointerArray[i]; + DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); + for (unsigned int i = 0; i<(*g_gcDacGlobals->max_gen + 2 + dac_finalize_queue::ExtraSegCount); i++) + { + detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); + } } return S_OK; @@ -146,7 +173,9 @@ HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapD HRESULT ClrDataAccess::ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData) { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(addr)); + TADDR heapAddress = TO_TADDR(addr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; oom_history pOOMInfo = pHeap->oom_info; oomData->reason = pOOMInfo.reason; @@ -193,7 +222,9 @@ HRESULT ClrDataAccess::ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr, DacpGcH return E_INVALIDARG; } - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); + TADDR heapAddress = TO_TADDR(heapAddr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; analyzeData->heapAddr = heapAddr; analyzeData->internal_root_array = (CLRDATA_ADDRESS)pHeap->internal_root_array; @@ -221,7 +252,9 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) for (int i = 0; i < heaps; i++) { - DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2); DacEnumMemoryRegion(dac_cast(pHeap), sizeof(dac_gc_heap)); @@ -235,7 +268,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(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++) { - DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(pHeap, i)->start_segment; + DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(heapAddress, i)->start_segment; while (seg) { DacEnumMemoryRegion(PTR_HOST_TO_TADDR(seg), sizeof(dac_heap_segment)); @@ -270,18 +303,20 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) for (int i = 0; i < heaps; ++i) { // Basic heap info. - DPTR(dac_gc_heap) heap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); - dac_generation gen0 = *ServerGenerationTableIndex(heap, 0); - dac_generation gen1 = *ServerGenerationTableIndex(heap, 1); - dac_generation gen2 = *ServerGenerationTableIndex(heap, 2); - dac_generation loh = *ServerGenerationTableIndex(heap, 3); - dac_generation poh = *ServerGenerationTableIndex(heap, 4); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; + dac_generation gen0 = *ServerGenerationTableIndex(heapAddress, 0); + dac_generation gen1 = *ServerGenerationTableIndex(heapAddress, 1); + dac_generation gen2 = *ServerGenerationTableIndex(heapAddress, 2); + dac_generation loh = *ServerGenerationTableIndex(heapAddress, 3); + dac_generation poh = *ServerGenerationTableIndex(heapAddress, 4); pHeaps[i].YoungestGenPtr = (CORDB_ADDRESS)gen0.allocation_context.alloc_ptr; pHeaps[i].YoungestGenLimit = (CORDB_ADDRESS)gen0.allocation_context.alloc_limit; pHeaps[i].Gen0Start = (CORDB_ADDRESS)gen0.allocation_start; - pHeaps[i].Gen0End = (CORDB_ADDRESS)heap->alloc_allocated; + pHeaps[i].Gen0End = (CORDB_ADDRESS)pHeap->alloc_allocated; pHeaps[i].Gen1Start = (CORDB_ADDRESS)gen1.allocation_start; // Segments @@ -300,9 +335,9 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) for (; seg && (j < count); ++j) { pHeaps[i].Segments[j].Start = (CORDB_ADDRESS)seg->mem; - if (seg.GetAddr() == heap->ephemeral_heap_segment.GetAddr()) + if (seg.GetAddr() == pHeap->ephemeral_heap_segment.GetAddr()) { - pHeaps[i].Segments[j].End = (CORDB_ADDRESS)heap->alloc_allocated; + pHeaps[i].Segments[j].End = (CORDB_ADDRESS)pHeap->alloc_allocated; pHeaps[i].EphemeralSegment = j; pHeaps[i].Segments[j].Generation = 1; } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index c34bc7b2fbd5d4..c8805434531c98 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45566,6 +45566,44 @@ bool GCHeap::IsConcurrentGCEnabled() #endif //BACKGROUND_GC } +#ifdef MULTIPLE_HEAPS +int gc_heap_field_offsets[] = { + offsetof(gc_heap, alloc_allocated), // 0 + offsetof(gc_heap, ephemeral_heap_segment), // 1 + offsetof(gc_heap, finalize_queue), // 2 + offsetof(gc_heap, oom_info), // 3 + offsetof(gc_heap, interesting_data_per_heap), // 4 + offsetof(gc_heap, compact_reasons_per_heap), // 5 + offsetof(gc_heap, expand_mechanisms_per_heap), // 6 + offsetof(gc_heap, interesting_mechanism_bits_per_heap), // 7 + offsetof(gc_heap, internal_root_array), // 8 + offsetof(gc_heap, internal_root_array_index), // 9 + offsetof(gc_heap, heap_analyze_success), // 10 + offsetof(gc_heap, card_table), // 11 +#ifdef BACKGROUND_GC + offsetof(gc_heap, mark_array), // 12 + offsetof(gc_heap, next_sweep_obj), // 13 + offsetof(gc_heap, background_saved_lowest_address), // 14 + offsetof(gc_heap, background_saved_highest_address), // 15 +#ifndef USE_REGIONS + offsetof(gc_heap, saved_sweep_ephemeral_seg), // 16 + offsetof(gc_heap, saved_sweep_ephemeral_start), // 17 +#else + -1, // 16 + -1, // 17 +#endif //!USE_REGIONS +#else + -1, // 12 + -1, // 13 + -1, // 14 + -1, // 15 + -1, // 16 + -1, // 17 +#endif //BACKGROUND_GC + offsetof(gc_heap, generation_table) // 18 +}; +#endif //MULTIPLE_HEAPS + void PopulateDacVars(GcDacVars *gcDacVars) { #ifndef DACCESS_COMPILE @@ -45582,10 +45620,10 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->generation_size = sizeof(generation); gcDacVars->total_generation_count = total_generation_count; gcDacVars->max_gen = &g_max_generation; + gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); #ifndef MULTIPLE_HEAPS gcDacVars->mark_array = &gc_heap::mark_array; gcDacVars->ephemeral_heap_segment = reinterpret_cast(&gc_heap::ephemeral_heap_segment); - gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); #ifdef USE_REGIONS gcDacVars->saved_sweep_ephemeral_seg = 0; gcDacVars->saved_sweep_ephemeral_start = 0; @@ -45615,6 +45653,7 @@ void PopulateDacVars(GcDacVars *gcDacVars) #else gcDacVars->n_heaps = &gc_heap::n_heaps; gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); + gcDacVars->gc_heap_field_offsets = reinterpret_cast(&gc_heap_field_offsets); #endif // MULTIPLE_HEAPS #else UNREFERENCED_PARAMETER(gcDacVars); diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index 348279b5b69110..0cdd72120fa301 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -147,6 +147,13 @@ class dac_gc_heap { uint8_t* internal_root_array; size_t internal_root_array_index; BOOL heap_analyze_success; + uint32_t* card_table; + uint32_t* mark_array; + uint8_t* next_sweep_obj; + uint8_t* background_saved_lowest_address; + uint8_t* background_saved_highest_address; + DPTR(dac_heap_segment) saved_sweep_ephemeral_seg; + uint8_t* saved_sweep_ephemeral_start; // The generation table must always be last, because the size of this array // (stored inline in the gc_heap class) can vary. diff --git a/src/coreclr/gc/gcinterface.dacvars.def b/src/coreclr/gc/gcinterface.dacvars.def index b572e6cb3764bf..fa78385b8af969 100644 --- a/src/coreclr/gc/gcinterface.dacvars.def +++ b/src/coreclr/gc/gcinterface.dacvars.def @@ -60,6 +60,7 @@ GC_DAC_ARRAY_VAR (size_t, compact_reasons_per_heap) GC_DAC_ARRAY_VAR (size_t, expand_mechanisms_per_heap) GC_DAC_ARRAY_VAR (size_t, interesting_mechanism_bits_per_heap) GC_DAC_VAR (dac_handle_table_map, handle_table_map) +GC_DAC_ARRAY_VAR (int, gc_heap_field_offsets) #undef GC_DAC_VAR #undef GC_DAC_ARRAY_VAR diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index c6d7dd668868e4..ea2249d464dccd 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3426,9 +3426,6 @@ class gc_heap GCEvent bgc_start_event; #endif //BACKGROUND_GC - // The variables in this block are known to the DAC and must come first - // in the gc_heap class. - // Keeps track of the highest address allocated by Alloc PER_HEAP uint8_t* alloc_allocated; @@ -3468,12 +3465,9 @@ class gc_heap PER_HEAP BOOL heap_analyze_success; - // The generation table. Must always be last. PER_HEAP generation generation_table [total_generation_count]; - // End DAC zone - #ifdef USE_REGIONS #ifdef STRESS_REGIONS // TODO: could consider dynamically grow this. @@ -4933,26 +4927,6 @@ class gc_heap void update_collection_counts (); }; // class gc_heap -#define ASSERT_OFFSETS_MATCH(field) \ - static_assert(offsetof(dac_gc_heap, field) == offsetof(gc_heap, field), #field " offset mismatch") - -#ifndef USE_REGIONS -#ifdef MULTIPLE_HEAPS -ASSERT_OFFSETS_MATCH(alloc_allocated); -ASSERT_OFFSETS_MATCH(ephemeral_heap_segment); -ASSERT_OFFSETS_MATCH(finalize_queue); -ASSERT_OFFSETS_MATCH(oom_info); -ASSERT_OFFSETS_MATCH(interesting_data_per_heap); -ASSERT_OFFSETS_MATCH(compact_reasons_per_heap); -ASSERT_OFFSETS_MATCH(expand_mechanisms_per_heap); -ASSERT_OFFSETS_MATCH(interesting_mechanism_bits_per_heap); -ASSERT_OFFSETS_MATCH(internal_root_array); -ASSERT_OFFSETS_MATCH(internal_root_array_index); -ASSERT_OFFSETS_MATCH(heap_analyze_success); -ASSERT_OFFSETS_MATCH(generation_table); -#endif // MULTIPLE_HEAPS -#endif //USE_REGIONS - #ifdef FEATURE_PREMORTEM_FINALIZATION class CFinalize { From c2224461ab453c952c693d4c6612e9a66aa48374 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Thu, 29 Jul 2021 15:10:34 -0700 Subject: [PATCH 2/4] Fix another compiler error --- src/coreclr/gc/gc.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index c8805434531c98..ddcc75e5a5414e 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45566,8 +45566,12 @@ bool GCHeap::IsConcurrentGCEnabled() #endif //BACKGROUND_GC } +void PopulateDacVars(GcDacVars *gcDacVars) +{ +#ifndef DACCESS_COMPILE + #ifdef MULTIPLE_HEAPS -int gc_heap_field_offsets[] = { +static int gc_heap_field_offsets[] = { offsetof(gc_heap, alloc_allocated), // 0 offsetof(gc_heap, ephemeral_heap_segment), // 1 offsetof(gc_heap, finalize_queue), // 2 @@ -45604,9 +45608,6 @@ int gc_heap_field_offsets[] = { }; #endif //MULTIPLE_HEAPS -void PopulateDacVars(GcDacVars *gcDacVars) -{ -#ifndef DACCESS_COMPILE assert(gcDacVars != nullptr); *gcDacVars = {}; // Note: these version numbers are not actually checked by SOS, so if you change From 3b5b73024e61eb420f04be131891d7b6b222d23f Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Fri, 30 Jul 2021 13:42:36 -0700 Subject: [PATCH 3/4] Some quick code review feedback --- src/coreclr/debug/daccess/request.cpp | 4 ++-- src/coreclr/debug/daccess/request_common.h | 6 +++--- src/coreclr/debug/daccess/request_svr.cpp | 4 ++-- src/coreclr/gc/gc.cpp | 2 +- src/coreclr/gc/gcinterface.dac.h | 4 ++++ src/coreclr/gc/gcinterface.dacvars.def | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 82d0f940d32bdc..4e729c8733964b 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2807,7 +2807,7 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_highest_address; // get bounds for the different generations - for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++) + 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(generation->start_segment); @@ -2821,7 +2821,7 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) { DPTR(dac_finalize_queue) fq = Dereference(g_gcDacGlobals->finalize_queue); DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for (unsigned int i = 0; i<(*g_gcDacGlobals->max_gen + 2 + dac_finalize_queue::ExtraSegCount); i++) + for (unsigned int i = 0; i < DAC_NUMBERGENERATIONS + 3; i++) { detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); } diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index a7ce71517aa87d..4abc57bb223b4d 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -29,10 +29,10 @@ DPTR(T) Dereference(DPTR(T*) ptr) // Indexes into the global heap table, returning a TADDR to the requested // heap instance. inline TADDR -HeapTableIndex(DPTR(dac_gc_heap**) heaps, size_t index) +HeapTableIndex(DPTR(opaque_gc_heap**) heaps, size_t index) { - DPTR(dac_gc_heap*) heap_table = Dereference(heaps); - DPTR(dac_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(dac_gc_heap*)); + DPTR(opaque_gc_heap*) heap_table = Dereference(heaps); + DPTR(opaque_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(void*)); return Dereference(ptr).GetAddr(); } diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index e34e7e643b4e2f..691171f3af91cb 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -147,7 +147,7 @@ ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails * detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)pHeap->background_saved_highest_address; // get bounds for the different generations - for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++) + for (unsigned int i=0; i < DAC_NUMBERGENERATIONS; i++) { DPTR(dac_generation) generation = ServerGenerationTableIndex(heapAddress, i); detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); @@ -161,7 +161,7 @@ ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails * if (fq.IsValid()) { DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for (unsigned int i = 0; i<(*g_gcDacGlobals->max_gen + 2 + dac_finalize_queue::ExtraSegCount); i++) + for (unsigned int i = 0; i < DAC_NUMBERGENERATIONS + 3; i++) { detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index ddcc75e5a5414e..75267a84aae76a 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45653,7 +45653,7 @@ static int gc_heap_field_offsets[] = { #endif // HEAP_ANALYZE #else gcDacVars->n_heaps = &gc_heap::n_heaps; - gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); + gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); gcDacVars->gc_heap_field_offsets = reinterpret_cast(&gc_heap_field_offsets); #endif // MULTIPLE_HEAPS #else diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index 0cdd72120fa301..b2426b5a1e19c4 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -169,6 +169,10 @@ class dac_gc_heap { dac_generation generation_table[1]; }; +struct opaque_gc_heap +{ + uint8_t unused; +}; // The DAC links against six symbols that build as part of the VM DACCESS_COMPILE // build. These symbols are considered to be GC-private functions, but the DAC needs diff --git a/src/coreclr/gc/gcinterface.dacvars.def b/src/coreclr/gc/gcinterface.dacvars.def index fa78385b8af969..2f27df72e1cbc0 100644 --- a/src/coreclr/gc/gcinterface.dacvars.def +++ b/src/coreclr/gc/gcinterface.dacvars.def @@ -53,7 +53,7 @@ GC_DAC_PTR_VAR (uint8_t*, internal_root_array) GC_DAC_VAR (size_t, internal_root_array_index) GC_DAC_VAR (BOOL, heap_analyze_success) GC_DAC_VAR (int, n_heaps) -GC_DAC_PTR_VAR (dac_gc_heap*, g_heaps) +GC_DAC_PTR_VAR (opaque_gc_heap*, g_heaps) GC_DAC_VAR (int32_t, gc_structures_invalid_cnt) GC_DAC_ARRAY_VAR (size_t, interesting_data_per_heap) GC_DAC_ARRAY_VAR (size_t, compact_reasons_per_heap) From 4d47b85d2018d95ba17de54197ed7f4b327055ce Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Fri, 30 Jul 2021 15:10:22 -0700 Subject: [PATCH 4/4] Eliminate redundancy --- src/coreclr/debug/daccess/request_common.h | 51 ++++++++++----------- src/coreclr/gc/gc.cpp | 52 +++++++--------------- src/coreclr/gc/gc_typefields.h | 32 +++++++++++++ src/coreclr/gc/gcinterface.dac.h | 31 ++++++------- 4 files changed, 86 insertions(+), 80 deletions(-) create mode 100644 src/coreclr/gc/gc_typefields.h diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index 4abc57bb223b4d..1b86b463802048 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -53,15 +53,17 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index) // field_offset = g_gcDacGlobals->gc_heap_field_offsets // p_field_offset = field_offset[field_index] // p_field = heap + p_field_offset -#define LOAD_BASE(field_name, field_index, field_type) \ +// field_index++ +#define LOAD_BASE(field_name, field_type) \ DPTR(int) p_##field_name##_offset = TableIndex(field_offsets, field_index, sizeof(int)); \ int field_name##_offset = *p_##field_name##_offset; \ - DPTR(field_type) p_##field_name = heap + field_name##_offset; + DPTR(field_type) p_##field_name = heap + field_name##_offset; \ + field_index++; // if (field_offset != -1) // result.field = *p_field -#define LOAD(field_name, field_index, field_type) \ - LOAD_BASE(field_name, field_index, field_type) \ +#define LOAD(field_name, field_type) \ + LOAD_BASE(field_name, field_type) \ if (field_name##_offset != -1) \ { \ field_type field_name = *p_##field_name; \ @@ -70,8 +72,8 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index) // if (field_offset != -1) // result.field = DPTR(field_type)field_name -#define LOAD_DPTR(field_name, field_index, field_type) \ - LOAD_BASE(field_name, field_index, field_type*) \ +#define LOAD_DPTR(field_name, field_type) \ + LOAD_BASE(field_name, field_type*) \ if (field_name##_offset != -1) \ { \ field_type* field_name = *p_##field_name; \ @@ -82,8 +84,8 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index) // for i from 0 to array_length - 1 // result.field[i] = *p_field // p_field = p_field + 1 -#define LOAD_ARRAY(field_name, field_index, field_type, array_length) \ - LOAD_BASE(field_name, field_index, field_type) \ +#define LOAD_ARRAY(field_name, field_type, array_length) \ + LOAD_BASE(field_name, field_type) \ if (field_name##_offset != -1) \ { \ for (int i = 0; i < array_length; i++) \ @@ -99,7 +101,8 @@ inline DPTR(dac_generation) ServerGenerationTableIndex(TADDR heap, size_t index) { DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; - LOAD_BASE (generation_table, 18, dac_generation); + int field_index = GENERATION_TABLE_FIELD_INDEX; + LOAD_BASE (generation_table, dac_generation); assert (generation_table_offset != -1); return TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size); } @@ -114,25 +117,19 @@ LoadGcHeapData(TADDR heap) memset(&result, 0, sizeof(dac_gc_heap)); DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = 0; - LOAD (alloc_allocated, 0, uint8_t*); - LOAD_DPTR (ephemeral_heap_segment, 1, dac_heap_segment); - LOAD_DPTR (finalize_queue, 2, dac_finalize_queue); - LOAD (oom_info, 3, oom_history); - LOAD_ARRAY(interesting_data_per_heap, 4, size_t, NUM_GC_DATA_POINTS); - LOAD_ARRAY(compact_reasons_per_heap, 5, size_t, MAX_COMPACT_REASONS_COUNT); - LOAD_ARRAY(expand_mechanisms_per_heap, 6, size_t, MAX_EXPAND_MECHANISMS_COUNT); - LOAD_ARRAY(interesting_mechanism_bits_per_heap,7, size_t, MAX_GC_MECHANISM_BITS_COUNT); - LOAD (internal_root_array, 8, uint8_t*); - LOAD (internal_root_array_index, 9, size_t); - LOAD (heap_analyze_success, 10, BOOL); - LOAD (card_table, 11, uint32_t*); - LOAD (mark_array, 12, uint32_t*); - LOAD (next_sweep_obj, 13, uint8_t*); - LOAD (background_saved_lowest_address, 14, uint8_t*); - LOAD (background_saved_highest_address, 15, uint8_t*); - LOAD_DPTR (saved_sweep_ephemeral_seg, 16, dac_heap_segment); - LOAD (saved_sweep_ephemeral_start, 17, uint8_t*); +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) LOAD(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) LOAD_DPTR(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) LOAD_ARRAY(field_name, field_type, array_length); + +#include "../../gc/gc_typefields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS return result; } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 75267a84aae76a..f10786003b102c 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45571,41 +45571,23 @@ void PopulateDacVars(GcDacVars *gcDacVars) #ifndef DACCESS_COMPILE #ifdef MULTIPLE_HEAPS -static int gc_heap_field_offsets[] = { - offsetof(gc_heap, alloc_allocated), // 0 - offsetof(gc_heap, ephemeral_heap_segment), // 1 - offsetof(gc_heap, finalize_queue), // 2 - offsetof(gc_heap, oom_info), // 3 - offsetof(gc_heap, interesting_data_per_heap), // 4 - offsetof(gc_heap, compact_reasons_per_heap), // 5 - offsetof(gc_heap, expand_mechanisms_per_heap), // 6 - offsetof(gc_heap, interesting_mechanism_bits_per_heap), // 7 - offsetof(gc_heap, internal_root_array), // 8 - offsetof(gc_heap, internal_root_array_index), // 9 - offsetof(gc_heap, heap_analyze_success), // 10 - offsetof(gc_heap, card_table), // 11 -#ifdef BACKGROUND_GC - offsetof(gc_heap, mark_array), // 12 - offsetof(gc_heap, next_sweep_obj), // 13 - offsetof(gc_heap, background_saved_lowest_address), // 14 - offsetof(gc_heap, background_saved_highest_address), // 15 -#ifndef USE_REGIONS - offsetof(gc_heap, saved_sweep_ephemeral_seg), // 16 - offsetof(gc_heap, saved_sweep_ephemeral_start), // 17 -#else - -1, // 16 - -1, // 17 -#endif //!USE_REGIONS -#else - -1, // 12 - -1, // 13 - -1, // 14 - -1, // 15 - -1, // 16 - -1, // 17 -#endif //BACKGROUND_GC - offsetof(gc_heap, generation_table) // 18 -}; + static int gc_heap_field_offsets[] = { + +#define DEFINE_FIELD(field_name, field_type) offsetof(gc_heap, field_name), +#define DEFINE_DPTR_FIELD(field_name, field_type) offsetof(gc_heap, field_name), +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) offsetof(gc_heap, field_name), +#define DEFINE_MISSING_FIELD -1, + +#include "gc_typefields.h" + +#undef DEFINE_MISSING_FIELD +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD + + offsetof(gc_heap, generation_table) + }; + static_assert(sizeof(gc_heap_field_offsets) == (GENERATION_TABLE_FIELD_INDEX + 1) * sizeof(int), "GENERATION_TABLE_INDEX mismatch"); #endif //MULTIPLE_HEAPS assert(gcDacVars != nullptr); diff --git a/src/coreclr/gc/gc_typefields.h b/src/coreclr/gc/gc_typefields.h new file mode 100644 index 00000000000000..f690a6cddc8ead --- /dev/null +++ b/src/coreclr/gc/gc_typefields.h @@ -0,0 +1,32 @@ +DEFINE_FIELD (alloc_allocated, uint8_t*) +DEFINE_DPTR_FIELD (ephemeral_heap_segment, dac_heap_segment) +DEFINE_DPTR_FIELD (finalize_queue, dac_finalize_queue) +DEFINE_FIELD (oom_info, oom_history) +DEFINE_ARRAY_FIELD (interesting_data_per_heap, size_t, NUM_GC_DATA_POINTS) +DEFINE_ARRAY_FIELD (compact_reasons_per_heap, size_t, MAX_COMPACT_REASONS_COUNT) +DEFINE_ARRAY_FIELD (expand_mechanisms_per_heap, size_t, MAX_EXPAND_MECHANISMS_COUNT) +DEFINE_ARRAY_FIELD (interesting_mechanism_bits_per_heap,size_t, MAX_GC_MECHANISM_BITS_COUNT) +DEFINE_FIELD (internal_root_array, uint8_t*) +DEFINE_FIELD (internal_root_array_index, size_t) +DEFINE_FIELD (heap_analyze_success, BOOL) +DEFINE_FIELD (card_table, uint32_t*) +#if defined(ALL_FIELDS) || defined(BACKGROUND_GC) +DEFINE_FIELD (mark_array, uint32_t*) +DEFINE_FIELD (next_sweep_obj, uint8_t*) +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*) +#else +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +#endif +#else +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +#endif diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index b2426b5a1e19c4..3a4697a96da2bd 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -136,24 +136,17 @@ struct oom_history // GC heap (of which there are multiple, with server GC). class dac_gc_heap { public: - uint8_t* alloc_allocated; - DPTR(dac_heap_segment) ephemeral_heap_segment; - DPTR(dac_finalize_queue) finalize_queue; - oom_history oom_info; - size_t interesting_data_per_heap[NUM_GC_DATA_POINTS]; - size_t compact_reasons_per_heap[MAX_COMPACT_REASONS_COUNT]; - size_t expand_mechanisms_per_heap[MAX_EXPAND_MECHANISMS_COUNT]; - size_t interesting_mechanism_bits_per_heap[MAX_GC_MECHANISM_BITS_COUNT]; - uint8_t* internal_root_array; - size_t internal_root_array_index; - BOOL heap_analyze_success; - uint32_t* card_table; - uint32_t* mark_array; - uint8_t* next_sweep_obj; - uint8_t* background_saved_lowest_address; - uint8_t* background_saved_highest_address; - DPTR(dac_heap_segment) saved_sweep_ephemeral_seg; - uint8_t* saved_sweep_ephemeral_start; +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) field_type field_name; +#define DEFINE_DPTR_FIELD(field_name, field_type) DPTR(field_type) field_name; +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) field_type field_name[array_length]; + +#include "gc_typefields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS // The generation table must always be last, because the size of this array // (stored inline in the gc_heap class) can vary. @@ -169,6 +162,8 @@ class dac_gc_heap { dac_generation generation_table[1]; }; +#define GENERATION_TABLE_FIELD_INDEX 18 + struct opaque_gc_heap { uint8_t unused;