Skip to content

Commit f291404

Browse files
authored
bpo-45637: Store the frame pointer in the cframe (GH-29267)
* Rename 'frame' to 'current_frame'
1 parent 0a68b36 commit f291404

File tree

10 files changed

+42
-41
lines changed

10 files changed

+42
-41
lines changed

Include/cpython/pystate.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ typedef struct _cframe {
4646
* accessed outside of their lifetime.
4747
*/
4848
int use_tracing;
49+
/* Pointer to the currently executing frame (it can be NULL) */
50+
struct _interpreter_frame *current_frame;
4951
struct _cframe *previous;
5052
} CFrame;
5153

@@ -77,8 +79,6 @@ struct _ts {
7779
struct _ts *next;
7880
PyInterpreterState *interp;
7981

80-
/* Borrowed reference to the current frame (it can be NULL) */
81-
struct _interpreter_frame *frame;
8282
int recursion_depth;
8383
int recursion_headroom; /* Allow 50 more calls to handle any errors. */
8484
int stackcheck_counter;

Modules/_tracemalloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ traceback_get_frames(traceback_t *traceback)
396396
return;
397397
}
398398

399-
InterpreterFrame *pyframe = tstate->frame;
399+
InterpreterFrame *pyframe = tstate->cframe->current_frame;
400400
for (; pyframe != NULL;) {
401401
if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
402402
tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);

Modules/_xxsubinterpretersmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1839,7 +1839,7 @@ _is_running(PyInterpreterState *interp)
18391839
}
18401840

18411841
assert(!PyErr_Occurred());
1842-
InterpreterFrame *frame = tstate->frame;
1842+
InterpreterFrame *frame = tstate->cframe->current_frame;
18431843
if (frame == NULL) {
18441844
return 0;
18451845
}

Modules/signalmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1788,7 +1788,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
17881788
*/
17891789
_Py_atomic_store(&is_tripped, 0);
17901790

1791-
InterpreterFrame *frame = tstate->frame;
1791+
InterpreterFrame *frame = tstate->cframe->current_frame;
17921792
signal_state_t *state = &signal_global_state;
17931793
for (int i = 1; i < NSIG; i++) {
17941794
if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) {

Objects/genobject.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
193193
Py_INCREF(result);
194194
_PyFrame_StackPush(frame, result);
195195

196-
frame->previous = tstate->frame;
196+
frame->previous = tstate->cframe->current_frame;
197197

198198
gen->gi_exc_state.previous_item = tstate->exc_info;
199199
tstate->exc_info = &gen->gi_exc_state;
@@ -207,7 +207,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
207207
tstate->exc_info = gen->gi_exc_state.previous_item;
208208
gen->gi_exc_state.previous_item = NULL;
209209

210-
assert(tstate->frame == frame->previous);
210+
assert(tstate->cframe->current_frame == frame->previous);
211211
/* Don't keep the reference to previous any longer than necessary. It
212212
* may keep a chain of frames alive or it could create a reference
213213
* cycle. */
@@ -435,17 +435,17 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
435435
will be reported correctly to the user. */
436436
/* XXX We should probably be updating the current frame
437437
somewhere in ceval.c. */
438-
InterpreterFrame *prev = tstate->frame;
438+
InterpreterFrame *prev = tstate->cframe->current_frame;
439439
frame->previous = prev;
440-
tstate->frame = frame;
440+
tstate->cframe->current_frame = frame;
441441
/* Close the generator that we are currently iterating with
442442
'yield from' or awaiting on with 'await'. */
443443
PyFrameState state = gen->gi_xframe->f_state;
444444
gen->gi_xframe->f_state = FRAME_EXECUTING;
445445
ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
446446
typ, val, tb);
447447
gen->gi_xframe->f_state = state;
448-
tstate->frame = prev;
448+
tstate->cframe->current_frame = prev;
449449
frame->previous = NULL;
450450
} else {
451451
/* `yf` is an iterator or a coroutine-like object. */

Python/ceval.c

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,16 +1561,18 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
15611561
tstate->cframe = &cframe;
15621562

15631563
assert(frame->depth == 0);
1564-
/* push frame */
1565-
tstate->frame = frame;
1564+
/* Push frame */
1565+
frame->previous = prev_cframe->current_frame;
1566+
cframe.current_frame = frame;
15661567

15671568
start_frame:
15681569
if (_Py_EnterRecursiveCall(tstate, "")) {
15691570
tstate->recursion_depth++;
15701571
goto exit_eval_frame;
15711572
}
15721573

1573-
assert(frame == tstate->frame);
1574+
assert(tstate->cframe == &cframe);
1575+
assert(frame == cframe.current_frame);
15741576

15751577
if (cframe.use_tracing) {
15761578
if (trace_function_entry(tstate, frame)) {
@@ -4641,8 +4643,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
46414643
goto error;
46424644
}
46434645
_PyFrame_SetStackPointer(frame, stack_pointer);
4646+
new_frame->previous = frame;
4647+
cframe.current_frame = frame = new_frame;
46444648
new_frame->depth = frame->depth + 1;
4645-
tstate->frame = frame = new_frame;
46464649
goto start_frame;
46474650
}
46484651
}
@@ -4723,9 +4726,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
47234726
STACK_SHRINK(1);
47244727
Py_DECREF(func);
47254728
_PyFrame_SetStackPointer(frame, stack_pointer);
4726-
new_frame->previous = tstate->frame;
4729+
new_frame->previous = frame;
4730+
frame = cframe.current_frame = new_frame;
47274731
new_frame->depth = frame->depth + 1;
4728-
tstate->frame = frame = new_frame;
47294732
goto start_frame;
47304733
}
47314734

@@ -5258,23 +5261,24 @@ MISS_WITH_OPARG_COUNTER(BINARY_MULTIPLY)
52585261
_Py_LeaveRecursiveCall(tstate);
52595262

52605263
if (frame->depth) {
5261-
_PyFrame_StackPush(frame->previous, retval);
5264+
cframe.current_frame = frame->previous;
5265+
_PyFrame_StackPush(cframe.current_frame, retval);
52625266
if (_PyEvalFrameClearAndPop(tstate, frame)) {
52635267
retval = NULL;
52645268
}
5265-
frame = tstate->frame;
5269+
frame = cframe.current_frame;
52665270
if (retval == NULL) {
52675271
assert(_PyErr_Occurred(tstate));
52685272
throwflag = 1;
52695273
}
52705274
retval = NULL;
52715275
goto resume_frame;
52725276
}
5273-
tstate->frame = frame->previous;
52745277

5275-
/* Restore previous cframe */
5278+
/* Restore previous cframe. */
52765279
tstate->cframe = cframe.previous;
52775280
tstate->cframe->use_tracing = cframe.use_tracing;
5281+
assert(tstate->cframe->current_frame == frame->previous);
52785282
return _Py_CheckFunctionResult(tstate, NULL, retval, __func__);
52795283
}
52805284

@@ -5891,8 +5895,6 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFrameConstructor *con,
58915895
_PyFrame_Clear(frame, 0);
58925896
return NULL;
58935897
}
5894-
frame->previous = tstate->frame;
5895-
tstate->frame = frame;
58965898
return frame;
58975899
}
58985900

@@ -5906,7 +5908,6 @@ _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame)
59065908
return -1;
59075909
}
59085910
--tstate->recursion_depth;
5909-
tstate->frame = frame->previous;
59105911
_PyThreadState_PopFrame(tstate, frame);
59115912
return 0;
59125913
}
@@ -6518,17 +6519,17 @@ InterpreterFrame *
65186519
_PyEval_GetFrame(void)
65196520
{
65206521
PyThreadState *tstate = _PyThreadState_GET();
6521-
return tstate->frame;
6522+
return tstate->cframe->current_frame;
65226523
}
65236524

65246525
PyFrameObject *
65256526
PyEval_GetFrame(void)
65266527
{
65276528
PyThreadState *tstate = _PyThreadState_GET();
6528-
if (tstate->frame == NULL) {
6529+
if (tstate->cframe->current_frame == NULL) {
65296530
return NULL;
65306531
}
6531-
PyFrameObject *f = _PyFrame_GetFrameObject(tstate->frame);
6532+
PyFrameObject *f = _PyFrame_GetFrameObject(tstate->cframe->current_frame);
65326533
if (f == NULL) {
65336534
PyErr_Clear();
65346535
}
@@ -6538,7 +6539,7 @@ PyEval_GetFrame(void)
65386539
PyObject *
65396540
_PyEval_GetBuiltins(PyThreadState *tstate)
65406541
{
6541-
InterpreterFrame *frame = tstate->frame;
6542+
InterpreterFrame *frame = tstate->cframe->current_frame;
65426543
if (frame != NULL) {
65436544
return frame->f_builtins;
65446545
}
@@ -6571,7 +6572,7 @@ PyObject *
65716572
PyEval_GetLocals(void)
65726573
{
65736574
PyThreadState *tstate = _PyThreadState_GET();
6574-
InterpreterFrame *current_frame = tstate->frame;
6575+
InterpreterFrame *current_frame = tstate->cframe->current_frame;
65756576
if (current_frame == NULL) {
65766577
_PyErr_SetString(tstate, PyExc_SystemError, "frame does not exist");
65776578
return NULL;
@@ -6590,7 +6591,7 @@ PyObject *
65906591
PyEval_GetGlobals(void)
65916592
{
65926593
PyThreadState *tstate = _PyThreadState_GET();
6593-
InterpreterFrame *current_frame = tstate->frame;
6594+
InterpreterFrame *current_frame = tstate->cframe->current_frame;
65946595
if (current_frame == NULL) {
65956596
return NULL;
65966597
}
@@ -6601,7 +6602,7 @@ int
66016602
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
66026603
{
66036604
PyThreadState *tstate = _PyThreadState_GET();
6604-
InterpreterFrame *current_frame = tstate->frame;
6605+
InterpreterFrame *current_frame = tstate->cframe->current_frame;
66056606
int result = cf->cf_flags != 0;
66066607

66076608
if (current_frame != NULL) {
@@ -6651,7 +6652,7 @@ PyEval_GetFuncDesc(PyObject *func)
66516652
#define C_TRACE(x, call) \
66526653
if (use_tracing && tstate->c_profilefunc) { \
66536654
if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, \
6654-
tstate, tstate->frame, \
6655+
tstate, tstate->cframe->current_frame, \
66556656
PyTrace_C_CALL, func)) { \
66566657
x = NULL; \
66576658
} \
@@ -6661,13 +6662,13 @@ if (use_tracing && tstate->c_profilefunc) { \
66616662
if (x == NULL) { \
66626663
call_trace_protected(tstate->c_profilefunc, \
66636664
tstate->c_profileobj, \
6664-
tstate, tstate->frame, \
6665+
tstate, tstate->cframe->current_frame, \
66656666
PyTrace_C_EXCEPTION, func); \
66666667
/* XXX should pass (type, value, tb) */ \
66676668
} else { \
66686669
if (call_trace(tstate->c_profilefunc, \
66696670
tstate->c_profileobj, \
6670-
tstate, tstate->frame, \
6671+
tstate, tstate->cframe->current_frame, \
66716672
PyTrace_C_RETURN, func)) { \
66726673
Py_DECREF(x); \
66736674
x = NULL; \

Python/pylifecycle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2031,7 +2031,7 @@ Py_EndInterpreter(PyThreadState *tstate)
20312031
if (tstate != _PyThreadState_GET()) {
20322032
Py_FatalError("thread is not current");
20332033
}
2034-
if (tstate->frame != NULL) {
2034+
if (tstate->cframe->current_frame != NULL) {
20352035
Py_FatalError("thread still has a frame");
20362036
}
20372037
interp->finalizing = 1;

Python/pystate.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -636,12 +636,12 @@ new_threadstate(PyInterpreterState *interp, int init)
636636

637637
tstate->interp = interp;
638638

639-
tstate->frame = NULL;
640639
tstate->recursion_depth = 0;
641640
tstate->recursion_headroom = 0;
642641
tstate->stackcheck_counter = 0;
643642
tstate->tracing = 0;
644643
tstate->root_cframe.use_tracing = 0;
644+
tstate->root_cframe.current_frame = NULL;
645645
tstate->cframe = &tstate->root_cframe;
646646
tstate->gilstate_counter = 0;
647647
tstate->async_exc = NULL;
@@ -861,7 +861,7 @@ PyThreadState_Clear(PyThreadState *tstate)
861861
{
862862
int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;
863863

864-
if (verbose && tstate->frame != NULL) {
864+
if (verbose && tstate->cframe->current_frame != NULL) {
865865
/* bpo-20526: After the main thread calls
866866
_PyRuntimeState_SetFinalizing() in Py_FinalizeEx(), threads must
867867
exit when trying to take the GIL. If a thread exit in the middle of
@@ -1134,10 +1134,10 @@ PyFrameObject*
11341134
PyThreadState_GetFrame(PyThreadState *tstate)
11351135
{
11361136
assert(tstate != NULL);
1137-
if (tstate->frame == NULL) {
1137+
if (tstate->cframe->current_frame == NULL) {
11381138
return NULL;
11391139
}
1140-
PyFrameObject *frame = _PyFrame_GetFrameObject(tstate->frame);
1140+
PyFrameObject *frame = _PyFrame_GetFrameObject(tstate->cframe->current_frame);
11411141
if (frame == NULL) {
11421142
PyErr_Clear();
11431143
}
@@ -1277,7 +1277,7 @@ _PyThread_CurrentFrames(void)
12771277
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
12781278
PyThreadState *t;
12791279
for (t = i->tstate_head; t != NULL; t = t->next) {
1280-
InterpreterFrame *frame = t->frame;
1280+
InterpreterFrame *frame = t->cframe->current_frame;
12811281
if (frame == NULL) {
12821282
continue;
12831283
}

Python/sysmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,7 @@ sys__getframe_impl(PyObject *module, int depth)
18131813
/*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/
18141814
{
18151815
PyThreadState *tstate = _PyThreadState_GET();
1816-
InterpreterFrame *frame = tstate->frame;
1816+
InterpreterFrame *frame = tstate->cframe->current_frame;
18171817

18181818
if (_PySys_Audit(tstate, "sys._getframe", NULL) < 0) {
18191819
return NULL;

Python/traceback.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
10821082
PUTS(fd, "Stack (most recent call first):\n");
10831083
}
10841084

1085-
frame = tstate->frame;
1085+
frame = tstate->cframe->current_frame;
10861086
if (frame == NULL) {
10871087
PUTS(fd, " <no Python frame>\n");
10881088
return;

0 commit comments

Comments
 (0)