diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 968664489d8909..4e729c8733964b 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; - for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++) + // 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(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; @@ -2817,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*)); } @@ -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..1b86b463802048 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(opaque_gc_heap**) heaps, size_t index) +{ + DPTR(opaque_gc_heap*) heap_table = Dereference(heaps); + DPTR(opaque_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(void*)); + 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,99 @@ 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 +// 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; \ + field_index++; + +// if (field_offset != -1) +// result.field = *p_field +#define LOAD(field_name, field_type) \ + LOAD_BASE(field_name, 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_type) \ + LOAD_BASE(field_name, 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_type, array_length) \ + LOAD_BASE(field_name, 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; + 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); } -// 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; + int field_index = 0; + +#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; } +#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..691171f3af91cb 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; igeneration_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 < DAC_NUMBERGENERATIONS + 3; 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..f10786003b102c 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45569,6 +45569,27 @@ bool GCHeap::IsConcurrentGCEnabled() void PopulateDacVars(GcDacVars *gcDacVars) { #ifndef DACCESS_COMPILE + +#ifdef MULTIPLE_HEAPS + 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); *gcDacVars = {}; // Note: these version numbers are not actually checked by SOS, so if you change @@ -45582,10 +45603,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; @@ -45614,7 +45635,8 @@ void PopulateDacVars(GcDacVars *gcDacVars) #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 UNREFERENCED_PARAMETER(gcDacVars); 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 348279b5b69110..3a4697a96da2bd 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -136,17 +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; +#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. @@ -162,6 +162,12 @@ class dac_gc_heap { dac_generation generation_table[1]; }; +#define GENERATION_TABLE_FIELD_INDEX 18 + +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 b572e6cb3764bf..2f27df72e1cbc0 100644 --- a/src/coreclr/gc/gcinterface.dacvars.def +++ b/src/coreclr/gc/gcinterface.dacvars.def @@ -53,13 +53,14 @@ 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) 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 {