Implement missing pieces for NetworkInformation - #1
Merged
sethjackson merged 1 commit intoJun 15, 2026
Merged
Conversation
sethjackson
force-pushed
the
port-sys-netinfo-openbsd
branch
from
June 15, 2026 22:38
c45029e to
cf3a04a
Compare
rzikm
pushed a commit
that referenced
this pull request
Jun 23, 2026
…on ARM32 (dotnet#129672) Enables the cDAC GC stress verification leg on `linux_arm` (arm32) in `runtime-diagnostics.yml`. While bringing arm32 online surfaced a long-standing type confusion in the cDAC managed side that this PR also fixes. ## Pipeline change Adds `linux_arm` to the `cdacStressPlatforms` default in [`eng/pipelines/runtime-diagnostics.yml`](https://github.com/dotnet/runtime/blob/main/eng/pipelines/runtime-diagnostics.yml). The Helix queue mapping already existed in `prepare-cdac-stress-helix-steps.yml` (`helix_linux_arm32_oldest`), so this is a one-line enablement. ## arm32 failure surfaced by enabling the leg First run on arm32 failed every verification with the same shape - e.g. `DynamicMethods`: `1694 verifications (18 pass / 1676 fail / 0 known-issue)`, with every frame appearing duplicated at consecutive IPs differing by 1: ``` Frame #0 <0xea89cc4e> MISMATCH cDAC=0 RT=2 ONLY(RT) Frame #1 <0xea89cc4f> MISMATCH cDAC=2 RT=0 ONLY(cDAC) <-- same refs, IP|1 ``` **Root cause:** ARM32 control PCs carry the Thumb bit (LSB) to indicate execution mode. The native runtime applies `PCODEToPINSTR` ([utilcode.h](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/utilcode.h#L119)) before reporting an IP as `StackRefData.Source`: - Legacy DAC: `src/coreclr/debug/daccess/daccess.cpp:7558` -- `dsc->pc = PCODEToPINSTR(GetControlPC(pRD))` - In-process stress oracle: `src/coreclr/vm/cdacstress.cpp:781-782` -- same masking The cDAC stored raw PCODE in `GcScanContext.InstructionPointer` and emitted it as the Source, so every cDAC ref got keyed at `IP|1` while the runtime reported at `IP`. ## Fix: type the IP/return-address surface as `TargetCodePointer` Rather than masking the Thumb bit ad-hoc at one consumer site, the proper fix is to **type these values correctly throughout the stack** so the compiler stops the next person from mixing code pointers and data pointers: **Managed contract surface promoted `TargetPointer` → `TargetCodePointer`:** - `IPlatformContext.InstructionPointer` and every per-arch impl (`X86Context`, `AMD64Context`, `ARMContext`, `ARM64Context`, `LoongArch64Context`, `RISCV64Context`) - `IPlatformAgnosticContext.InstructionPointer` and `ContextHolder<T>.InstructionPointer` - `IStackWalk.GetInstructionPointer`, `FrameIterator.GetCurrentReturnAddress`, `FrameHelpers.GetReturnAddress` - `[Field]` properties on `Data.TransitionBlock.ReturnAddress`, `Data.HijackFrame.ReturnAddress`, `Data.SoftwareExceptionFrame.ReturnAddress`, `Data.TailCallFrame.ReturnAddress`, `Data.InlinedCallFrame.CallerReturnAddress` **Native data-descriptor changes** (`src/coreclr/vm/datadescriptor/datadescriptor.inc`) - the corresponding 5 `CDAC_TYPE_FIELD` declarations switched from `T_POINTER` to `TYPE(CodePointer)` so the descriptor's advertised type matches what the field actually holds. Each was verified to carry the Thumb bit on ARM32: | Field | Evidence | |---|---| | `TransitionBlock::m_ReturnAddress` | `callingconvention.h:140-148` - **explicitly aliased** to `{r4..r11, lr}` (saved LR = PC\|1) | | `InlinedCallFrame::m_pCallerReturnAddress` | ARM asm `str lr, [...]` (`pinvokestubs.S:96, 182`); read back as PCODE (`stubs.cpp:1348-1349`) | | `HijackFrame::m_ReturnAddress` | ctor sourced from on-stack saved LR (`threadsuspend.cpp:4546`) | | `SoftwareExceptionFrame::m_ReturnAddress` | copied straight into ARM `Pc` register field (`excep.cpp:10474-10475`) | | `TailCallFrame::m_ReturnAddress` | x86-only (descriptor guarded by `TARGET_X86`); `CodePointer` still semantically correct | **Conversion lives in one place:** `GcScanContext.SetSource` calls `CodePointerUtils.AddressFromCodePointer` (the existing single source of truth for PCODE → PINSTR on a target) when populating `StackRefData.Source`. Other consumers that want code pointers (`IsManaged`, `IsInterpreterCode`, `_eman.GetCodeBlockHandle`) now receive `TargetCodePointer` directly. The few places that need raw data addresses (AMD64 unwinder's `controlPC` arithmetic with `imageBase`, x64-only `SOSDacImpl.GetJumpThunkTarget`) call `.AsTargetPointer` explicitly. ## Validation - `./build.cmd clr.runtime -c Release` succeeded; data descriptor regenerated with `TYPE(CodePointer)` fields. - cDAC unit tests: `Passed: 2571, Failed: 0, Skipped: 16`. - CI: every `CdacBuild`, `CdacDumpTest`, and `CdacStressTest` leg green - **including the new `CdacStressTest linux-arm` leg** that surfaced the bug, plus existing `linux-arm64`, `linux-x64`, `windows-arm64`, `windows-x64` legs. ## Notes for reviewers - `IStackWalk` and `IPlatformAgnosticContext` live in `Microsoft.Diagnostics.DataContractReader.Abstractions`. Per the cDAC `API Review` guidance ([`cdac.instructions.md`](https://github.com/dotnet/runtime/blob/main/.github/instructions/cdac.instructions.md#api-review-net-11-dev-branches-only)), implementations of `IContract` are not under formal API review on .NET 11 dev branches, and the contract assemblies are internal/unstable. Changing the IP/return-address types is intentional and not a breaking-change event. - `CodePointerUtils.AddressFromCodePointer` already throws `NotImplementedException` for `HasArm64PtrAuth`; when that's wired up, the single conversion in `SetSource` picks it up with no further changes. > [!NOTE] > This PR was authored with assistance from GitHub Copilot. --------- Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rzikm
pushed a commit
that referenced
this pull request
Jun 23, 2026
…dotnet#129280) (dotnet#129591) ## Problem `Wasm.Build.Tests.WasmTemplateTests.TypeScriptDefinitionsCopiedToWwwrootOnBuild(config: Debug, emitTypeScriptDts: True)` fails its `dotnet build -question` rebuild check with: ``` MSBUILD : error : Building target "_BuildCopyStaticWebAssetsPreserveNewest" partially, because some output files are out of date with respect to their input files. [_BuildStaticWebAssetsPreserveNewest: Input = obj\Debug\net11.0\compressed\{hash}-{0}-{fp}-{fp}.gz, Output = bin\Debug\net11.0\wwwroot\_framework\dotnet.{fp}.js.gz] Input file is newer than output file. ``` This is the same family of bug as dotnet#129280 (different surface: upstream variant where MSBuild flags `_WriteBuildWasmBootJsonFile` itself as stale; ours is the downstream cascade through compression). ## Root cause Binlog analysis: 1. `_WriteBuildWasmBootJsonFile` runs `GenerateWasmBootJson` (uses `ArtifactWriter.PersistFileIfChanged`, preserves old mtime on unchanged content) followed by `<Touch Files="$(_WasmBuildBootJsonPath)" />` (added in dotnet#125367 to keep MSBuild's I/O check on this target happy). 2. `$(_WasmBuildBootJsonPath)` — `obj/{cfg}/{tfm}/dotnet.js` — is also a source for the StaticWebAssets compression pipeline (`GenerateBuildCompressedStaticWebAssets` → `GZipCompress`). 3. `GZipCompress.cs` skips when `input.mtime < output.mtime` (strict `<`). When `Touch` lands close enough in time to the `.gz` write (or any subsequent target re-stamps dotnet.js), equal/newer mtimes send the next build's compression task down the re-compress path. 4. Re-compression on build #2 bumps `obj/.../{0}.gz` mtime past `bin/.../dotnet.{fp}.js.gz` (which was copied during build #1 and isn't touched since), so `_BuildCopyStaticWebAssetsPreserveNewest` reports its input newer than its output. `-question` fails. This is a regression of dotnet#118637 (Aug 2025, *"Override boot config only when the content changes"*), which fixed the exact same `_BuildCopyStaticWebAssetsPreserveNewest` symptom in dotnet/aspnetcore#63207 by introducing `ArtifactWriter.PersistFileIfChanged`. PR dotnet#125367's `<Touch>` undid that protection. ## Fix Touch a separate `wasm-bootjson-{build,publish}.complete.stamp` file rather than the boot JSON itself, and use the stamp as the target's `Outputs=`. MSBuild's incrementality check on the boot-JSON target stays correct (its declared output has a current mtime after every successful run), while the boot JSON's mtime remains content-derived — preserving dotnet#118637's invariant for downstream consumers. Applied to both: - `_WriteBuildWasmBootJsonFile` (build) - `GeneratePublishWasmBootJson` (publish) Both have identical shape and the same downstream consumers (StaticWebAssets compression / Copy targets). ## What's not fixed here - `_ConvertBuildDllsToWebcil` (line 431) uses the same `<Touch>` pattern but on per-item-batched `@(_WasmConvertedWebcilOutputs)`. It is *probably* exposed to the same cascade for the webcil files; not addressed here pending a per-item analysis. - Defense-in-depth in `dotnet/sdk`: `GZipCompress`/`BrotliCompress` `<` mtime check could become `<=` to harden the entire StaticWebAssets pipeline against this class of cascade. Worth a separate dotnet/sdk PR. ## Verification - Reproduces on `dotnet/runtime` PR dotnet#129454 build https://dev.azure.com/dnceng-public/public/_build/results?buildId=1470806 (`browser-wasm windows Release WasmBuildTests`, workitem `WBT-NoWebcil-MONO-ST-Wasm.Build.Tests.WasmTemplateTests`). - The WBT theory case `TypeScriptDefinitionsCopiedToWwwrootOnBuild(Debug|Release, emitTypeScriptDts:True)` exercises the `dotnet build -question` second-build check that this fix addresses. Fixes dotnet#129280 > [!NOTE] > This pull request was created with the assistance of GitHub Copilot. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
sethjackson
pushed a commit
that referenced
this pull request
Aug 1, 2026
) Fixes dotnet#106712. ## Summary `GC.GetTotalMemory(false)` intermittently returns a **negative** value under the **regions** GC (the default since .NET 7). The value originates in `GCHeap::ApproxTotalBytesInUse`, which estimates gen0 live bytes as `gen0_size - gen0_frag` using unsigned `size_t` arithmetic. `gen0_frag` (free-list + free-object space) is a *per-generation* total that spans **every** gen0 region, but `gen0_size` only summed region spans up to the **ephemeral** region. When gen0 retains another region (for example one pinned in place and swept rather than compacted), that region's fragmentation stays in `gen0_frag` while its span is dropped from `gen0_size`, so `gen0_frag > gen0_size`, the subtraction underflows, and the public API casts the near-`2^64` `size_t` to a negative `long`. **In plain words:** gen0 live bytes are "space minus holes." With **segments**, gen0 is a single contiguous block, so the holes are always a subset of the space and the subtraction can't go negative. With **regions**, gen0 is a linked list of blocks, and the code summed the holes over the whole list but measured the space over only part of it - so the holes could exceed the space and the unsigned subtraction wrapped. The negative is only the *visible* symptom. The same miscount also makes `GetTotalMemory` **silently under-report** gen0 whenever the dropped span is smaller than `gen0_frag` (positive but too low) - observed returning ~0.4 MB where the correct value was ~16.0 MB. ## Root cause ```cpp size_t gen0_frag = generation_free_list_space(gen0) + generation_free_obj_space(gen0); // gen0_size summed region spans, but stopped at the ephemeral region: // if (gen0_seg == current_eph_seg) break; totsize = gen0_size - gen0_frag; // size_t underflow when gen0_frag > gen0_size ``` Two mechanisms, neither a GC race: 1. **Multi-region gen0 span miscount (dominant).** Any gen0 region linked after the ephemeral one had its span dropped from `gen0_size` while its fragmentation stayed in `gen0_frag`. 2. **Discard-branch transient (secondary and minor).** In `a_fit_free_list_p`'s free-list discard path, `free_obj_space` is incremented before `free_list_space` is decremented, so a lock-free reader could briefly observe both - a transient over-count. ### Why a forced `GC.GetTotalMemory(true)` (and continued allocation) self-heals The reported observation that a forced `GetTotalMemory(true)` returns a sane value and stops the negatives - and that continued allocation walks the value back positive - follows directly from Mechanism #1. The bytes are never wrong; only the lock-free *measurement* is. - **`GetTotalMemory(true)` forces blocking, compacting GC(s).** Without pinning, gen0 is fully compacted: survivors are relocated, the swept-in-place regions linked *after* the ephemeral one are reclaimed, and gen0's free-space counters reset. Gen0 collapses to a clean layout where the counted span again covers all its fragmentation (`gen0_frag ≤ gen0_size`), so the next computation is correct — the bad **layout is repaired**. - **Continued allocation also recovers it without a GC.** As the mutator allocates, `alloc_allocated` advances in the ephemeral region, so the counted `gen0_size` grows; once it climbs back above `gen0_frag` the subtraction stops underflowing. The value flip-flops as allocation and GCs change which snapshot a read catches. ## The fix - **`src/coreclr/gc/interface.cpp`** - walk **every** gen0 region when computing `gen0_size` (removing the early `break` at the ephemeral region), so the counted span matches the per-generation fragmentation total. This mirrors how `generation_size()` in `plan_phase.cpp` walks the whole region chain - **defensive clamp** - compute `totsize = (gen0_size > gen0_frag) ? (gen0_size - gen0_frag) : 0` instead of an unguarded `size_t` subtraction. The first fix removes the reproducible underflow at its source; the clamp guarantees the residual lock-free transient described below can never surface as a negative from `GC.GetTotalMemory` - (cancelled) **`src/coreclr/gc/allocation.cpp`** - reorder the discard-branch bookkeeping (`unlink` → `free_list_space -=` → `free_obj_space +=`) so the only transient a concurrent reader can observe is a harmless **under-count** instead of an over-count that could underflow. The final state is identical; this flips the transient's direction rather than removing it. After discussion this was not taken, as also inaccurate and misleading. ## Why this is regions-only With segments, gen0 lives inside a single contiguous ephemeral segment; its fragmentation is by construction a subset of the counted span, so the subtraction can never underflow. The bug requires gen0 to span multiple regions with one retained past the ephemeral one — only possible under regions. Empirically, with the same source and workload: built-in `coreclr.dll` (regions) → NEG −12,194,016 @ 97 ms; standalone `clrgcexp.dll` (regions) → NEG −12,158,984 @ 96 ms; standalone `clrgc.dll` (segments) → **0 negatives** over 13.5 M probes. Matches the field report that `DOTNET_GCName=clrgc.dll` doesn't repro. ## Reproduction Two repros, both run by swapping only `coreclr.dll` between fixed and unfixed builds: - **Amplifier (reliable, used by the regression test).** A console app keeps a large, continuously-refreshed ring of **pinned** tiny objects (forcing retained gen0 regions) while flooding gen0 with garbage and probing `GC.GetTotalMemory` on another thread. Fails in well under a second (~60–70 K probes, e.g. NEG −12,183,896), and fires even single-threaded (`threads=1`) — confirming a structural miscount, not a race. - **The reporter's exact repros from the issue** (only change: a wall-clock cap), which use **no pinning**: | @kg repro (unmodified logic) | Unfixed net11 | Fixed net11 | |---|---|---| | **Multithreaded** (8 threads churning strings) | ❌ NEG **−2,883,184** after 140,958 probes @ **703 ms** — "fails instantly", as reported | ✅ **9.3 M** probes / 25 s, no negative | | **Single-threaded** (rare) | did not fire in our windows (Debug 356 K / 900 s, Release 5.3 M / 900 s, min ≥ 0) — matches "takes longer to reproduce" | ✅ clean | Takeaway: pinning is a *reliable amplifier*, **not a prerequisite** — heavy multithreaded churn triggers frequent GCs that transiently reshuffle the gen0 region list into the same buggy layout. ## Testing ### New regression test `src/tests/GC/API/GC/GetTotalMemoryConcurrent.cs` (+ `.csproj`), priority 1, process-isolated, `GCStressIncompatible`, `[Fact] TestEntryPoint` idiom. It runs the pinned + concurrent-probe workload and fails if any probe is negative. Pinning converts the rare transient into a deterministic, structural repro that fires in milliseconds. **Proven fail → pass** (swapping only `coreclr.dll` fixed↔unfixed), on **both Debug and full Release**: | Build | Runtime | Result | |---|---|---| | **Debug** | Unfixed | ❌ exit **101** — negative `-11,997,832` after 100,285 probes | | **Debug** | Fixed | ✅ exit **100**, 3/3 runs, ~2.8–2.9 M probes each, min ≈ +566,768 | | **Release** | Unfixed | ❌ exit **101** — negative `-11,970,520` after only 83,187 probes | | **Release** | Fixed | ✅ exit **100**, 40.7–43.6 M probes, min ≈ +571,472 | The Release run proves the fix holds on an optimized runtime; the unfixed Release binary reproduces the negative even faster than Debug. ### Existing suite (no regressions) `GC/API/GC/GetTotalMemory`, `TotalMemory`, `TotalMemory2`, `GetGCMemoryInfo`, `GetTotalAllocatedBytes`, `GetAllocatedBytesForCurrentThread` — all exit 100 against the fixed runtime (default regions GC). ## The ".NET 10 fixed the single-threaded repro" claim — disproved The issue notes the single-threaded (no-pin) repro was "fixed on .NET 10." Testing shows this is a **measurement artifact, not a code fix**: the accounting site is byte-identical since regions shipped in .NET 7 (`git log -S` on the guard block returns only PR dotnet#59283 plus mechanical `gc.cpp → interface.cpp` split commits — no .NET 8/9/10 change to the gen0 loop or subtraction). Against installed retail runtimes: | Repro variant | net 8.0.27 | net 9.0.16 | net 10.0.8 | net 11 (unfixed) | |---|---|---|---|---| | **pinned, single-threaded** | NEG −12,141,504 @ 18 ms | NEG −11,967,528 @ 49 ms | NEG −12,103,120 @ 15 ms | NEG −12,189,472 @ 147 ms | | **no-pin, multithreaded** | NEG −417,696 @ 50 ms | NEG −2,083,192 @ 10 ms | NEG −741,272 @ 25 ms | *(regions repro)* | | **no-pin, single-threaded** | 0 neg / 60 s | 0 neg / 120 s | 0 neg / 120 s | 0 neg / 60 s | The structural underflow is single-thread-reproducible on **every** shipping version (15–49 ms with pinning). The no-pin single-threaded case is simply a rare transient on all versions (identical .NET 9 vs 10 behavior) — the perceived ".NET 10 fix" is timing noise, not a behavioral change. This PR is the first actual correction of the root cause. ## Impact & blast radius `ApproxTotalBytesInUse` is reached only via `GCHeap::GetTotalBytesInUse`, whose only callers are the `System.GC.GetTotalMemory(bool)` QCall (CoreCLR) and `RhpGetTotalBytesInUse` (NativeAOT). The one in-box managed consumer is `RuntimeEventSource`'s **`gc-heap-size`** `PollingCounter` (`GC.GetTotalMemory(false) / 1e6`), which surfaces the negative through EventCounters / `dotnet-counters` / EventPipe / APM telemetry. - **No public API surface change** — same signature and semantics, just a corrected number. Also repairs the `forceFullCollection: true` stabilization loop in `GetTotalMemory(bool)`, whose `diff = (newSize − size) / size` convergence test was meaningless while `size` was underflowed. - **Risk is confined to accounting** — the change alters nothing about what the GC collects, promotes, or decommits. `interface.cpp` adds a bounded region walk (gen0 region count, single digits) plus a clamped subtraction, both under the already-held `gc_lock`. ## Performance impact `GetTotalMemory` is a diagnostic API (the `gc-heap-size` counter polls it ~1×/sec), not a hot path. Local A/B (same build, only `coreclr.dll` swapped; no allocation in the timed section; batched quantum-free mean; workstation GC, x64): **Release (shipping configuration — authoritative):** | Scenario | Unfixed | Fixed | Delta | |---|---|---|---| | Common case (`pins=0`, single gen0 region) | ~45.4 ns | ~43.7 ns | **≈0 ns** (identical result 626,712) | | Fragmented (`pins=40000`, several regions) | ~48.8 ns (under-counts: 0.4 M) | ~47.0 ns (correct: 16.0 M) | **≈0 ns** (within noise) | **Debug (checked; absolute numbers and delta both inflated by contract checks):** | Scenario | Unfixed | Fixed | Delta | |---|---|---|---| | Common case (`pins=0`) | ~535.7 ns | ~537.8 ns | +~2 ns (≈0 %) | | Fragmented (`pins=40000`) | ~558.5 ns (under-counts: 0.4 M) | ~611.2 ns (correct: 16.0 M) | +~53 ns (+~9 %) | The common case is free on either config (a single gen0 region means the fix walks the same one region). The Debug fragmented +53 ns is **Debug-accessor overhead** (contract checks on `heap_segment_next/_mem/_allocated`, `in_range_for_segment`), not a real cost — Release shows ≈0 in both scenarios. Cost is bounded by the (inherently small) gen0 region count. > [!NOTE] > This pull request was prepared with the assistance of AI (GitHub Copilot). The root-cause analysis, fix, and regression test were reviewed by me before submitting. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Copilot-Session: 975e6875-e7d4-4172-8d1f-5ed514017a4d Copilot-Session: 2da4f5bf-503e-4a71-a1df-f73e8aedbfe2 Copilot-Session: ad1ce451-e247-42ec-accc-c4a688fcd555
sethjackson
pushed a commit
that referenced
this pull request
Aug 1, 2026
…otnet#131536) The test intentionally expects an unhandled exception to occur. The helix test wrapper enables crash reporting in https://github.com/dotnet/runtime/blob/d75c1ca395b6f4e4d14925207c3d0e421f6e78e1/eng/testing/RunnerTemplate.sh#L118-L119, but this test specifically disables `DOTNET_DbgEnableMiniDump` to disable the only crash reporter at the time, createdump. With the in-proc crashreporter supported on macOS and Linux, there are now two crash reporting mechanisms, with the in-proc crash reporter being enabled should `DOTNET_EnableCrashReport`/`DOTNET_EnableCrashReportOnly` be set while `DOTNET_DbgEnableMiniDump` is unset. As a result, this test unintentionally began crash reporting after inducing unhandled exception scenarios. ## Originally ``` Test process unhandled.dll with argument main exited "Unhandled exception. System.Exception: Test" " at TestUnhandledException.Program.Main(String[] args)" Test process exited with expected error code and produced expected output ``` ## InProc CrashReporter enabled ``` Test process unhandled.dll with argument main exited "Unhandled exception. System.Exception: Test" " at TestUnhandledException.Program.Main(String[] args)" "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** " ".NET Crash Report v1.0.0" "Build: 42.42.42.42424 @Commit: c1b4860" "ABI: arm64" "Cmdline: corerun" "pid: 4263" "signal 6 (SIGABRT)" "" "--- thread 0x164f8f (crashed) ---" " managed exception: System.Exception (0x80131500)" " #00 [0] TestUnhandledException.Program.Main + 0x1e (token=0x6000009)" " #1 [1] System.Environment.CallEntryPoint + 0x1c (token=0x60004a1)" "" "--- thread 0x164f95 ---" " (no managed frames)" "" "modules:" " [0] unhandled {5818b8c6-ff2f-4925-82a6-4ed6871d1d16}" " [1] System.Private.CoreLib {9fdb0c05-8392-43fe-8a44-1df8a41aaf06}" " *** *** *** *** *** *** *** *** *** *** *** *** *** *** " "" Test process exited with expected error code and produced expected output ``` This PR cleans the test output by removing DOTNET_EnableCrashReport, thereby disabling the inproc crash reporter. It applies the same changes for similarly crash-expecting tests --------- Copilot-Session: 13d168eb-c2c9-410e-b5fb-be2637ac4e9a
sethjackson
pushed a commit
that referenced
this pull request
Aug 6, 2026
…otnet#130530) This PR contains two related optimizations to generic type loading / interface slot handling in the CoreCLR type loader. ## 1. Reuse typical instantiation DispatchMap for generic instantiations When loading a non-typical instantiation of a generic type that undergoes a full `MethodTableBuilder` run (the `__Canon` canonical form and value-type instantiations such as `List<int>`), the interface `DispatchMap` was rebuilt from scratch via `PlaceInterfaceMethods` for every instantiation. The encoded `DispatchMap` is instantiation-independent (it stores type IDs and slot numbers), so it can instead be built once while constructing the type's *typical* instantiation and reused for all of its non-typical instantiations. - **Release**: `PlaceInterfaceMethods` is skipped for a non-typical instantiation when the typical instantiation's `DispatchMap` can be reused, and the typical instantiation's encoded map bytes are copied into the new `MethodTable`'s inline `DispatchMap`. - **Debug/Checked**: the specific instantiation's `DispatchMap` is still built and asserted to be byte-for-byte identical to the typical instantiation's map, guarding the instantiation-independence invariant. This is safe because `PlaceInterfaceMethods` only produces `DispatchMap` interface entries (it does not mutate the vtable; `PlaceMethodImpls` still always runs), and the two consumers that read the half-built dispatch map after `PlaceInterfaceMethods` (`ValidateInterfaceMethodConstraints` and `VerifyVirtualMethodsImplemented`) are already skipped for non-typical instantiations because `fNoSanityChecks` is `TRUE` for them. ## 2. Avoid iterating interface methods to size virtual-static slot table `bmtInterfaceEntry::CreateSlotTable` walked every method of an interface that has virtual static methods, counting the static+virtual ones solely to size the `bmtInterfaceSlotImpl` array. The subsequent loop already recomputes the exact per-method placement, so the array can simply be over-allocated to the interface's method count, eliminating the extra `MethodIterator` walk. ## Validation - Release and Checked `clr.runtime` builds succeed with 0 warnings/errors. - The Debug/Checked byte-equality assert (change #1) was exercised at runtime on a small generics workload: the reuse+validation branch executed 141 times, all passing the byte-equality assert, with correct interface dispatch. ## Performance Measured on an Rx cold-start micro-benchmark that isolates the `System.Reactive` construct+initialize type-loading path (interleaved A/B, 60 iterations each, release `coreclr.dll` swapped, baseline = before both changes): | Variant | Median workload | vs baseline | |---|---|---| | Baseline (neither change) | 252.15 ms | — | | DispatchMap reuse only | 248.61 ms | −3.07 ms (−1.2%) | | **Both changes** | **248.62 ms** | **−3.53 ms (−1.4%)** | Standard deviation was ~1.8 ms, so the ~1.4% improvement is a clear signal on type-loading-bound workloads. On WPF R2R startup (where type loading is a much smaller fraction of total startup) the effect is smaller and within run-to-run noise. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Aaron R Robinson <arobins@microsoft.com> Copilot-Session: 3bea685d-50eb-4245-b1ea-4310df00c7d3 Copilot-Session: 11ab8b48-7c38-47af-a41b-d1a9637c5f96
sethjackson
pushed a commit
that referenced
this pull request
Aug 6, 2026
…rs (dotnet#129688) See discussion at dotnet#121981 (comment) # SuperPMI ASM diffs: ExtractMostSignificantBits Base JIT: `artifacts/asmdiff/builds/59979e64/core_root/libclrjit.so` Diff JIT: `artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/libclrjit.so` MCH: `/tmp/ExtractMostSignificantBits_final.mch` Base commit: `59979e6401a` (`origin/main`) Diff commit: `e37c3840564` ## Short summary Diffs are based on <span style="color:#1460aa">39</span> contexts (<span style="color:#1460aa">0</span> MinOpts, <span style="color:#1460aa">39</span> FullOpts). <details> <summary>Overall (<span style="color:green">-480</span> bytes)</summary> <div style="margin-left:1em"> |Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs |---|--:|--:|--:| |ExtractMostSignificantBits_final.mch|8,492|<span style="color:green">-480</span>|<span style="color:green">-28.40%</span>| </div></details> <details> <summary>FullOpts (<span style="color:green">-480</span> bytes)</summary> <div style="margin-left:1em"> |Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs |---|--:|--:|--:| |ExtractMostSignificantBits_final.mch|8,492|<span style="color:green">-480</span>|<span style="color:green">-28.40%</span>| </div></details> ## SuperPMI summary Diffs are based on <span style="color:#1460aa">39</span> contexts (<span style="color:#1460aa">0</span> MinOpts, <span style="color:#1460aa">39</span> FullOpts). <details> <summary>Overall (<span style="color:green">-480</span> bytes)</summary> <div style="margin-left:1em"> |Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs |---|--:|--:|--:| |ExtractMostSignificantBits_final.mch|8,492|<span style="color:green">-480</span>|<span style="color:green">-28.40%</span>| </div></details> <details> <summary>FullOpts (<span style="color:green">-480</span> bytes)</summary> <div style="margin-left:1em"> |Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs |---|--:|--:|--:| |ExtractMostSignificantBits_final.mch|8,492|<span style="color:green">-480</span>|<span style="color:green">-28.40%</span>| </div></details> <details> <summary>Example diffs</summary> <div style="margin-left:1em"> <details> <summary>ExtractMostSignificantBits_final.mch</summary> <div style="margin-left:1em"> <details> <summary><span style="color:green">-44</span> (<span style="color:green">-52.38%</span>) : 17.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts)</summary> <div style="margin-left:1em"> ```diff @@ -7,10 +7,9 @@ ; No matching PGO data ; Final local variable assignments ; -; V00 arg0 [V00,T02] ( 3, 3 ) simd16 -> d0 single-def <System.Runtime.Intrinsics.Vector128`1[byte]> +; V00 arg0 [V00,T01] ( 3, 3 ) simd16 -> d0 single-def <System.Runtime.Intrinsics.Vector128`1[byte]> ; V01 arg1 [V01,T00] ( 3, 3 ) ubyte -> x0 single-def ;# V02 OutArgs [V02 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace" <Empty> -; V03 rat0 [V03,T01] ( 3, 6 ) simd16 -> d16 "ReplaceWithLclVar is creating a new local variable" ; ; Lcl frame size = 0 @@ -18,33 +17,20 @@ G_M10966_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, stp fp, lr, [sp, #-0x10]! mov fp, sp ;; size=8 bbWeight=1 PerfScore 1.50 -G_M10966_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz +G_M10966_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref uxtb w0, w0 dup v16.16b, w0 cmhs v16.16b, v0.16b, v16.16b - movi v17.16b, #0x80 - and v16.16b, v16.16b, v17.16b - ldr q17, [@rwd00] - ushl v16.16b, v16.16b, v17.16b - uxtl2 v17.8h, v16.16b - shl v17.8h, v17.8h, dotnet#8 - uaddw v16.8h, v17.8h, v16.8b - addv h16, v16.8h - umov w0, v16.h[0] - movi v16.8b, #0 - ins v16.s[0], w0 - cnt v16.8b, v16.8b - addv b16, v16.8b - umov w0, v16.s[0] - ;; size=68 bbWeight=1 PerfScore 20.00 + ushr v16.16b, v16.16b, dotnet#7 + addv b16, v16.16b + umov w0, v16.b[0] + ;; size=24 bbWeight=1 PerfScore 7.50 G_M10966_IG03: ; bbWeight=1, epilog, nogc, extend ldp fp, lr, [sp], #0x10 ret lr ;; size=8 bbWeight=1 PerfScore 2.00 -RWD00 dq 00FFFEFDFCFBFAF9h, 00FFFEFDFCFBFAF9h - -; Total bytes of code 84, prolog size 8, PerfScore 23.50, instruction count 21, allocated bytes for code 84 (MethodHash=3eafd529) for method TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) +; Total bytes of code 40, prolog size 8, PerfScore 11.00, instruction count 10, allocated bytes for code 40 (MethodHash=3eafd529) for method TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) ; ============================================================ Unwind Info: @@ -55,7 +41,7 @@ Unwind Info: E bit : 0 X bit : 0 Vers : 0 - Function Length : 21 (0x00015) Actual length = 84 (0x000054) + Function Length : 10 (0x0000a) Actual length = 40 (0x000028) ---- Epilog scopes ---- ---- Scope 0 Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e) ``` </div></details> <details> <summary><span style="color:green">-32</span> (<span style="color:green">-47.06%</span>) : 12.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts)</summary> <div style="margin-left:1em"> ```diff @@ -17,29 +17,19 @@ G_M46948_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, stp fp, lr, [sp, #-0x10]! mov fp, sp ;; size=8 bbWeight=1 PerfScore 1.50 -G_M46948_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz +G_M46948_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref dup v16.4s, w0 cmgt v16.4s, v16.4s, v0.4s - movi v17.4s, #0x80, LSL dotnet#24 - and v16.4s, v16.4s, v17.4s - ldr q17, [@rwd00] - ushl v16.4s, v16.4s, v17.4s + ushr v16.4s, v16.4s, dotnet#31 addv s16, v16.4s - smov x0, v16.s[0] - movi v16.8b, #0 - ins v16.s[0], w0 - cnt v16.8b, v16.8b - addv b16, v16.8b umov w0, v16.s[0] - ;; size=52 bbWeight=1 PerfScore 15.50 + ;; size=20 bbWeight=1 PerfScore 7.00 G_M46948_IG03: ; bbWeight=1, epilog, nogc, extend ldp fp, lr, [sp], #0x10 ret lr ;; size=8 bbWeight=1 PerfScore 2.00 -RWD00 dq FFFFFFE2FFFFFFE1h, FFFFFFE4FFFFFFE3h - -; Total bytes of code 68, prolog size 8, PerfScore 19.00, instruction count 17, allocated bytes for code 68 (MethodHash=d8b1489b) for method TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) +; Total bytes of code 36, prolog size 8, PerfScore 10.50, instruction count 9, allocated bytes for code 36 (MethodHash=d8b1489b) for method TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) ; ============================================================ Unwind Info: @@ -50,7 +40,7 @@ Unwind Info: E bit : 0 X bit : 0 Vers : 0 - Function Length : 17 (0x00011) Actual length = 68 (0x000044) + Function Length : 9 (0x00009) Actual length = 36 (0x000024) ---- Epilog scopes ---- ---- Scope 0 Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e) ``` </div></details> <details> <summary><span style="color:green">-32</span> (<span style="color:green">-47.06%</span>) : 27.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts)</summary> <div style="margin-left:1em"> ```diff @@ -18,29 +18,19 @@ G_M44223_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, stp fp, lr, [sp, #-0x10]! mov fp, sp ;; size=8 bbWeight=1 PerfScore 1.50 -G_M44223_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz +G_M44223_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref dup v16.2s, w0 cmgt v16.2s, v16.2s, v0.2s - movi v17.2s, #0x80, LSL dotnet#24 - and v16.2s, v16.2s, v17.2s - ldr d17, [@rwd00] - ushl v16.2s, v16.2s, v17.2s + ushr v16.2s, v16.2s, dotnet#31 addp v16.2s, v16.2s, v16.2s - smov x0, v16.s[0] - movi v16.8b, #0 - ins v16.s[0], w0 - cnt v16.8b, v16.8b - addv b16, v16.8b umov w0, v16.s[0] - ;; size=52 bbWeight=1 PerfScore 15.50 + ;; size=20 bbWeight=1 PerfScore 7.00 G_M44223_IG03: ; bbWeight=1, epilog, nogc, extend ldp fp, lr, [sp], #0x10 ret lr ;; size=8 bbWeight=1 PerfScore 2.00 -RWD00 dq FFFFFFE2FFFFFFE1h - -; Total bytes of code 68, prolog size 8, PerfScore 19.00, instruction count 17, allocated bytes for code 68 (MethodHash=6ccd5340) for method TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts) +; Total bytes of code 36, prolog size 8, PerfScore 10.50, instruction count 9, allocated bytes for code 36 (MethodHash=6ccd5340) for method TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts) ; ============================================================ Unwind Info: @@ -51,7 +41,7 @@ Unwind Info: E bit : 0 X bit : 0 Vers : 0 - Function Length : 17 (0x00011) Actual length = 68 (0x000044) + Function Length : 9 (0x00009) Actual length = 36 (0x000024) ---- Epilog scopes ---- ---- Scope 0 Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e) ``` </div></details> <details> <summary><span style="color:green">-8</span> (<span style="color:green">-13.33%</span>) : 33.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts)</summary> <div style="margin-left:1em"> ```diff @@ -21,23 +21,21 @@ G_M59363_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, uxtb w0, w0 dup v16.8b, w0 cmhs v16.8b, v0.8b, v16.8b - movi v17.8b, #0x80 - and v16.8b, v16.8b, v17.8b ldr d17, [@rwd00] - ushl v16.8b, v16.8b, v17.8b - addv b16, v16.8b + movi v18.8b, #0x21 + bsl v16.8b, v17.8b, v18.8b + uminv b16, v16.8b umov w0, v16.b[0] - rbit w0, w0 - clz w0, w0 - ;; size=44 bbWeight=1 PerfScore 12.00 + sub w0, w0, #1 + ;; size=36 bbWeight=1 PerfScore 11.00 G_M59363_IG03: ; bbWeight=1, epilog, nogc, extend ldp fp, lr, [sp], #0x10 ret lr ;; size=8 bbWeight=1 PerfScore 2.00 -RWD00 dq 00FFFEFDFCFBFAF9h +RWD00 dq 0807060504030201h -; Total bytes of code 60, prolog size 8, PerfScore 15.50, instruction count 15, allocated bytes for code 60 (MethodHash=312b181c) for method TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) +; Total bytes of code 52, prolog size 8, PerfScore 14.50, instruction count 13, allocated bytes for code 52 (MethodHash=312b181c) for method TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) ; ============================================================ Unwind Info: @@ -48,7 +46,7 @@ Unwind Info: E bit : 0 X bit : 0 Vers : 0 - Function Length : 15 (0x0000f) Actual length = 60 (0x00003c) + Function Length : 13 (0x0000d) Actual length = 52 (0x000034) ---- Epilog scopes ---- ---- Scope 0 Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e) ``` </div></details> <details> <summary><span style="color:green">-8</span> (<span style="color:green">-13.33%</span>) : 23.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts)</summary> <div style="margin-left:1em"> ```diff @@ -21,23 +21,21 @@ G_M61416_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, uxth w0, w0 dup v16.4h, w0 cmhs v16.4h, v0.4h, v16.4h - movi v17.4h, #0x80, LSL dotnet#8 - and v16.4h, v16.4h, v17.4h ldr d17, [@rwd00] - ushl v16.4h, v16.4h, v17.4h - addv h16, v16.4h + movi v18.4h, #0x21 + bsl v16.4h, v17.4h, v18.4h + uminv h16, v16.4h umov w0, v16.h[0] - rbit w0, w0 - clz w0, w0 - ;; size=44 bbWeight=1 PerfScore 12.00 + sub w0, w0, #1 + ;; size=36 bbWeight=1 PerfScore 11.00 G_M61416_IG03: ; bbWeight=1, epilog, nogc, extend ldp fp, lr, [sp], #0x10 ret lr ;; size=8 bbWeight=1 PerfScore 2.00 -RWD00 dq FFF4FFF3FFF2FFF1h +RWD00 dq 0004000300020001h -; Total bytes of code 60, prolog size 8, PerfScore 15.50, instruction count 15, allocated bytes for code 60 (MethodHash=ba031017) for method TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts) +; Total bytes of code 52, prolog size 8, PerfScore 14.50, instruction count 13, allocated bytes for code 52 (MethodHash=ba031017) for method TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts) ; ============================================================ Unwind Info: @@ -48,7 +46,7 @@ Unwind Info: E bit : 0 X bit : 0 Vers : 0 - Function Length : 15 (0x0000f) Actual length = 60 (0x00003c) + Function Length : 13 (0x0000d) Actual length = 52 (0x000034) ---- Epilog scopes ---- ---- Scope 0 Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e) ``` </div></details> <details> <summary><span style="color:green">-8</span> (<span style="color:green">-13.33%</span>) : 8.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts)</summary> <div style="margin-left:1em"> ```diff @@ -21,23 +21,21 @@ G_M44819_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, uxth w0, w0 dup v16.8h, w0 cmhs v16.8h, v0.8h, v16.8h - movi v17.8h, #0x80, LSL dotnet#8 - and v16.8h, v16.8h, v17.8h ldr q17, [@rwd00] - ushl v16.8h, v16.8h, v17.8h - addv h16, v16.8h + movi v18.8h, #0x21 + bsl v16.8h, v17.8h, v18.8h + uminv h16, v16.8h umov w0, v16.h[0] - rbit w0, w0 - clz w0, w0 - ;; size=44 bbWeight=1 PerfScore 12.00 + sub w0, w0, #1 + ;; size=36 bbWeight=1 PerfScore 11.00 G_M44819_IG03: ; bbWeight=1, epilog, nogc, extend ldp fp, lr, [sp], #0x10 ret lr ;; size=8 bbWeight=1 PerfScore 2.00 -RWD00 dq FFF4FFF3FFF2FFF1h, FFF8FFF7FFF6FFF5h +RWD00 dq 0004000300020001h, 0008000700060005h -; Total bytes of code 60, prolog size 8, PerfScore 15.50, instruction count 15, allocated bytes for code 60 (MethodHash=016950ec) for method TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts) +; Total bytes of code 52, prolog size 8, PerfScore 14.50, instruction count 13, allocated bytes for code 52 (MethodHash=016950ec) for method TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts) ; ============================================================ Unwind Info: @@ -48,7 +46,7 @@ Unwind Info: E bit : 0 X bit : 0 Vers : 0 - Function Length : 15 (0x0000f) Actual length = 60 (0x00003c) + Function Length : 13 (0x0000d) Actual length = 52 (0x000034) ---- Epilog scopes ---- ---- Scope 0 Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e) ``` </div></details> </div></details> </div></details> <details> <summary>Details</summary> <div style="margin-left:1em"> #### Size improvements/regressions per collection |Collection|Contexts with diffs|Improvements|Regressions|Same size|Improvements (bytes)|Regressions (bytes)| |---|--:|--:|--:|--:|--:|--:| |ExtractMostSignificantBits_final.mch|24|<span style="color:green">24</span>|<span style="color:red">0</span>|<span style="color:blue">0</span>|<span style="color:green">-480</span>|<span style="color:red">+0</span>| --- #### PerfScore improvements/regressions per collection |Collection|Contexts with diffs|Improvements|Regressions|Same PerfScore|Improvements (PerfScore)|Regressions (PerfScore)|PerfScore Overall in FullOpts| |---|--:|--:|--:|--:|--:|--:|--:| |ExtractMostSignificantBits_final.mch|24|<span style="color:green">24</span>|<span style="color:red">0</span>|<span style="color:blue">0</span>|<span style="color:green">-28.40%</span>|0.00%|<span style="color:green">-18.5844%</span>| --- #### Context information |Collection|Diffed contexts|MinOpts|FullOpts|Missed, base|Missed, diff| |---|--:|--:|--:|--:|--:| |ExtractMostSignificantBits_final.mch|39|0|39|0 (0.00%)|0 (0.00%)| --- #### jit-analyze output <details> <summary>ExtractMostSignificantBits_final.mch</summary> <div style="margin-left:1em"> ``` Summary of Code Size diffs: (Lower is better) Total bytes of base: 8492 (overridden on cmd) Total bytes of diff: 8012 (overridden on cmd) Total bytes of delta: -480 (-5.65 % of base) diff is an improvement. relative diff is an improvement. ``` <details> <summary>Detail diffs</summary> ``` Top file improvements (bytes): -44 : 17.dasm (-52.38 % of base) -32 : 22.dasm (-44.44 % of base) -32 : 7.dasm (-44.44 % of base) -32 : 32.dasm (-44.44 % of base) -32 : 27.dasm (-47.06 % of base) -32 : 12.dasm (-47.06 % of base) -28 : 16.dasm (-38.89 % of base) -28 : 15.dasm (-38.89 % of base) -20 : 18.dasm (-27.78 % of base) -16 : 30.dasm (-26.67 % of base) -16 : 6.dasm (-26.67 % of base) -16 : 5.dasm (-26.67 % of base) -16 : 10.dasm (-28.57 % of base) -16 : 26.dasm (-28.57 % of base) -16 : 25.dasm (-28.57 % of base) -16 : 21.dasm (-26.67 % of base) -16 : 11.dasm (-28.57 % of base) -16 : 31.dasm (-26.67 % of base) -16 : 20.dasm (-26.67 % of base) -8 : 33.dasm (-13.33 % of base) 24 total files with Code Size differences (24 improved, 0 regressed), 0 unchanged. Top method improvements (bytes): -44 (-52.38 % of base) : 17.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -32 (-44.44 % of base) : 32.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) -32 (-44.44 % of base) : 7.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts) -32 (-44.44 % of base) : 22.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts) -32 (-47.06 % of base) : 12.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) -32 (-47.06 % of base) : 27.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts) -28 (-38.89 % of base) : 15.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -28 (-38.89 % of base) : 16.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -20 (-27.78 % of base) : 18.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -16 (-26.67 % of base) : 30.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-28.57 % of base) : 10.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 25.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -16 (-26.67 % of base) : 5.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 20.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 31.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-28.57 % of base) : 11.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 26.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -16 (-26.67 % of base) : 6.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 21.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -8 (-13.33 % of base) : 33.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) Top method improvements (percentages): -44 (-52.38 % of base) : 17.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -32 (-47.06 % of base) : 12.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) -32 (-47.06 % of base) : 27.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts) -32 (-44.44 % of base) : 32.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) -32 (-44.44 % of base) : 7.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts) -32 (-44.44 % of base) : 22.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts) -28 (-38.89 % of base) : 15.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -28 (-38.89 % of base) : 16.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -16 (-28.57 % of base) : 10.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 25.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 11.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 26.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -20 (-27.78 % of base) : 18.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -16 (-26.67 % of base) : 30.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-26.67 % of base) : 5.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 20.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 31.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-26.67 % of base) : 6.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 21.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -8 (-14.29 % of base) : 13.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) 24 total methods with Code Size differences (24 improved, 0 regressed). ``` </details> -------------------------------------------------------------------------------- </div></details> </div></details> ## Jit-analyze summary ``` Summary of Code Size diffs: (Lower is better) Total bytes of base: 8492 (overridden on cmd) Total bytes of diff: 8012 (overridden on cmd) Total bytes of delta: -480 (-5.65 % of base) diff is an improvement. relative diff is an improvement. ``` <details> <summary>Detail diffs</summary> ``` Top file improvements (bytes): -44 : 17.dasm (-52.38 % of base) -32 : 22.dasm (-44.44 % of base) -32 : 7.dasm (-44.44 % of base) -32 : 32.dasm (-44.44 % of base) -32 : 27.dasm (-47.06 % of base) -32 : 12.dasm (-47.06 % of base) -28 : 16.dasm (-38.89 % of base) -28 : 15.dasm (-38.89 % of base) -20 : 18.dasm (-27.78 % of base) -16 : 30.dasm (-26.67 % of base) -16 : 6.dasm (-26.67 % of base) -16 : 5.dasm (-26.67 % of base) -16 : 10.dasm (-28.57 % of base) -16 : 26.dasm (-28.57 % of base) -16 : 25.dasm (-28.57 % of base) -16 : 21.dasm (-26.67 % of base) -16 : 11.dasm (-28.57 % of base) -16 : 31.dasm (-26.67 % of base) -16 : 20.dasm (-26.67 % of base) -8 : 33.dasm (-13.33 % of base) 24 total files with Code Size differences (24 improved, 0 regressed), 0 unchanged. Top method improvements (bytes): -44 (-52.38 % of base) : 17.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -32 (-44.44 % of base) : 32.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) -32 (-44.44 % of base) : 7.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts) -32 (-44.44 % of base) : 22.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts) -32 (-47.06 % of base) : 12.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) -32 (-47.06 % of base) : 27.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts) -28 (-38.89 % of base) : 15.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -28 (-38.89 % of base) : 16.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -20 (-27.78 % of base) : 18.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -16 (-26.67 % of base) : 30.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-28.57 % of base) : 10.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 25.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -16 (-26.67 % of base) : 5.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 20.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 31.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-28.57 % of base) : 11.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 26.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -16 (-26.67 % of base) : 6.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 21.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -8 (-13.33 % of base) : 33.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) Top method improvements (percentages): -44 (-52.38 % of base) : 17.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -32 (-47.06 % of base) : 12.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) -32 (-47.06 % of base) : 27.dasm - TestExtractMostSignificantBits.Program:CountLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):int (FullOpts) -32 (-44.44 % of base) : 32.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):int (FullOpts) -32 (-44.44 % of base) : 7.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):int (FullOpts) -32 (-44.44 % of base) : 22.dasm - TestExtractMostSignificantBits.Program:CountGreaterThanOrEqualUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):int (FullOpts) -28 (-38.89 % of base) : 15.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -28 (-38.89 % of base) : 16.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):bool (FullOpts) -16 (-28.57 % of base) : 10.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 25.dasm - TestExtractMostSignificantBits.Program:AnyLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 11.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):bool (FullOpts) -16 (-28.57 % of base) : 26.dasm - TestExtractMostSignificantBits.Program:NoneLessThanInt3264(System.Runtime.Intrinsics.Vector64`1[int],int):bool (FullOpts) -20 (-27.78 % of base) : 18.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstGreaterThanOrEqualByte(System.Runtime.Intrinsics.Vector128`1[byte],byte):int (FullOpts) -16 (-26.67 % of base) : 30.dasm - TestExtractMostSignificantBits.Program:AnyGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-26.67 % of base) : 5.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 20.dasm - TestExtractMostSignificantBits.Program:AnyLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 31.dasm - TestExtractMostSignificantBits.Program:NoneGreaterThanOrEqualByte64(System.Runtime.Intrinsics.Vector64`1[byte],byte):bool (FullOpts) -16 (-26.67 % of base) : 6.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt16(System.Runtime.Intrinsics.Vector128`1[ushort],ushort):bool (FullOpts) -16 (-26.67 % of base) : 21.dasm - TestExtractMostSignificantBits.Program:NoneLessThanUInt1664(System.Runtime.Intrinsics.Vector64`1[ushort],ushort):bool (FullOpts) -8 (-14.29 % of base) : 13.dasm - TestExtractMostSignificantBits.Program:IndexOfFirstLessThanInt32(System.Runtime.Intrinsics.Vector128`1[int],int):int (FullOpts) 24 total methods with Code Size differences (24 improved, 0 regressed). ``` </details> -------------------------------------------------------------------------------- ## Generated artifacts - SuperPMI log: `artifacts/spmi/superpmi.27.log` - Short summary: `artifacts/spmi/diff_short_summary.11.md` - Full summary: `artifacts/spmi/diff_summary.11.md` - Jit-analyze summary: `artifacts/spmi/asm.ExtractMostSignificantBits_final/summary.md` - Base asm: `artifacts/spmi/asm.ExtractMostSignificantBits_final/base/` - Diff asm: `artifacts/spmi/asm.ExtractMostSignificantBits_final/diff/` --------- Co-authored-by: Egor Bogatov <egorbo@gmail.com>
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.
No description provided.