@@ -25,6 +25,11 @@ const char *GetTType( TraceType tt);
25
25
26
26
#define IsSingleStep(exception) ((exception) == EXCEPTION_SINGLE_STEP)
27
27
28
+ typedef enum __TailCallFunctionType {
29
+ TailCallThatReturns = 1,
30
+ StoreTailCallArgs = 2
31
+ } TailCallFunctionType;
32
+
28
33
// -------------------------------------------------------------------------
29
34
// DebuggerController routines
30
35
// -------------------------------------------------------------------------
@@ -5631,10 +5636,10 @@ static bool IsTailCallJitHelper(const BYTE * ip)
5631
5636
// control flow will be a little peculiar in that the function will return
5632
5637
// immediately, so we need special handling in the debugger for it. This
5633
5638
// function detects that case to be used for those scenarios.
5634
- static bool IsTailCallThatReturns (const BYTE * ip, ControllerStackInfo* info)
5639
+ static bool IsTailCall (const BYTE * ip, ControllerStackInfo* info, TailCallFunctionType type )
5635
5640
{
5636
5641
MethodDesc* pTailCallDispatcherMD = TailCallHelp::GetTailCallDispatcherMD();
5637
- if (pTailCallDispatcherMD == NULL)
5642
+ if (pTailCallDispatcherMD == NULL && type == TailCallFunctionType::TailCallThatReturns )
5638
5643
{
5639
5644
return false;
5640
5645
}
@@ -5650,6 +5655,11 @@ static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
5650
5655
? trace.GetMethodDesc()
5651
5656
: g_pEEInterface->GetNativeCodeMethodDesc(trace.GetAddress());
5652
5657
5658
+ if (type == TailCallFunctionType::StoreTailCallArgs)
5659
+ {
5660
+ return (pTargetMD->IsDynamicMethod() && pTargetMD->AsDynamicMethodDesc()->GetILStubType() == DynamicMethodDesc::StubTailCallStoreArgs);
5661
+ }
5662
+
5653
5663
if (pTargetMD != pTailCallDispatcherMD)
5654
5664
{
5655
5665
return false;
@@ -5881,6 +5891,13 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
5881
5891
fCallingIntoFunclet = IsAddrWithinMethodIncludingFunclet(ji, info->m_activeFrame.md, walker.GetNextIP()) &&
5882
5892
((CORDB_ADDRESS)(SIZE_T)walker.GetNextIP() != ji->m_addrOfCode);
5883
5893
#endif
5894
+ // If we are stepping into a tail call that uses the StoreTailCallArgs
5895
+ // we need to enable the method enter, otherwise it will behave like a resume
5896
+ if (in && IsTailCall(walker.GetNextIP(), info, TailCallFunctionType::StoreTailCallArgs))
5897
+ {
5898
+ EnableMethodEnter();
5899
+ return true;
5900
+ }
5884
5901
// At this point, we know that the call/branch target is not
5885
5902
// in the current method. The possible cases is that this is
5886
5903
// a jump or a tailcall-via-helper. There are two separate
@@ -5892,7 +5909,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
5892
5909
// is done by stepping out to the previous user function
5893
5910
// (non IL stub).
5894
5911
if ((fIsJump && !fCallingIntoFunclet) || IsTailCallJitHelper(walker.GetNextIP()) ||
5895
- IsTailCallThatReturns (walker.GetNextIP(), info))
5912
+ IsTailCall (walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns ))
5896
5913
{
5897
5914
// A step-over becomes a step-out for a tail call.
5898
5915
if (!in)
@@ -6038,7 +6055,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
6038
6055
return true;
6039
6056
}
6040
6057
6041
- if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCallThatReturns (walker.GetNextIP(), info))
6058
+ if (IsTailCallJitHelper(walker.GetNextIP()) || IsTailCall (walker.GetNextIP(), info, TailCallFunctionType::TailCallThatReturns ))
6042
6059
{
6043
6060
if (!in)
6044
6061
{
0 commit comments