Skip to content

Commit 44a6dd2

Browse files
authored
[cDAC] implement GetGCHeapDetails and GetGCHeapStaticData (#119119)
* Implement GetGCHeapDetails * Implement GetGCHeapStaticData * Expand GC data descriptor
1 parent 77ed0f6 commit 44a6dd2

File tree

14 files changed

+967
-30
lines changed

14 files changed

+967
-30
lines changed

docs/design/datacontracts/GC.md

Lines changed: 276 additions & 14 deletions
Large diffs are not rendered by default.

src/coreclr/gc/datadescriptor/datadescriptor.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,43 @@ namespace GC_NAMESPACE {
2828

2929
// On non-MSVC builds explicit specializations must be declared in the namespace the template was defined.
3030
// Due to the gc being built into coreclr, cdac_data must be defined in the global scope.
31+
32+
#ifdef SERVER_GC
33+
#define GC_HEAP_FIELD(cdacName, fieldName) static constexpr size_t cdacName = offsetof(GC_NAMESPACE::gc_heap, fieldName);
34+
#else // !SERVER_GC
35+
#define GC_HEAP_FIELD(cdacName, fieldName) static constexpr decltype(&GC_NAMESPACE::gc_heap::fieldName) cdacName = &GC_NAMESPACE::gc_heap::fieldName;
36+
#endif // !SERVER_GC
37+
3138
template<>
3239
struct cdac_data<GC_NAMESPACE::gc_heap>
3340
{
34-
#ifdef MULTIPLE_HEAPS
41+
#ifdef BACKGROUND_GC
42+
static constexpr c_gc_state* CurrentGCState = const_cast<c_gc_state*>(&GC_NAMESPACE::gc_heap::current_c_gc_state);
43+
#endif // BACKGROUND_GC
44+
#ifdef SERVER_GC
3545
static constexpr GC_NAMESPACE::gc_heap*** Heaps = &GC_NAMESPACE::gc_heap::g_heaps;
36-
#endif // MULTIPLE_HEAPS
46+
#endif // SERVER_GC
47+
48+
GC_HEAP_FIELD(MarkArray, mark_array)
49+
GC_HEAP_FIELD(NextSweepObj, next_sweep_obj)
50+
GC_HEAP_FIELD(BackgroundMinSavedAddr, background_saved_lowest_address)
51+
GC_HEAP_FIELD(BackgroundMaxSavedAddr, background_saved_highest_address)
52+
GC_HEAP_FIELD(AllocAllocated, alloc_allocated)
53+
GC_HEAP_FIELD(EphemeralHeapSegment, ephemeral_heap_segment)
54+
GC_HEAP_FIELD(CardTable, card_table)
55+
GC_HEAP_FIELD(FinalizeQueue, finalize_queue)
56+
57+
GC_HEAP_FIELD(GenerationTable, generation_table)
58+
59+
#ifndef USE_REGIONS
60+
GC_HEAP_FIELD(SavedSweepEphemeralSeg, saved_sweep_ephemeral_seg)
61+
GC_HEAP_FIELD(SavedSweepEphemeralStart, saved_sweep_ephemeral_start)
62+
#endif // !USE_REGIONS
63+
};
64+
65+
template<>
66+
struct cdac_data<GC_NAMESPACE::CFinalize>
67+
{
68+
static constexpr size_t FillPointers = offsetof(GC_NAMESPACE::CFinalize, m_FillPointers);
69+
static constexpr size_t FillPointersLength = sizeof(GC_NAMESPACE::CFinalize::m_FillPointers) / sizeof(GC_NAMESPACE::CFinalize::m_FillPointers[0]);
3770
};

src/coreclr/gc/datadescriptor/datadescriptor.inc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,61 @@
1010
CDAC_BASELINE("empty")
1111
CDAC_TYPES_BEGIN()
1212

13+
#ifdef SERVER_GC
14+
CDAC_TYPE_BEGIN(GCHeap)
15+
CDAC_TYPE_INDETERMINATE(GCHeap)
16+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, MarkArray, cdac_data<GC_NAMESPACE::gc_heap>::MarkArray)
17+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, NextSweepObj, cdac_data<GC_NAMESPACE::gc_heap>::NextSweepObj)
18+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, BackgroundMinSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMinSavedAddr)
19+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, BackgroundMaxSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMaxSavedAddr)
20+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, AllocAllocated, cdac_data<GC_NAMESPACE::gc_heap>::AllocAllocated)
21+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, EphemeralHeapSegment, cdac_data<GC_NAMESPACE::gc_heap>::EphemeralHeapSegment)
22+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, CardTable, cdac_data<GC_NAMESPACE::gc_heap>::CardTable)
23+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, FinalizeQueue, cdac_data<GC_NAMESPACE::gc_heap>::FinalizeQueue)
24+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, GenerationTable, cdac_data<GC_NAMESPACE::gc_heap>::GenerationTable)
25+
#ifndef USE_REGIONS
26+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, SavedSweepEphemeralSeg, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralSeg)
27+
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, SavedSweepEphemeralStart, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralStart)
28+
#endif // !USE_REGIONS
29+
CDAC_TYPE_END(GCHeap)
30+
#endif // SERVER_GC
31+
32+
CDAC_TYPE_BEGIN(Generation)
33+
CDAC_TYPE_SIZE(sizeof(GC_NAMESPACE::generation))
34+
CDAC_TYPE_FIELD(Generation, /*AllocContext*/, AllocationContext, offsetof(GC_NAMESPACE::generation, allocation_context))
35+
CDAC_TYPE_FIELD(Generation, /*pointer*/, StartSegment, offsetof(GC_NAMESPACE::generation, start_segment))
36+
#ifndef USE_REGIONS
37+
CDAC_TYPE_FIELD(Generation, /*pointer*/, AllocationStart, offsetof(GC_NAMESPACE::generation, allocation_start))
38+
#endif // !USE_REGIONS
39+
CDAC_TYPE_END(Generation)
40+
41+
CDAC_TYPE_BEGIN(CFinalize)
42+
CDAC_TYPE_INDETERMINATE(CFinalize)
43+
CDAC_TYPE_FIELD(CFinalize, /*pointer*/, FillPointers, cdac_data<GC_NAMESPACE::CFinalize>::FillPointers)
44+
CDAC_TYPE_END(CFinalize)
45+
1346
CDAC_TYPES_END()
1447

1548
CDAC_GLOBALS_BEGIN()
1649

50+
CDAC_GLOBAL(TotalGenerationCount, /*uint32*/, (uint32_t)total_generation_count)
51+
CDAC_GLOBAL(CFinalizeFillPointersLength, /*uint32*/, (uint32_t)cdac_data<GC_NAMESPACE::CFinalize>::FillPointersLength)
52+
53+
#ifndef SERVER_GC
54+
CDAC_GLOBAL_POINTER(GCHeapMarkArray, cdac_data<GC_NAMESPACE::gc_heap>::MarkArray)
55+
CDAC_GLOBAL_POINTER(GCHeapNextSweepObj, cdac_data<GC_NAMESPACE::gc_heap>::NextSweepObj)
56+
CDAC_GLOBAL_POINTER(GCHeapBackgroundMinSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMinSavedAddr)
57+
CDAC_GLOBAL_POINTER(GCHeapBackgroundMaxSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMaxSavedAddr)
58+
CDAC_GLOBAL_POINTER(GCHeapAllocAllocated, cdac_data<GC_NAMESPACE::gc_heap>::AllocAllocated)
59+
CDAC_GLOBAL_POINTER(GCHeapEphemeralHeapSegment, cdac_data<GC_NAMESPACE::gc_heap>::EphemeralHeapSegment)
60+
CDAC_GLOBAL_POINTER(GCHeapCardTable, cdac_data<GC_NAMESPACE::gc_heap>::CardTable)
61+
CDAC_GLOBAL_POINTER(GCHeapFinalizeQueue, cdac_data<GC_NAMESPACE::gc_heap>::FinalizeQueue)
62+
CDAC_GLOBAL_POINTER(GCHeapGenerationTable, cdac_data<GC_NAMESPACE::gc_heap>::GenerationTable)
63+
#ifndef USE_REGIONS
64+
CDAC_GLOBAL_POINTER(GCHeapSavedSweepEphemeralSeg, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralSeg)
65+
CDAC_GLOBAL_POINTER(GCHeapSavedSweepEphemeralStart, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralStart)
66+
#endif // !USE_REGIONS
67+
#endif // !SERVER_GC
1768

1869
#ifdef SERVER_GC
1970
#define GC_TYPE server
@@ -30,7 +81,12 @@ CDAC_GLOBALS_BEGIN()
3081
// CDAC_GLOBAL_STRING takes a single value argument.
3182
// To avoid issues with commas in the string we wrap the input string in a macro.
3283
#define GC_IDENTIFIER(...) __VA_ARGS__ // GC_IDENTIFIER(gc, heap) expands to: gc, heap
84+
85+
#ifdef BACKGROUND_GC
86+
CDAC_GLOBAL_STRING(GCIdentifiers, GC_IDENTIFIER(GC_TYPE, HEAP_TYPE, background))
87+
#else
3388
CDAC_GLOBAL_STRING(GCIdentifiers, GC_IDENTIFIER(GC_TYPE, HEAP_TYPE))
89+
#endif // BACKGROUND_GC
3490

3591
CDAC_GLOBAL_POINTER(MaxGeneration, &::g_max_generation)
3692
CDAC_GLOBAL_POINTER(StructureInvalidCount, &GCScan::m_GcStructuresInvalidCnt)
@@ -40,4 +96,8 @@ CDAC_GLOBAL_POINTER(NumHeaps, &GC_NAMESPACE::gc_heap::n_heaps)
4096
CDAC_GLOBAL_POINTER(Heaps, cdac_data<GC_NAMESPACE::gc_heap>::Heaps)
4197
#endif // SERVER_GC
4298

99+
#ifdef BACKGROUND_GC
100+
CDAC_GLOBAL_POINTER(CurrentGCState, cdac_data<GC_NAMESPACE::gc_heap>::CurrentGCState)
101+
#endif // BACKGROUND_GC
102+
43103
CDAC_GLOBALS_END()

src/coreclr/gc/gcpriv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5680,6 +5680,7 @@ class CFinalize
56805680
{
56815681

56825682
friend class CFinalizeStaticAsserts;
5683+
friend struct ::cdac_data<CFinalize>;
56835684

56845685
private:
56855686

src/coreclr/vm/datadescriptor/datadescriptor.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,9 @@ CDAC_GLOBAL_POINTER(PlatformMetadata, &::g_cdacPlatformMetadata)
10051005
CDAC_GLOBAL_POINTER(ProfilerControlBlock, &::g_profControlBlock)
10061006
CDAC_GLOBAL_POINTER(MethodDescSizeTable, &MethodDesc::s_ClassificationSizeTable)
10071007

1008+
CDAC_GLOBAL_POINTER(GCLowestAddress, &g_lowest_address)
1009+
CDAC_GLOBAL_POINTER(GCHighestAddress, &g_highest_address)
1010+
10081011
CDAC_GLOBAL_SUB_DESCRIPTOR(GC, &(g_gc_dac_vars.gc_descriptor))
10091012

10101013
CDAC_GLOBALS_END()

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IGC.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,62 @@
66

77
namespace Microsoft.Diagnostics.DataContractReader.Contracts;
88

9-
public class GCIdentifiers
9+
public static class GCIdentifiers
1010
{
1111
public const string Server = "server";
1212
public const string Workstation = "workstation";
1313

1414
public const string Regions = "regions";
1515
public const string Segments = "segments";
16+
17+
public const string Background = "background";
18+
}
19+
20+
public readonly struct GCHeapData
21+
{
22+
public TargetPointer MarkArray { get; init; }
23+
public TargetPointer NextSweepObject { get; init; }
24+
public TargetPointer BackGroundSavedMinAddress { get; init; }
25+
public TargetPointer BackGroundSavedMaxAddress { get; init; }
26+
27+
public TargetPointer AllocAllocated { get; init; }
28+
public TargetPointer EphemeralHeapSegment { get; init; }
29+
public TargetPointer CardTable { get; init; }
30+
public IReadOnlyList<GCGenerationData> GenerationTable { get; init; }
31+
32+
public IReadOnlyList<TargetPointer> FillPointers { get; init; }
33+
34+
// Fields only valid in segment GC builds
35+
public TargetPointer SavedSweepEphemeralSegment { get; init; }
36+
public TargetPointer SavedSweepEphemeralStart { get; init; }
37+
}
38+
39+
public readonly struct GCGenerationData
40+
{
41+
public TargetPointer StartSegment { get; init; }
42+
public TargetPointer AllocationStart { get; init; }
43+
public TargetPointer AllocationContextPointer { get; init; }
44+
public TargetPointer AllocationContextLimit { get; init; }
1645
}
1746

1847
public interface IGC : IContract
1948
{
2049
static string IContract.Name { get; } = nameof(GC);
2150

2251
string[] GetGCIdentifiers() => throw new NotImplementedException();
52+
2353
uint GetGCHeapCount() => throw new NotImplementedException();
2454
bool GetGCStructuresValid() => throw new NotImplementedException();
2555
uint GetMaxGeneration() => throw new NotImplementedException();
56+
void GetGCBounds(out TargetPointer minAddr, out TargetPointer maxAddr) => throw new NotImplementedException();
57+
uint GetCurrentGCState() => throw new NotImplementedException();
2658
IEnumerable<TargetPointer> GetGCHeaps() => throw new NotImplementedException();
59+
60+
/* WKS only APIs */
61+
GCHeapData WKSGetHeapData() => throw new NotImplementedException();
62+
63+
/* SVR only APIs */
64+
GCHeapData SVRGetHeapData(TargetPointer heapAddress) => throw new NotImplementedException();
2765
}
2866

2967
public readonly struct GC : IGC

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public enum DataType
1919
nuint,
2020
pointer,
2121

22+
/* VM Data Types */
23+
2224
GCHandle,
2325
CodePointer,
2426
Thread,
@@ -129,4 +131,11 @@ public enum DataType
129131
HijackFrame,
130132
TailCallFrame,
131133
StubDispatchFrame,
134+
135+
136+
/* GC Data Types */
137+
138+
GCHeap,
139+
Generation,
140+
CFinalize,
132141
}

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public static class Globals
7474
public const string OperatingSystem = nameof(OperatingSystem);
7575

7676
public const string GCInfoVersion = nameof(GCInfoVersion);
77+
public const string GCLowestAddress = nameof(GCLowestAddress);
78+
public const string GCHighestAddress = nameof(GCHighestAddress);
7779

7880
// Globals found on GCDescriptor
7981
// see src/coreclr/gc/datadescriptors/datadescriptor.inc
@@ -82,6 +84,21 @@ public static class Globals
8284
public const string StructureInvalidCount = nameof(StructureInvalidCount);
8385
public const string NumHeaps = nameof(NumHeaps);
8486
public const string Heaps = nameof(Heaps);
87+
public const string CurrentGCState = nameof(CurrentGCState);
88+
public const string CFinalizeFillPointersLength = nameof(CFinalizeFillPointersLength);
89+
public const string TotalGenerationCount = nameof(TotalGenerationCount);
90+
91+
public const string GCHeapMarkArray = nameof(GCHeapMarkArray);
92+
public const string GCHeapNextSweepObj = nameof(GCHeapNextSweepObj);
93+
public const string GCHeapBackgroundMinSavedAddr = nameof(GCHeapBackgroundMinSavedAddr);
94+
public const string GCHeapBackgroundMaxSavedAddr = nameof(GCHeapBackgroundMaxSavedAddr);
95+
public const string GCHeapAllocAllocated = nameof(GCHeapAllocAllocated);
96+
public const string GCHeapEphemeralHeapSegment = nameof(GCHeapEphemeralHeapSegment);
97+
public const string GCHeapCardTable = nameof(GCHeapCardTable);
98+
public const string GCHeapFinalizeQueue = nameof(GCHeapFinalizeQueue);
99+
public const string GCHeapGenerationTable = nameof(GCHeapGenerationTable);
100+
public const string GCHeapSavedSweepEphemeralSeg = nameof(GCHeapSavedSweepEphemeralSeg);
101+
public const string GCHeapSavedSweepEphemeralStart = nameof(GCHeapSavedSweepEphemeralStart);
85102
}
86103
public static class FieldNames
87104
{

0 commit comments

Comments
 (0)