[cDAC] PR 1/5: Stack walk GC reference scanning and bug fixes#8
Draft
max-charlamb wants to merge 5871 commits intomainfrom
Draft
[cDAC] PR 1/5: Stack walk GC reference scanning and bug fixes#8max-charlamb wants to merge 5871 commits intomainfrom
max-charlamb wants to merge 5871 commits intomainfrom
Conversation
…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>
… integrity and refactor config merge (dotnet#127030)
…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
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>
7c419ec to
6c234d9
Compare
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>
6c234d9 to
0ee4452
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.