Skip to content

[cDAC] PR 1/5: Stack walk GC reference scanning and bug fixes#8

Draft
max-charlamb wants to merge 5871 commits intomainfrom
cdac-stackrefs-pr1
Draft

[cDAC] PR 1/5: Stack walk GC reference scanning and bug fixes#8
max-charlamb wants to merge 5871 commits intomainfrom
cdac-stackrefs-pr1

Conversation

@max-charlamb
Copy link
Copy Markdown
Owner

Part 1 of 5 stacked PRs splitting dotnet#126408.

Stack walker fixes + GC reference scanning foundation.

Note

This PR was created with AI assistance from Copilot.

Copilot AI and others added 30 commits April 16, 2026 22:11
…6987)

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: MihaZupan <25307628+MihaZupan@users.noreply.github.com>
…nValue/MaxValue (dotnet#127009)

## Fix

`TimeZoneInfo.ConvertTime` returns incorrect results when converting a
`DateTime` near `DateTime.MinValue` between positive-offset time zones
(or near `DateTime.MaxValue` between negative-offset time zones).

### Root Cause

`ConvertTime` works by first converting the input to UTC, then from UTC
to the destination time zone. When the intermediate UTC value has
negative ticks (outside `DateTime` range), `SafeCreateDateTimeFromTicks`
clamps it to `DateTime.MinValue` (ticks = 0). The destination offset is
then added to this **clamped** value, producing a wrong result.

**Example:** Converting `0001-01-01 01:13:15` from UTC+4 to UTC+3:
- Intermediate UTC ticks = `1h13m15s - 4h` = **negative** (before epoch)
- Clamped to `DateTime.MinValue` (ticks = 0)
- Add destination offset (+3h) → `0001-01-01 03:00:00` ❌
- Expected: `0001-01-01 00:13:15` ✅

### Fix

Changed `TryLocalToUtc` to return raw `long utcTicks` instead of a
clamped `DateTime`. `ConvertTime` now computes the final result from raw
ticks (`utcTicks + destOffset.Ticks`), only creating a clamped
`DateTime` for transition-table offset lookups. This avoids precision
loss from double-clamping when the intermediate UTC value is outside
`DateTime` range but the **final** result is valid.

### Testing

- Added 7 new `[Theory]` test cases using custom time zones
(cross-platform):
- 4 cases for near-`DateTime.MinValue` with positive offsets (including
exact repro from issue)
- 3 cases for near-`DateTime.MaxValue` with negative offsets (symmetric)
- All 68,715+ `System.Runtime.Tests` pass with zero failures.
- Local benchmarking shows no performance regression.

Fixes dotnet#126940

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
The LDAP server is very simplified, and only has features that were
already being tested when a manual server was specified. Further
functionality can be added as it is needed to satisfy tests.

The server supports LDAP, LDAP+STARTTLS, and LDAPS.
…values that are structs (dotnet#126772)

This addresses an assert in wasm codegen with a release SPC, i.e.:

```
--targetos:browser
--targetarch:wasm
--obj-format=wasm
--parallelism:1
--print-repro-instructions
--codegenopt:JitWasmNyiToR2RUnsupported=1
--codegenopt:JitDump=System.Nullable`1[System.Reflection.Metadata.TypeNameParseOptions]:op_Explicit
-r:"Z:\runtime\artifacts\tests\coreclr\browser.wasm.Release\Tests\Core_Root\*.dll"
"Z:\runtime\artifacts\tests\coreclr\browser.wasm.Release\Tests\Core_Root\System.Private.CoreLib.dll"
--out:"Z:\runtime\artifacts\spc.wasm"
--singlemethodtypename:"System.Nullable`1[[System.Reflection.Metadata.TypeNameParseOptions]]"
--singlemethodname:"op_Explicit"
--singlemethodindex:1
```

Would produce:
```
Single method repro args:--singlemethodtypename "System.Nullable`1[[System.Reflection.Metadata.TypeNameParseOptions]]" --singlemethodname "op_Explicit" --singlemethodindex 1
N004 (  7,  7) [000020] n---G+-----                         *  IND       ubyte  <l:$141, c:$181>
N003 (  3,  4) [000019] -----+-----                         \--*  ADD       byref  $200
N001 (  1,  1) [000012] -----+-----                            +--*  LCL_VAR   byref  V01 arg0         u:1 (last use) $c0
N002 (  1,  2) [000018] -----+-----                            \--*  CNS_INT   int    1 $41
Z:\runtime\src\coreclr\jit\gentree.cpp:16961
Assertion failed '!"Incompatible types for gtNewTempStore"' in 'System.Nullable`1[System.Reflection.Metadata.TypeNameParseOptions]:op_Explicit(System.Nullable`1[System.Reflection.Metadata.TypeNameParseOptions]):System.Reflection.Metadata.TypeNameParseOptions' during 'Lowering nodeinfo' (IL size 8; hash 0xbc4e1b69; FullOpts)
```

The problem is that we are creating a temporary local of struct type
using the `retTypeClass`, but the type of the return value was erased,
so we try to turn a `GT_IND` of type `TYP_UBYTE` into a temp of
`TYP_STRUCT` which can't possibly work the way `ReplaceWithLclVar` is
constructed.

EDIT:
In this scenario what we need to do is zero-extend the mis-sized return
value (a byte or short, most likely) to match the native return type's
size. So I wrap the return value in a CAST.
…n in R2R reflection library (dotnet#126486)

As part of enabling async thunks to be generated in composite mode,
we'll need a number of tests to validate things work as expected.
Instead of having to carefully craft coreclr tests and make sure they
test what we expect, it would be helpful to have unit tests that can
assert things about the output that aren't easily tested in behavioral
tests. For example, we can validate that a method was inlined, or
certain methods were or weren't compiled.

Create a new ILCompiler.ReadyToRun.Tests.csproj project to more
granularly test readytorun outputs. The tests work similarly to ILLink.
They compile the source via an in-memory Roslyn compilation, then shells
out to crossgen2 to compile the app (since the JIT library cannot be
initialized twice in the same process). Then, the
ILCompiler.Reflection.ReadyToRun library is used to assert expectations
about the final compiled R2R image.

Also add CrossModuleInliningInfoSection to the R2R reflection library
and add functionality to InliningInfoSection2 to allow resolving the
inliner/inlinee.

Adds a few tests to validate ReadyToRun output related to async codegen
and cross-module inlining. Some tests exist that validate async method
compilation in composite mode are skipped since that hasn't been
implemented yet.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary
Implement RequiresAlign8 on DacDbiImpl in the cDAC.

## Changes
 - MethodTableFlags_1.cs - added RequiresAlign8 flag and property
- IRuntimeTypeSystem.cs / RuntimeTypeSystem_1.cs - added RequiresAlign8
contract method
- DacDbiImpl.cs - RequiresAlign8 implementation with #if DEBUG legacy
validation
 - methodtable.h - added [cDAC] contract annotation on native flag
 - RuntimeTypeSystem.md - updated contract design doc
 - Tests - new tests covering flag-set/flag-unset across architecture

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
…dotnet#126078)

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>
…64 and ARM64 (dotnet#126848)

- [x] Save volatile argument registers (RDX/R8/R9) in Windows AMD64 GC
probe hijack frames
- [x] Save volatile argument registers (RSI/RDI/R8/R9) in Unix AMD64 GC
probe hijack frames
- [x] Use CFI-aware push_register/pop_register macros for proper unwind
directives
- [x] Save volatile argument registers (x3-x7) in ARM64 GC probe hijack
frames
- [x] Update RBM_INTERFACELOOKUP_FOR_SLOT_TRASH to trash all
non-argument volatile registers
- [x] Save all FP argument registers in GC probe hijack frames
- [x] Merge main and apply targeted JIT PHI jump threading fix for
dotnet#126976
- [x] Add project exclusions for arm64 Windows tests
- [x] Fix JITDUMP formatting in redundantbranchopts.cpp for jitformat
checker

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mangod9 <61718172+mangod9@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Co-authored-by: jakobbotsch <7887810+jakobbotsch@users.noreply.github.com>
Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
… blocks and remove PAL usage (dotnet#126263)

`parallelsuperpmi.cpp` was littered with `#ifdef TARGET_UNIX` guards
scattered throughout function bodies, mixing platform logic with control
flow and making the code hard to read. Additionally, Ctrl+C signal
handling was missing on POSIX (left as `TODO-Porting`), and the POSIX
code path was calling Win32/PAL APIs such as `WaitForMultipleObjects`
and `CreateFileA`/`CloseHandle`. This refactor reorganizes all
platform-specific code into clean, separated implementations and removes
PAL API usage from the POSIX path.

## Description

### Process spawning
- **Split `StartProcess`** into two complete, standalone implementations
— one for Win32 (using `CreateProcess`) and one for POSIX (using
`fork`/`execv`) — replacing the original single function body that was
threaded with interleaved `#ifndef TARGET_UNIX` / `#else` / `#endif`
guards.
- **Added `ParseCommandLineToArgv`** helper for the POSIX path to
tokenize the command-line string into an `argv` array for `execv`.
Supports single-quote, double-quote, and backslash escaping so paths
with spaces are handled correctly.
- **Added `SpmiProcessHandle` typedef** (`pid_t` on POSIX, `HANDLE` on
Windows) to unify the process handle array type used throughout the
file.
- **Closed `pi.hThread`** after a successful `CreateProcess` to avoid
accumulating leaked thread handles when spawning many workers.

### POSIX Ctrl+C handling (previously unimplemented)
- **Added `PosixCtrlHandler`** signal handler using `signal(SIGINT,
...)`, implementing the previously skipped `TODO-Porting` for graceful
Ctrl+C handling on Unix. The handler validates the `signal()` return
value against `SIG_ERR`.
- Changed `closeRequested` from `volatile bool` to `volatile
sig_atomic_t` — the correct async-signal-safe type for flags written
from signal handlers.
- Moved `#include <signal.h>` outside the `#ifdef TARGET_UNIX` guard so
`sig_atomic_t` is available on all platforms.

### Elimination of scattered `#ifdef TARGET_UNIX` guards in
`doParallelSuperPMI`
- **Extracted all remaining inline `#ifdef TARGET_UNIX` guards** from
`doParallelSuperPMI` into named helper functions: `RegisterCtrlHandler`,
`GetTempFolderPath`, `GetDefaultWorkerCount`, `GetCurrentExePath`,
`OpenWorkerOutputFiles`, `CloseWorkerOutputFiles`,
`WaitForWorkerProcesses`, `GetWorkerExitCode`, `FreeWorkerExitCodes`.
- **Consolidated all helper implementations into one `#ifdef
TARGET_UNIX` block**: all POSIX implementations appear first, then all
Windows implementations — no `#ifdef` appears inside any function body.
- `doParallelSuperPMI` itself now contains zero preprocessor guards.

### PAL/Win32 API removal from POSIX path
- **Replaced `WaitForMultipleObjects`** with a `waitpid` loop in the
POSIX `WaitForWorkerProcesses` implementation, removing one of the last
usages of `WaitForMultipleObjects` with multiple objects on non-Windows.
The loop retries on `EINTR` so interrupted waits do not incorrectly mark
a worker as failed or leave zombie processes.
- Worker output files on POSIX now use `open()`/`close()` with
`O_CLOEXEC` instead of `CreateFileA`/`CloseHandle`.
- `OpenWorkerOutputFiles` (both POSIX and Windows) now closes the
already-opened stdout handle/fd and resets it before returning false
when the stderr open fails, preventing resource leaks.
- The Windows `WaitForWorkerProcesses` now checks the
`WaitForMultipleObjects` return value for `WAIT_FAILED` and logs an
error rather than silently proceeding.

```cpp
#ifdef TARGET_UNIX

static bool RegisterCtrlHandler() { /* signal(SIGINT, ...) with SIG_ERR check */ }
static bool GetTempFolderPath(char* tempPath) { /* getenv("TMPDIR") */ }
// ... all other POSIX impls ...

#else // !TARGET_UNIX

static bool RegisterCtrlHandler() { /* SetConsoleCtrlHandler */ }
static bool GetTempFolderPath(char* tempPath) { /* GetTempPath */ }
// ... all other Windows impls ...

#endif // TARGET_UNIX
```

> [!NOTE]
> This PR description was generated with AI assistance.

<!-- 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: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
…er (dotnet#126893)

## Description

NativeAOT builds fail intermittently on macOS-15 arm64 because Swift
auto-linked libraries (`swift_Builtin_float`, `swift_errno`, etc.) from
`libSystem.Security.Cryptography.Native.Apple.a` cannot be found. The
linker targets hardcode `-L/usr/lib/swift`, but on macOS 15+ these shims
may only exist under the Xcode SDK path.

iOS-like platforms are unaffected because they already resolve the SDK
via `xcrun --show-sdk-path` and pass `-isysroot` which makes Apple's
`ld` remap all `-L` paths relative to the sysroot. macOS desktop targets
(`_targetOS == 'osx'`) previously didn't participate in this SDK
resolution, so the hardcoded `/usr/lib/swift` path was the only search
location.

**Changes:**
- Set `_AppleSdkName` to `macosx` for osx targets, matching how iOS-like
platforms already define their SDK names
- Broaden the existing `Xcrun` property initialization, `command -v`
check, and `xcrun --show-sdk-path` conditions from `_IsiOSLikePlatform`
to `_IsApplePlatform` so macOS also resolves its SDK path into `SysRoot`
- The existing `-isysroot "$(SysRoot)"` linker argument (already
conditioned on `_IsApplePlatform`) then automatically remaps
`-L/usr/lib/swift` to `<SDK>/usr/lib/swift`
- Error conditions for missing xcrun and missing SDK remain scoped to
`_IsiOSLikePlatform` so macOS builds degrade gracefully if xcrun is
unavailable (e.g., cross-compilation from non-macOS hosts where
`SysRoot` would be set manually)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: agocke <515774+agocke@users.noreply.github.com>
- Remove the unused `HAVE_EVP_MAC` macro from
`src/native/libs/System.Security.Cryptography.Native/pal_hmac.c`
- Inline the equivalent `g_evpMacHmac != NULL` check at its only call
site

Fixes dotnet#127034

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
dotnet#126142)

This property will never be null, because failing to resolve the core
assembly would throw when creating the MLC. We update the property's
nullability annotation, and simplify code flow to make this evident.

---------

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
…om behavior if contract is not found (dotnet#127019)

Currently, we access the contracts through GetContract, which throws
NotImplementedException if the contract is not found. In the vast
majority of cases, this fits neatly into the desired behavior - either
we use this contract as part of an API that is supposed to return
`E_NOTIMPL` when the feature is not enabled, or it is a catastrophic
failure if the contract is not found, or both. However, a small subset
of APIs have different behavior - we want to, say, return `S_OK` or
branch and try another behavior. Currently, doing this requires our
control flow to rely on these exceptions. This seeks to eliminate this
pattern; in the rare case when a caller wants a different behavior, it
can call `TryGetContract` and handle the true and false cases in a
custom way.



More context:
dotnet#126963 (comment)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…27040)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
> [!NOTE]
> This PR was AI/Copilot-generated.

This updates the `update-os-coverage` skill guidance so the example tag
check fails explicitly when the requested prereqs image tag is missing.

- replace the `jq -r ... | .[]` example with `jq -e ... any(...)`
- make the missing-tag case unambiguous and easier to script

Addresses skipped review feedback from dotnet#126524 (discussion_r3034880248).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributes to dotnet#18837.

## Summary

On Linux, `SslStream` previously closed the transport without sending a
TLS alert when certificate validation failed. This PR makes `SslStream`
send appropriate TLS alerts (e.g. `bad_certificate`, `unknown_ca`,
`certificate_expired`, `certificate_required`) by moving certificate
validation inline into the OpenSSL handshake via
`SSL_CTX_set_cert_verify_cb`.

## How it works

Instead of validating the peer certificate after the handshake completes
(post-handshake), the validation now runs inside OpenSSL's certificate
verification callback during the handshake itself. This allows OpenSSL
to send the appropriate TLS alert to the peer when validation fails,
since the handshake is still in progress.

The `CertVerifyCallback` (registered on the `SSL_CTX`) extracts the
certificate chain from the `X509_STORE_CTX`, then calls the existing
managed `VerifyRemoteCertificate` logic — including the user's
`RemoteCertificateValidationCallback` if one is registered. If
validation fails, the callback maps the failure reason to an
`X509_V_ERR_*` status code, which OpenSSL translates into the
corresponding TLS alert.

### Connection info during the callback

Because the callback fires mid-handshake, connection properties like
`SslProtocol` and `CipherAlgorithm` would normally not be available yet.
To preserve backward compatibility with user callbacks that access these
properties, `_connectionInfo` is populated before invoking the user
callback. On TLS 1.2, `SSL_get_current_cipher()` returns NULL at this
point (the session cipher is set at ChangeCipherSpec), so the native
code falls back to `SSL_get_pending_cipher()` which is available once
`ServerHello` has been processed.

### Propagating exceptions from validation callback

The exception that would normally be thrown from the cert validation
(either AuthenticationException, or whatever user code throws) is caught
and stored in `SafeSslHandle` before returning back to OpenSSL code, and
when the control flow returns from `SSL_do_handshake`, the exception
gets rethrown.

### Client certificates and `ClientCertificateRequired`

OpenSSL only invokes the cert verify callback when the peer actually
sends a certificate. When a server sets `ClientCertificateRequired =
true` but the client sends no certificate, the callback never fires. Two
cases are handled:

- **No user callback registered:** `SSL_VERIFY_FAIL_IF_NO_PEER_CERT` is
set alongside `SSL_VERIFY_PEER`, so OpenSSL itself rejects the handshake
and sends the `certificate_required` (TLS 1.3) or `handshake_failure`
(TLS 1.2) alert.
- **User callback registered:** Only `SSL_VERIFY_PEER` is set. The
handshake succeeds, and managed `CompleteHandshake` code detects that
`_remoteCertificate` is still null, then calls `VerifyRemoteCertificate`
which invokes the user's callback with
`SslPolicyErrors.RemoteCertificateNotAvailable`. This preserves the
existing behavior where applications can accept connections without a
client certificate via the callback, **unfortunately, no TLS alert is
sent in this case.**

### Resumed sessions

On resumed sessions, OpenSSL skips the cert verify callback since the
certificate was already validated in the original handshake.
`CompleteHandshake` detects this (`_remoteCertificate` is null) and
retrieves the peer certificate from the SSL handle via
`GetRemoteCertificate` and valites it post-handshake, previous behavior
is preserved (no TLS alert is sent if revalidation fails, but this is
not expected to happen often in practice).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…126566)

`instGen_MemoryBarrier` on RISC-V ignored the `barrierKind` parameter
and always emitted `fence rw,rw`. The RISC-V fence instruction has
per-bit control over predecessor and successor ordering (read, write, or
both), so there's no reason to always use the heaviest option.

This maps `BarrierKind` to the matching fence variant:

| BarrierKind | Before | After |
|---|---|---|
| `BARRIER_FULL` | `fence rw,rw` | `fence rw,rw` (unchanged) |
| `BARRIER_LOAD_ONLY` | `fence rw,rw` | `fence r,rw` (acquire) |
| `BARRIER_STORE_ONLY` | `fence rw,rw` | `fence rw,w` (release) |

ARM64 does the same thing with `DMB ISHLD` for load-only and `DMB ISH`
for full. The load/store variants use acquire/release semantics rather
than just load-load or store-store ordering, since .NET's volatile
semantics require it.

The two call sites that benefit today are `GT_MEMORYBARRIER` with
`GTF_MEMORYBARRIER_LOAD`/`GTF_MEMORYBARRIER_STORE` flags, and the
post-volatile-CpBlk load barrier.

Validated the encoding on QEMU (`fence rw,rw` = `0x0330000f`, `fence
r,rw` = `0x0230000f`, `fence rw,w` = `0x0310000f`).
…otnet#126988)

## Summary

PR dotnet#125673 changed `Microsoft.NET.ILLink.targets` to skip creating the
`TrimmerRootAssembly` item for Library-output projects. The
`RootEntireIntermediateAssembly` target in
`eng/testing/tests.mobile.targets` relied on that item existing so it
could update its `RootMode` metadata from `EntryPoint` to `all`.

Since the item no longer exists for Library projects, the metadata
update is a no-op and the test assembly is left unrooted. ILLink trims
it entirely, causing **all Release library tests on tvOS** (both CoreCLR
and Mono) to fail with:
```
Test libs were not found (*.Tests.dll was not found in .../AppBundle/...)
```

## Fix

Change `RootEntireIntermediateAssembly` to use `Remove`+`Include`
instead of metadata update, so the item is unconditionally created with
`RootMode=all` regardless of whether the SDK already created one.

cc @sbomer

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…vices (dotnet#127001)

## Description

Implements the approved API for union type support in
`System.Runtime.CompilerServices`:

```csharp
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(Class | Struct, AllowMultiple = false, Inherited = false)]
    public sealed class UnionAttribute : Attribute;

    public interface IUnion
    {
        object? Value { get; }
    }
}
```

### Changes

- **New source files** — `UnionAttribute.cs` and `IUnion.cs` in
`System.Private.CoreLib/src/System/Runtime/CompilerServices/`
- **Project registration** — Added `<Compile>` entries in
`System.Private.CoreLib.Shared.projitems`
- **Reference assembly** — Added entries in
`System.Runtime/ref/System.Runtime.cs` (with `UnionAttribute` marked
`sealed` and `Inherited = false` in both implementation and ref)
- **Tests** — Added `UnionAttributeTests` in the existing
`AttributesTests.cs` covering attribute usage constraints including
`Inherited = false` and `IsSealed`
- **XML documentation** — Both types include concise `<remarks>`
sections describing how the compiler recognizes union types via
`UnionAttribute` and how `IUnion` provides runtime access to the union's
value. The docs clarify that implementing `IUnion` is not required for
compiler-provided union behaviors. The two types cross-reference each
other via `<seealso>`. Documentation intentionally avoids referencing
specific proposal details or patterns that may change in the future.

### Usage

```csharp
[Union]
public struct Pet : IUnion
{
    public Pet(Cat value) => Value = value;
    public Pet(Dog value) => Value = value;
    public object? Value { get; }
}
```

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>
Co-authored-by: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
## Summary

Fix a CI coverage gap where changes to `src/native/package.json` /
`package-lock.json` did not trigger the browser-wasm CoreCLR build legs
that actually run `npm run rollup`.

This gap allowed Dependabot PRs (dotnet#125230, dotnet#126217) to pass CI without
testing the rollup build, causing post-merge breaks. The same `crypto is
not defined` failure has now occurred **three times**.

## Changes

### 1. Pipeline path detection (`evaluate-default-paths.yml`)

Add JS build input files to `_wasm_src_native`:
- `src/native/package.json`
- `src/native/package-lock.json`  
- `src/native/tsconfig.json`
- `src/native/.npmrc`
- `src/native/rollup.config*`

This ensures changes to these files trigger the `wasmbuildtests`,
`wasm_mono_runtimetests`, and `wasm_coreclr_runtimetests` subsets.

### 2. npm override for `serialize-javascript` (`package.json`)

Pin `serialize-javascript` to `~6.0.2` via npm overrides. The emsdk
bundles Node v18.17.1, which lacks the global `crypto` API that
`serialize-javascript` v7+ requires (Node 20+). This is an interim fix
until the emsdk Node transport package is updated.

## Root Cause

The `_wasm_src_native` path list already included
`src/native/libs/Common/JavaScript/*` and other native JS paths, but not
the top-level npm config files (`package.json`, `package-lock.json`) or
rollup configuration. When Dependabot bumped `serialize-javascript` from
6.0.2 to 7.0.5 (via `@rollup/plugin-terser` 0.4.4 → 1.0.0), the PR CI
only ran LibraryTests legs (which do not invoke rollup). The CoreCLR
legs that run `npm ci` + `npm run rollup` were skipped.

Post-merge, any full runtime build hitting the browser-wasm CoreCLR legs
would fail with:
```
[!] ReferenceError: crypto is not defined
    at generateUID (serialize-javascript/index.js:54:17)
```

## Related

- Fixes dotnet#127008  
- Root cause of reverts: dotnet#125340 (Mar 9), dotnet#126986 (Apr 16)
- Dependabot PRs that broke: dotnet#125230, dotnet#126217

/cc @pavelsavara @lewing

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…otnet#126371)

Fixes dotnet#126363

This re-works the disasm for reg to reg instructions to cover some
additional cases and make it a bit more consistent.

Many of the widening and narrowing instructions were showing the same
size for source and target register.

Diff for the current vector byte multiply implementation:

```diff
        62F17C481002         vmovups  zmm0, zmmword ptr [rdx]
        62F17C4828C8         vmovaps  zmm1, zmm0
-       62F27D4820C9         vpmovsxbw zmm1, zmm1
+       62F27D4820C9         vpmovsxbw zmm1, ymm1
        62D17C481010         vmovups  zmm2, zmmword ptr [r8]
        62F17C4828DA         vmovaps  zmm3, zmm2
-       62F27D4820DB         vpmovsxbw zmm3, zmm3
+       62F27D4820DB         vpmovsxbw zmm3, ymm3
        62F16548D5C9         vpmullw  zmm1, zmm3, zmm1
-       62F27E4830C9         vpmovwb  zmm1, zmm1
+       62F27E4830C9         vpmovwb  ymm1, zmm1
        62F37D483BC001       vextracti32x8 ymm0, zmm0, 1
-       62F27D4820C0         vpmovsxbw zmm0, zmm0
+       62F27D4820C0         vpmovsxbw zmm0, ymm0
        62F37D483BD201       vextracti32x8 ymm2, zmm2, 1
-       62F27D4820D2         vpmovsxbw zmm2, zmm2
+       62F27D4820D2         vpmovsxbw zmm2, ymm2
        62F16D48D5C0         vpmullw  zmm0, zmm2, zmm0
-       62F27E4830C0         vpmovwb  zmm0, zmm0
+       62F27E4830C0         vpmovwb  ymm0, zmm0
        62F375483AC001       vinserti32x8 zmm0, zmm1, ymm0, 1
        62F17C481101         vmovups  zmmword ptr [rcx], zmm0
        488BC1               mov      rax, rcx
        C5F877               vzeroupper 
        C3                   ret      
```

This also catches a few cases where embedded rounding was not included
in the disasm. ex:

```diff
-    vcvtss2si eax, xmm0
+    vcvtss2si eax, xmm0 {rd-sae}
```

Confirmed with local `jit-diff` that there are no text changes aside
from the above intended ones.
…ndow (dotnet#124478)

This solves the issue of wrongly returned RetryAfter value, however only
in the FixedWindowRateLimiter.
The queue is not taken into consideration in this implementation.

dotnet#92557
…7062)

This PR sets the value with `Marshal.SetLastPInvokeError(42)` before the
assert. The assertion `Assert.Equal(0, errObj.LastDllError)` passes by
accident on most platforms but races with unrelated P/Invoke activity on
Apple mobile.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…6398)

This PR is the second part of dotnet#115508, following dotnet#123717.

The mov/movprfx logic for embedded masked operations are moved from
codegen into the emit functions in a similar way to dotnet#123717. The main
difference is that we can use predicated movprfx (zeroing or merging)
for embedded masked operations, depending on the false argument of the
wrapped conditional select. This information is passed into the
`emitInsSve_Mov` helper using a new option `mopt`, which defaults to
`INS_SVE_MOV_OPTS_UNPRED`.

@dotnet/arm64-contrib @a74nh @dhartglassMSFT
jakobbotsch and others added 27 commits April 25, 2026 21:45
Several optimizations around suspension/resumption:
- Reduce number of TLS accesses by storing `Thread.CurrentThread` inside
`RuntimeAsyncAwaitState`, and only accessing `RuntimeAsyncAwaitState`
- Remove a number of write barriers by moving TLS object fields into a
`ref struct`. Allocate this ref struct on the stack in the two places
that initiate runtime async chains: task-returning thunks and
`DispatchContinuations`. Keep a pointer to this in the TLS.
- Use `Unsafe` in a couple of places to avoid unnecessary cast checks on
the hot path

For a suspension heavy benchmark this improves performance by around
17%.
…et#127427)

> [!NOTE]
> This PR was authored with assistance from GitHub Copilot (AI-generated
content).

Rewrites the vectorized fill in `Enumerable.FillIncrementing<T>` to use
the safe `while (span.Length >= CONST) { ...; span = span.Slice(CONST);
}` loop pattern, removing all `Unsafe.*` / `MemoryMarshal.GetReference`
plumbing. JIT recognizes this shape and elides the bounds checks.

# Codegen

Small [diffs](MihuBot/runtime-utils#1859), no
new checks. No [perf
impact.](EgorBot/Benchmarks#151)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…net#127280)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t#127433)

As part of the "remove unsafe" work, we're introducing lots of new
`Span.Slice`, `Vector.Create`, etc calls. It turns out these negatively
impact on the inliner time budget and lead to bad regressions (I've hit
it in dotnet#127429).

<img width="1268" height="182"
alt="{B127EBE7-9CB9-4219-BD0D-9B4FE009E9CC}"
src="https://github.com/user-attachments/assets/4507d429-4abc-4f59-bcc4-11a6a719f541"
/>

I suggest we exclude these from the budget check just like we already do
for small methods.

Just a few [hits](MihuBot/runtime-utils#1864)
with PMI jit-diffs.
…t#127434)

Fixes an issue where we bail out early in the RBO dominator walk due to
comparing a successor that was skipped through empty `BBJ_ALWAYS` blocks
against the current block.

The jit dump was like

```
Checking BB04 for redundant dominating branches
BB03 and BB04 have shared successor BB06
Optimizing branch in dominating BB03 with relop [000011] based on BB04's relop [000015]

Redundant dominating branch opt in BB03:

removing useless STMT00003 ( 0x008[E--] ... 0x00A )
N004 (  5,  5) [000012] -----------                         ▌  JTRUE     void   $VN.Void
N003 (  3,  3) [000011] -----------                         └──▌  CNS_INT   int    0
 from BB03

BB03 becomes empty
setting likelihood of BB03 -> BB04 from 0.5 to 1

Conditional folded at BB03
BB03 becomes a BBJ_ALWAYS to BB04
Compiler::optRedundantDominatingBranch removed tree:
N004 (  5,  5) [000012] -----------                         ▌  JTRUE     void   $VN.Void
N003 (  3,  3) [000011] -----------                         └──▌  CNS_INT   int    0

continuing to the next immediate dominator
failed -- BB02 is degnerate
```

after `BB03` is folded into an empty `BBJ_ALWAYS` to `BB04`, we continue
walking to the next dominator `BB02`, but when checking `BB02`, we
skipped side effect free blocks on its successors so that we end up
comparing `BB04` against `BB03`.

Codegen diff:

```diff
 G_M29168_IG01:  ;; offset=0x0000
        sub      rsp, 40
                                                 ;; size=4 bbWeight=0.50 PerfScore 0.12
 G_M29168_IG02:  ;; offset=0x0004
-       cmp      ecx, 2
-       jle      SHORT G_M29168_IG03
        cmp      ecx, 8
        jle      SHORT G_M29168_IG03
        mov      ecx, 1
        call     [System.Console:WriteLine(int)]
-                                                ;; size=21 bbWeight=0.50 PerfScore 2.88
+                                                ;; size=16 bbWeight=0.50 PerfScore 2.25
-G_M29168_IG03:  ;; offset=0x0019
+G_M29168_IG03:  ;; offset=0x0014
        nop
                                                 ;; size=1 bbWeight=1 PerfScore 0.25
-G_M29168_IG04:  ;; offset=0x001A
+G_M29168_IG04:  ;; offset=0x0015
        add      rsp, 40
        ret
                                                 ;; size=5 bbWeight=1 PerfScore 1.25
```

Fixes dotnet#127432 

/cc: @AndyAyersMS
Introduce NullableUnwrappedGenericParameterValue to represent a
typeof(T) that was unwrapped via Nullable.GetUnderlyingType.

This fixes an issue where
`typeof(Gen<>).MakeGenericType(Nullable.GetUnderlyingType(typeof(T)))`
would make ILC precompile `Gen<T>`, not produce a warning, and then fail
at runtime because we actually need `Gen<Nullable<T>>`.
…` as intrinsically handled (dotnet#127258)

`RequiresDynamicCodeAnalyzer` currently warns on `Enum.GetValues(Type)`
even when the enum type is statically known, while ILC already treats
that shape as safe. This change aligns analyzer behavior with the
existing ILC `IntrinsicId.Enum_GetValues` handling.
…0.7778.56 (dotnet#127430)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
…27264)

Adds a `Validate` overload to the `OptionsBuilder` that registers an
`IValidateOptions` type that validates the option type.

Closes dotnet#115200

---------

Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
dotnet#127274)

Fixes System.Console.Tests failures on MacCatalyst discovered in
runtime-extra-platforms build
[#1388505](https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1388505).

## Failure

**Build**:
[#1388505](https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1388505)
(2026-04-21)
**Job**: `maccatalyst-arm64 Release AllSubsets_Mono`  
**Helix job**: `f4caa84e-1526-4c12-a872-6f24ac6f3ba1`  
**Work item**: System.Console.Tests  
**Platform**: MacCatalyst arm64 (also affects maccatalyst-x64)

### Failed tests

Four tests failed with `PlatformNotSupportedException`:

1. `OpenStandardInputHandle_ReturnsValidHandle`
2. `OpenStandardOutputHandle_ReturnsValidHandle`
3. `OpenStandardErrorHandle_ReturnsValidHandle`
4. `OpenStandardHandles_DoNotOwnHandle`

````text
[FAIL] System.Tests.ConsoleTests.OpenStandardInputHandle_ReturnsValidHandle
System.PlatformNotSupportedException : Operation is not supported on this platform.
   at System.ConsolePal.OpenStandardInputHandle()
   at System.Console.OpenStandardInputHandle()
````

### Root cause

The `Console.OpenStandardXXXHandle()` methods throw
`PlatformNotSupportedException` on mobile platforms (iOS, tvOS, Android,
MacCatalyst) because these platforms do not expose the underlying file
handles for standard streams.

The existing tests already had `[PlatformSpecific]` attributes excluding
iOS, tvOS, and Android, but **MacCatalyst was missing** from the
exclusion list. This is an oversight because MacCatalyst has the same
limitation as other Apple mobile platforms.

### Fix

Add `TestPlatforms.MacCatalyst` to the exclusion list (using `&
~TestPlatforms.MacCatalyst`) on all five tests that attempt to use these
APIs, and add it to the inclusion list on the three
"ThrowsOnUnsupportedPlatforms" tests that validate the exception is
thrown.

This makes the skip coverage consistent across all mobile platforms:
- Skip on: iOS, tvOS, MacCatalyst, Android, Browser (where applicable)
- Run on: Windows, Linux, macOS desktop

## Testing

After this fix, the four failing tests will be skipped on MacCatalyst in
the `runtime-extra-platforms` pipeline, matching the behavior on iOS,
tvOS, and Android.

---

> [!NOTE]
> This PR was created by GitHub Copilot after analyzing mobile platform
CI failures in the runtime-extra-platforms pipeline (build 1388505).




> [!NOTE]
> <details>
> <summary>🔒 Integrity filter blocked 1 item</summary>
>
> The following item were blocked because they don't meet the GitHub
integrity level.
>
> - [dotnet#126805](dotnet#126805)
`search_pull_requests`: has lower integrity than agent requires. The
agent cannot read data with integrity below "approved".
>
> To allow these resources, lower `min-integrity` in your GitHub
frontmatter:
>
> ```yaml
> tools:
>   github:
>     min-integrity: approved  # merged | approved | unapproved | none
> ```
>
> </details>


> Generated by [Mobile Platform Failure
Scanner](https://github.com/dotnet/runtime/actions/runs/24774805343/agentic_workflow)
· ● 2.2M ·
[◷](https://github.com/search?q=repo%3Adotnet%2Fruntime+%22gh-aw-workflow-id%3A+mobile-scan%22&type=pullrequests)

<!-- gh-aw-agentic-workflow: Mobile Platform Failure Scanner, engine:
copilot, model: claude-sonnet-4.5, id: 24774805343, workflow_id:
mobile-scan, run:
https://github.com/dotnet/runtime/actions/runs/24774805343 -->

<!-- gh-aw-workflow-id: mobile-scan -->

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* Remove duplicate instructions.
* Add missing comma

---------

Co-authored-by: Tanner Gooding <tagoo@microsoft.com>
…rized (dotnet#127429)

> [!NOTE]
> This PR was authored with assistance from GitHub Copilot (AI-generated
content).

This PR replaces unsafe code with safe one. Also, slightly changes the
code to check overflow status in the end so we don't pay for overflow
check every iteration and assume overflow happens rarely and when it
does - the cost of the exception is so big that it doesn't make sense to
quit earlier.

## Perf

Benchmark: [`@EgorBot`
request](dotnet#127429 (comment))
sweeping `int[].Sum()` and `long[].Sum()` over `N ∈ {4, 8, 16, 32, 50,
100, 256, 1024, 4096, 16384, 65536, 1_000_000}`. Full results:
EgorBot/Benchmarks#155.

**TL;DR: neutral on most sizes, with notable wins around the
small-vectorized regime (N=32-256). No regressions.**

Highlights (`main` time vs PR time, ratio = main/PR; values >1.00 mean
PR is faster):

| Hardware | Workload | N | main | PR | main/PR |
|---|---|---:|---:|---:|---:|
| Apple M4 | `SumInt`  | 32     |   2.73 ns |   1.82 ns | **1.51x** |
| Apple M4 | `SumInt` | 16 | 1.11 ns | 1.06 ns | 1.05x |
| Apple M4 | `SumInt` | 65536 | 7.89 us | 7.69 us | 1.03x |
| Intel Xeon | `SumInt` | 32 | 4.53 ns | 3.71 ns | **1.22x** |
| Intel Xeon | `SumLong` | 32 | 5.63 ns | 4.60 ns | **1.22x** |
| Intel Xeon | `SumInt` | 50 | 6.04 ns | 5.18 ns | **1.17x** |
| Intel Xeon | `SumInt` | 256 | 21.14 ns | 19.26 ns | **1.10x** |
| Intel Xeon | `SumLong` | 1M | 272.7 us | 248.4 us | **1.10x** |

All other size/workload combinations are within run-to-run noise (ratio
in [0.99, 1.03]).

The wins at N=32-256 are mostly the deferred-overflow-check paying off
(the test+branch is a meaningful fraction of cycles when the loop body
is small and only runs a few times). The 1.51x at N=32 on M4 is
amplified because Apple Silicon also benefits from the simpler control
flow (one fewer branch per main-loop iter).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
> [!NOTE]
> This PR description was generated by GitHub Copilot.

## Summary
- Rewrite only `RightShiftSelf` to use sliced `Span<nuint>` inputs with
`Vector*.Create` and `CopyTo`
- Keep `LeftShiftSelf` unchanged from `main`
- Remove the previous ref arithmetic / `LoadUnsafe` / `StoreUnsafe`
pattern from the right-shift vector loop

## Validation
- `dotnet.cmd build
src\libraries\System.Runtime.Numerics\src\System.Runtime.Numerics.csproj
-v:minimal`
- `dotnet.cmd build /t:test
src\libraries\System.Runtime.Numerics\tests\System.Runtime.Numerics.Tests.csproj
-v:minimal` (3033 tests, 0 failed)


[Diffs](MihuBot/runtime-utils#1858) -
improvements.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
Refactor the lowering-time store coalescing machinery so adjacent
constant GT_STORE_LCL_FLD writes can reuse the existing combine logic
that was previously limited to STOREIND/STORE_BLK. Gate the new
local-field path from LowerStoreLocCommon with
JitEnableStoreLclFldCoalescing. Extend the struct-promotion regression
coverage for the newly handled cases.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…dotnet#127047)

dotnet#103155

~~Use WriteStringValueSegment for large strings~~
~~In `StringConverter.Write`, this PR use chunk-based
`WriteStringValueSegment` instead of `WriteStringValue` when the input
string length exceeds the safe threshold. This prevents
`IndexOutOfRangeException` that could occur when writing extremely large
strings.~~

This PR precompute maxRequiredBytes before dispatching to
`Utf8JsonWriter.WriteStringMinimized` and
`Utf8JsonWriter.WriteStringIndented`, using the original input length.
 
 - With escaping:  value.Length * `MaxExpansionFactorWhileEscaping (6)`
- Without escaping: value.Length * `MaxExpansionFactorWhileTranscoding
(3)`
 
The new calculation is safe for inputs up to `int.MaxValue / 6` (~357M
chars). `Utf8JsonWriter.WriteStringValue` enforces a maximum input size
of `166_666_666` chars (`JsonConstants.MaxUnescapedTokenSize`), so no
overflow occurs in practice.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This PR adds runtime async support to the armel interpreter.
Tested: `async/async/async.sh` with `RunInterpreter=1`

\+ Fix an issue on stack size for function call on armel

---------

Co-authored-by: David Wrighton <davidwr@microsoft.com>
…tnet#127245)

Since runtime async is now enabled by default, we no longer need to
explicitly enable it in a separate pipeline job.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Fixes crash in dotnet#123395

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add better error checking to libCorerun.js
- Add handling of relocs/tableBase to WebCIL v1 images
- Actually handle PortableEntryPoint correctly in the ReadyToRun code
- Generate WASM_TABLE_INDEX_I32 relocs in the the
RuntimeFunctionsTableNode
- Adjust DoesSlotCallPrestub to return false and not assert all the time
on Wasm. In the absence of code versioning, returning false appears to
be adequate.

---------

Co-authored-by: Pavel Savara <pavel.savara@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Adam Perlin <adamp@nanosoft.com>
## Automated Dependency Update

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `7c1931f`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `0ef2d61`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `051f8f1`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `754a73d`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `20b45a0`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `7a5b1a8`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `f0d4e84`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `2d2df03`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `58f51fb`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `6ad25da`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `05e16d1`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `09e23d7`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `0d1628f`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `f3eb05c`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `8dc85a0`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `0fc4e37`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `51d0879`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `b6a2e70`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `7be7701`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `dc020b6`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `5b8a4bb`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `e601475`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `9165c90`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `5908b2e`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `6f5f90b`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `cd8001a`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `846c828`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `3278744`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `567cec8`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `f38b4db`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `3d3aa4e`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `e688700`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `a31af6e`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `46268aa`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `2b2d3b9`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `bbc4191`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `8c9ecb5`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `5a2238e`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `b62d3e5`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `8e2b84e`
|
| mcr.microsoft.com/dotnet-buildtools/prereqs | pinDigest | → `462906a`
|

This PR has been created automatically by the [.NET Renovate
Bot](https://redirect.github.com/dotnet/arcade/blob/main/Documentation/Renovate.md)
to update one or more dependencies in your repo. Please review the
changes and merge the PR if everything looks good.

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDkuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEzOS44IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
…se + Crc32) (dotnet#127327)

Implements the approved API proposal to extend
`System.Runtime.Intrinsics.Arm` with `nint`/`nuint` overloads. Per
reviewer guidance, this PR is scoped down to **Option C**: the `ArmBase`
+ `Crc32` managed surface plus the `GenTreeHWIntrinsic` auxiliary-type
refactor. The bulk of the proposal (`AdvSimd` + `AdvSimd.Arm64`) is
deferred to follow-up PRs.

## Description

### Managed surface (implementation, `PlatformNotSupported` mirror, and
ref assembly)

- `ArmBase`
  - `LeadingZeroCount(nint)`, `LeadingZeroCount(nuint)`
  - `ReverseElementBits(nint)`, `ReverseElementBits(nuint)`
- `ArmBase.Arm64`
  - `LeadingSignCount(nint)`
- `Crc32`
  - `ComputeCrc32(uint crc, nuint data)`
  - `ComputeCrc32C(uint crc, nuint data)`

No APIs are added beyond the approved proposal. The managed bodies are
simple self-call intrinsic stubs; the JIT handles dispatch via the
hwintrinsic list (see below).

### JIT hwintrinsic list — 64-bit instruction slots for the 32-bit
classes

In `src/coreclr/jit/hwintrinsiclistarm64.h`, the `TYP_LONG`/`TYP_ULONG`
slots of the 32-bit-class entries are now populated so that
`nint`/`nuint` overloads (which `JitType2PreciseVarType` maps to
`TYP_LONG`/`TYP_ULONG` on 64-bit) dispatch to the correct Arm64
instruction without needing a managed-side redirect to `*.Arm64.*`:

- `NI_ArmBase_LeadingZeroCount` — added `INS_clz` for
`TYP_LONG`/`TYP_ULONG`
- `NI_ArmBase_ReverseElementBits` — added `INS_rbit` for
`TYP_LONG`/`TYP_ULONG`
- `NI_Crc32_ComputeCrc32` — added `INS_crc32x` for `TYP_ULONG`
- `NI_Crc32_ComputeCrc32C` — added `INS_crc32cx` for `TYP_ULONG`

Codegen uses `emitActualTypeSize(intrin.baseType)` for
`HW_Category_Scalar`, so the 8-byte operand size flows through
automatically. On Arm32, `nint`/`nuint` is 32-bit and these
`TYP_LONG`/`TYP_ULONG` slots are never reached.

### JIT refactor — `GenTreeHWIntrinsic` auxiliary type

Switched the tracked auxiliary type from `CorInfoType` to `var_types`:

- `gtAuxiliaryJitType` → `gtAuxiliaryType`, default changed from
`CORINFO_TYPE_UNDEF` to `TYP_UNKNOWN`.
- `GetAuxiliaryJitType()` / `SetAuxiliaryJitType(CorInfoType)` removed.
`GetAuxiliaryType()` now returns the stored `var_types` directly; new
`SetAuxiliaryType(var_types)` added.
- All ~18 call sites migrated across `hwintrinsic.cpp`,
`hwintrinsicarm64.cpp`, `hwintrinsicxarch.cpp`, `gentree.cpp`, and
`valuenum.cpp`. Sentinels `CORINFO_TYPE_PTR` / `CORINFO_TYPE_UNDEF` are
translated at the boundary to `TYP_U_IMPL` / `TYP_UNKNOWN`.
- The now-dead `getBaseJitTypeAndSizeOfSIMDType` /
`getBaseJitTypeOfSIMDType` helpers are removed from `compiler.h` and
`simd.cpp`; callers use the existing `var_types`-returning
`getBaseTypeAndSizeOfSIMDType` / `getBaseTypeOfSIMDType`.

### Tests

New generator inputs added in
`src/tests/Common/GenerateHWIntrinsicTests/Arm/BaseTests.cs` for the
`nint` / `nuint` overloads of `LeadingZeroCount`, `LeadingSignCount`,
`ReverseElementBits`, `ComputeCrc32`, and `ComputeCrc32C`.

While there, the bit-by-bit `for`-loop expected-result computations for
all `LeadingZeroCount_*` and `LeadingSignCount_*` validators
(pre-existing entries plus the new ones) were rewritten to use the BCL
`T.LeadingZeroCount` API directly. This fixes a pre-existing
non-termination bug for edge inputs (`data == 0` for LZC, `0` or `-1`
for LSC) where the loop counter would go negative without ever exiting.

- `LeadingZeroCount_*`: `int expectedResult =
(int)T.LeadingZeroCount(data);` (with `T` being `int` / `uint` / `long`
/ `ulong` / `nint` / `nuint`).
- `LeadingSignCount_*`: `int expectedResult =
(int)T.LeadingZeroCount(data ^ (data >> (N-1))) - 1;` — an
arithmetic-shift sign-extension XOR that matches Arm `CLS` semantics for
all inputs (verified for `0` → `N-1`, `-1` → `N-1`, `int.MinValue` →
`0`, etc.).

For the new `Crc32` `nuint` overloads (`ComputeCrc32_UIntPtr`,
`ComputeCrc32C_UIntPtr`), the validator compares against the
explicit-typed ground-truth overloads via a JIT-constant branch on
`UIntPtr.Size`:

```csharp
uint expectedResult = (UIntPtr.Size == sizeof(ulong))
    ? Crc32.Arm64.ComputeCrc32(left, (ulong)right)
    : Crc32.ComputeCrc32(left, (uint)right);
```

This gives end-to-end coverage on both Arm32 (CRC32W via the `uint`
overload) and Arm64 (CRC32X via the `Arm64.ulong` overload), confirms
the new `nuint` overload dispatches to the correct instruction width,
and catches any self-recursion or wrong-width lowering.

### Scope deferred to follow-up PRs

- `AdvSimd` and `AdvSimd.Arm64` `nint` / `nuint` overloads (hundreds of
methods in `AdvSimd.cs` / `AdvSimd.PlatformNotSupported.cs`).
- Matching test-generator entries for `AdvSimd` overloads.

## Testing

- ✅ `./build.sh clr+libs -rc release` — **0 errors, 0 warnings**. JIT
C++ refactor compiles clean on x64; the managed surface (including the
ref assembly) compiles clean.
- ✅ `./build.sh clr.alljits -c release` — cross-compiles all JIT targets
including `libclrjit_universal_arm64_x64.so`, exercising the updated
`hwintrinsiclistarm64.h`. **0 errors, 0 warnings**.
- ✅ `GenerateHWIntrinsicTests_Arm` builds clean and emits the expected
validator code for all new tests (`LeadingZeroCount_*`,
`LeadingSignCount_*`, `ReverseElementBits_*`, `ComputeCrc32_UIntPtr`,
`ComputeCrc32C_UIntPtr`) across Int32/UInt32/Int64/UInt64/IntPtr/UIntPtr
variants.
- ⚠️ No on-device Arm64 test execution was performed in this sandbox —
the generated tests will exercise the new APIs end-to-end once run in
the Arm64 test pipeline.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tannergooding <10487869+tannergooding@users.noreply.github.com>
Co-authored-by: Tanner Gooding <tagoo@outlook.com>
…lback mode (dotnet#127028)

> [!NOTE]
> This PR description was AI/Copilot-generated.

## Summary

Implements a managed `[GeneratedComClass]` wrapper
(`MetaDataImportImpl`) that adapts
`System.Reflection.Metadata.MetadataReader` to the `IMetaDataImport`,
`IMetaDataImport2`, and `IMetaDataAssemblyImport` COM interfaces. This
enables SOS and ClrMD to query metadata in cDAC mode, with optional
legacy DAC fallback for methods not yet implemented in the managed
layer.

## Motivation

In cDAC no-fallback mode, `ClrDataModule.GetInterface()` returned
`NotHandled` for `IMetaDataImport` QIs when `_legacyModulePointer == 0`,
meaning diagnostic tools couldn't access type/method/field metadata. The
cDAC already has access to `MetadataReader` via the `EcmaMetadata`
contract, so a thin COM wrapper bridges the gap.

When a legacy DAC *is* available, the wrapper uses it for `#if DEBUG`
validation (asserting that cDAC and DAC produce identical results) and
as a fallback for the ~45 methods not yet implemented in managed code.

## Changes

| File | Description |
|------|-------------|
| `IMetaDataImport.cs` | Managed `[GeneratedComInterface]` definitions
for IMetaDataImport (51 methods), IMetaDataImport2 (8 methods),
IMetaDataAssemblyImport (14 methods), ASSEMBLYMETADATA struct, and
internal `CldbHResults` constants |
| `MetaDataImportImpl.cs` | `[GeneratedComClass]` implementation — 28
full cDAC implementations via MetadataReader + ~45 legacy-delegated
stubs. Uses explicit interface notation. |
| `OutputBufferHelpers.cs` | `CopyStringToBuffer` split into two
overloads: `void` (for callers that don't check truncation) and `out
bool truncated` (for MetaDataImportImpl) |
| `ClrDataModule.cs` | Wire up wrapper via `ICustomQueryInterface` —
creates `MetaDataImportImpl` with both MetadataReader and optional
legacy IMetaDataImport |
| `MetaDataImportImplTests.cs` | 50 unit tests using synthetic metadata
built with `MetadataBuilder` |
| `MetaDataImportDumpTests.cs` | 3 dump-based integration tests
verifying semantic parity against real metadata |
| `MultiModule` debuggee | Test debuggee with non-const fields, user
strings, and methods for dump tests |

### Implemented methods (28 cDAC, ~45 legacy fallback)

**Enum (cDAC):** `EnumInterfaceImpls`, `EnumFields`,
`EnumGenericParams`, `CloseEnum`, `CountEnum`, `ResetEnum`

**Properties (cDAC):** `GetTypeDefProps`, `GetTypeRefProps`,
`GetMethodProps`, `GetFieldProps`, `GetMemberProps`,
`GetInterfaceImplProps`, `GetNestedClassProps`, `GetGenericParamProps`,
`GetMemberRefProps`, `GetModuleRefProps`, `GetParamProps`,
`GetClassLayout`, `GetUserString`, `GetParamForMethodIndex`

**Blob/token (cDAC):** `GetRVA`, `GetSigFromToken`,
`GetTypeSpecFromToken`, `GetCustomAttributeByName`, `IsValidToken`,
`FindTypeDefByName`

**Assembly (cDAC):** `GetAssemblyProps`, `GetAssemblyRefProps`,
`GetAssemblyFromScope`

**Legacy fallback:** All remaining methods delegate to
`_legacyImport`/`_legacyImport2`/`_legacyAssemblyImport` or return
`E_NOTIMPL` when no legacy is available.

### Native parity behaviors

- **`<Module>` parent mapping**:
`GetMethodProps`/`GetFieldProps`/`GetMemberRefProps` map TypeDef RID 1
to `mdTypeDefNil` (0x00000000) via `MapGlobalParentToken`, matching
native RegMeta
- **Constant defaults**: `GetFieldProps`/`GetParamProps` return
`ELEMENT_TYPE_VOID` when no constant is present
- **User string heap**: `GetUserString` uses raw `#US` heap byte parsing
to exactly match native blob size validation (odd-length check, terminal
byte stripping)
- **Assembly flags**: `GetAssemblyProps` ORs `afPublicKey` into flags
when public key blob is non-empty
- **Truncation**: All string-returning methods return
`CLDB_S_TRUNCATION` when buffer is too small
- **Record not found**:
`GetNestedClassProps`/`GetClassLayout`/`GetAssemblyProps` return
`CLDB_E_RECORD_NOTFOUND` for missing records

### Design decisions

- **Explicit interface implementation**: All ~73 COM methods use
explicit interface notation (`int IMetaDataImport.Method(...)`) to keep
the public surface clean
- **ICustomQueryInterface**: QI for `IMetaDataImport` returns an
`IMetaDataImport2` vtable so callers always get the full interface
- **HCORENUM pattern**: Uses `GCHandle.Alloc` to box `MetadataEnum`
objects; `ConcurrentDictionary<nint, byte>` tracks ownership for routing
CloseEnum/CountEnum/ResetEnum between cDAC and legacy handles
- **`#if DEBUG` validation**: Every cDAC-implemented method (with 2
justified exceptions) cross-checks its output against the legacy DAC in
debug builds
- **CopyStringToBuffer overloads**: `void` overload for callers that
don't need truncation info; `out bool truncated` overload for
MetaDataImportImpl callers that return `CLDB_S_TRUNCATION`

## Testing

- **1845 unit tests** pass (all cDAC tests including 50
MetaDataImportImpl tests)
- **214 dump-based tests** pass locally (3 are MetaDataImport-specific)
- Tests cover: enum pagination, global/non-global parent mapping,
constant handling, user string char counts, truncation, nested classes,
generic params, assembly properties, invalid tokens, QI vtable
correctness, and E_NOTIMPL fallback behavior

---------

Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement GC reference scanning for stub/transition frames and fix
stack walker state machine bugs:

- PromoteCallerStack/PromoteCallerStackUsingGCRefMap for transition frames
- GCRefMap decoder for ReadyToRun import section resolution
- FindGCRefMap with FindReadyToRunModule fallback
- SOSDacImpl.GetStackReferences using cDAC contract
- Fix IsFirst preserved for skipped frames
- Fix skipped frame handling moved to UpdateState
- GCInfoDecoder goto removal (ReportUntrackedAndSucceed local function)
- RequiresInstArg, IsAsyncMethod, HasRetBuffArg on IRuntimeTypeSystem
- ExceptionInfo ClauseForCatch fields for catch handler detection
- Data descriptor additions for frame types and TransitionBlock layout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.