Skip to content

Conversation

janvorli
Copy link
Member

@janvorli janvorli commented Apr 2, 2025

This change moves exception handling funclets invocation to the ICodeManager derived classes so that it can be done differently for JITted/crossgened code and interpreted code.

This change moves exception handling funclets invocation to the
ICodeManager so that it can be done differently for JITted/crossgened
code and interpreted code.
@janvorli janvorli added this to the 10.0.0 milestone Apr 2, 2025
@janvorli janvorli requested review from kg, cshung, BrzVlad and jkotas April 2, 2025 23:08
@janvorli janvorli self-assigned this Apr 2, 2025
@Copilot Copilot AI review requested due to automatic review settings April 2, 2025 23:08
Copy link
Contributor

@Copilot 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 moves funclet invocation for exception handling into ICodeManager‑derived classes so that different implementations can be provided for JITted/crossgened versus interpreted code.

  • Removed direct usage of GetEstablisherFrame and handler function calls in catch, finally, and filter funclet blocks in exceptionhandling.cpp.
  • Updated EECodeManager in eetwain.cpp and its corresponding interface in eetwain.h to include a CallFunclet virtual method for funclet invocation.

Reviewed Changes

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

File Description
src/coreclr/vm/exceptionhandling.cpp Replaced direct funclet calls with CodeManager::CallFunclet invocations.
src/coreclr/vm/eetwain.cpp Added alternative implementation for CallFunclet and GetEstablisherFrame.
src/coreclr/inc/eetwain.h Updated the virtual method declarations for CallFunclet.

CastHandlerFn(pfnHandler),
GetFirstNonVolatileRegisterAddress(pvRegDisplay->pCurrentContext),
pFuncletCallerSP);
dwResumePC = exInfo->m_frameIter.m_crawl.GetCodeManager()->CallFunclet(throwable, pHandlerIP, pvRegDisplay, exInfo, false /* isFilterFunclet */);
Copy link
Preview

Copilot AI Apr 2, 2025

Choose a reason for hiding this comment

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

Ensure that the new CallFunclet invocation in the catch funclet correctly replicates the behavior (especially the resume address) of the previous direct handler call. It may be beneficial to document any behavioral differences introduced by delegating to the CodeManager.

Copilot uses AI. Check for mistakes.

DWORD_PTR dwResumePC = pfnHandler(establisherFrame, NULL);
#endif

exInfo->m_frameIter.m_crawl.GetCodeManager()->CallFunclet(NULL, pHandlerIP, pvRegDisplay, exInfo, false /* isFilterFunclet */);
Copy link
Preview

Copilot AI Apr 2, 2025

Choose a reason for hiding this comment

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

Confirm that discarding the return value from CallFunclet in the finally funclet case is intentional and that no downstream logic depends on it; consider adding a clarifying comment if necessary.

Copilot uses AI. Check for mistakes.

@janvorli
Copy link
Member Author

janvorli commented Apr 2, 2025

cc: @filipnavara

dwResumePC = exInfo->m_frameIter.m_crawl.GetCodeManager()->CallFunclet(throwable, pHandlerIP, pvRegDisplay, exInfo, false /* isFilterFunclet */);

#ifdef USE_FUNCLET_CALL_HELPER
FixContext(pvRegDisplay->pCurrentContext);
Copy link
Member

Choose a reason for hiding this comment

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

It would make sense to move the FixContext logic inside EECodeManager::CallFunclet. Afterall I don't expect it to be relevant for interpreter (ignoring the fact that we don't support interpreter on x86) and it only calls back into the code manager anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've actually had it there, but moved it back. It is used for catch funclet only, so I would have to add another flag to the signature to distinguish catch. The context fixing is only relevant to the resuming after catch and that happens here, not in the code manager. I would actually prefer replacing the fixcontext here by its body and ifdef it on x86, since the function does nothing for all other architectures.

@janvorli
Copy link
Member Author

janvorli commented Apr 3, 2025

There is some Linux problem, I am investigating.

I've missed the fact that the macro is defined in the
exceptionhandling.cpp only, so the move to eetwain.cpp disabled this
feature.
Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Unix test failures look real

@janvorli
Copy link
Member Author

janvorli commented Apr 4, 2025

Unix test failures look real

@jkotas Yes, I've been looking into that whole day and finally found the culprit. The C++ compiler optimized the call to the actual funclet from the CallFunclet as a tail call, so the m_csfEHClause wasn't the caller SP. The StackFrameIterator depends on that. I have fixed that by disabling optimizations for the CallFunclet on Windows / disabling tail calling on Unix. I am running the tests now and will update the PR soon.

#else
HandlerFn* pfnHandler = (HandlerFn*)pHandler;

pExInfo->m_csfEHClause = CallerStackFrame((UINT_PTR)GetCurrentSP());
Copy link
Member

Choose a reason for hiding this comment

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

Can this line be in the #else of #ifdef USE_FUNCLET_CALL_HELPER?

Copy link
Member

Choose a reason for hiding this comment

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

(It would be nice to update x64 to use the asm helper too at some point, so we should keep all workarounds related to that under the !asm helper ifdef.

Switching x64 to asm helper should improve code size of the EH codegen and remove unnecessary differences between architectures.

Comment on lines 2238 to 2239

pExInfo->m_csfEHClause = CallerStackFrame((UINT_PTR)GetCurrentSP());
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pExInfo->m_csfEHClause = CallerStackFrame((UINT_PTR)GetCurrentSP());

@janvorli janvorli merged commit e72f368 into dotnet:main Apr 7, 2025
98 checks passed
@janvorli janvorli deleted the move-funclet-calls-to-code-manager branch April 7, 2025 13:24
@github-actions github-actions bot locked and limited conversation to collaborators May 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants