Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
34f599c
Initial plan
Copilot Feb 26, 2026
50cb033
Add ISOSMemoryEnum/SOSMemoryRegion interfaces and GC data descriptors…
Copilot Feb 26, 2026
04b43d8
Add managed Data classes, DataType entries, Constants.Globals, IGCHea…
Copilot Feb 26, 2026
4f6b717
Implement GC_1 memory region methods, SOSMemoryEnum class, and SOSDac…
Copilot Feb 26, 2026
4bbdf38
Add tests for GC memory region methods in IGC contract
Copilot Feb 26, 2026
2c5d3f5
Changes before error encountered
Copilot Feb 26, 2026
50041df
Add edge-case tests: empty buckets, multiple segments, multiple bookk…
Copilot Feb 27, 2026
6320ebd
Use TotalCpuCount instead of GetGCHeapCount for handle table slot lim…
Copilot Feb 27, 2026
a47d22d
Add extern declaration for g_totalCpuCount in datadescriptor.h to fix…
Copilot Feb 27, 2026
0e2f8c9
Revert all previous changes to start fresh from base
Copilot Feb 27, 2026
7641ef4
Merge remote-tracking branch 'origin/main' into copilot/implement-mem…
Copilot Feb 27, 2026
8c95b43
Re-implement cDAC Memory Region APIs on top of latest main with PR #1…
Copilot Feb 27, 2026
7943eab
Fix GCMemoryRegionTests to use MockMemorySpace correctly
Copilot Feb 27, 2026
d4af9be
Update GC.md documentation with new API types, data descriptors, glob…
Copilot Feb 27, 2026
6e3291f
Fix native build: add conditional compilation guards for GC fields an…
Copilot Feb 27, 2026
b3ddcf1
Fix build break: use FREE_REGION_KINDS macro instead of namespaced co…
Copilot Feb 28, 2026
99dd629
Address review feedback: use ToClrDataAddress helper, null-check memR…
Copilot Mar 2, 2026
f87a031
Merge branch 'main' into copilot/implement-memory-region-apis
max-charlamb Mar 2, 2026
f9672e8
Add cDAC dump tests for GetHandleTableMemoryRegions, GetGCBookkeeping…
Copilot Mar 2, 2026
9940359
Changes before error encountered
Copilot Mar 6, 2026
5bef595
Rename memRegion to memRegions in SOSMemoryEnum.Next and clean up sta…
Copilot Mar 7, 2026
5663378
Update SOSDacImpl memory region APIs to use DacComNullableByRef and D…
Copilot Mar 7, 2026
a845ce3
Merge main into branch, resolve SOSDacImpl.cs conflicts and remove du…
Copilot Mar 9, 2026
fa3cfed
Fix PR diff: rebase changes onto current main, remove unrelated chang…
Copilot Mar 10, 2026
e4f2b86
Rebase: reset to main with only memory region API changes
Copilot Mar 10, 2026
730f7d1
Adding _tls_index global pointer to DACVARs (#125318)
rcj1 Mar 10, 2026
eb18cbd
Run CI for all copilot/* PRs (#125380)
adamsitnik Mar 10, 2026
244947c
[coreclr] Fix LoadLibraryInitializer test (#125176)
ilonatommy Mar 10, 2026
70625ba
JIT: Fix patchpoint info out-of-bounds read for special OSR locals (#…
jakobbotsch Mar 10, 2026
17b81fe
[RyuJIT] Add a JIT flag for Portable Entry Points and set it by defau…
kg Mar 10, 2026
b359089
[main] Update dependencies from dotnet/icu, dotnet/runtime-assets (#1…
dotnet-maestro[bot] Mar 10, 2026
967848a
Emit runtime-async methods in crossgen2 (#124203)
jtschuster Mar 10, 2026
eae0993
[Wasm RyuJIT] Disable multireg ret assert on Wasm because we don't ha…
kg Mar 10, 2026
7a0ab18
Extract diagnostic reporting out of COM class generator (#125308)
DoctorKrolic Mar 10, 2026
e0b2110
Implement SVE2 non-temporal gather loads (#123890)
ylpoonlg Mar 10, 2026
23853c3
Fix Ping RoundtripTime returning 0 for TtlExpired replies (#124424)
lufen Mar 10, 2026
5e2087f
[Wasm RyuJIT] Move genHomeRegisterParams' output out of the prolog (#…
kg Mar 10, 2026
a1f023f
JIT: Stop treating GT_LCLHEAP as inherently exceptional and remove de…
Copilot Mar 10, 2026
d208296
[main] Update dependencies from dotnet/xharness (#124164)
dotnet-maestro[bot] Mar 11, 2026
52554f3
Replace AsnValueReader with ValueAsnReader and remove internal type
Copilot Mar 11, 2026
1ce2774
Update copilot-instructions with git confirmation and code-review ski…
AaronRobinsonMSFT Mar 11, 2026
f0d0c10
[cDAC] Implement SOSDacImpl.GetRCWInterfaces (#124939)
Copilot Mar 11, 2026
f2cd380
Fix Directory_Delete_MountVolume test: guard Unmount calls with Direc…
Copilot Mar 11, 2026
d938474
Add Antlr license in THIRD-PARTY-NOTICES.TXT (#125387)
am11 Mar 11, 2026
e652b3c
[wasm][coreclr] Fix vtable issue and interpreter I4/I8 arithmetic (#1…
radekdoulik Mar 11, 2026
1e26335
[LoongArch64] Place async resumption info in read-write section which…
shushanhf Mar 11, 2026
bf41314
[LoongArch64] Enable Runtime Async. (issue#124935) (#125114)
LuckyXu-HF Mar 11, 2026
94bc9a9
JIT: Fix invalid IR and weights in if-conversion (#125072)
BoyBaykiller Mar 11, 2026
65d4799
[LoongArch64] Fix the risk of boundary overflow for Unsigned GT_LE in…
LuckyXu-HF Mar 11, 2026
8bb3977
Fix source generator diagnostics to support #pragma warning disable (…
eiriktsarpalis Mar 11, 2026
98c8c2d
[wasm] Bump chrome for testing - linux: 145.0.7632.159, windows: 146.…
github-actions[bot] Mar 11, 2026
65c2efc
[wasm][coreclr] Enable async v2 in tests (#125430)
radekdoulik Mar 11, 2026
629daf6
[RyuJit Wasm] Fix Signature Generation Bug with Un-called methods (#1…
adamperlin Mar 11, 2026
0eb8e34
[cDAC] Implement GetContext and GetAppDomain on ClrDataFrame (#125064)
max-charlamb Mar 11, 2026
c6056bf
Remove duplicated SVE GatherVector APIs (#124033)
ylpoonlg Mar 11, 2026
2544925
Fix TOCTOU race in AppDomain::LoadAssembly fast-path (#125408)
AaronRobinsonMSFT Mar 11, 2026
7ca1657
arm64: Remove widening casts before truncating (#123546)
jonathandavies-arm Mar 11, 2026
7bb4b14
Align final section to file alignment, not to virtual image size (#12…
jkoritzinsky Mar 11, 2026
2815ba1
Mark Runtime_76219 GC regression test as CLRTestTargetUnsupported (#1…
Copilot Mar 11, 2026
d4f42f5
Fix a regression to collection asserting in `AssemblyChecker` (#125443)
mrvoorhe Mar 11, 2026
b8df434
Fix running native aot testing locally (#125354)
MichalStrehovsky Mar 11, 2026
d49b57a
Add html.escape to func_name in superpmi diffs report (#125442)
Copilot Mar 11, 2026
45acfa4
Support for variable sized locals in morph and lclmorph (#124516)
snickolls-arm Mar 11, 2026
40a080b
Enable devirtualization of async methods in crossgen2 (#125420)
jtschuster Mar 12, 2026
7b16483
`ref struct` ASN.1 Decoder type generation
vcsjones Mar 12, 2026
40718bc
fix #125301 (NOL bug for partial loads/stores) (#125425)
EgorBo Mar 12, 2026
b010506
arm64: Fix and/bic issue when bailing early (#125428)
jonathandavies-arm Mar 12, 2026
4c9da22
Fix crossgen2 crash on Apple mobile for InstantiatedType token resolu…
kotlarmilos Mar 12, 2026
61f6112
[browser][CoreCLR] startup helpers cleanup (#125429)
pavelsavara Mar 12, 2026
7e2a350
Add TraverseEHInfo cDAC API (#125198)
rcj1 Mar 12, 2026
2441553
Streamline `SystemIPGlobalProperties` (#125002)
pentp Mar 12, 2026
01daf7d
Convert some COM interop to UCO (#125326)
am11 Mar 12, 2026
d8ae323
[clr-interp] Fix Swift error handling for marshaled P/Invokes in inte…
kotlarmilos Mar 12, 2026
3dec8fb
Add `SafeFileHandle.CreateAnonymousPipe` with per-end async support, …
Copilot Mar 12, 2026
cb2632f
Sync cDAC's RV64/LA64 implementations with ARM64 (#125353)
am11 Mar 12, 2026
acface4
Feature and ifdef FEATURE_MULTITHREADING (#124959)
pavelsavara Mar 12, 2026
42d73cf
Fix memory overwrites in SystemNative_GetNetworkInterfaces (#125022)
gwr Mar 12, 2026
024e901
Fix missing big-endian conversions for multi-byte NTLM wire fields (#…
Copilot Mar 12, 2026
7ef0288
Prepare for xunit.v3.assert migration: forward-compatibility changes …
Copilot Mar 12, 2026
1279fad
Add tests for lazy quantifier inside optional group (#125474)
stephentoub Mar 12, 2026
25ece7d
Fix clang -Walloc-size error in CloseHandle test by removing unused W…
Copilot Mar 12, 2026
e30b480
Fix race condition leak in RegisterResumptionStub (#125407)
jtschuster Mar 12, 2026
39e9278
[wasm] Restore net472 multi-targeting for WasmAppBuilder (#125373)
Copilot Mar 13, 2026
4331cf0
Fix Tensor stride computation for single-element (length <= 1) tensor…
Copilot Mar 13, 2026
dada8dc
Fix RhpThrowImpl on ARM32 (#125253)
eduardo-vp Mar 13, 2026
dfb9e0d
Remove redundant NULL check for pDir in ClrDataAccess::GetMetaDataFil…
Copilot Mar 13, 2026
9907333
[HTTP] Stress fix for the new Windows VM (#125125)
ManickaP Mar 13, 2026
4574075
Propagate BackgroundService exceptions from the host (#124863)
svick Mar 13, 2026
9b92210
Support reload in ChainedConfigurationSource (#125122)
martincostello Mar 13, 2026
aa535c9
Fix CallSiteFactoryResolvesIEnumerableOfOpenGenericServiceAfterResolv…
Copilot Mar 13, 2026
d5c1856
[tvOS] Skip symlink and named pipe tests that fail on iOS/tvOS (#125503)
Copilot Mar 13, 2026
94e4dff
JIT: Bump JIT-EE GUID after removal of hardware intrinsics (#125515)
jakobbotsch Mar 13, 2026
fa39d85
[browser][coreCLR] Loading WebCIL (#124904)
pavelsavara Mar 13, 2026
5b93788
Simplify ILLink/ILC root assembly handling: TrimmerRootAssembly assem…
Copilot Mar 13, 2026
a2190dc
Add curl retry flags to wasi-sdk Linux download (#125488)
steveisok Mar 13, 2026
cfc2e0a
Fix GetGCFreeRegions to handle non-regions GC builds gracefully
Copilot Mar 13, 2026
d51157e
Merge remote-tracking branch 'origin/main' into copilot/implement-mem…
Copilot Mar 13, 2026
33ece94
Address review feedback: add SOSMemoryEnum validation, explain pointe…
Copilot Mar 13, 2026
fab2501
Fix handle table iteration cap and add dump tests for memory region APIs
Mar 17, 2026
302fbd9
Update GC.md pseudocode: remove Read<> and data type-dependent syntax…
Copilot Mar 18, 2026
5ce81c0
comments
Mar 20, 2026
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
196 changes: 196 additions & 0 deletions docs/design/datacontracts/GC.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,33 @@ public readonly struct GCOomData
HandleType[] GetHandleTypes(uint[] types);
// Gets the global allocation context pointer and limit
void GetGlobalAllocationContext(out TargetPointer allocPtr, out TargetPointer allocLimit);

// Gets handle table memory regions (segments)
IReadOnlyList<GCMemoryRegionData> GetHandleTableMemoryRegions();
// Gets GC bookkeeping memory regions (card table info linked list)
IReadOnlyList<GCMemoryRegionData> GetGCBookkeepingMemoryRegions();
// Gets GC free regions (free region lists and freeable segments)
IReadOnlyList<GCMemoryRegionData> GetGCFreeRegions();
```

```csharp
public enum FreeRegionKind
{
FreeUnknownRegion = 0,
FreeGlobalHugeRegion = 1,
FreeGlobalRegion = 2,
FreeRegion = 3,
FreeSohSegment = 4,
FreeUohSegment = 5,
}

public readonly struct GCMemoryRegionData
{
public TargetPointer Start { get; init; }
public ulong Size { get; init; }
public ulong ExtraData { get; init; }
public int Heap { get; init; }
}
```

## Version 1
Expand Down Expand Up @@ -175,6 +202,13 @@ Data descriptors used:
| `TableSegment` | RgAllocation | GC | Circular block-list links per block |
| `TableSegment` | RgValue | GC | Start of handle value storage |
| `TableSegment` | RgUserData | GC | Auxiliary per-block metadata (e.g. secondary handle blocks) |
| `CardTableInfo` | Recount | GC | Reference count for the card table |
| `CardTableInfo` | Size | GC | Total size of the bookkeeping allocation |
| `CardTableInfo` | NextCardTable | GC | Pointer to the next card table in the linked list |
| `RegionFreeList` | HeadFreeRegion | GC | Head of the free region segment list |
| `GCHeap` | FreeableSohSegment | GC | Head of the freeable SOH segment linked list (server builds, background GC) |
| `GCHeap` | FreeableUohSegment | GC | Head of the freeable UOH segment linked list (server builds, background GC) |
| `GCHeap` | FreeRegions | GC | Start of the per-heap free region list array (server builds, region GC) |
| `GCAllocContext` | AllocBytes | VM | Number of bytes allocated on SOH by this context |
| `GCAllocContext` | AllocBytesLoh | VM | Number of bytes allocated not on SOH by this context |
| `EEAllocContext` | GCAllocationContext | VM | The `GCAllocContext` struct within an `EEAllocContext` |
Expand Down Expand Up @@ -229,6 +263,15 @@ Global variables used:
| `FeatureJavaMarshal` | byte | VM | Non-zero when Java marshal support is enabled |
| `GlobalAllocContext` | TargetPointer | VM | Pointer to the global `EEAllocContext` |
| `TotalCpuCount` | uint | GC | Number of available processors |
| `HandleSegmentSize` | uint | GC | Size of each handle table segment allocation |
| `CardTableInfoSize` | uint | GC | Size of the `dac_card_table_info` structure |
| `CountFreeRegionKinds` | uint | GC | Number of free region kinds (basic, large, huge) |
| `GlobalFreeHugeRegions` | TargetPointer | GC | Pointer to the global free huge region list |
| `GlobalRegionsToDecommit` | TargetPointer | GC | Pointer to the global regions-to-decommit array |
| `BookkeepingStart` | TargetPointer | GC | Pointer to the bookkeeping start address |
| `GCHeapFreeableSohSegment` | TargetPointer | GC | Pointer to the freeable SOH segment head (workstation builds) |
| `GCHeapFreeableUohSegment` | TargetPointer | GC | Pointer to the freeable UOH segment head (workstation builds) |
| `GCHeapFreeRegions` | TargetPointer | GC | Pointer to the free regions array (workstation builds) |

Contracts used:
| Contract Name |
Expand Down Expand Up @@ -740,3 +783,156 @@ void IGC.GetGlobalAllocationContext(out TargetPointer allocPtr, out TargetPointe
allocLimit = target.ReadPointer(globalAllocContextAddress + /* EEAllocContext::GCAllocationContext offset */ + /* GCAllocContext::Limit offset */);
}
```

GetHandleTableMemoryRegions
```csharp
IReadOnlyList<GCMemoryRegionData> IGC.GetHandleTableMemoryRegions()
{
List<GCMemoryRegionData> regions = new();
uint handleSegmentSize = /* global value "HandleSegmentSize" */;
uint tableCount = isServerGC
? /* global value "TotalCpuCount" */
: 1;

// Safety caps matching native DAC
const int MaxHandleTableRegions = 8192;
const int MaxBookkeepingRegions = 32;
const int MaxSegmentListIterations = 2048;

int maxRegions = MaxHandleTableRegions;
TargetPointer handleTableMap = target.ReadGlobalPointer("HandleTableMap");
while (handleTableMap != TargetPointer.Null && maxRegions >= 0)
{
TargetPointer bucketsPtr = target.ReadPointer(handleTableMap + /* HandleTableMap::BucketsPtr offset */);
foreach (/* read global variable "InitialHandleTableArraySize" bucketPtrs starting at bucketsPtr */)
{
if (bucketPtr == TargetPointer.Null) continue;
TargetPointer table = target.ReadPointer(bucketPtr + /* HandleTableBucket::Table offset */);
for (uint j = 0; j < tableCount; j++)
{
TargetPointer htPtr = target.ReadPointer(table + j * target.PointerSize);
if (htPtr == TargetPointer.Null) continue;
TargetPointer segList = target.ReadPointer(htPtr + /* HandleTable::SegmentList offset */);
if (segList == TargetPointer.Null) continue;
TargetPointer seg = segList;
TargetPointer first = seg;
do
{
regions.Add(new GCMemoryRegionData { Start = seg, Size = handleSegmentSize, Heap = (int)j });
seg = target.ReadPointer(seg + /* TableSegment::NextSegment offset */);
} while (seg != TargetPointer.Null && seg != first);
}
}
handleTableMap = target.ReadPointer(handleTableMap + /* HandleTableMap::Next offset */);
maxRegions--;
}
return regions;
}
```

GetGCBookkeepingMemoryRegions
```csharp
IReadOnlyList<GCMemoryRegionData> IGC.GetGCBookkeepingMemoryRegions()
{
List<GCMemoryRegionData> regions = new();
TargetPointer bkGlobal = target.ReadGlobalPointer("BookkeepingStart");
if (bkGlobal == TargetPointer.Null) throw E_FAIL;
TargetPointer bookkeepingStart = target.ReadPointer(bkGlobal);
if (bookkeepingStart == TargetPointer.Null) throw E_FAIL;

uint cardTableInfoSize = /* global value "CardTableInfoSize" */;
uint recount = target.ReadNUInt(bookkeepingStart + /* CardTableInfo::Recount offset */);
ulong size = target.ReadNUInt(bookkeepingStart + /* CardTableInfo::Size offset */);
if (recount != 0 && size != 0)
regions.Add(new GCMemoryRegionData { Start = bookkeepingStart, Size = size });

TargetPointer next = target.ReadPointer(bookkeepingStart + /* CardTableInfo::NextCardTable offset */);
TargetPointer firstNext = next;
int maxRegions = MaxBookkeepingRegions;
// Compare next > cardTableInfoSize to guard against underflow when subtracting
// cardTableInfoSize. Matches native DAC: `while (next > card_table_info_size)`.
while (next != TargetPointer.Null && next > cardTableInfoSize && maxRegions > 0)
{
TargetPointer ctAddr = next - cardTableInfoSize;
recount = target.ReadNUInt(ctAddr + /* CardTableInfo::Recount offset */);
size = target.ReadNUInt(ctAddr + /* CardTableInfo::Size offset */);
if (recount != 0 && size != 0)
regions.Add(new GCMemoryRegionData { Start = ctAddr, Size = size });
next = target.ReadPointer(ctAddr + /* CardTableInfo::NextCardTable offset */);
if (next == firstNext) break;
maxRegions--;
}
return regions;
}
```

GetGCFreeRegions
```csharp
IReadOnlyList<GCMemoryRegionData> IGC.GetGCFreeRegions()
{
List<GCMemoryRegionData> regions = new();
uint countFreeRegionKinds = min(/* global value "CountFreeRegionKinds" */, 16);
uint regionFreeListSize = /* size of RegionFreeList data descriptor */;

// Global free huge regions
if (target.TryReadGlobalPointer("GlobalFreeHugeRegions", out TargetPointer? globalHuge))
AddFreeList(globalHuge, FreeGlobalHugeRegion, regions);

// Global regions to decommit
if (target.TryReadGlobalPointer("GlobalRegionsToDecommit", out TargetPointer? globalDecommit))
for (int i = 0; i < countFreeRegionKinds; i++)
AddFreeList(globalDecommit + i * regionFreeListSize, FreeGlobalRegion, regions);

if (isServerGC)
{
// For each server heap: enumerate per-heap free regions + freeable segments
for each heap in server heaps:
TargetPointer freeRegionsBase = heapAddress + /* GCHeap::FreeRegions offset */;
if (freeRegionsBase != TargetPointer.Null)
for (int j = 0; j < countFreeRegionKinds; j++)
AddFreeList(freeRegionsBase + j * regionFreeListSize, FreeRegion, regions, heapIndex);
TargetPointer sohSeg = target.ReadPointer(heapAddress + /* GCHeap::FreeableSohSegment offset */);
AddSegmentList(sohSeg, FreeSohSegment, regions, heapIndex);
TargetPointer uohSeg = target.ReadPointer(heapAddress + /* GCHeap::FreeableUohSegment offset */);
AddSegmentList(uohSeg, FreeUohSegment, regions, heapIndex);
}
else
{
// Workstation: use globals for free regions and freeable segments
if (target.TryReadGlobalPointer("GCHeapFreeRegions", out TargetPointer? freeRegions))
for (int i = 0; i < countFreeRegionKinds; i++)
AddFreeList(freeRegions + i * regionFreeListSize, FreeRegion, regions);
if (target.TryReadGlobalPointer("GCHeapFreeableSohSegment", out TargetPointer? soh))
AddSegmentList(target.ReadPointer(soh), FreeSohSegment, regions);
if (target.TryReadGlobalPointer("GCHeapFreeableUohSegment", out TargetPointer? uoh))
AddSegmentList(target.ReadPointer(uoh), FreeUohSegment, regions);
}
return regions;
}

void AddFreeList(TargetPointer freeListAddr, FreeRegionKind kind, List<GCMemoryRegionData> regions, int heap = 0)
{
TargetPointer headFreeRegion = target.ReadPointer(freeListAddr + /* RegionFreeList::HeadFreeRegion offset */);
if (headFreeRegion != TargetPointer.Null)
AddSegmentList(headFreeRegion, kind, regions, heap);
}

void AddSegmentList(TargetPointer start, FreeRegionKind kind, List<GCMemoryRegionData> regions, int heap = 0)
{
int iterationMax = MaxSegmentListIterations;
TargetPointer curr = start;
while (curr != TargetPointer.Null)
{
TargetPointer mem = target.ReadPointer(curr + /* HeapSegment::Mem offset */);
if (mem != TargetPointer.Null)
{
TargetPointer committed = target.ReadPointer(curr + /* HeapSegment::Committed offset */);
ulong size = (mem < committed) ? committed - mem : 0;
regions.Add(new GCMemoryRegionData { Start = mem, Size = size, ExtraData = kind, Heap = heap });
}
curr = target.ReadPointer(curr + /* HeapSegment::Next offset */);
if (curr == start) break;
if (iterationMax-- <= 0) break;
}
}
```
13 changes: 13 additions & 0 deletions src/coreclr/gc/datadescriptor/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ struct cdac_data<GC_NAMESPACE::gc_heap>
GC_HEAP_FIELD(CompactReasons, compact_reasons_per_heap)
GC_HEAP_FIELD(ExpandMechanisms, expand_mechanisms_per_heap)
GC_HEAP_FIELD(InterestingMechanismBits, interesting_mechanism_bits_per_heap)
/* For use in GCFreeRegions APIs */
#ifdef BACKGROUND_GC
GC_HEAP_FIELD(FreeableSohSegment, freeable_soh_segment)
GC_HEAP_FIELD(FreeableUohSegment, freeable_uoh_segment)
#endif // BACKGROUND_GC
#ifdef USE_REGIONS
GC_HEAP_FIELD(FreeRegions, free_regions)

static constexpr decltype(&GC_NAMESPACE::gc_heap::global_free_huge_regions) GlobalFreeHugeRegions = &GC_NAMESPACE::gc_heap::global_free_huge_regions;
static constexpr decltype(&GC_NAMESPACE::gc_heap::global_regions_to_decommit) GlobalRegionsToDecommit = &GC_NAMESPACE::gc_heap::global_regions_to_decommit;
#endif // USE_REGIONS

static constexpr decltype(&GC_NAMESPACE::gc_heap::bookkeeping_start) BookkeepingStart = &GC_NAMESPACE::gc_heap::bookkeeping_start;
};

template<>
Expand Down
36 changes: 36 additions & 0 deletions src/coreclr/gc/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ CDAC_TYPE_FIELD(GCHeap, /*pointer*/, InterestingData, cdac_data<GC_NAMESPACE::gc
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, CompactReasons, cdac_data<GC_NAMESPACE::gc_heap>::CompactReasons)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, ExpandMechanisms, cdac_data<GC_NAMESPACE::gc_heap>::ExpandMechanisms)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, InterestingMechanismBits, cdac_data<GC_NAMESPACE::gc_heap>::InterestingMechanismBits)
#ifdef BACKGROUND_GC
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, FreeableSohSegment, cdac_data<GC_NAMESPACE::gc_heap>::FreeableSohSegment)
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, FreeableUohSegment, cdac_data<GC_NAMESPACE::gc_heap>::FreeableUohSegment)
#endif // BACKGROUND_GC
#ifdef USE_REGIONS
CDAC_TYPE_FIELD(GCHeap, /*pointer*/, FreeRegions, cdac_data<GC_NAMESPACE::gc_heap>::FreeRegions)
#endif // USE_REGIONS
CDAC_TYPE_END(GCHeap)
#endif // SERVER_GC

Expand Down Expand Up @@ -104,6 +111,18 @@ CDAC_TYPE_FIELD(TableSegment, /*uint8_t[]*/, RgValue, offsetof(TableSegment, rgV
CDAC_TYPE_FIELD(TableSegment, /*uint8_t[]*/, RgUserData, offsetof(TableSegment, rgUserData))
CDAC_TYPE_END(TableSegment)

CDAC_TYPE_BEGIN(CardTableInfo)
CDAC_TYPE_SIZE(sizeof(dac_card_table_info))
CDAC_TYPE_FIELD(CardTableInfo, /*uint32*/, Recount, offsetof(dac_card_table_info, recount))
CDAC_TYPE_FIELD(CardTableInfo, /*nuint*/, Size, offsetof(dac_card_table_info, size))
CDAC_TYPE_FIELD(CardTableInfo, /*pointer*/, NextCardTable, offsetof(dac_card_table_info, next_card_table))
CDAC_TYPE_END(CardTableInfo)

CDAC_TYPE_BEGIN(RegionFreeList)
CDAC_TYPE_SIZE(sizeof(dac_region_free_list))
CDAC_TYPE_FIELD(RegionFreeList, /*pointer*/, HeadFreeRegion, offsetof(dac_region_free_list, head_free_region))
CDAC_TYPE_END(RegionFreeList)

CDAC_TYPES_END()

CDAC_GLOBALS_BEGIN()
Expand All @@ -125,6 +144,11 @@ CDAC_GLOBAL(HandleBlocksPerSegment, /*uint32*/, HANDLE_BLOCKS_PER_SEGMENT)
CDAC_GLOBAL(HandleMaxInternalTypes, /*uint32*/, HANDLE_MAX_INTERNAL_TYPES)
CDAC_GLOBAL(HandlesPerBlock, /*uint32*/, HANDLE_HANDLES_PER_BLOCK)
CDAC_GLOBAL(BlockInvalid, /*uint8*/, BLOCK_INVALID)
CDAC_GLOBAL(HandleSegmentSize, /*uint32*/, HANDLE_SEGMENT_SIZE)
CDAC_GLOBAL(CardTableInfoSize, /*uint32*/, (uint32_t)sizeof(dac_card_table_info))
#ifdef USE_REGIONS
CDAC_GLOBAL(CountFreeRegionKinds, /*uint32*/, (uint32_t)FREE_REGION_KINDS)
#endif // USE_REGIONS


#ifndef SERVER_GC
Expand All @@ -149,9 +173,21 @@ CDAC_GLOBAL_POINTER(GCHeapInterestingData, cdac_data<GC_NAMESPACE::gc_heap>::Int
CDAC_GLOBAL_POINTER(GCHeapCompactReasons, cdac_data<GC_NAMESPACE::gc_heap>::CompactReasons)
CDAC_GLOBAL_POINTER(GCHeapExpandMechanisms, cdac_data<GC_NAMESPACE::gc_heap>::ExpandMechanisms)
CDAC_GLOBAL_POINTER(GCHeapInterestingMechanismBits, cdac_data<GC_NAMESPACE::gc_heap>::InterestingMechanismBits)
#ifdef BACKGROUND_GC
CDAC_GLOBAL_POINTER(GCHeapFreeableSohSegment, cdac_data<GC_NAMESPACE::gc_heap>::FreeableSohSegment)
CDAC_GLOBAL_POINTER(GCHeapFreeableUohSegment, cdac_data<GC_NAMESPACE::gc_heap>::FreeableUohSegment)
#endif // BACKGROUND_GC
#ifdef USE_REGIONS
CDAC_GLOBAL_POINTER(GCHeapFreeRegions, cdac_data<GC_NAMESPACE::gc_heap>::FreeRegions)
#endif // USE_REGIONS
#endif // !SERVER_GC

CDAC_GLOBAL_POINTER(HandleTableMap, &g_HandleTableMap)
CDAC_GLOBAL_POINTER(BookkeepingStart, cdac_data<GC_NAMESPACE::gc_heap>::BookkeepingStart)
#ifdef USE_REGIONS
CDAC_GLOBAL_POINTER(GlobalFreeHugeRegions, cdac_data<GC_NAMESPACE::gc_heap>::GlobalFreeHugeRegions)
CDAC_GLOBAL_POINTER(GlobalRegionsToDecommit, cdac_data<GC_NAMESPACE::gc_heap>::GlobalRegionsToDecommit)
#endif // USE_REGIONS

#ifdef SERVER_GC
#define GC_TYPE server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,24 @@ public readonly struct GCOomData
public bool LohP { get; init; }
}

public enum FreeRegionKind
{
FreeUnknownRegion = 0,
FreeGlobalHugeRegion = 1,
FreeGlobalRegion = 2,
FreeRegion = 3,
FreeSohSegment = 4,
FreeUohSegment = 5,
}

public readonly struct GCMemoryRegionData
{
public TargetPointer Start { get; init; }
public ulong Size { get; init; }
public ulong ExtraData { get; init; }
public int Heap { get; init; }
}

public interface IGC : IContract
{
static string IContract.Name { get; } = nameof(GC);
Expand Down Expand Up @@ -128,6 +146,10 @@ public interface IGC : IContract
HandleType[] GetHandleTypes(uint[] types) => throw new NotImplementedException();

void GetGlobalAllocationContext(out TargetPointer allocPtr, out TargetPointer allocLimit) => throw new NotImplementedException();

IReadOnlyList<GCMemoryRegionData> GetHandleTableMemoryRegions() => throw new NotImplementedException();
IReadOnlyList<GCMemoryRegionData> GetGCBookkeepingMemoryRegions() => throw new NotImplementedException();
IReadOnlyList<GCMemoryRegionData> GetGCFreeRegions() => throw new NotImplementedException();
}

public readonly struct GC : IGC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,6 @@ public enum DataType
HandleTableBucket,
HandleTable,
TableSegment,
CardTableInfo,
RegionFreeList,
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ public static class Globals
public const string HandlesPerBlock = nameof(HandlesPerBlock);
public const string BlockInvalid = nameof(BlockInvalid);
public const string TotalCpuCount = nameof(TotalCpuCount);
public const string HandleSegmentSize = nameof(HandleSegmentSize);
public const string CardTableInfoSize = nameof(CardTableInfoSize);
public const string CountFreeRegionKinds = nameof(CountFreeRegionKinds);
public const string GlobalFreeHugeRegions = nameof(GlobalFreeHugeRegions);
public const string GlobalRegionsToDecommit = nameof(GlobalRegionsToDecommit);
public const string BookkeepingStart = nameof(BookkeepingStart);
public const string GCHeapFreeableSohSegment = nameof(GCHeapFreeableSohSegment);
public const string GCHeapFreeableUohSegment = nameof(GCHeapFreeableUohSegment);
public const string GCHeapFreeRegions = nameof(GCHeapFreeRegions);
}
public static class FieldNames
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public GCHeapWKS(Target target)
CompactReasons = target.ReadGlobalPointer(Constants.Globals.GCHeapCompactReasons);
ExpandMechanisms = target.ReadGlobalPointer(Constants.Globals.GCHeapExpandMechanisms);
InterestingMechanismBits = target.ReadGlobalPointer(Constants.Globals.GCHeapInterestingMechanismBits);

if (target.TryReadGlobalPointer(Constants.Globals.GCHeapFreeableSohSegment, out TargetPointer? freeableSohSegPtr))
FreeableSohSegment = target.ReadPointer(freeableSohSegPtr.Value);
if (target.TryReadGlobalPointer(Constants.Globals.GCHeapFreeableUohSegment, out TargetPointer? freeableUohSegPtr))
FreeableUohSegment = target.ReadPointer(freeableUohSegPtr.Value);
if (target.TryReadGlobalPointer(Constants.Globals.GCHeapFreeRegions, out TargetPointer? freeRegionsPtr))
FreeRegions = freeRegionsPtr.Value;
}

public TargetPointer MarkArray { get; }
Expand All @@ -57,4 +64,8 @@ public GCHeapWKS(Target target)
public TargetPointer CompactReasons { get; }
public TargetPointer ExpandMechanisms { get; }
public TargetPointer InterestingMechanismBits { get; }

public TargetPointer? FreeableSohSegment { get; }
public TargetPointer? FreeableUohSegment { get; }
public TargetPointer? FreeRegions { get; }
}
Loading