Skip to content

Conversation

@jakobbotsch
Copy link
Member

Previously we considered all locals to be live across all async calls in MinOpts. This includes JIT created temps. We can avoid saving and restoring these locals based on the same invariant that EnC and OSR use: namely that the JIT creates only a very specific set of long-lived live state in MinOpts.

Unlike EnC and OSR we do have IL stack entries that can be live across async calls. This PR adds a bit to LclVarDsc to mark these locals and then aggressively spills to such temps around async calls when compiling in MinOpts.

Fix #116370

@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 Jan 22, 2026
@dotnet-policy-service
Copy link
Contributor

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

@jakobbotsch
Copy link
Member Author

/azp run Fuzzlyn

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
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

Purpose: This PR optimizes the size of async continuations in MinOpts (unoptimized) code by avoiding the capture of unnecessary JIT-created temporary variables. Previously, all locals (including JIT temps) were considered live across async calls in MinOpts. This change leverages the same invariant used by EnC and OSR: in MinOpts, the JIT only creates a specific set of long-lived state (IL locals and spilled IL stack entries).

Changes:

  • Adds a new lvLiveAcrossAsync bit field to LclVarDsc to mark locals that must be preserved across async suspension points in MinOpts
  • Updates async call setup to aggressively spill IL stack entries to temps and mark them with lvLiveAcrossAsync when compiling in MinOpts
  • Modifies AsyncLiveness::IsLive to check the new field when liveness information is unavailable, returning true only for IL locals or temps marked as live across async

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/coreclr/jit/compiler.h Adds lvLiveAcrossAsync bit field to LclVarDsc and updates impSetupAsyncCall signature to accept numILArgs parameter
src/coreclr/jit/importercalls.cpp Updates impSetupAsyncCall to spill IL stack entries around async calls in MinOpts and marks the resulting temps with lvLiveAcrossAsync; passes numILArgs from call signature to impSetupAsyncCall
src/coreclr/jit/async.cpp Marks async ExecutionContext and SynchronizationContext variables with lvLiveAcrossAsync; updates AsyncLiveness::IsLive to check the new field when liveness is unavailable

@jakobbotsch
Copy link
Member Author

/azp run Fuzzlyn

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

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.

JIT: Avoid capturing all jit temps in debug for runtime async

1 participant