@@ -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
// -------------------------------------------------------------------------
@@ -5636,10 +5641,10 @@ static bool IsTailCallJitHelper(const BYTE * ip)
5636
5641
// control flow will be a little peculiar in that the function will return
5637
5642
// immediately, so we need special handling in the debugger for it. This
5638
5643
// 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 )
5640
5645
{
5641
5646
MethodDesc* pTailCallDispatcherMD = TailCallHelp::GetTailCallDispatcherMD ();
5642
- if (pTailCallDispatcherMD == NULL )
5647
+ if (pTailCallDispatcherMD == NULL && type == TailCallFunctionType::TailCallThatReturns )
5643
5648
{
5644
5649
return false ;
5645
5650
}
@@ -5655,6 +5660,11 @@ static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
5655
5660
? trace.GetMethodDesc ()
5656
5661
: g_pEEInterface->GetNativeCodeMethodDesc (trace.GetAddress ());
5657
5662
5663
+ if (type == TailCallFunctionType::StoreTailCallArgs)
5664
+ {
5665
+ return (pTargetMD->IsDynamicMethod () && pTargetMD->AsDynamicMethodDesc ()->GetILStubType () == DynamicMethodDesc::StubTailCallStoreArgs);
5666
+ }
5667
+
5658
5668
if (pTargetMD != pTailCallDispatcherMD)
5659
5669
{
5660
5670
return false ;
@@ -5886,6 +5896,13 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
5886
5896
fCallingIntoFunclet = IsAddrWithinMethodIncludingFunclet (ji, info->m_activeFrame .md , walker.GetNextIP ()) &&
5887
5897
((CORDB_ADDRESS)(SIZE_T)walker.GetNextIP () != ji->m_addrOfCode );
5888
5898
#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
+ }
5889
5906
// At this point, we know that the call/branch target is not
5890
5907
// in the current method. The possible cases is that this is
5891
5908
// a jump or a tailcall-via-helper. There are two separate
@@ -5897,7 +5914,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
5897
5914
// is done by stepping out to the previous user function
5898
5915
// (non IL stub).
5899
5916
if ((fIsJump && !fCallingIntoFunclet ) || IsTailCallJitHelper (walker.GetNextIP ()) ||
5900
- IsTailCallThatReturns (walker.GetNextIP (), info))
5917
+ IsTailCall (walker.GetNextIP (), info, TailCallFunctionType::TailCallThatReturns ))
5901
5918
{
5902
5919
// A step-over becomes a step-out for a tail call.
5903
5920
if (!in)
@@ -6043,7 +6060,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
6043
6060
return true ;
6044
6061
}
6045
6062
6046
- if (IsTailCallJitHelper (walker.GetNextIP ()) || IsTailCallThatReturns (walker.GetNextIP (), info))
6063
+ if (IsTailCallJitHelper (walker.GetNextIP ()) || IsTailCall (walker.GetNextIP (), info, TailCallFunctionType::TailCallThatReturns ))
6047
6064
{
6048
6065
if (!in)
6049
6066
{
0 commit comments