Skip to content

JIT: Do not skip reference prolog zero inits in async methods - #132326

Merged
jakobbotsch merged 1 commit into
dotnet:mainfrom
jakobbotsch:fix-126750-zeroinit
Aug 14, 2026
Merged

JIT: Do not skip reference prolog zero inits in async methods#132326
jakobbotsch merged 1 commit into
dotnet:mainfrom
jakobbotsch:fix-126750-zeroinit

Conversation

@jakobbotsch

@jakobbotsch jakobbotsch commented Aug 14, 2026

Copy link
Copy Markdown
Member

optRemoveRedundantZeroInits marks a reference local as having an explicit init when its first reference is a full store that is not preceded by a GC safe point, which lets codegen drop the zero initialization from the prolog.

In an async method the resumption path branches straight to a resumption block, skipping that store. If the local is GC reportable and is not restored from the continuation, the GC then scans stack garbage. This is reachable today in async versions of synchronous Task-returning methods, which do not save and restore contexts and so have no GC safe point ahead of their user code.

Skip the optimization for async methods. Add a regression test that crashes the runtime under TC=0 and GCStress=0xC (which is exercised by the GC stress pipeline).

Fix #126750

optRemoveRedundantZeroInits marks a local as having an explicit init when its
first reference is a full store that is not preceded by a GC safe point, which
lets codegen drop the zero initialization from the prolog.

In an async method the resumption path branches straight to a resumption block,
skipping that store. If the local is GC reportable and is not restored from the
continuation, the GC then scans stack garbage. This is reachable today in async
versions of synchronous Task-returning methods, which do not save and restore
contexts and so have no GC safe point ahead of their user code.

Skip the optimization for async methods.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: fe20bc01-0eae-4c21-8c3d-8dbc26cc2f4a
Copilot AI lite review requested due to automatic review settings August 14, 2026 17:10
@azure-pipelines

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

@jakobbotsch

jakobbotsch commented Aug 14, 2026

Copy link
Copy Markdown
Member Author

cc @dotnet/jit-contrib PTAL @AndyAyersMS

I checked diffs locally on a commit before HEAD and there were just a handful of diffs, all in libraries_tests_no_tiered_compilation -- 14 improvements 2 regressions. Improvements primarily because keeping the prolog zeroing allows the async transformation to reason that those locals are null and do not need to be saved/restored in the continuation.

@jakobbotsch jakobbotsch changed the title JIT: Do not skip zero initialization in async methods JIT: Do not skip reference prolog zero inits in async methods Aug 14, 2026
@jkotas jkotas added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI and removed area-GC-coreclr labels Aug 14, 2026

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.

Pull request overview

This PR fixes a correctness issue in the CoreCLR JIT where optRemoveRedundantZeroInits could suppress prolog zero-initialization for GC-reportable locals in runtime-async methods, allowing resumption paths to observe uninitialized stack slots (leading to GC scanning invalid references). It also adds a regression test to reproduce the failure under GC stress.

Changes:

  • Disable the “explicit init” marking optimization in optRemoveRedundantZeroInits for runtime async methods (compIsAsync()).
  • Add a new async regression test (Runtime_126750) that exercises the resumption-path hazard.
  • Add a dedicated test project file to build/run the new regression test.

Reviewed changes

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

File Description
src/coreclr/jit/optimizer.cpp Prevents the zero-init suppression optimization from applying to runtime-async methods.
src/tests/async/regression/126750.cs Adds a regression test that triggers GC scanning of an uninitialized stack slot on async resumption.
src/tests/async/regression/126750.csproj Adds the minimal csproj needed to compile the new regression test.

Comment thread src/coreclr/jit/optimizer.cpp
@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 AndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder if there are other places where we make similar assumptions. Eg VN or VN dead stores?

@jakobbotsch

Copy link
Copy Markdown
Member Author

I wonder if there are other places where we make similar assumptions. Eg VN or VN dead stores?

I don't see other assignments to lvHasExplicitInit than the one from this phase, so I don't think so.

The part of this transformation that tries to reason about GC safe points seems to happen a bit too early. It would probably be more reasonable for this to happen much later (perhaps done by LSRA itself).

@jakobbotsch

Copy link
Copy Markdown
Member Author

/ba-g Known failures

@jakobbotsch
jakobbotsch merged commit 3cad7b3 into dotnet:main Aug 14, 2026
147 of 154 checks passed
@jakobbotsch
jakobbotsch deleted the fix-126750-zeroinit branch August 14, 2026 20:09
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Aug 17, 2026
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 runtime-async

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JIT: Double check lvHasExplicitInit when resuming runtime async functions

4 participants