From 89b7f41bd19e4a15099cb5214bfa0b2e0a3169ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 06:13:53 +0000 Subject: [PATCH 1/2] Initial plan From 52cb6f4dd3007a38da4927db6b23a994d1d3be83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 15:27:38 +0000 Subject: [PATCH 2/2] Add CodePointerLookupFrame class for interface dispatch - Added CodePointerLookupFrame frame type to FrameTypes.h - Defined CodePointerLookupFrame class in frames.h inheriting from TransitionFrame - Implemented constructor and TraceFrame_Impl in frames.cpp - This frame avoids double GC reporting by inheriting directly from TransitionFrame instead of FramedMethodFrame - Built and verified CoreCLR compiles successfully Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/vm/FrameTypes.h | 1 + src/coreclr/vm/frames.cpp | 23 +++++++++++++ src/coreclr/vm/frames.h | 64 +++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/src/coreclr/vm/FrameTypes.h b/src/coreclr/vm/FrameTypes.h index 83a4e0aa6de455..af90d964bfd816 100644 --- a/src/coreclr/vm/FrameTypes.h +++ b/src/coreclr/vm/FrameTypes.h @@ -30,6 +30,7 @@ FRAME_TYPE_NAME(HijackFrame) FRAME_TYPE_NAME(PrestubMethodFrame) FRAME_TYPE_NAME(CallCountingHelperFrame) FRAME_TYPE_NAME(StubDispatchFrame) +FRAME_TYPE_NAME(CodePointerLookupFrame) FRAME_TYPE_NAME(ExternalMethodFrame) FRAME_TYPE_NAME(DynamicHelperFrame) FRAME_TYPE_NAME(ProtectValueClassFrame) diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp index 11b48a3f227908..a6257498a52f24 100644 --- a/src/coreclr/vm/frames.cpp +++ b/src/coreclr/vm/frames.cpp @@ -952,6 +952,29 @@ Frame::Interception StubDispatchFrame::GetInterception_Impl() return INTERCEPTION_NONE; } +#ifndef DACCESS_COMPILE +CodePointerLookupFrame::CodePointerLookupFrame(TransitionBlock * pTransitionBlock) + : TransitionFrame(FrameIdentifier::CodePointerLookupFrame), m_pTransitionBlock(dac_cast(pTransitionBlock)) +{ + LIMITED_METHOD_CONTRACT; + + m_pZapModule = NULL; + m_pIndirection = (TADDR)NULL; +} +#endif + +BOOL CodePointerLookupFrame::TraceFrame_Impl(Thread *thread, BOOL fromPatch, + TraceDestination *trace, REGDISPLAY *regs) +{ + WRAPPER_NO_CONTRACT; + + // CodePointerLookupFrame is used for interface dispatch resolution and never directly calls managed code. + // Returning false instructs the debugger to step out of the call that erected this frame. + LOG((LF_CORDB, LL_INFO1000, "CodePointerLookupFrame::TraceFrame: return FALSE\n")); + + return FALSE; +} + #ifndef DACCESS_COMPILE CallCountingHelperFrame::CallCountingHelperFrame(TransitionBlock *pTransitionBlock, MethodDesc *pMD) : FramedMethodFrame(FrameIdentifier::CallCountingHelperFrame, pTransitionBlock, pMD) diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 5491e238918411..3810aa44386c35 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -1723,6 +1723,70 @@ struct cdac_data typedef DPTR(class StubDispatchFrame) PTR_StubDispatchFrame; +//------------------------------------------------------------------------ +// CodePointerLookupFrame is used for resolving interface dispatch calls. +// Unlike StubDispatchFrame, it inherits directly from TransitionFrame to +// avoid double GC reporting of argument registers. The calling code handles +// GC reporting via the TransitionFrame base class. +//------------------------------------------------------------------------ + +class CodePointerLookupFrame : public TransitionFrame +{ + TADDR m_pTransitionBlock; + + // Indirection cell and containing module. + PTR_Module m_pZapModule; + TADDR m_pIndirection; + +public: + CodePointerLookupFrame(TransitionBlock * pTransitionBlock); + + TADDR GetTransitionBlock_Impl() + { + LIMITED_METHOD_DAC_CONTRACT; + return m_pTransitionBlock; + } + +#ifndef DACCESS_COMPILE + void SetCallSite(Module * pZapModule, TADDR pIndirection) + { + LIMITED_METHOD_CONTRACT; + + m_pZapModule = pZapModule; + m_pIndirection = pIndirection; + } +#endif + + PCODE GetUnadjustedReturnAddress() + { + LIMITED_METHOD_DAC_CONTRACT; + return GetReturnAddress_Impl(); + } + + BOOL TraceFrame_Impl(Thread *thread, BOOL fromPatch, + TraceDestination *trace, REGDISPLAY *regs); + + int GetFrameType_Impl() + { + LIMITED_METHOD_CONTRACT; + return TYPE_CALL; + } + + Interception GetInterception_Impl() + { + LIMITED_METHOD_DAC_CONTRACT; + return INTERCEPTION_NONE; + } + + ETransitionType GetTransitionType_Impl() + { + LIMITED_METHOD_DAC_CONTRACT; + return TT_InternalCall; + } +}; + +typedef DPTR(class CodePointerLookupFrame) PTR_CodePointerLookupFrame; + typedef DPTR(class CallCountingHelperFrame) PTR_CallCountingHelperFrame; class CallCountingHelperFrame : public FramedMethodFrame