Skip to content

Conversation

@janvorli
Copy link
Member

There were two issues. One is that the SfiNextWorker was incorrectly advancing the stack frame iterator in case the interpreter was called from CallDescrWorkerInternal in some cases.
The second was that the call to MethodDesc::GetMethodDescOfVirtualizedCode that is made by the InterpExecMethod can end up running managed code and throw managed exception. So it needs to have PAL_TRY/PAL_EXCEPT around the invocation, since the main loop of the interpreter can only catch and process C++ exceptions.

This fixes the Loader\classloader\regressions\vsw529206\vsw529206ModuleCctor test.

There were two issues. One is that the SfiNextWorker was incorrectly
advancing the stack frame iterator in case the interpreter was called
from CallDescrWorker in some cases.
The second was that the call to MethodDesc::GetMethodDescOfVirtualizedCode
that is made by the InterpExecMethod can end up running managed code and
throw managed exception. So it needs to have PAL_TRY/PAL_EXCEPT around
the invocation, since the main loop of the interpreter can only catch
and process C++ exceptions.
@janvorli janvorli added this to the 11.0.0 milestone Oct 30, 2025
@janvorli janvorli self-assigned this Oct 30, 2025
Copilot AI review requested due to automatic review settings October 30, 2025 18:51
@janvorli janvorli requested review from BrzVlad and kg as code owners October 30, 2025 18:51
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @BrzVlad, @janvorli, @kg
See info in area-owners.md if you want to be subscribed.

Copy link
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 improves exception handling in the CoreCLR interpreter by:

  1. Wrapping calls to GetMethodDescOfVirtualizedCode in a new helper function that properly handles both C++ and managed exceptions
  2. Refining the stack frame iteration logic to correctly distinguish between managed and native callers during exception unwinding

Key changes:

  • Introduces CallGetMethodDescOfVirtualizedCode wrapper function for proper exception handling
  • Updates virtual call and delegate invocation sites to use the new wrapper
  • Improves exception handling logic to check if return addresses point to managed code before advancing the stack frame iterator

Reviewed Changes

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

File Description
src/coreclr/vm/interpexec.cpp Adds CallGetMethodDescOfVirtualizedCode wrapper function and updates two call sites to use it for proper exception handling
src/coreclr/vm/exceptionhandling.cpp Refines stack frame unwinding logic to properly distinguish managed from native callers using ExecutionManager::IsManagedCode

// The caller is a managed code, so we can update the regdisplay to point to it.
pInterpreterFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet(), /* updateFloats */ true);
}
// The caller of the interpreted code is a managed code
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

Comment should say 'is managed code' rather than 'is a managed code' for consistency with line 3985.

Suggested change
// The caller of the interpreted code is a managed code
// The caller of the interpreted code is managed code

Copilot uses AI. Check for mistakes.
Comment on lines +3975 to +3981
if (ExecutionManager::IsManagedCode(returnAddress))
{
// The caller is a managed code, so we can update the regdisplay to point to it.
pInterpreterFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet(), /* updateFloats */ true);
}
// The caller of the interpreted code is a managed code
retVal = pThis->Next();
_ASSERTE(retVal != SWA_FAILED);
_ASSERTE(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD);
isNativeTransition = false;
Copy link

Copilot AI Oct 30, 2025

Choose a reason for hiding this comment

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

The comment at line 3977 should explain why we call Next() when the caller is managed code, to clarify that we're advancing to the managed caller frame. Consider expanding: 'The caller of the interpreted code is managed code, so advance to that frame.'

Copilot uses AI. Check for mistakes.
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.

1 participant