@@ -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
// -------------------------------------------------------------------------
@@ -5789,10 +5794,10 @@ static bool IsTailCallJitHelper(const BYTE * ip)
5789
5794
// control flow will be a little peculiar in that the function will return
5790
5795
// immediately, so we need special handling in the debugger for it. This
5791
5796
// function detects that case to be used for those scenarios.
5792
- static bool IsTailCallThatReturns (const BYTE * ip, ControllerStackInfo* info)
5797
+ static bool IsTailCall (const BYTE * ip, ControllerStackInfo* info, TailCallFunctionType type )
5793
5798
{
5794
5799
MethodDesc* pTailCallDispatcherMD = TailCallHelp::GetTailCallDispatcherMD ();
5795
- if (pTailCallDispatcherMD == NULL )
5800
+ if (pTailCallDispatcherMD == NULL && type == TailCallFunctionType::TailCallThatReturns )
5796
5801
{
5797
5802
return false ;
5798
5803
}
@@ -5808,6 +5813,11 @@ static bool IsTailCallThatReturns(const BYTE * ip, ControllerStackInfo* info)
5808
5813
? trace.GetMethodDesc ()
5809
5814
: g_pEEInterface->GetNativeCodeMethodDesc (trace.GetAddress ());
5810
5815
5816
+ if (type == TailCallFunctionType::StoreTailCallArgs)
5817
+ {
5818
+ return (pTargetMD->IsDynamicMethod () && pTargetMD->AsDynamicMethodDesc ()->GetILStubType () == DynamicMethodDesc::StubTailCallStoreArgs);
5819
+ }
5820
+
5811
5821
if (pTargetMD != pTailCallDispatcherMD)
5812
5822
{
5813
5823
return false ;
@@ -6039,6 +6049,13 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
6039
6049
fCallingIntoFunclet = IsAddrWithinMethodIncludingFunclet (ji, info->m_activeFrame .md , walker.GetNextIP ()) &&
6040
6050
((CORDB_ADDRESS)(SIZE_T)walker.GetNextIP () != ji->m_addrOfCode );
6041
6051
#endif
6052
+ // If we are stepping into a tail call that uses the StoreTailCallArgs
6053
+ // we need to enable the method enter, otherwise it will behave like a resume
6054
+ if (in && IsTailCall (walker.GetNextIP (), info, TailCallFunctionType::StoreTailCallArgs))
6055
+ {
6056
+ EnableMethodEnter ();
6057
+ return true ;
6058
+ }
6042
6059
// At this point, we know that the call/branch target is not
6043
6060
// in the current method. The possible cases is that this is
6044
6061
// a jump or a tailcall-via-helper. There are two separate
@@ -6050,7 +6067,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
6050
6067
// is done by stepping out to the previous user function
6051
6068
// (non IL stub).
6052
6069
if ((fIsJump && !fCallingIntoFunclet ) || IsTailCallJitHelper (walker.GetNextIP ()) ||
6053
- IsTailCallThatReturns (walker.GetNextIP (), info))
6070
+ IsTailCall (walker.GetNextIP (), info, TailCallFunctionType::TailCallThatReturns ))
6054
6071
{
6055
6072
// A step-over becomes a step-out for a tail call.
6056
6073
if (!in)
@@ -6196,7 +6213,7 @@ bool DebuggerStepper::TrapStep(ControllerStackInfo *info, bool in)
6196
6213
return true ;
6197
6214
}
6198
6215
6199
- if (IsTailCallJitHelper (walker.GetNextIP ()) || IsTailCallThatReturns (walker.GetNextIP (), info))
6216
+ if (IsTailCallJitHelper (walker.GetNextIP ()) || IsTailCall (walker.GetNextIP (), info, TailCallFunctionType::TailCallThatReturns ))
6200
6217
{
6201
6218
if (!in)
6202
6219
{
0 commit comments