Skip to content

[wasm] Regalloc: Allow Non-exposed GC Ref Locals to Live in Wasm Locals - #135543

Draft
adamperlin wants to merge 4 commits into
dotnet:mainfrom
adamperlin:adamperlin/wasm-enregister-gcsafe-refs
Draft

adamperlin wants to merge 4 commits into
dotnet:mainfrom
adamperlin:adamperlin/wasm-enregister-gcsafe-refs

Conversation

@adamperlin

@adamperlin adamperlin commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

The GC does not have any visibility into references which are on the wasm value stack or in wasm locals. As a result, we currently assign stack homes to all GC typed tracked locals unconditionally for GC safety. However, this is not actually necessary for tracked locals which are never exposed to a GC. We can make this determination by tracking liveness across all GC safepoints in a method. A GC safe point can be hit along a non-throwing code path at any call site except for NoGC marked helpers, as well as at explicit GC-poll points. Additionally, invoking a finally funclet may cause a GC.

For throwing code paths, we must account for any LIR node which could possibly throw (this includes all null checks, div-by-zero checks, range checks, etc.) and also track which live locals are actually live on the throwing path. A reference stored in a local is not actually exposed to GC over an exception-only GC safepoint path unless it is also live into a handler for that site.

We can then treat all GC-ref tracked locals which are meaningfully live at a safepoint as before and continue to spill them but allow safe unexposed locals to be Wasm register candidates and thus receive local homes.

…r a method and checks the state of local liveness

at each potential GC safepoint to determine which locals are live across a safepoint.
It distinguishes between normal GC safepoints triggered by a call or and exception-only GC safepoints, where an operation can only collect on its throwing path.
This allows us to effectively discount locals as gc-exposed if they are only exposed to GC on a throwing path but are NOT live into
a handler.

The set of gc-safe locals is the set of gc exposed locals subracted from the set of all locals. This reduced set of gc-safe locals
can be used by Wasm regalloc to make gc refs into wasm-local candidates.
…asses to allow safely placing select GC references in locals
@adamperlin
adamperlin requested a balanced review from Copilot October 9, 2026 21:35
@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 Oct 9, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@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.

Copilot AI left a comment

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.

🟡 Changes recommended

The tests do not automatically verify that eligible references are actually assigned Wasm-local homes.

3 open findings
What changed in this PR

Adds Wasm GC-reference liveness analysis so safe reference locals can use Wasm-local homes.

Changes:

  • Identifies tracked GC references not live across safepoints.
  • Enables their register allocation and preserves call arguments via spills.
  • Adds GC-liveness correctness scenarios.
File Description
src/​coreclr/​jit/​fgwasm.cpp Implements candidate analysis and spill handling.
src/​coreclr/​jit/​regallocwasm.cpp Allows identified references into Wasm locals.
src/​coreclr/​jit/​compiler.cpp Runs the new analysis phase.
src/​coreclr/​jit/​compiler.h Declares candidate state and phase method.
src/​coreclr/​jit/​compphases.h Registers the new phase.
src/​coreclr/​jit/​compmemkind.h Adds candidate-set allocation tracking.
src/​tests/​JIT/​Directed/​WasmGCLiveness/​WasmGCLiveness.cs Adds GC-liveness scenarios.
src/​tests/​JIT/​Directed/​WasmGCLiveness/​WasmGCLiveness.csproj Configures the isolated priority-one test.

🧠 Review effort: Balanced

Comment on lines +190 to +192
bool isRefCandidate =
varDsc->lvTracked &&
VarSetOps::IsMember(m_compiler, *m_compiler->m_wasmGCRefCandidates, varDsc->lvVarIndex);
VarSetOps::Assign(this, compCurLife, block->bbLiveIn);
for (GenTree* tree : LIR::AsRange(block))
{
// compCurLife should reflect livness into this tree;
// of the test objects.
//
// Build this project with src/tests/build.sh -Test
// JIT/Directed/WasmGcLiveness/WasmGcLiveness.csproj -priority1, adding the target

This branch has not been deployed

No deployments
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.

2 participants