Skip to content

JIT: Superpmi wasm32 neardiff#128967

Open
AndyAyersMS wants to merge 5 commits into
dotnet:mainfrom
AndyAyersMS:superpmi-wasm32-neardiff
Open

JIT: Superpmi wasm32 neardiff#128967
AndyAyersMS wants to merge 5 commits into
dotnet:mainfrom
AndyAyersMS:superpmi-wasm32-neardiff

Conversation

@AndyAyersMS
Copy link
Copy Markdown
Member

Update coredistools version to 1.7.0 to pick up Wasm disassembly support.

Implement neardiff support for Wasm.

AndyAyersMS and others added 4 commits May 29, 2026 18:57
Teach the SuperPMI near-differ how to route wasm32 collections through the
coredistools framing-aware code paths, and add a wasm-specific offset
comparator that consults the JIT-recorded relocation table.

Changes:

 * NearDiffer::InitAsmDiff: map `wasm` / `wasm32` target architecture to
   Target_Wasm32. Existing NearDiffCodeBlocks / DumpCodeBlock /
   DumpDiffBlocks auto-route to the framed implementations in coredistools
   when configured for Target_Wasm32, so no plumbing through new entry
   points is needed.

 * NearDiffer::compareOffsets: dispatch to new compareOffsetsWasm when
   SpmiTargetArchitecture is WASM32 instead of replaying the generic
   IP-relative heuristics, which do not apply to wasm.

 * NearDiffer::compareOffsetsWasm: look up recorded relocations in cr1 and
   cr2 at the immediate-payload byte (a small window starting one byte past
   the opcode) and accept iff both sides have a reloc with matching kind
   and equal target (after addlDelta correction). Asymmetric relocs,
   different kinds, and different targets are treated as real diffs in v1.

 * CompileResult::findRelocationInRange: linear-scan helper that maps a
   buffer-relative offset window back to a recorded Agnostic_RecordRelocation
   entry. Used by compareOffsetsWasm.

 * CompileResult::applyRelocs: skip patching for wasm32. The JIT emits
   PADDED_RELOC_SIZE bytes of `80 80 80 80 00` (a ULEB/SLEB that decodes
   to zero) at every reloc site. Both baseline and diff JITs emit
   identical placeholder bytes there, so byte-by-byte comparison already
   succeeds at reloc sites without any patching; compareOffsetsWasm
   handles the case where bytes actually do differ.

Requires coredistools >= 1.7.0 for the Target_Wasm32 enum value. The
eng/Versions.props bump to MicrosoftNETCoreCoreDisToolsVersion=1.7.0 is
left to a follow-up once the dotnet/jitutils PR dotnet#437 lands and a real
1.7.0 nupkg publishes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Picks up the wasm32 disassembly + framed near-differ entry points added
in dotnet/jitutils PR dotnet#437.

Changes:

 * eng/Versions.props: MicrosoftNETCoreCoreDisToolsVersion 1.6.0 -> 1.7.0
   to match the published nupkg containing the framed Wasm code-buffer
   support.

 * src/coreclr/inc/coredistools.h: re-sync from
   dotnet/jitutils/src/coredistools/coredistools.h:
     - Adds Target_Wasm32 to the TargetArch enum (must match the value
       used inside coredistools.dll).
     - Declares the framed entry points NearDiffCodeBlocksFramed,
       DumpCodeBlockFramed, DumpDiffBlocksFramed for callers that want
       to invoke them directly. The non-framed entry points
       (NearDiffCodeBlocks, DumpCodeBlock, DumpDiffBlocks) automatically
       delegate to the framed implementations when the differ is
       configured for Target_Wasm32, so the existing SuperPMI
       neardiffer wiring (added in the parent commit) needs no changes
       beyond passing Target_Wasm32 at init time.

Together with the parent commit `SuperPMI: wasm32 near-differ
support'', this enables `superpmi.py asmdiffs -target_os browser
-target_arch wasm'' to produce textual asm diffs against wasm32
collections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 4, 2026 01:32
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 4, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@AndyAyersMS
Copy link
Copy Markdown
Member Author

@dotnet/wasm-contrib PTAL
fyi @dotnet/jit-contrib

This is the last piece of SPMI support. Validated locally by modifying the JIT to insert NOPs in some random places, and got reasonable looking diff reports.

The reloc comparison may need some fine-tuning; we'll have to see how well it holds up over time.

D:\repos\runtime0\src\coreclr\scripts>py superpmi.py asmdiffs -target_os browser -target_arch wasm
[09:53:15] ================ Logging to D:\repos\runtime0\artifacts\spmi\superpmi.25.log
[09:53:15] Overriding 'mch_arch' to 'x64'
[09:53:15] Overriding 'altjit' to True for wasm cross-target JIT
[09:53:15] Using JIT/EE Version from jiteeversionguid.h: 31a04b06-915e-42a0-bbd2-c9c397677ae5
[09:53:15] Baseline hash: 8c85699181373b892a8dcbb51cdbd753b03272e0
[09:53:15] Using baseline D:\repos\runtime0\artifacts\spmi\basejit\8c85699181373b892a8dcbb51cdbd753b03272e0.windows.x64.Checked\clrjit_universal_wasm_x64.dll
[09:53:15] Using coredistools found at D:\repos\runtime0\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\coredistools.dll
[09:53:15] Found download cache directory "D:\repos\runtime0\artifacts\spmi\mch\31a04b06-915e-42a0-bbd2-c9c397677ae5.browser.x64" and --force_download not set; skipping download
[09:53:15] SuperPMI ASM diffs
[09:53:15] Base JIT Path: D:\repos\runtime0\artifacts\spmi\basejit\8c85699181373b892a8dcbb51cdbd753b03272e0.windows.x64.Checked\clrjit_universal_wasm_x64.dll
[09:53:15] Diff JIT Path: D:\repos\runtime0\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\clrjit_universal_wasm_x64.dll
[09:53:15] Using MCH files:
[09:53:15]   D:\repos\runtime0\artifacts\spmi\mch\31a04b06-915e-42a0-bbd2-c9c397677ae5.browser.x64\corelib.crossgen2.windows.x64.checked.mch
[09:53:15] Running asm diffs of D:\repos\runtime0\artifacts\spmi\mch\31a04b06-915e-42a0-bbd2-c9c397677ae5.browser.x64\corelib.crossgen2.windows.x64.checked.mch
[09:53:20] Asm diffs found
[09:53:20] Creating dasm files: D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\base D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\diff
[09:53:24] Differences found. To replay SuperPMI use:
[09:53:24]
[09:53:24] set DOTNET_JitEnableNoWayAssert=1
[09:53:24] set DOTNET_JitNoForceFallback=1
[09:53:24] set DOTNET_JitAlignLoops=0
[09:53:24] set DOTNET_JitDisasm=*
[09:53:24] set DOTNET_JitUnwindDump=*
[09:53:24] set DOTNET_JitEHDump=*
[09:53:24] set DOTNET_JitDisasmDiffable=1
[09:53:24] set DOTNET_JitDisasmWithGC=1
[09:53:24] D:\repos\runtime0\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\superpmi.exe -target wasm -jitoption force AltJit=* -jitoption force AltJitNgen=* -jit2option force AltJit=* -jit2option force AltJitNgen=* -jitoption force AltJit=* -jitoption force AltJitNgen=* -c ### D:\repos\runtime0\artifacts\tests\coreclr\windows.x64.Checked\Tests\Core_Root\clrjit_universal_wasm_x64.dll D:\repos\runtime0\artifacts\spmi\mch\31a04b06-915e-42a0-bbd2-c9c397677ae5.browser.x64\corelib.crossgen2.windows.x64.checked.mch
[09:53:24]
[09:53:24] Total bytes of base: 9197191
[09:53:24] Total bytes of diff: 9207469
[09:53:24] Total bytes of delta: 10278 (0.11% of base)
[09:53:24]
[09:53:24] Total PerfScore of base: 4142235.662632996
[09:53:24] Total PerfScore of diff: 4166315.9770329986
[09:53:24] Total PerfScore of delta: 24080.31440000236 (0.58% of base)
[09:53:24]
[09:53:24] Relative PerfScore Geomean: 0.2182%
[09:53:24] Relative PerfScore Geomean (Diffs): 1.7957%
[09:53:24]
[09:53:24] Generated asm is located under D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\base D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\diff
[09:53:24] Textual differences found in generated asm.
[09:53:24] Invoking: d:\repos\jitutils\bin\jit-analyze.exe --md D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\summary.md -r --base D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\base --diff D:\repos\runtime0\artifacts\spmi\asm.corelib.crossgen2.windows.x64.checked.3\diff --override-total-base-metric 9197191 --override-total-diff-metric 9207469 --is-subset-of-diffs
[09:53:31] Found 92 files with textual diffs.
[09:53:31]
[09:53:31] Summary of Code Size diffs:
[09:53:31] (Lower is better)
[09:53:31]
[09:53:31] Total bytes of base: 9197191 (overridden on cmd)
[09:53:31] Total bytes of diff: 9207469 (overridden on cmd)
[09:53:31] Total bytes of delta: 10278 (0.11 % of base)
[09:53:31]     diff is a regression.
[09:53:31]     relative diff is a regression.
[09:53:31]
[09:53:31]
[09:53:31] Top file regressions (bytes):
[09:53:31]          172 : 23970.dasm (0.41% of base)
[09:53:31]           62 : 17333.dasm (1.26% of base)
[09:53:31]           61 : 2333.dasm (0.47% of base)
[09:53:31]           60 : 20397.dasm (1.73% of base)

... etc ...

[09:53:31] --------------------------------------------------------------------------------
[09:53:31] 3,001 contexts with diffs (0 size improvements, 3,001 size regressions, 0 same size)
[09:53:31]                           (1 PerfScore improvements, 2,999 PerfScore regressions, 1 same PerfScore)
[09:53:31]   +10,278 bytes
[09:53:31]   -0.51%/+1.80% PerfScore
[09:53:31]
[09:53:31]
[09:53:31] Warning: SuperPMI encountered missing data during the diff. The diff summary printed above may be misleading.
[09:53:31] Missing with base JIT: 381. Missing with diff JIT: 381. Total contexts: 24887.

Note the collection and asmdiff currently pass JitWasmNyiToR2RUnsupported=1 (implicit on replay since it gets captured by SPMI during collection).

The 381 missing methods are largely unsupported runtime async.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates SuperPMI’s asm near-diffing pipeline to understand wasm32 code streams by (1) bumping CoreDisTools to a version that supports wasm disassembly/framing and (2) adding wasm-specific offset/relocation handling in SuperPMI’s NearDiffer / CompileResult glue.

Changes:

  • Update CoreDisTools package version to 1.7.0 and extend the local coredistools.h interface with Target_Wasm32 plus framed entrypoints.
  • Teach SuperPMI NearDiffer to configure CoreDisTools for wasm32 (Target_Wasm32) and route offset equivalence checks through a wasm-specific comparator.
  • Add a CompileResult helper to locate relocations by location range, and skip applyRelocs for wasm32.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/coreclr/tools/superpmi/superpmi/neardiffer.h Adds a wasm-specific offset comparator declaration.
src/coreclr/tools/superpmi/superpmi/neardiffer.cpp Maps wasm/wasm32 to CoreDisTools Target_Wasm32 and implements compareOffsetsWasm.
src/coreclr/tools/superpmi/superpmi-shared/compileresult.h Declares findRelocationInRange for wasm near-diff relocation lookup.
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Skips applyRelocs for wasm32 and implements relocation range lookup.
src/coreclr/inc/coredistools.h Adds Target_Wasm32 and framed near-diff/disasm API surface.
eng/Versions.props Updates MicrosoftNETCoreCoreDisToolsVersion to 1.7.0.

Comment thread src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp

const DiffData* data = (const DiffData*)payload;

// Payload byte for an un-prefixed wasm opcode is opcode-byte + 1. For prefixed
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some un-prefixed memory instructions, we do have a reloc type we can emit which is a reloc of the internal offset immediate for loads/stores, so we'd have <memop> <align>:u32 <relocated-offset>:u32 where the relocated piece would be at opcode-byte + 2 in practice. Can we update the comment here to reflect this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed the comment to indicate it will scan for relocs at any location after the opcode byte

- compileresult.cpp findRelocationInRange: guard against size_t wraparound on
  rangeLo + windowSize, and short-circuit when windowSize == 0 so the helper's
  half-open range contract is self-contained (Copilot review).

- neardiffer.cpp compareOffsetsWasm: clarify the docstring and inline comment
  to note that the recorded reloc payload sits at opcode-byte + 1 for
  un-prefixed i32.const/call/etc., but at opcode-byte + 2 for un-prefixed
  memory ops (i32.load/i32.store/...) after the align u32. The existing
  immediate-window scan covers both cases unchanged; this is a comment-only
  update (adamperlin review).

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

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants