Skip to content

Commit

Permalink
Support step into a tail call (#110438)
Browse files Browse the repository at this point in the history
Addressing Tom's and Mikelle's comments

Removing unrelated change and adding enum

Changing the comment.

Co-authored-by: Thays Grazia <thtaglia@microsoft.com>
Co-authored-by: Thays Grazia <thaystg@gmail.com>
  • Loading branch information
3 people authored Dec 11, 2024
1 parent 23d6092 commit 454fffd
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions src/coreclr/debug/ee/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const char *GetTType( TraceType tt);

#define IsSingleStep(exception) ((exception) == EXCEPTION_SINGLE_STEP)

typedef enum __TailCallFunctionType {
TailCallThatReturns = 1,
StoreTailCallArgs = 2
} TailCallFunctionType;

// -------------------------------------------------------------------------
// DebuggerController routines
// -------------------------------------------------------------------------
Expand Down Expand Up @@ -5631,10 +5636,10 @@ static bool IsTailCallJitHelper(const BYTE * ip)
// control flow will be a little peculiar in that the function will return
// immediately, so we need special handling in the debugger for it. This
// function detects that case to be used for those scenarios.
static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
static bool IsTailCall(const BYTE * ip, ControllerStackInfo* info, TailCallFunctionType type)
{
MethodDesc* pTailCallDispatcherMD = TailCallHelp::GetTailCallDispatcherMD();
if (pTailCallDispatcherMD == NULL)
if (pTailCallDispatcherMD == NULL && type == TailCallFunctionType::TailCallThatReturns)
{
return false;
}
Expand All @@ -5650,6 +5655,11 @@ static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
? trace.GetMethodDesc()
: g_pEEInterface->GetNativeCodeMethodDesc(trace.GetAddress());

if (type == TailCallFunctionType::StoreTailCallArgs)
{
return (pTargetMD->IsDynamicMethod() && pTargetMD->AsDynamicMethodDesc()->GetILStubType() == DynamicMethodDesc::StubTailCallStoreArgs);
}

if (pTargetMD != pTailCallDispatcherMD)
{
return false;
Expand Down Expand Up @@ -5881,6 +5891,13 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
fCallingIntoFunclet = IsAddrWithinMethodIncludingFunclet(ji, info->m_activeFrame.md, walker.GetNextIP()) &&
((CORDB_ADDRESS)(SIZE_T)walker.GetNextIP() != ji->m_addrOfCode);
#endif
// If we are stepping into a tail call that uses the StoreTailCallArgs
// we need to enable the method enter, otherwise it will behave like a resume
if (in && IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::StoreTailCallArgs))
{
EnableMethodEnter();
return true;
}
// At this point, we know that the call/branch target is not
// in the current method. The possible cases is that this is
// a jump or a tailcall-via-helper. There are two separate
Expand All @@ -5892,7 +5909,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
// is done by stepping out to the previous user function
// (non IL stub).
if ((fIsJump && !fCallingIntoFunclet) || IsTailCallJitHelper(walker.GetNextIP()) ||
IsTailCallThatReturns(walker.GetNextIP(), info))
IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns))
{
// A step-over becomes a step-out for a tail call.
if (!in)
Expand Down Expand Up @@ -6038,7 +6055,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
return true;
}

if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCallThatReturns(walker.GetNextIP(), info))
if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns))
{
if (!in)
{
Expand Down

0 comments on commit 454fffd

Please sign in to comment.