JIT: Add a runtime async optimization to skip saving unmutated locals into reused continuations#125615
Draft
jakobbotsch wants to merge 19 commits intodotnet:mainfrom
Draft
JIT: Add a runtime async optimization to skip saving unmutated locals into reused continuations#125615jakobbotsch wants to merge 19 commits intodotnet:mainfrom
jakobbotsch wants to merge 19 commits intodotnet:mainfrom
Conversation
This reverts commit 8e54df1.
Contributor
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a runtime async optimization to skip saving locals that haven't been mutated since the last resumption point when reusing continuation objects. It builds on PR #125556 (which added continuation reuse) by leveraging the knowledge that a reused continuation already holds correct values for unmutated locals, thus eliminating unnecessary write barriers and improving performance by ~10%.
Changes:
- Introduces
PreservedValueAnalysis, a forward dataflow analysis that computes which tracked locals may have been mutated since the previous resumption point, enabling the optimization to skip saving unchanged locals. - Restructures continuation layout handling: replaces the old per-call
ContinuationLayoutwith aContinuationLayoutBuilder/ContinuationLayoutsplit where a shared layout can be computed across all suspension points, and switches flag encoding fromHAS_*bitmasks to index-based encoding of exception/context/result offsets. - Splits
CreateSuspensionandCreateResumptioninto block-creation and IR-population phases, with the newCreateResumptionsAndSuspensionsmethod driving the two-phase approach and handling shared vs per-call layouts.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/inc/corinfo.h | Replaces HAS_* flag bits with index-based encoding for exception, context, and result offsets |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs | Updates managed ContinuationFlags enum and access methods to use new index-based encoding |
| src/coreclr/vm/object.h | Updates GetResultStorage and GetExceptionObjectStorage to use index-based decoding |
| src/coreclr/vm/interpexec.cpp | Updates interpreter suspension/resumption to use index-based flag encoding |
| src/coreclr/interpreter/compiler.cpp | Updates interpreter compiler to emit index-based flag encoding |
| src/coreclr/jit/async.h | Introduces ReturnTypeInfo, ReturnInfo, ContinuationLayoutBuilder, AsyncState, SaveSet; restructures ContinuationLayout and AsyncTransformation |
| src/coreclr/jit/async.cpp | Core implementation: PreservedValueAnalysis, CreateSharedLayout, continuation reuse logic, split save sets |
| src/coreclr/jit/jitconfigvalues.h | Adds JitAsyncReuseContinuations and JitAsyncPreservedValueAnalysisRange config knobs |
| src/coreclr/jit/jitstd/vector.h | Adds const overload of data() to support ContainsLocal const method |
| } | ||
|
|
||
| if (layout.ReturnSize > 0) | ||
| // Now allocate all returns |
| ContinuationContextIndexNumBits = 2, | ||
|
|
||
| ResultIndexFirstBit = 7, | ||
| ResultIndexBits = 25, |
| , Call(call) | ||
| , CallDefInfo(callDefInfo) | ||
| , SuspensionBB(suspensionBB) | ||
| , ResumptionBB(resumptionBB) |
Comment on lines
5858
to
5862
| returnValueDataStartOffset = currentOffset; | ||
| encodeIndex(currentOffset, CORINFO_CONTINUATION_RESULT_INDEX_FIRST_BIT, CORINFO_CONTINUATION_RESULT_INDEX_NUM_BITS); | ||
| // Handle return value first | ||
| if (returnValueVar == -1) | ||
| continue; |
This was referenced Mar 16, 2026
Open
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.
With #125556 we learn something whenever we reuse a continuation -- specifically that the continuation was created at one of the other suspension points that can reach the current suspension point. We can use that knowledge to skip saving all locals that cannot possibly have been mutated since any previous suspension point. This saves a lot of write barriers when we reuse continuations.
Micro benchmark with warmup
(with
DOTNET_TC_OnStackReplacement=0due to #120865) this improves performance by about 10%.Codegen diff
Based on #125556