Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
290 changes: 276 additions & 14 deletions docs/design/datacontracts/GC.md

Large diffs are not rendered by default.

37 changes: 35 additions & 2 deletions src/coreclr/gc/datadescriptor/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,43 @@ namespace GC_NAMESPACE {

// On non-MSVC builds explicit specializations must be declared in the namespace the template was defined.
// Due to the gc being built into coreclr, cdac_data must be defined in the global scope.

#ifdef SERVER_GC
#define GC_HEAP_FIELD(cdacName, fieldName) static constexpr size_t cdacName = offsetof(GC_NAMESPACE::gc_heap, fieldName);
#else // !SERVER_GC
#define GC_HEAP_FIELD(cdacName, fieldName) static constexpr decltype(&GC_NAMESPACE::gc_heap::fieldName) cdacName = &GC_NAMESPACE::gc_heap::fieldName;
#endif // !SERVER_GC

template<>
struct cdac_data<GC_NAMESPACE::gc_heap>
{
#ifdef MULTIPLE_HEAPS
#ifdef BACKGROUND_GC
static constexpr c_gc_state* CurrentGCState = const_cast<c_gc_state*>(&GC_NAMESPACE::gc_heap::current_c_gc_state);
#endif // BACKGROUND_GC
#ifdef SERVER_GC
static constexpr GC_NAMESPACE::gc_heap*** Heaps = &GC_NAMESPACE::gc_heap::g_heaps;
#endif // MULTIPLE_HEAPS
#endif // SERVER_GC

GC_HEAP_FIELD(MarkArray, mark_array)
GC_HEAP_FIELD(NextSweepObj, next_sweep_obj)
GC_HEAP_FIELD(BackgroundMinSavedAddr, background_saved_lowest_address)
GC_HEAP_FIELD(BackgroundMaxSavedAddr, background_saved_highest_address)
GC_HEAP_FIELD(AllocAllocated, alloc_allocated)
GC_HEAP_FIELD(EphemeralHeapSegment, ephemeral_heap_segment)
GC_HEAP_FIELD(CardTable, card_table)
GC_HEAP_FIELD(FinalizeQueue, finalize_queue)

GC_HEAP_FIELD(GenerationTable, generation_table)

#ifndef USE_REGIONS
GC_HEAP_FIELD(SavedSweepEphemeralSeg, saved_sweep_ephemeral_seg)
GC_HEAP_FIELD(SavedSweepEphemeralStart, saved_sweep_ephemeral_start)
#endif // !USE_REGIONS
};

template<>
struct cdac_data<GC_NAMESPACE::CFinalize>
{
static constexpr size_t FillPointers = offsetof(GC_NAMESPACE::CFinalize, m_FillPointers);
static constexpr size_t FillPointersLength = sizeof(GC_NAMESPACE::CFinalize::m_FillPointers) / sizeof(GC_NAMESPACE::CFinalize::m_FillPointers[0]);
};
60 changes: 60 additions & 0 deletions src/coreclr/gc/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,61 @@
CDAC_BASELINE("empty")
CDAC_TYPES_BEGIN()

#ifdef SERVER_GC
CDAC_TYPE_BEGIN(GCHeap)
CDAC_TYPE_INDETERMINATE(GCHeap)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, MarkArray, cdac_data<GC_NAMESPACE::gc_heap>::MarkArray)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, NextSweepObj, cdac_data<GC_NAMESPACE::gc_heap>::NextSweepObj)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, BackgroundMinSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMinSavedAddr)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, BackgroundMaxSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMaxSavedAddr)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, AllocAllocated, cdac_data<GC_NAMESPACE::gc_heap>::AllocAllocated)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, EphemeralHeapSegment, cdac_data<GC_NAMESPACE::gc_heap>::EphemeralHeapSegment)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, CardTable, cdac_data<GC_NAMESPACE::gc_heap>::CardTable)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, FinalizeQueue, cdac_data<GC_NAMESPACE::gc_heap>::FinalizeQueue)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, GenerationTable, cdac_data<GC_NAMESPACE::gc_heap>::GenerationTable)
#ifndef USE_REGIONS
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, SavedSweepEphemeralSeg, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralSeg)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, SavedSweepEphemeralStart, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralStart)
#endif // !USE_REGIONS
CDAC_TYPE_END(GCHeap)
#endif // SERVER_GC

CDAC_TYPE_BEGIN(Generation)
CDAC_TYPE_SIZE(sizeof(GC_NAMESPACE::generation))
CDAC_TYPE_FIELD(Generation, /*AllocContext*/, AllocationContext, offsetof(GC_NAMESPACE::generation, allocation_context))
CDAC_TYPE_FIELD(Generation, /*pointer*/, StartSegment, offsetof(GC_NAMESPACE::generation, start_segment))
#ifndef USE_REGIONS
CDAC_TYPE_FIELD(Generation, /*pointer*/, AllocationStart, offsetof(GC_NAMESPACE::generation, allocation_start))
#endif // !USE_REGIONS
CDAC_TYPE_END(Generation)

CDAC_TYPE_BEGIN(CFinalize)
CDAC_TYPE_INDETERMINATE(CFinalize)
CDAC_TYPE_FIELD(CFinalize, /*pointer*/, FillPointers, cdac_data<GC_NAMESPACE::CFinalize>::FillPointers)
CDAC_TYPE_END(CFinalize)

CDAC_TYPES_END()

CDAC_GLOBALS_BEGIN()

CDAC_GLOBAL(TotalGenerationCount, /*uint32*/, (uint32_t)total_generation_count)
CDAC_GLOBAL(CFinalizeFillPointersLength, /*uint32*/, (uint32_t)cdac_data<GC_NAMESPACE::CFinalize>::FillPointersLength)

#ifndef SERVER_GC
CDAC_GLOBAL_POINTER(GCHeapMarkArray, cdac_data<GC_NAMESPACE::gc_heap>::MarkArray)
CDAC_GLOBAL_POINTER(GCHeapNextSweepObj, cdac_data<GC_NAMESPACE::gc_heap>::NextSweepObj)
CDAC_GLOBAL_POINTER(GCHeapBackgroundMinSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMinSavedAddr)
CDAC_GLOBAL_POINTER(GCHeapBackgroundMaxSavedAddr, cdac_data<GC_NAMESPACE::gc_heap>::BackgroundMaxSavedAddr)
CDAC_GLOBAL_POINTER(GCHeapAllocAllocated, cdac_data<GC_NAMESPACE::gc_heap>::AllocAllocated)
CDAC_GLOBAL_POINTER(GCHeapEphemeralHeapSegment, cdac_data<GC_NAMESPACE::gc_heap>::EphemeralHeapSegment)
CDAC_GLOBAL_POINTER(GCHeapCardTable, cdac_data<GC_NAMESPACE::gc_heap>::CardTable)
CDAC_GLOBAL_POINTER(GCHeapFinalizeQueue, cdac_data<GC_NAMESPACE::gc_heap>::FinalizeQueue)
CDAC_GLOBAL_POINTER(GCHeapGenerationTable, cdac_data<GC_NAMESPACE::gc_heap>::GenerationTable)
#ifndef USE_REGIONS
CDAC_GLOBAL_POINTER(GCHeapSavedSweepEphemeralSeg, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralSeg)
CDAC_GLOBAL_POINTER(GCHeapSavedSweepEphemeralStart, cdac_data<GC_NAMESPACE::gc_heap>::SavedSweepEphemeralStart)
#endif // !USE_REGIONS
#endif // !SERVER_GC

#ifdef SERVER_GC
#define GC_TYPE server
Expand All @@ -30,7 +81,12 @@ CDAC_GLOBALS_BEGIN()
// CDAC_GLOBAL_STRING takes a single value argument.
// To avoid issues with commas in the string we wrap the input string in a macro.
#define GC_IDENTIFIER(...) __VA_ARGS__ // GC_IDENTIFIER(gc, heap) expands to: gc, heap

#ifdef BACKGROUND_GC
CDAC_GLOBAL_STRING(GCIdentifiers, GC_IDENTIFIER(GC_TYPE, HEAP_TYPE, background))
#else
CDAC_GLOBAL_STRING(GCIdentifiers, GC_IDENTIFIER(GC_TYPE, HEAP_TYPE))
#endif // BACKGROUND_GC

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

#ifdef BACKGROUND_GC
CDAC_GLOBAL_POINTER(CurrentGCState, cdac_data<GC_NAMESPACE::gc_heap>::CurrentGCState)
#endif // BACKGROUND_GC

CDAC_GLOBALS_END()
1 change: 1 addition & 0 deletions src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -5680,6 +5680,7 @@ class CFinalize
{

friend class CFinalizeStaticAsserts;
friend struct ::cdac_data<CFinalize>;

private:

Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,9 @@ CDAC_GLOBAL_POINTER(PlatformMetadata, &::g_cdacPlatformMetadata)
CDAC_GLOBAL_POINTER(ProfilerControlBlock, &::g_profControlBlock)
CDAC_GLOBAL_POINTER(MethodDescSizeTable, &MethodDesc::s_ClassificationSizeTable)

CDAC_GLOBAL_POINTER(GCLowestAddress, &g_lowest_address)
CDAC_GLOBAL_POINTER(GCHighestAddress, &g_highest_address)

CDAC_GLOBAL_SUB_DESCRIPTOR(GC, &(g_gc_dac_vars.gc_descriptor))

CDAC_GLOBALS_END()
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,62 @@

namespace Microsoft.Diagnostics.DataContractReader.Contracts;

public class GCIdentifiers
public static class GCIdentifiers
{
public const string Server = "server";
public const string Workstation = "workstation";

public const string Regions = "regions";
public const string Segments = "segments";

public const string Background = "background";
}

public readonly struct GCHeapData
{
public TargetPointer MarkArray { get; init; }
public TargetPointer NextSweepObject { get; init; }
public TargetPointer BackGroundSavedMinAddress { get; init; }
public TargetPointer BackGroundSavedMaxAddress { get; init; }

public TargetPointer AllocAllocated { get; init; }
public TargetPointer EphemeralHeapSegment { get; init; }
public TargetPointer CardTable { get; init; }
public IReadOnlyList<GCGenerationData> GenerationTable { get; init; }

public IReadOnlyList<TargetPointer> FillPointers { get; init; }

// Fields only valid in segment GC builds
public TargetPointer SavedSweepEphemeralSegment { get; init; }
public TargetPointer SavedSweepEphemeralStart { get; init; }
}

public readonly struct GCGenerationData
{
public TargetPointer StartSegment { get; init; }
public TargetPointer AllocationStart { get; init; }
public TargetPointer AllocationContextPointer { get; init; }
public TargetPointer AllocationContextLimit { get; init; }
}

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

string[] GetGCIdentifiers() => throw new NotImplementedException();

uint GetGCHeapCount() => throw new NotImplementedException();
bool GetGCStructuresValid() => throw new NotImplementedException();
uint GetMaxGeneration() => throw new NotImplementedException();
void GetGCBounds(out TargetPointer minAddr, out TargetPointer maxAddr) => throw new NotImplementedException();
uint GetCurrentGCState() => throw new NotImplementedException();
IEnumerable<TargetPointer> GetGCHeaps() => throw new NotImplementedException();

/* WKS only APIs */
GCHeapData WKSGetHeapData() => throw new NotImplementedException();

/* SVR only APIs */
GCHeapData SVRGetHeapData(TargetPointer heapAddress) => throw new NotImplementedException();
}

public readonly struct GC : IGC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public enum DataType
nuint,
pointer,

/* VM Data Types */

GCHandle,
CodePointer,
Thread,
Expand Down Expand Up @@ -129,4 +131,11 @@ public enum DataType
HijackFrame,
TailCallFrame,
StubDispatchFrame,


/* GC Data Types */

GCHeap,
Generation,
CFinalize,
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public static class Globals
public const string OperatingSystem = nameof(OperatingSystem);

public const string GCInfoVersion = nameof(GCInfoVersion);
public const string GCLowestAddress = nameof(GCLowestAddress);
public const string GCHighestAddress = nameof(GCHighestAddress);

// Globals found on GCDescriptor
// see src/coreclr/gc/datadescriptors/datadescriptor.inc
Expand All @@ -82,6 +84,21 @@ public static class Globals
public const string StructureInvalidCount = nameof(StructureInvalidCount);
public const string NumHeaps = nameof(NumHeaps);
public const string Heaps = nameof(Heaps);
public const string CurrentGCState = nameof(CurrentGCState);
public const string CFinalizeFillPointersLength = nameof(CFinalizeFillPointersLength);
public const string TotalGenerationCount = nameof(TotalGenerationCount);

public const string GCHeapMarkArray = nameof(GCHeapMarkArray);
public const string GCHeapNextSweepObj = nameof(GCHeapNextSweepObj);
public const string GCHeapBackgroundMinSavedAddr = nameof(GCHeapBackgroundMinSavedAddr);
public const string GCHeapBackgroundMaxSavedAddr = nameof(GCHeapBackgroundMaxSavedAddr);
public const string GCHeapAllocAllocated = nameof(GCHeapAllocAllocated);
public const string GCHeapEphemeralHeapSegment = nameof(GCHeapEphemeralHeapSegment);
public const string GCHeapCardTable = nameof(GCHeapCardTable);
public const string GCHeapFinalizeQueue = nameof(GCHeapFinalizeQueue);
public const string GCHeapGenerationTable = nameof(GCHeapGenerationTable);
public const string GCHeapSavedSweepEphemeralSeg = nameof(GCHeapSavedSweepEphemeralSeg);
public const string GCHeapSavedSweepEphemeralStart = nameof(GCHeapSavedSweepEphemeralStart);
}
public static class FieldNames
{
Expand Down
Loading