Skip to content

[clr-interp] Add initial CoreCLR interpreter func-eval support#126576

Open
matouskozak wants to merge 9 commits intodotnet:mainfrom
matouskozak:interpreter-debugger-funceval
Open

[clr-interp] Add initial CoreCLR interpreter func-eval support#126576
matouskozak wants to merge 9 commits intodotnet:mainfrom
matouskozak:interpreter-debugger-funceval

Conversation

@matouskozak
Copy link
Copy Markdown
Member

@matouskozak matouskozak commented Apr 6, 2026

Description

This adds initial func-eval support for threads stopped in CoreCLR interpreter code.

  • Queue interpreter func-eval requests in the existing pending evals hash table (ProcessAnyPendingEvals) instead of using native-context hijacking
  • Execute pending evals from InterpBreakpoint after the debugger callback returns, reusing the shared dispatch path for both interpreter and exception-time evals
  • Skip native-only setup for interpreter evals: executable breakpoint segment allocation, SP alignment validation, and register/context updates that rely on real native frames
  • Rename m_evalDuringException to m_evalUsesHijack (inverted logic) to accurately describe the flag's purpose now that it covers both exception and interpreter paths
  • Move Init() skip logic inside DebuggerEval so callers don't need interpreter-specific conditionals
  • Return CORDBG_E_FUNC_EVAL_BAD_START_POINT for func-eval requests on interpreter threads not stopped at a breakpoint
  • Reuse the direct completion path for interpreter evals, where completion is signaled without the native breakpoint trap mechanism

Testing

  • Locally on iOS simulator
  • DiagnosticTests: FuncEval (NestedFuncEval, EscapeSecondPass), Breakpoints, Stepping, all pass with --clrinterpreter

Future Work

  • JMC stepping and CallEntryPoint frame filtering for interpreter
  • Exception interception support for interpreter

#125959

@matouskozak matouskozak self-assigned this Apr 6, 2026
Copilot AI review requested due to automatic review settings April 6, 2026 12:14
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

Adds initial debugger func-eval support when the target thread is stopped in CoreCLR interpreter code, by avoiding native-context hijacking and instead running queued evals from the interpreter breakpoint path.

Changes:

  • Adds a pending func-eval slot to the interpreter thread context and triggers execution after the breakpoint debugger callback returns.
  • Extends DebugInterface/Debugger with an interpreter-specific hook to execute pending evals.
  • Adjusts FuncEvalSetup / DebuggerEval initialization to skip native-only setup (e.g., executable breakpoint segment allocation, SP alignment checks) for interpreter evals.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/coreclr/vm/interpexec.h Adds InterpThreadContext::m_pPendingFuncEval storage for interpreter-thread func-evals.
src/coreclr/vm/interpexec.cpp Executes pending interpreter func-evals from the INTOP_BREAKPOINT handler using a synthetic filter context.
src/coreclr/vm/dbginterface.h Adds ExecutePendingInterpreterFuncEval(Thread*) to the debug interface under FEATURE_INTERPRETER.
src/coreclr/debug/ee/debugger.h Declares the Debugger implementation of ExecutePendingInterpreterFuncEval.
src/coreclr/debug/ee/debugger.cpp Implements pending-eval execution and updates FuncEvalSetup/DebuggerEval to support interpreter eval flow.

Comment thread src/coreclr/debug/ee/debugger.cpp
Comment thread src/coreclr/debug/ee/debugger.cpp Outdated
Comment thread src/coreclr/vm/interpexec.cpp Outdated
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Comment thread src/coreclr/vm/interpexec.h Outdated
Comment thread src/coreclr/debug/ee/debugger.cpp Outdated
Comment thread src/coreclr/debug/ee/debugger.cpp Outdated
Comment thread src/coreclr/debug/ee/debugger.cpp Outdated
Comment thread src/coreclr/debug/ee/debugger.cpp
Copilot AI review requested due to automatic review settings April 15, 2026 16:09
…r-funceval

# Conflicts:
#	src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/DebuggerEval.cs
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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread src/coreclr/vm/interpexec.cpp
Comment thread src/coreclr/debug/ee/debugger.cpp Outdated
@kotlarmilos kotlarmilos marked this pull request as ready for review April 15, 2026 16:20
…ec.h include

- Restore m_bypassAddress/m_bypassOpcode in EX_CATCH before EX_RETHROW so
  bypass state is not corrupted if func-eval throws
- Remove unused interpexec.h include from debugger.cpp (GetInterpThreadContext
  is declared on Thread, not in interpexec.h)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pThread->SetFilterContext(NULL);
pThreadContext->m_bypassAddress = savedBypassAddress;
pThreadContext->m_bypassOpcode = savedBypassOpcode;
EX_RETHROW;
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.

Is this code ever reached ? I would imagine func evals should catch all exceptions and never crash the app.

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.

Looking at the code for funceval, while all exceptions from the funceval invocation are caught in FuncEvalHijackRealWorker, there are methods called after the funceval itself that are marked as THROWS, e.g. the Debugger::FuncEvalComplete. I am not sure what are all the exception kinds that can stem from there, but one of them is OOM.

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'm wondering if it makes more sense to assert in checked build here rather than rethrowing, otherwise silently ignore the error. Seems wrong to have a function called from the debugger crash the app.

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.

It doesn't sound right to ignore OOM exceptions. Those would very likely kick in a bit later again anyways.

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.

8 participants