@@ -37,6 +37,7 @@ typedef struct {
3737 PyCodeObject * code ; // The code object for the bounds. May be NULL.
3838 int instr_prev ; // Only valid if code != NULL.
3939 PyCodeAddressRange bounds ; // Only valid if code != NULL.
40+ CFrame cframe ;
4041} PyTraceInfo ;
4142
4243
@@ -1109,8 +1110,6 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type,
11091110static int do_raise (PyThreadState * tstate , PyObject * exc , PyObject * cause );
11101111static int unpack_iterable (PyThreadState * , PyObject * , int , int , PyObject * * );
11111112
1112- #define _Py_TracingPossible (ceval ) ((ceval)->tracing_possible)
1113-
11141113
11151114PyObject *
11161115PyEval_EvalCode (PyObject * co , PyObject * globals , PyObject * locals )
@@ -1307,7 +1306,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
13071306
13081307#define DISPATCH () \
13091308 { \
1310- if (_Py_TracingPossible(ceval2) OR_DTRACE_LINE OR_LLTRACE) { \
1309+ if (trace_info.cframe.use_tracing OR_DTRACE_LINE OR_LLTRACE) { \
13111310 goto tracing_dispatch; \
13121311 } \
13131312 f->f_lasti = INSTR_OFFSET(); \
@@ -1595,8 +1594,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
15951594 int oparg ; /* Current opcode argument, if any */
15961595 PyObject * * fastlocals , * * freevars ;
15971596 PyObject * retval = NULL ; /* Return value */
1598- struct _ceval_state * const ceval2 = & tstate -> interp -> ceval ;
1599- _Py_atomic_int * const eval_breaker = & ceval2 -> eval_breaker ;
1597+ _Py_atomic_int * const eval_breaker = & tstate -> interp -> ceval .eval_breaker ;
16001598 PyCodeObject * co ;
16011599
16021600 const _Py_CODEUNIT * first_instr ;
@@ -1616,11 +1614,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
16161614 /* Mark trace_info as uninitialized */
16171615 trace_info .code = NULL ;
16181616
1617+ /* WARNING: Because the CFrame lives on the C stack,
1618+ * but can be accessed from a heap allocated object (tstate)
1619+ * strict stack discipline must be maintained.
1620+ */
1621+ CFrame * prev_cframe = tstate -> cframe ;
1622+ trace_info .cframe .use_tracing = prev_cframe -> use_tracing ;
1623+ trace_info .cframe .previous = prev_cframe ;
1624+ tstate -> cframe = & trace_info .cframe ;
1625+
16191626 /* push frame */
16201627 tstate -> frame = f ;
16211628 co = f -> f_code ;
16221629
1623- if (tstate -> use_tracing ) {
1630+ if (trace_info . cframe . use_tracing ) {
16241631 if (tstate -> c_tracefunc != NULL ) {
16251632 /* tstate->c_tracefunc, if defined, is a
16261633 function that will be called on *every* entry
@@ -1782,7 +1789,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
17821789
17831790 /* line-by-line tracing support */
17841791
1785- if (_Py_TracingPossible ( ceval2 ) &&
1792+ if (trace_info . cframe . use_tracing &&
17861793 tstate -> c_tracefunc != NULL && !tstate -> tracing ) {
17871794 int err ;
17881795 /* see maybe_call_line_trace()
@@ -4543,7 +4550,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
45434550 PUSH (val );
45444551 PUSH (exc );
45454552 JUMPTO (handler );
4546- if (_Py_TracingPossible ( ceval2 ) ) {
4553+ if (trace_info . cframe . use_tracing ) {
45474554 trace_info .instr_prev = INT_MAX ;
45484555 }
45494556 /* Resume normal execution */
@@ -4567,7 +4574,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
45674574 f -> f_stackdepth = 0 ;
45684575 f -> f_state = FRAME_RAISED ;
45694576exiting :
4570- if (tstate -> use_tracing ) {
4577+ if (trace_info . cframe . use_tracing ) {
45714578 if (tstate -> c_tracefunc ) {
45724579 if (call_trace_protected (tstate -> c_tracefunc , tstate -> c_traceobj ,
45734580 tstate , f , & trace_info , PyTrace_RETURN , retval )) {
@@ -4584,6 +4591,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
45844591
45854592 /* pop frame */
45864593exit_eval_frame :
4594+ /* Restore previous cframe */
4595+ tstate -> cframe = trace_info .cframe .previous ;
4596+ tstate -> cframe -> use_tracing = trace_info .cframe .use_tracing ;
4597+
45874598 if (PyDTrace_FUNCTION_RETURN_ENABLED ())
45884599 dtrace_function_return (f );
45894600 _Py_LeaveRecursiveCall (tstate );
@@ -5507,7 +5518,7 @@ call_trace(Py_tracefunc func, PyObject *obj,
55075518 if (tstate -> tracing )
55085519 return 0 ;
55095520 tstate -> tracing ++ ;
5510- tstate -> use_tracing = 0 ;
5521+ tstate -> cframe -> use_tracing = 0 ;
55115522 if (frame -> f_lasti < 0 ) {
55125523 frame -> f_lineno = frame -> f_code -> co_firstlineno ;
55135524 }
@@ -5517,7 +5528,7 @@ call_trace(Py_tracefunc func, PyObject *obj,
55175528 }
55185529 result = func (obj , frame , what , arg );
55195530 frame -> f_lineno = 0 ;
5520- tstate -> use_tracing = ((tstate -> c_tracefunc != NULL )
5531+ tstate -> cframe -> use_tracing = ((tstate -> c_tracefunc != NULL )
55215532 || (tstate -> c_profilefunc != NULL ));
55225533 tstate -> tracing -- ;
55235534 return result ;
@@ -5528,15 +5539,15 @@ _PyEval_CallTracing(PyObject *func, PyObject *args)
55285539{
55295540 PyThreadState * tstate = _PyThreadState_GET ();
55305541 int save_tracing = tstate -> tracing ;
5531- int save_use_tracing = tstate -> use_tracing ;
5542+ int save_use_tracing = tstate -> cframe -> use_tracing ;
55325543 PyObject * result ;
55335544
55345545 tstate -> tracing = 0 ;
5535- tstate -> use_tracing = ((tstate -> c_tracefunc != NULL )
5546+ tstate -> cframe -> use_tracing = ((tstate -> c_tracefunc != NULL )
55365547 || (tstate -> c_profilefunc != NULL ));
55375548 result = PyObject_Call (func , args , NULL );
55385549 tstate -> tracing = save_tracing ;
5539- tstate -> use_tracing = save_use_tracing ;
5550+ tstate -> cframe -> use_tracing = save_use_tracing ;
55405551 return result ;
55415552}
55425553
@@ -5590,15 +5601,15 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
55905601 tstate -> c_profilefunc = NULL ;
55915602 tstate -> c_profileobj = NULL ;
55925603 /* Must make sure that tracing is not ignored if 'profileobj' is freed */
5593- tstate -> use_tracing = tstate -> c_tracefunc != NULL ;
5604+ tstate -> cframe -> use_tracing = tstate -> c_tracefunc != NULL ;
55945605 Py_XDECREF (profileobj );
55955606
55965607 Py_XINCREF (arg );
55975608 tstate -> c_profileobj = arg ;
55985609 tstate -> c_profilefunc = func ;
55995610
56005611 /* Flag that tracing or profiling is turned on */
5601- tstate -> use_tracing = (func != NULL ) || (tstate -> c_tracefunc != NULL );
5612+ tstate -> cframe -> use_tracing = (func != NULL ) || (tstate -> c_tracefunc != NULL );
56025613 return 0 ;
56035614}
56045615
@@ -5626,22 +5637,20 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
56265637 return -1 ;
56275638 }
56285639
5629- struct _ceval_state * ceval2 = & tstate -> interp -> ceval ;
56305640 PyObject * traceobj = tstate -> c_traceobj ;
5631- ceval2 -> tracing_possible += (func != NULL ) - (tstate -> c_tracefunc != NULL );
56325641
56335642 tstate -> c_tracefunc = NULL ;
56345643 tstate -> c_traceobj = NULL ;
56355644 /* Must make sure that profiling is not ignored if 'traceobj' is freed */
5636- tstate -> use_tracing = (tstate -> c_profilefunc != NULL );
5645+ tstate -> cframe -> use_tracing = (tstate -> c_profilefunc != NULL );
56375646 Py_XDECREF (traceobj );
56385647
56395648 Py_XINCREF (arg );
56405649 tstate -> c_traceobj = arg ;
56415650 tstate -> c_tracefunc = func ;
56425651
56435652 /* Flag that tracing or profiling is turned on */
5644- tstate -> use_tracing = ((func != NULL )
5653+ tstate -> cframe -> use_tracing = ((func != NULL )
56455654 || (tstate -> c_profilefunc != NULL ));
56465655
56475656 return 0 ;
@@ -5836,7 +5845,7 @@ PyEval_GetFuncDesc(PyObject *func)
58365845}
58375846
58385847#define C_TRACE (x , call ) \
5839- if (tstate-> use_tracing && tstate->c_profilefunc) { \
5848+ if (trace_info->cframe. use_tracing && tstate->c_profilefunc) { \
58405849 if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, \
58415850 tstate, tstate->frame, trace_info, \
58425851 PyTrace_C_CALL, func)) { \
@@ -5917,7 +5926,7 @@ call_function(PyThreadState *tstate,
59175926 Py_ssize_t nargs = oparg - nkwargs ;
59185927 PyObject * * stack = (* pp_stack ) - nargs - nkwargs ;
59195928
5920- if (tstate -> use_tracing ) {
5929+ if (trace_info -> cframe . use_tracing ) {
59215930 x = trace_call_function (tstate , trace_info , func , stack , nargs , kwnames );
59225931 }
59235932 else {
@@ -5950,7 +5959,7 @@ do_call_core(PyThreadState *tstate,
59505959 }
59515960 else if (Py_IS_TYPE (func , & PyMethodDescr_Type )) {
59525961 Py_ssize_t nargs = PyTuple_GET_SIZE (callargs );
5953- if (nargs > 0 && tstate -> use_tracing ) {
5962+ if (nargs > 0 && trace_info -> cframe . use_tracing ) {
59545963 /* We need to create a temporary bound method as argument
59555964 for profiling.
59565965
0 commit comments