Skip to content

[clr-interp] Report async-suspension locals to the debugger via GetAsyncLocals#127757

Open
kotlarmilos wants to merge 1 commit intodotnet:mainfrom
kotlarmilos:interp-async-debug-locals
Open

[clr-interp] Report async-suspension locals to the debugger via GetAsyncLocals#127757
kotlarmilos wants to merge 1 commit intodotnet:mainfrom
kotlarmilos:interp-async-debug-locals

Conversation

@kotlarmilos
Copy link
Copy Markdown
Member

@kotlarmilos kotlarmilos commented May 4, 2026

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, so ICorDebugAsyncFrame::GetArgument returned CORDBG_E_IL_VAR_NOT_AVAILABLE for every IL variable on every interpreted async frame.

This adds a small parallel pipeline for the interpreter. InterpAsyncSuspendData now carries a per suspension point table of {ilVarNum, dataOffset} entries. On the DAC side, GetAsyncLocals detects an interpreter method and decodes the bytecode at startIp + state.

This fixes the following interpreter debugger test failures:

  • Async.AsyncSimple
  • Async.AsyncBreakpoint
  • Async.AsyncBreakpointJmc
  • Async.AsyncGeneric
  • Async.AsyncRecursive
  • Async.AsyncSharedGeneric
  • Async.AsyncV2CallingAsyncV1Iterator
  • Async.AsyncGenericStepInto

Copilot AI review requested due to automatic review settings May 4, 2026 14:54
@kotlarmilos kotlarmilos marked this pull request as draft May 4, 2026 14:55
@kotlarmilos kotlarmilos changed the title [interp] Report async-suspension locals to the debugger via GetAsyncLocals [interp] Report async locals to the debugger via GetAsyncLocals May 4, 2026
@kotlarmilos kotlarmilos changed the title [interp] Report async locals to the debugger via GetAsyncLocals [clr-interp] Report async locals to the debugger via GetAsyncLocals May 4, 2026
@kotlarmilos kotlarmilos added this to the 11.0.0 milestone May 4, 2026
@kotlarmilos kotlarmilos requested review from noahfalk and tommcdon May 4, 2026 14:57
@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch 3 times, most recently from 35b435b to d41eea4 Compare May 4, 2026 14:59
Copy link
Copy Markdown
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

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 InterpAsyncDebugVar and adds a per-suspension-point { ilVarNum, dataOffset } table to InterpAsyncSuspendData.
  • Emits and persists interpreter async-local debug metadata during EmitSuspend, storing the debug-var tables in the finalized method data.
  • Updates the DAC GetAsyncLocals implementation to detect interpreted methods, decode the suspension-point bytecode via state, 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

Comment thread src/coreclr/debug/daccess/dacdbiimpl.cpp Outdated
Comment thread src/coreclr/debug/daccess/dacdbiimpl.cpp Outdated
Comment thread src/coreclr/debug/daccess/dacdbiimpl.cpp Outdated
Comment thread src/coreclr/debug/daccess/dacdbiimpl.cpp Outdated
@kotlarmilos kotlarmilos changed the title [clr-interp] Report async locals to the debugger via GetAsyncLocals [clr-interp] Report async-suspension locals to the debugger via GetAsyncLocals May 4, 2026
@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch from d41eea4 to c873f5a Compare May 4, 2026 15:19
Copilot AI review requested due to automatic review settings May 4, 2026 15:19
@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch from c873f5a to 59cef97 Compare May 4, 2026 15:19
Copy link
Copy Markdown
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.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 1

Comment thread src/coreclr/debug/daccess/dacdbiimpl.cpp Outdated
Comment thread src/coreclr/interpreter/inc/interpretershared.h Outdated
@kotlarmilos kotlarmilos self-assigned this May 5, 2026
@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch from 59cef97 to 8207ffc Compare May 5, 2026 08:46
Copilot AI review requested due to automatic review settings May 5, 2026 12:51
Copy link
Copy Markdown
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.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 1

Comment thread src/coreclr/interpreter/compiler.cpp
m_compHnd->setBoundaries(m_methodInfo->ftn, m_ILToNativeMapSize, m_pILToNativeMap);
m_pILToNativeMap = NULL; // Ownership transferred to the VM

int32_t numSuspensionPoints = m_asyncDebugSuspensionPoints.GetSize();
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.

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Extracted into InterpCompiler::ReportAsyncDebugInfo(), called from EmitCode after setVars/setBoundaries

@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch from 8207ffc to a275e72 Compare May 5, 2026 14:09
Copilot AI review requested due to automatic review settings May 5, 2026 14:10
@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch from a275e72 to 1f75069 Compare May 5, 2026 14:10
…ocals

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos kotlarmilos force-pushed the interp-async-debug-locals branch from 1f75069 to f1be050 Compare May 5, 2026 14:13
Copy link
Copy Markdown
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.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants