From: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 25 Aug 2021 15:26:12 +0000 (-0700) Subject: [release/6.0] Fix enum memory code paths (#58076) X-Git-Tag: accepted/tizen/unified/20220110.054933~273 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba336a27669420d291df7f69aa2a11eba73147b7;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [release/6.0] Fix enum memory code paths (#58076) * Fix enum memory code paths * Fix wks enumeration Co-authored-by: Andrew Au --- diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 6ffcc76..71a7528 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -3780,24 +3780,24 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) Dereference(g_gcDacGlobals->finalize_queue).EnumMem(); // Enumerate the entire generation table, which has variable size - size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2); - DacEnumMemoryRegion(dac_cast(g_gcDacGlobals->generation_table), gen_table_size); + EnumGenerationTable(dac_cast(g_gcDacGlobals->generation_table)); if (g_gcDacGlobals->generation_table.IsValid()) { - // enumerating the generations from max (which is normally gen2) to max+1 gives you - // the segment list for all the normal segements plus the large heap segment (max+1) - // 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++) + ULONG first = IsRegion() ? 0 : (*g_gcDacGlobals->max_gen); + // enumerating the first to max + 2 gives you + // the segment list for all the normal segments plus the pinned heap segment (max + 2) + // this is the convention in the GC so it is repeated here + for (ULONG i = first; i <= *g_gcDacGlobals->max_gen + 2; i++) + { + dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i); + __DPtr seg = dac_cast(gen.start_segment); + while (seg) { - dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i); - __DPtr seg = dac_cast(gen.start_segment); - while (seg) - { - DacEnumMemoryRegion(dac_cast(seg), sizeof(dac_heap_segment)); - seg = seg->next; - } + DacEnumMemoryRegion(dac_cast(seg), sizeof(dac_heap_segment)); + seg = seg->next; } + } } } diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index e6c976f..742d24f 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -63,6 +63,15 @@ HeapTableIndex(DPTR(unused_gc_heap**) heaps, size_t index) } // if (field_offset != -1) +// p_field.EnumMem(); +#define ENUM(field_name, field_type) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + p_##field_name.EnumMem(); \ + } + +// if (field_offset != -1) // result.field = DPTR(field_type)field_name #define LOAD_DPTR(field_name, field_type) \ LOAD_BASE(field_name, field_type*) \ @@ -87,6 +96,13 @@ HeapTableIndex(DPTR(unused_gc_heap**) heaps, size_t index) } \ } +#define ENUM_ARRAY(field_name, field_type, array_length) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + DacEnumMemoryRegion(p_##field_name.GetAddr(), sizeof(field_type) * array_length); \ + } + inline bool IsRegion() { return (g_gcDacGlobals->minor_version_number & 1) != 0; @@ -121,6 +137,26 @@ LoadGcHeapData(TADDR heap) return result; } +inline void EnumGcHeap(TADDR heap) +{ + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = 0; + +#define BASE heap +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) ENUM_ARRAY(field_name, field_type, array_length) + +#include "../../gc/dac_gcheap_fields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS +#undef BASE +} + // Load an instance of dac_generation for the generation pointed by generation. // Fields that does not exist in the current generation instance is zero initialized. // Return the dac_generation object. @@ -148,6 +184,26 @@ LoadGeneration(TADDR generation) return result; } +inline void EnumGeneration(TADDR generation) +{ + DPTR(int) field_offsets = g_gcDacGlobals->generation_field_offsets; + int field_index = 0; + +#define BASE generation +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) ENUM_ARRAY(field_name, field_type, array_length) + +#include "../../gc/dac_generation_fields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS +#undef BASE +} + // Indexes into a given generation table, returning a dac_generation inline dac_generation GenerationTableIndex(DPTR(unused_generation) base, size_t index) @@ -155,10 +211,7 @@ GenerationTableIndex(DPTR(unused_generation) base, size_t index) return LoadGeneration(TableIndex(base, index, g_gcDacGlobals->generation_size).GetAddr()); } -// Indexes into a heap's generation table, given the heap instance -// and the desired index. Returns a dac_generation -inline dac_generation -ServerGenerationTableIndex(TADDR heap, size_t index) +inline TADDR ServerGenerationTableAddress(TADDR heap) { DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; int field_index = GENERATION_TABLE_FIELD_INDEX; @@ -166,9 +219,27 @@ ServerGenerationTableIndex(TADDR heap, size_t index) LOAD_BASE (generation_table, unused_generation); #undef BASE assert (generation_table_offset != -1); + return p_generation_table.GetAddr(); +} + +// Indexes into a heap's generation table, given the heap instance +// and the desired index. Returns a dac_generation +inline dac_generation +ServerGenerationTableIndex(TADDR heap, size_t index) +{ + DPTR(unused_generation) p_generation_table = ServerGenerationTableAddress(heap); return LoadGeneration(TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size).GetAddr()); } +inline void EnumGenerationTable(TADDR generation_table) +{ + DPTR(unused_generation) p_generation_table = generation_table; + for (unsigned int i = 0; i < *g_gcDacGlobals->max_gen + 2; i++) + { + EnumGeneration(TableIndex(p_generation_table, i, g_gcDacGlobals->generation_size).GetAddr()); + } +} + #undef LOAD_ARRAY #undef LOAD_DPTR #undef LOAD diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index 5ff14b0..afe3e9d 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -252,21 +252,19 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) for (int i = 0; i < heaps; i++) { - TADDR heapAddress = 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)); + EnumGcHeap(heapAddress); + TADDR generationTable = ServerGenerationTableAddress(heapAddress); + EnumGenerationTable(generationTable); DacEnumMemoryRegion(dac_cast(pHeap->finalize_queue), sizeof(dac_finalize_queue)); - TADDR taddrTable = dac_cast(pHeap) + offsetof(dac_gc_heap, generation_table); - DacEnumMemoryRegion(taddrTable, gen_table_size); - - // enumerating the generations from max (which is normally gen2) to max+1 gives you - // the segment list for all the normal segements plus the large heap segment (max+1) + ULONG first = IsRegion() ? 0 : (*g_gcDacGlobals->max_gen); + // enumerating the first to max + 2 gives you + // the segment list for all the normal segments plus the pinned heap segment (max + 2) // 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++) + for (ULONG i = first; i <= *g_gcDacGlobals->max_gen + 2; i++) { dac_generation generation = ServerGenerationTableIndex(heapAddress, i); DPTR(dac_heap_segment) seg = generation.start_segment;