Skip to content

Implement cDAC memory region APIs (GetHandleTableMemoryRegions, GetGCBookkeepingMemoryRegions, GetGCFreeRegions)#124926

Draft
Copilot wants to merge 98 commits intomainfrom
copilot/implement-memory-region-apis
Draft

Implement cDAC memory region APIs (GetHandleTableMemoryRegions, GetGCBookkeepingMemoryRegions, GetGCFreeRegions)#124926
Copilot wants to merge 98 commits intomainfrom
copilot/implement-memory-region-apis

Conversation

Copy link
Contributor

Copilot AI commented Feb 26, 2026

Implements three ISOSDacInterface13 APIs natively in the cDAC by extending the IGC contract: GetHandleTableMemoryRegions, GetGCBookkeepingMemoryRegions, and GetGCFreeRegions. These APIs previously delegated to legacy DAC or returned E_NOTIMPL.

Description

SOSMemoryEnum

  • Added SOSMemoryEnum implementation following the SOSHandleEnum pattern, with built-in #if DEBUG validation against the legacy DAC enum (validates Start, Size, ExtraData, Heap fields on Next(), Skip(), Reset(), and GetCount())

IGC Contract Extensions

  • Extended IGC contract with three new memory region enumeration methods
  • Safety caps as named constants matching native DAC: MaxHandleTableRegions (8192), MaxBookkeepingRegions (32), MaxSegmentListIterations (2048)
  • GetGCFreeRegions uses TryReadGlobal for CountFreeRegionKinds to gracefully handle non-regions GC builds
  • Added null guard for heap.FreeRegions value in server GC path
  • Bookkeeping loop includes underflow guard (next > cardTableInfoSize) matching native DAC daccess.cpp:8313

Data Types & Descriptors

  • Added CardTableInfo and RegionFreeList data classes
  • Extended GCHeap type descriptors with optional fields (FreeableSohSegment, FreeableUohSegment, FreeRegions) conditional on GC build configuration (BACKGROUND_GC, USE_REGIONS)
  • Native datadescriptor changes for new globals and types

Documentation & Tests

  • Updated docs/design/datacontracts/GC.md with new API types, data descriptors, globals, constants, and pseudocode
  • Added comprehensive unit tests (GCMemoryRegionTests.cs) covering single/multiple segments, empty buckets, linked segments, bookkeeping entries, and free regions
  • Added dump tests in ServerGCDumpTests.cs and WorkstationGCDumpTests.cs

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 4 commits February 26, 2026 22:41
… for memory region types

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
…p free region fields, and IGC contract methods

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
…Impl integration

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Add GCMemoryRegionTests with three test methods covering:
- GetHandleTableMemoryRegions: single map, bucket, and segment
- GetGCBookkeepingMemoryRegions: single card table entry
- GetGCFreeRegions: workstation GC with one free region

All tests use [Theory] with [ClassData(typeof(MockTarget.StdArch))]
to run across all four architecture combinations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement native cDAC Memory Region APIs Implement cDAC Memory Region APIs (GetHandleTableMemoryRegions, GetGCBookkeepingMemoryRegions, GetGCFreeRegions) Feb 26, 2026
@max-charlamb
Copy link
Member

@copilot , we need to update the cDAC docs and write tests for these new APIs

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
@rcj1
Copy link
Contributor

rcj1 commented Feb 27, 2026

@copilot try again

…eeping entries, empty/multiple free regions

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 27, 2026

@copilot try again

Updated the cDAC docs (GC.md) with new API types, data descriptors, globals, constants, and pseudocode for all three methods. Added 6 additional test methods covering edge cases (empty buckets, multiple linked segments, multiple bookkeeping entries, empty/multiple free regions). Total: 9 test methods × 4 architectures = 36 tests, all passing. See commit 50041df6.


int maxSlots = 1;
if (IsServerGC())
maxSlots = (int)GetGCHeapCount();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot this is incorrect. We need to ensure that we limit by the processor count in this case. See #124875

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6320ebd1. Changed maxSlots to read from TotalCpuCount (the processor count) instead of using GetGCHeapCount() for server GC, matching the fix in PR #124875. Added the TotalCpuCount global pointer to datadescriptor.inc (under SERVER_GC), Constants.Globals, and updated the GC.md pseudocode accordingly.

@rcj1
Copy link
Contributor

rcj1 commented Feb 27, 2026

@copilot fix the build break

@rcj1
Copy link
Contributor

rcj1 commented Feb 27, 2026

Ah I will merge my changes into main and then this should work better

…it in server GC

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
@rcj1 rcj1 marked this pull request as ready for review February 27, 2026 02:44
Copilot AI review requested due to automatic review settings February 27, 2026 02:44
@rcj1 rcj1 marked this pull request as draft February 27, 2026 02:44
eduardo-vp and others added 11 commits March 13, 2026 19:26
In RhpThrowImpl, before calling INLINE_GETTHREAD we were saving the caller-saved register r0 but we should save r2 as well since it contains the exception kind.

Fixes #123979.

---------

Co-authored-by: Eduardo Velarde <evelardepola@microsoft.com>
Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
…eInfoFromPEFile (#125502)

Fixes #125477

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
The new Windows VM image has newer `docker` command, so the dockerfile
must be within the build context.
And it doesn't have `docker compose` but `docker-compose`.
Fixes #67146 by throwing from
`IHost`.`RunAsync`/`StopAsync` with the default host when a `BackgroundService` fails with an
exception and `BackgroundServiceExceptionBehavior.StopHost` is set
(which is the default).
Add support for reloading configuration to `ChainedConfigurationSource`.

Fixes #58683.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
…ingClosedImplementation test for issue #57333 (#124326)

## Description

Issue #57333 reported that `GetServices<T>()` inconsistently resolves
services when mixing closed generic registrations (`IService<T> ->
Impl`) with open generic registrations (`IService<> -> GenericImpl<>`),
particularly when `GetService<T>()` is called first.

An existing test
`CallSiteFactoryResolvesIEnumerableOfOpenGenericServiceAfterResolvingClosedImplementation`
was intended to validate this scenario but was marked with
`[ActiveIssue("https://github.com/dotnet/runtime/issues/57333")]`
because it failed during execution. The failure was due to a test setup
issue, not an actual DI bug.

## Changes

* **Fixed existing test** in `CallSiteTests`:
-
`CallSiteFactoryResolvesIEnumerableOfOpenGenericServiceAfterResolvingClosedImplementation`
- The test uses `FakeOpenGenericService<TVal>` which requires a `TVal`
constructor parameter
- The test was failing because no service of type `TVal` was registered
in the DI container
  - Fixed by:
- Changed test from `IFakeOpenGenericService<int>` to
`IFakeOpenGenericService<string>` (reference type)
- Added `FakeStringService` class implementing
`IFakeOpenGenericService<string>`
- Registered `descriptors.AddSingleton<string>("Foo")` to provide the
required dependency
- Removed
`[ActiveIssue("https://github.com/dotnet/runtime/issues/57333")]`
attribute
  - Test now passes and properly validates the reported behavior

Example scenario validated:

```csharp
descriptors.Add(ServiceDescriptor.Scoped(typeof(IFakeOpenGenericService<string>), typeof(FakeStringService)));
descriptors.Add(ServiceDescriptor.Scoped(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>)));
descriptors.AddSingleton<string>("Foo"); // Required for FakeOpenGenericService<string> constructor

var single = provider.GetService<IFakeOpenGenericService<string>>();    // Returns FakeStringService
var enumerable = provider.GetService<IEnumerable<IFakeOpenGenericService<string>>>(); // Returns both FakeStringService and FakeOpenGenericService<string>
```

Test confirms the behavior works correctly - existing implementation
handles this scenario properly. No implementation code changes required.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>


----

*This section details on the original issue you should resolve*

<issue_title>Enumerable dependencies resolving not consistent when open
generic is used (area-Extensions-DependencyInjection)</issue_title>
<issue_description><!--This is just a template - feel free to delete any
and all of it and replace as appropriate.-->

### Description

<!--
* Please share a clear and concise description of the problem.
* Include minimal steps to reproduce the problem if possible. E.g.: the
smallest possible code snippet; or a small repo to clone, with steps to
run it.
* What behavior are you seeing, and what behavior would you expect?
  -->

Enumerable dependencies are not resolved consistently when open generic
services are registered later.

Ex:

#### Setup
```csharp
interface IProcessor<T> {}

record AnyProcessor<T> : IProcessor<T>;

record IntProcessor : IProcessor<int>;
```

#### Registration
```csharp
var services = new ServiceCollection();
services.TryAddEnumerable(ServiceDescriptor.Scoped(typeof(IProcessor<int>), typeof(IntProcessor)));
// Fix: ordering open generic above concretes
services.TryAddEnumerable(ServiceDescriptor.Scoped(typeof(IProcessor<>), typeof(AnyProcessor<>)));
```

#### Resolving
```csharp
var serviceProvider = services.BuildServiceProvider();

using var scope = serviceProvider.CreateAsyncScope();

// bug is reproducible only when below line enabled
var processor = scope.ServiceProvider.GetService<IProcessor<int>>();

var processors = scope.ServiceProvider.GetService<IEnumerable<IProcessor<int>>>() ?? Enumerable.Empty<IProcessor<int>>();

// prints "IntProcessor -- IntProcessor" instead of IntProcessor -- AnyProcessor`1 if line 17 commented.
Console.WriteLine(string.Join(" -- ", processors.Select(p => p.GetType().Name)));
```

### To Reproduce

sample repo to reproduce the bug
https://github.com/skclusive/EnumerableCallSiteBugConsole

### Configuration

<!--
* Which version of .NET is the code running on?
* What OS and version, and what distro if applicable?
* What is the architecture (x64, x86, ARM, ARM64)?
* Do you know whether it is specific to that configuration?
* If you're using Blazor, which web browser(s) do you see this issue in?
  -->
- `dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100-preview.7.21379.14
 Commit:    22d70b47bc

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22000
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.100-preview.7.21379.14\

Host (useful for support):
  Version: 6.0.0-preview.7.21377.19
  Commit:  91ba017

.NET SDKs installed:
  5.0.301 [C:\Program Files\dotnet\sdk]
  5.0.400 [C:\Program Files\dotnet\sdk]
  6.0.100-preview.7.21379.14 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.28 [C:\Program
Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.28 [C:\Program
Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.18 [C:\Program
Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.7 [C:\Program
Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.9 [C:\Program
Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0-preview.7.21378.6 [C:\Program
Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.28 [C:\Program
Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.18 [C:\Program
Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.7 [C:\Program
Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.9 [C:\Program
Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0-preview.7.21377.19 [C:\Program
Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.18 [C:\Program
Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.7 [C:\Program
Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.9 [C:\Program
Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.0-preview.7.21378.9 [C:\Program
Files\dotnet\shared\Microsoft.WindowsDesktop.App]
- Microsoft Visual Studio Community 2022 Preview (64-bit) Version 17.0.0
Preview 3.0

### Regression?

<!--
* Did this work in a previous build or release of .NET Core, or from
.NET Framework? If you can try a previous release or build to find out,
that can help us narrow down the problem. If you don't know, that's OK.
  -->

### Other information

<!--
* Please include any relevant stack traces or error messages. If
possible please include text as text rather than images (so it shows up
in searches).
* If you have an idea where the problem might lie, let us know that
here. Please include any pointers to code, relevant changes, or related
issues you know of.
* Do you know ...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #57333

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rosebyte <14963300+rosebyte@users.noreply.github.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Adam Sitnik <adam.sitnik@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
JIT CI is currently broken because #124033 removed some hardware
intrinsics from the JIT that makes the JIT incompatible with previous
versions of the BCL/SPMI collections.
…bly names only (#125365)

`TrimmerRootAssembly` items and the illink `-a` flag previously accepted
file paths, creating an MSBuild incremental build gap: illink could read
files not declared as build inputs. This aligns both ILLink and ILC to
accept only assembly names.

## Description

**ILLink command-line (`-a` flag)**
- `Driver.cs`: Remove `File.Exists()` pre-check; `-a` now accepts
assembly names only
- `RootAssemblyInputStep.cs`: Remove `File.Exists()` loading path
("quirks mode"); rename `LoadAssemblyFile()` → `LoadAssemblyByName()`
and `fileName` field/parameter → `assemblyName`, resolve exclusively via
`Context.TryResolve()`

**MSBuild targets**
- `Microsoft.NET.ILLink.targets`: Populate `TrimmerRootAssembly` with
`@(IntermediateAssembly->'%(Filename)')` (name, no extension) instead of
the full item path
- `Microsoft.NETCore.Native.targets`: Remove complex two-step `_Raw` +
`System.IO.File::Exists()` pattern that converted paths to names;
`TrimmerRootAssembly` is now used directly as assembly names;
`ManagedAssemblyToLink` still uses `%(Filename)` since it contains file
paths
- `BrowserWasmApp.targets`: Update condition to compare `%(Identity)`
against `$(AssemblyName)` instead of `@(IntermediateAssembly)`
- `AppleBuild.LocalBuild.targets`: Use
`%(AppleAssembliesToBundle.FileName)` (no extension) instead of
`%(Identity)` (full path)
- `eng/illink.targets`: Use explicit
`$(ILLinkTrimInputPath)$(TargetName)$(TargetExt)` for `AssemblyPaths`
instead of the ambiguous `$(ILLinkTrimInputAssembly)` property that
shares a name with the root-name item

**Test infrastructure**
- `TrimmingArgumentBuilder.cs`: Strip extension via
`Path.GetFileNameWithoutExtension()` when building `-a` arguments
- `TestCaseMetadataProvider.cs`: Move relative-path expansion from `-a`
to `-d` (search directory arguments); `-a` values are now passed through
as-is
- Update 21 test cases to use assembly names without extensions in
`[SetupLinkerArgument("-a", ...)]`
- `RootLibraryVisibleForwardersWithoutReference.cs`: Add explicit
`[SetupLinkerArgument("-reference", "isolated/library.dll")]` so the
subdirectory assembly is resolvable, and use assembly name `library` for
the `-a` argument
- `Mock.cs`: Update reflection-based field access from `"fileName"` to
`"assemblyName"` to match the renamed field in `RootAssemblyInput`

## Customer Impact

No direct customer impact; this is an internal build/tooling correctness
fix. Users who were passing file paths to `TrimmerRootAssembly`
(undocumented usage) will need to switch to assembly names.

## Regression

No — this is a proactive correctness fix, not a regression fix.

## Testing

All 377 affected ILLink test cases pass (`Mono.Linker.Tests`). All 108
`ILLink.Tasks.Tests` pass.

## Risk

Low. The change is contained to ILLink/ILC build integration and test
infrastructure. The linker's assembly resolution behavior is unchanged —
only the file-path loading shortcut is removed. MSBuild targets now pass
assembly names consistently, which is what downstream tools (ILC)
already required.

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sbomer <787361+sbomer@users.noreply.github.com>
Co-authored-by: Sven Boemer <sbomer@gmail.com>
## Summary

The Linux `curl` command in `AcquireWasiSdk.targets` has **no retry
logic**, unlike the Windows `download-wasi-sdk.ps1` which retries up to
8 times on partial transfers. This causes transient GitHub download
failures (rate limits, network blips, truncated responses) to fail the
entire build with a cryptic `tar` error:

```
tar: Error is not recoverable: exiting now
```

## Change

Add `--show-error --fail --retry 3 --retry-delay 5` to the Linux curl
invocation:

```diff
- curl --silent -L -o wasi-sdk-25.0.tar.gz <url>
+ curl --silent --show-error --fail --retry 3 --retry-delay 5 -L -o wasi-sdk-25.0.tar.gz <url>
```

- `--retry 3`: Retry up to 3 times on failure
- `--retry-delay 5`: Wait 5 seconds between retries

## Motivation

Build
[2924549](https://dev.azure.com/dnceng/internal/_build/results?buildId=2924549)
failed on `Linux_Alpine_x64` due to a transient wasi-sdk download
failure. The next scheduled build succeeded without any code change —
confirming the issue was transient. The Windows download script already
handles this case with up to 8 retry attempts.

cc @lewing

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Mar 13, 2026
Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
@max-charlamb max-charlamb removed the linkable-framework Issues associated with delivering a linker friendly framework label Mar 13, 2026
…r comparison, null guard, constants

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 13, 2026

@copilot , address feedback

All four feedback items addressed in 33ece94.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • n3kvsblobprodcus335.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/runtime/runtime/.dotnet/dotnet /home/REDACTED/work/runtime/runtime/.dotnet/dotnet /home/REDACTED/work/runtime/runtime/.dotnet/sdk/11.0.100-preview.1.26104.118/NuGet.Build.Tasks.Console.dll Recursive=True;CleanupAssetsForUnsupportedProjects=True;DisableParallel=False;Force=False;ForceEvaluate=False;HideWarningsAndErrors=False;IgnoreFailedSources=False;Interactive=False;NoCache=False;NoHttpCache=False;RestorePackagesConfig=False /home/REDACTED/work/runtime/runtime/.dotnet/sdk/11.0.100-preview.1.26104.118/MSBuild.dll /home/REDACTED/work/runtime/runtime/src/native/managed/cdac/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj VSTestTestCaseFilter=FullyQualifiedName~GCMemoryRegion;VSTestNoLogo=true;NuGetInteractive=false;VSTestArtifactsProcessingMode=collect;VSTestSessionCorrelationId=7354_16bbed7e-03a6-44dc-8315-cd0c30f9478b;EnableDefaultCompileItems=false;EnableDefaultEmbedde (dns block)
    • Triggering command: /home/REDACTED/work/runtime/runtime/.dotnet/dotnet /home/REDACTED/work/runtime/runtime/.dotnet/dotnet /home/REDACTED/work/runtime/runtime/.dotnet/sdk/11.0.100-preview.1.26104.118/NuGet.Build.Tasks.Console.dll Recursive=True;CleanupAssetsForUnsupportedProjects=True;DisableParallel=False;Force=False;ForceEvaluate=False;HideWarningsAndErrors=False;IgnoreFailedSources=False;Interactive=False;NoCache=False;NoHttpCache=False;RestorePackagesConfig=False /home/REDACTED/work/runtime/runtime/.dotnet/sdk/11.0.100-preview.1.26104.118/MSBuild.dll /home/REDACTED/work/runtime/runtime/src/native/managed/cdac/tests/Microsoft.Diagnostics.DataContractReader.Tests.csproj NuGetInteractive=false;EnableDefaultCompileItems=false;EnableDefaultEmbeddedResourceItems=false;EnableDefaultNoneItems=false;MSBuildRestoreSessionId=4aa506fd-6651-44aa-be6e-7f83b65a913d;MSBuildIsRestoring=True;ExcludeRestorePackageImports=True;OriginalMSB (dns block)
  • pe4vsblobprodcus351.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/runtime/runtime/.dotnet/dotnet dotnet build src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Microsoft.Diagnostics.DataContractReader.Contracts.csproj (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Rebase memory region API branch onto latest main to clean up PR diff Implement cDAC memory region APIs (GetHandleTableMemoryRegions, GetGCBookkeepingMemoryRegions, GetGCFreeRegions) Mar 13, 2026
@max-charlamb max-charlamb requested a review from Copilot March 13, 2026 20:35
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Comment on lines +514 to +553
int maxRegions = MaxHandleTableRegions;
TargetPointer handleTableMap = _target.ReadGlobalPointer(Constants.Globals.HandleTableMap);
while (handleTableMap != TargetPointer.Null && maxRegions >= 0)
{
Data.HandleTableMap map = _target.ProcessedData.GetOrAdd<Data.HandleTableMap>(handleTableMap);
foreach (TargetPointer bucketPtr in map.BucketsPtr)
{
if (bucketPtr == TargetPointer.Null)
continue;

Data.HandleTableBucket bucket = _target.ProcessedData.GetOrAdd<Data.HandleTableBucket>(bucketPtr);
for (uint j = 0; j < tableCount; j++)
{
TargetPointer handleTablePtr = _target.ReadPointer(bucket.Table + (ulong)(j * _target.PointerSize));
if (handleTablePtr == TargetPointer.Null)
continue;

Data.HandleTable handleTable = _target.ProcessedData.GetOrAdd<Data.HandleTable>(handleTablePtr);
if (handleTable.SegmentList == TargetPointer.Null)
continue;

TargetPointer segmentPtr = handleTable.SegmentList;
TargetPointer firstSegment = segmentPtr;
do
{
Data.TableSegment segment = _target.ProcessedData.GetOrAdd<Data.TableSegment>(segmentPtr);
regions.Add(new GCMemoryRegionData
{
Start = segmentPtr,
Size = handleSegmentSize,
Heap = (int)j,
});
segmentPtr = segment.NextSegment;
maxRegions--;
} while (segmentPtr != TargetPointer.Null && segmentPtr != firstSegment && maxRegions >= 0);
}
}
handleTableMap = map.Next;
maxRegions--;
}
curr = segment.Next;
if (curr == start)
break;
if (--iterationMax <= 0)
Comment on lines +799 to +832
// 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 != null && maxRegions >= 0)
{
HandleTableMap map = Read<HandleTableMap>(handleTableMap);
foreach (TargetPointer bucketPtr in map.BucketsPtr)
{
if (bucketPtr == null) continue;
HandleTableBucket bucket = Read<HandleTableBucket>(bucketPtr);
for (uint j = 0; j < tableCount; j++)
{
TargetPointer htPtr = ReadPointer(bucket.Table + j * PointerSize);
if (htPtr == null) continue;
HandleTable ht = Read<HandleTable>(htPtr);
if (ht.SegmentList == null) continue;
TargetPointer seg = ht.SegmentList;
TargetPointer first = seg;
do
{
TableSegment ts = Read<TableSegment>(seg);
regions.Add(new GCMemoryRegionData { Start = seg, Size = handleSegmentSize, Heap = (int)j });
seg = ts.NextSegment;
maxRegions--;
} while (seg != null && seg != first && maxRegions >= 0);
}
}
handleTableMap = map.Next;
maxRegions--;
}
Comment on lines +918 to +932
void AddSegmentList(TargetPointer start, FreeRegionKind kind, List<GCMemoryRegionData> regions, int heap = 0)
{
int iterationMax = MaxSegmentListIterations;
TargetPointer curr = start;
while (curr != null && iterationMax-- > 0)
{
HeapSegment seg = Read<HeapSegment>(curr);
if (seg.Mem != null)
{
ulong size = (seg.Mem < seg.Committed) ? seg.Committed - seg.Mem : 0;
regions.Add(new GCMemoryRegionData { Start = seg.Mem, Size = size, ExtraData = kind, Heap = heap });
}
curr = seg.Next;
if (curr == start) break;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.