Skip to content

Commit eda4c70

Browse files
Support step into a tail call (#110440)
Support step into a tail call Co-authored-by: Thays Grazia <[email protected]>
1 parent c8d152e commit eda4c70

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

src/coreclr/debug/ee/controller.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ const char *GetTType( TraceType tt);
2525

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

28+
typedef enum __TailCallFunctionType {
29+
TailCallThatReturns = 1,
30+
StoreTailCallArgs = 2
31+
} TailCallFunctionType;
32+
2833
// -------------------------------------------------------------------------
2934
// DebuggerController routines
3035
// -------------------------------------------------------------------------
@@ -5636,10 +5641,10 @@ static bool IsTailCallJitHelper(const BYTE * ip)
56365641
// control flow will be a little peculiar in that the function will return
56375642
// immediately, so we need special handling in the debugger for it. This
56385643
// function detects that case to be used for those scenarios.
5639-
static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
5644+
static bool IsTailCall(const BYTE * ip, ControllerStackInfo* info, TailCallFunctionType type)
56405645
{
56415646
MethodDesc* pTailCallDispatcherMD = TailCallHelp::GetTailCallDispatcherMD();
5642-
if (pTailCallDispatcherMD == NULL)
5647+
if (pTailCallDispatcherMD == NULL && type == TailCallFunctionType::TailCallThatReturns)
56435648
{
56445649
return false;
56455650
}
@@ -5655,6 +5660,11 @@ static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
56555660
? trace.GetMethodDesc()
56565661
: g_pEEInterface->GetNativeCodeMethodDesc(trace.GetAddress());
56575662

5663+
if (type == TailCallFunctionType::StoreTailCallArgs)
5664+
{
5665+
return (pTargetMD->IsDynamicMethod() && pTargetMD->AsDynamicMethodDesc()->GetILStubType() == DynamicMethodDesc::StubTailCallStoreArgs);
5666+
}
5667+
56585668
if (pTargetMD != pTailCallDispatcherMD)
56595669
{
56605670
return false;
@@ -5886,6 +5896,13 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
58865896
fCallingIntoFunclet = IsAddrWithinMethodIncludingFunclet(ji, info->m_activeFrame.md, walker.GetNextIP()) &&
58875897
((CORDB_ADDRESS)(SIZE_T)walker.GetNextIP() != ji->m_addrOfCode);
58885898
#endif
5899+
// If we are stepping into a tail call that uses the StoreTailCallArgs
5900+
// we need to enable the method enter, otherwise it will behave like a resume
5901+
if (in && IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::StoreTailCallArgs))
5902+
{
5903+
EnableMethodEnter();
5904+
return true;
5905+
}
58895906
// At this point, we know that the call/branch target is not
58905907
// in the current method. The possible cases is that this is
58915908
// a jump or a tailcall-via-helper. There are two separate
@@ -5897,7 +5914,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
58975914
// is done by stepping out to the previous user function
58985915
// (non IL stub).
58995916
if ((fIsJump && !fCallingIntoFunclet) || IsTailCallJitHelper(walker.GetNextIP()) ||
5900-
IsTailCallThatReturns(walker.GetNextIP(), info))
5917+
IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns))
59015918
{
59025919
// A step-over becomes a step-out for a tail call.
59035920
if (!in)
@@ -6043,7 +6060,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
60436060
return true;
60446061
}
60456062

6046-
if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCallThatReturns(walker.GetNextIP(), info))
6063+
if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns))
60476064
{
60486065
if (!in)
60496066
{

0 commit comments

Comments
 (0)