@@ -38,6 +38,7 @@ typedef struct {
38
38
PyCodeObject * code ; // The code object for the bounds. May be NULL.
39
39
int instr_prev ; // Only valid if code != NULL.
40
40
PyCodeAddressRange bounds ; // Only valid if code != NULL.
41
+ CFrame cframe ;
41
42
} PyTraceInfo ;
42
43
43
44
@@ -1306,7 +1307,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
1306
1307
1307
1308
#define DISPATCH () \
1308
1309
{ \
1309
- if (tstate-> use_tracing OR_DTRACE_LINE OR_LLTRACE) { \
1310
+ if (trace_info.cframe. use_tracing OR_DTRACE_LINE OR_LLTRACE) { \
1310
1311
goto tracing_dispatch; \
1311
1312
} \
1312
1313
f->f_lasti = INSTR_OFFSET(); \
@@ -1614,11 +1615,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1614
1615
/* Mark trace_info as uninitialized */
1615
1616
trace_info .code = NULL ;
1616
1617
1618
+ CFrame * prev_cframe = tstate -> cframe ;
1619
+ trace_info .cframe .use_tracing = prev_cframe -> use_tracing ;
1620
+ trace_info .cframe .previous = prev_cframe ;
1621
+ tstate -> cframe = & trace_info .cframe ;
1622
+
1617
1623
/* push frame */
1618
1624
tstate -> frame = f ;
1619
1625
co = f -> f_code ;
1620
1626
1621
- if (tstate -> use_tracing ) {
1627
+ if (trace_info . cframe . use_tracing ) {
1622
1628
if (tstate -> c_tracefunc != NULL ) {
1623
1629
/* tstate->c_tracefunc, if defined, is a
1624
1630
function that will be called on *every* entry
@@ -1780,7 +1786,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
1780
1786
1781
1787
/* line-by-line tracing support */
1782
1788
1783
- if (tstate -> use_tracing &&
1789
+ if (trace_info . cframe . use_tracing &&
1784
1790
tstate -> c_tracefunc != NULL && !tstate -> tracing ) {
1785
1791
int err ;
1786
1792
/* see maybe_call_line_trace()
@@ -4541,7 +4547,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
4541
4547
PUSH (val );
4542
4548
PUSH (exc );
4543
4549
JUMPTO (handler );
4544
- if (tstate -> use_tracing ) {
4550
+ if (trace_info . cframe . use_tracing ) {
4545
4551
trace_info .instr_prev = INT_MAX ;
4546
4552
}
4547
4553
/* Resume normal execution */
@@ -4565,7 +4571,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
4565
4571
f -> f_stackdepth = 0 ;
4566
4572
f -> f_state = FRAME_RAISED ;
4567
4573
exiting :
4568
- if (tstate -> use_tracing ) {
4574
+ if (trace_info . cframe . use_tracing ) {
4569
4575
if (tstate -> c_tracefunc ) {
4570
4576
if (call_trace_protected (tstate -> c_tracefunc , tstate -> c_traceobj ,
4571
4577
tstate , f , & trace_info , PyTrace_RETURN , retval )) {
@@ -4582,6 +4588,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
4582
4588
4583
4589
/* pop frame */
4584
4590
exit_eval_frame :
4591
+
4592
+ tstate -> cframe = trace_info .cframe .previous ;
4593
+ tstate -> cframe -> use_tracing = trace_info .cframe .use_tracing ;
4594
+
4585
4595
if (PyDTrace_FUNCTION_RETURN_ENABLED ())
4586
4596
dtrace_function_return (f );
4587
4597
_Py_LeaveRecursiveCall (tstate );
@@ -5505,7 +5515,7 @@ call_trace(Py_tracefunc func, PyObject *obj,
5505
5515
if (tstate -> tracing )
5506
5516
return 0 ;
5507
5517
tstate -> tracing ++ ;
5508
- tstate -> use_tracing = 0 ;
5518
+ tstate -> cframe -> use_tracing = 0 ;
5509
5519
if (frame -> f_lasti < 0 ) {
5510
5520
frame -> f_lineno = frame -> f_code -> co_firstlineno ;
5511
5521
}
@@ -5515,7 +5525,7 @@ call_trace(Py_tracefunc func, PyObject *obj,
5515
5525
}
5516
5526
result = func (obj , frame , what , arg );
5517
5527
frame -> f_lineno = 0 ;
5518
- tstate -> use_tracing = ((tstate -> c_tracefunc != NULL )
5528
+ tstate -> cframe -> use_tracing = ((tstate -> c_tracefunc != NULL )
5519
5529
|| (tstate -> c_profilefunc != NULL ));
5520
5530
tstate -> tracing -- ;
5521
5531
return result ;
@@ -5526,15 +5536,15 @@ _PyEval_CallTracing(PyObject *func, PyObject *args)
5526
5536
{
5527
5537
PyThreadState * tstate = _PyThreadState_GET ();
5528
5538
int save_tracing = tstate -> tracing ;
5529
- int save_use_tracing = tstate -> use_tracing ;
5539
+ int save_use_tracing = tstate -> cframe -> use_tracing ;
5530
5540
PyObject * result ;
5531
5541
5532
5542
tstate -> tracing = 0 ;
5533
- tstate -> use_tracing = ((tstate -> c_tracefunc != NULL )
5543
+ tstate -> cframe -> use_tracing = ((tstate -> c_tracefunc != NULL )
5534
5544
|| (tstate -> c_profilefunc != NULL ));
5535
5545
result = PyObject_Call (func , args , NULL );
5536
5546
tstate -> tracing = save_tracing ;
5537
- tstate -> use_tracing = save_use_tracing ;
5547
+ tstate -> cframe -> use_tracing = save_use_tracing ;
5538
5548
return result ;
5539
5549
}
5540
5550
@@ -5588,15 +5598,15 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
5588
5598
tstate -> c_profilefunc = NULL ;
5589
5599
tstate -> c_profileobj = NULL ;
5590
5600
/* Must make sure that tracing is not ignored if 'profileobj' is freed */
5591
- tstate -> use_tracing = tstate -> c_tracefunc != NULL ;
5601
+ tstate -> cframe -> use_tracing = tstate -> c_tracefunc != NULL ;
5592
5602
Py_XDECREF (profileobj );
5593
5603
5594
5604
Py_XINCREF (arg );
5595
5605
tstate -> c_profileobj = arg ;
5596
5606
tstate -> c_profilefunc = func ;
5597
5607
5598
5608
/* Flag that tracing or profiling is turned on */
5599
- tstate -> use_tracing = (func != NULL ) || (tstate -> c_tracefunc != NULL );
5609
+ tstate -> cframe -> use_tracing = (func != NULL ) || (tstate -> c_tracefunc != NULL );
5600
5610
return 0 ;
5601
5611
}
5602
5612
@@ -5629,15 +5639,15 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
5629
5639
tstate -> c_tracefunc = NULL ;
5630
5640
tstate -> c_traceobj = NULL ;
5631
5641
/* Must make sure that profiling is not ignored if 'traceobj' is freed */
5632
- tstate -> use_tracing = (tstate -> c_profilefunc != NULL );
5642
+ tstate -> cframe -> use_tracing = (tstate -> c_profilefunc != NULL );
5633
5643
Py_XDECREF (traceobj );
5634
5644
5635
5645
Py_XINCREF (arg );
5636
5646
tstate -> c_traceobj = arg ;
5637
5647
tstate -> c_tracefunc = func ;
5638
5648
5639
5649
/* Flag that tracing or profiling is turned on */
5640
- tstate -> use_tracing = ((func != NULL )
5650
+ tstate -> cframe -> use_tracing = ((func != NULL )
5641
5651
|| (tstate -> c_profilefunc != NULL ));
5642
5652
5643
5653
return 0 ;
@@ -5832,7 +5842,7 @@ PyEval_GetFuncDesc(PyObject *func)
5832
5842
}
5833
5843
5834
5844
#define C_TRACE (x , call ) \
5835
- if (tstate-> use_tracing && tstate->c_profilefunc) { \
5845
+ if (trace_info->cframe. use_tracing && tstate->c_profilefunc) { \
5836
5846
if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, \
5837
5847
tstate, tstate->frame, trace_info, \
5838
5848
PyTrace_C_CALL, func)) { \
@@ -5913,7 +5923,7 @@ call_function(PyThreadState *tstate,
5913
5923
Py_ssize_t nargs = oparg - nkwargs ;
5914
5924
PyObject * * stack = (* pp_stack ) - nargs - nkwargs ;
5915
5925
5916
- if (tstate -> use_tracing ) {
5926
+ if (trace_info -> cframe . use_tracing ) {
5917
5927
x = trace_call_function (tstate , trace_info , func , stack , nargs , kwnames );
5918
5928
}
5919
5929
else {
@@ -5946,7 +5956,7 @@ do_call_core(PyThreadState *tstate,
5946
5956
}
5947
5957
else if (Py_IS_TYPE (func , & PyMethodDescr_Type )) {
5948
5958
Py_ssize_t nargs = PyTuple_GET_SIZE (callargs );
5949
- if (nargs > 0 && tstate -> use_tracing ) {
5959
+ if (nargs > 0 && trace_info -> cframe . use_tracing ) {
5950
5960
/* We need to create a temporary bound method as argument
5951
5961
for profiling.
5952
5962
0 commit comments