[clr-interp] Report async-suspension locals to the debugger via GetAsyncLocals#127757
Open
kotlarmilos wants to merge 1 commit intodotnet:mainfrom
Open
[clr-interp] Report async-suspension locals to the debugger via GetAsyncLocals#127757kotlarmilos wants to merge 1 commit intodotnet:mainfrom
kotlarmilos wants to merge 1 commit intodotnet:mainfrom
Conversation
35b435b to
d41eea4
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends CoreCLR’s interpreter async-debugging support so the right-side debugger can retrieve live async locals/arguments for interpreted async frames via DacDbiInterfaceImpl::GetAsyncLocals, analogous to the existing JIT DebugInfoStore pipeline.
Changes:
- Introduces
InterpAsyncDebugVarand adds a per-suspension-point{ ilVarNum, dataOffset }table toInterpAsyncSuspendData. - Emits and persists interpreter async-local debug metadata during
EmitSuspend, storing the debug-var tables in the finalized method data. - Updates the DAC
GetAsyncLocalsimplementation to detect interpreted methods, decode the suspension-point bytecode viastate, and surface interpreter async locals to the debugger.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/interpreter/inc/interpretershared.h | Adds interpreter async debug-var metadata types/fields carried per suspension point. |
| src/coreclr/interpreter/compiler.cpp | Captures IL var → continuation offset mappings at suspend points and persists them into the unified method allocation. |
| src/coreclr/debug/daccess/dacdbiimpl.cpp | Implements interpreter-aware GetAsyncLocals decoding to return async locals for interpreted frames. |
Copilot's findings
- Files reviewed: 3/3 changed files
- Comments generated: 3
jakobbotsch
reviewed
May 4, 2026
d41eea4 to
c873f5a
Compare
c873f5a to
59cef97
Compare
Open
3 tasks
BrzVlad
reviewed
May 5, 2026
59cef97 to
8207ffc
Compare
jakobbotsch
approved these changes
May 5, 2026
3 tasks
BrzVlad
reviewed
May 5, 2026
| m_compHnd->setBoundaries(m_methodInfo->ftn, m_ILToNativeMapSize, m_pILToNativeMap); | ||
| m_pILToNativeMap = NULL; // Ownership transferred to the VM | ||
|
|
||
| int32_t numSuspensionPoints = m_asyncDebugSuspensionPoints.GetSize(); |
Member
There was a problem hiding this comment.
Seems like this code doesn't belong here, in EmitCode. Could we extract it in some other method and move it outside of this. I would also move the setVars block above
Member
Author
There was a problem hiding this comment.
Extracted into InterpCompiler::ReportAsyncDebugInfo(), called from EmitCode after setVars/setBoundaries
8207ffc to
a275e72
Compare
a275e72 to
1f75069
Compare
…ocals Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1f75069 to
f1be050
Compare
This was referenced May 5, 2026
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.
Description
When a managed async method is suspended at an await, the right-side debugger asks for the live values of the user's locals and arguments at that suspension point so they can be displayed on the call stack. The JIT path supplies this through
ICorJitInfo::reportAsyncDebugInfo. The interpreter compiler never hits that path, soICorDebugAsyncFrame::GetArgumentreturnedCORDBG_E_IL_VAR_NOT_AVAILABLEfor every IL variable on every interpreted async frame.This adds a small parallel pipeline for the interpreter.
InterpAsyncSuspendDatanow carries a per suspension point table of{ilVarNum, dataOffset}entries. On the DAC side,GetAsyncLocalsdetects an interpreter method and decodes the bytecode atstartIp + state.This fixes the following interpreter debugger test failures:
Async.AsyncSimpleAsync.AsyncBreakpointAsync.AsyncBreakpointJmcAsync.AsyncGenericAsync.AsyncRecursiveAsync.AsyncSharedGenericAsync.AsyncV2CallingAsyncV1IteratorAsync.AsyncGenericStepInto