Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit006e44f

Browse files
authored
GH-108035: Remove the_PyCFrame struct as it is no longer needed for performance. (GH-108036)
1 parent33e6e3f commit006e44f

21 files changed

+66
-103
lines changed

‎Include/cpython/pystate.h

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,6 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);
2929
#definePyTrace_C_RETURN 6
3030
#definePyTrace_OPCODE 7
3131

32-
// Internal structure: you should not use it directly, but use public functions
33-
// like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing().
34-
typedefstruct_PyCFrame {
35-
/* This struct will be threaded through the C stack
36-
* allowing fast access to per-thread state that needs
37-
* to be accessed quickly by the interpreter, but can
38-
* be modified outside of the interpreter.
39-
*
40-
* WARNING: This makes data on the C stack accessible from
41-
* heap objects. Care must be taken to maintain stack
42-
* discipline and make sure that instances of this struct cannot
43-
* accessed outside of their lifetime.
44-
*/
45-
/* Pointer to the currently executing frame (it can be NULL) */
46-
struct_PyInterpreterFrame*current_frame;
47-
struct_PyCFrame*previous;
48-
}_PyCFrame;
49-
5032
typedefstruct_err_stackitem {
5133
/* This struct represents a single execution context where we might
5234
* be currently handling an exception. It is a per-coroutine state
@@ -123,9 +105,8 @@ struct _ts {
123105
inttracing;
124106
intwhat_event;/* The event currently being monitored, if any. */
125107

126-
/* Pointer to current _PyCFrame in the C stack frame of the currently,
127-
* or most recently, executing _PyEval_EvalFrameDefault. */
128-
_PyCFrame*cframe;
108+
/* Pointer to currently executing frame. */
109+
struct_PyInterpreterFrame*current_frame;
129110

130111
Py_tracefuncc_profilefunc;
131112
Py_tracefuncc_tracefunc;
@@ -211,8 +192,6 @@ struct _ts {
211192
/* The thread's exception stack entry. (Always the last entry.) */
212193
_PyErr_StackItemexc_state;
213194

214-
/* The bottom-most frame on the stack. */
215-
_PyCFrameroot_cframe;
216195
};
217196

218197
/* WASI has limited call stack. Python's recursion limit depends on code

‎Include/internal/pycore_frame.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
196196
staticinline_PyInterpreterFrame*
197197
_PyThreadState_GetFrame(PyThreadState*tstate)
198198
{
199-
return_PyFrame_GetFirstComplete(tstate->cframe->current_frame);
199+
return_PyFrame_GetFirstComplete(tstate->current_frame);
200200
}
201201

202202
/* For use by _PyFrame_GetFrameObject

‎Include/internal/pycore_runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ typedef struct _Py_DebugOffsets {
8080
off_tprev;
8181
off_tnext;
8282
off_tinterp;
83-
off_tcframe;
83+
off_tcurrent_frame;
8484
off_tthread_id;
8585
off_tnative_thread_id;
8686
}thread_state;

‎Include/internal/pycore_runtime_init.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extern PyTypeObject _PyExc_MemoryError;
4545
.prev = offsetof(PyThreadState, prev), \
4646
.next = offsetof(PyThreadState, next), \
4747
.interp = offsetof(PyThreadState, interp), \
48-
.cframe = offsetof(PyThreadState,cframe), \
48+
.current_frame = offsetof(PyThreadState,current_frame), \
4949
.thread_id = offsetof(PyThreadState, thread_id), \
5050
.native_thread_id = offsetof(PyThreadState, native_thread_id), \
5151
}, \
@@ -56,10 +56,6 @@ extern PyTypeObject _PyExc_MemoryError;
5656
.localsplus = offsetof(_PyInterpreterFrame, localsplus), \
5757
.owner = offsetof(_PyInterpreterFrame, owner), \
5858
}, \
59-
.cframe = { \
60-
.current_frame = offsetof(_PyCFrame, current_frame), \
61-
.previous = offsetof(_PyCFrame, previous), \
62-
}, \
6359
.code_object = { \
6460
.filename = offsetof(PyCodeObject, co_filename), \
6561
.name = offsetof(PyCodeObject, co_name), \
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Remove the ``_PyCFrame`` struct, moving the pointer to the current intepreter frame
2+
back to the threadstate, as it was for 3.10 and earlier. The ``_PyCFrame``
3+
existed as a performance optimization for tracing. Since PEP 669 has been
4+
implemented, this optimization no longer applies.

‎Modules/_xxsubinterpretersmodule.c

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

371371
assert(!PyErr_Occurred());
372-
struct_PyInterpreterFrame*frame=tstate->cframe->current_frame;
372+
struct_PyInterpreterFrame*frame=tstate->current_frame;
373373
if (frame==NULL) {
374374
return0;
375375
}

‎Objects/genobject.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,17 +476,17 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
476476
will be reported correctly to the user. */
477477
/* XXX We should probably be updating the current frame
478478
somewhere in ceval.c. */
479-
_PyInterpreterFrame*prev=tstate->cframe->current_frame;
479+
_PyInterpreterFrame*prev=tstate->current_frame;
480480
frame->previous=prev;
481-
tstate->cframe->current_frame=frame;
481+
tstate->current_frame=frame;
482482
/* Close the generator that we are currently iterating with
483483
'yield from' or awaiting on with 'await'. */
484484
PyFrameStatestate=gen->gi_frame_state;
485485
gen->gi_frame_state=FRAME_EXECUTING;
486486
ret=_gen_throw((PyGenObject*)yf,close_on_genexit,
487487
typ,val,tb);
488488
gen->gi_frame_state=state;
489-
tstate->cframe->current_frame=prev;
489+
tstate->current_frame=prev;
490490
frame->previous=NULL;
491491
}else {
492492
/* `yf` is an iterator or a coroutine-like object. */
@@ -938,7 +938,7 @@ _Py_MakeCoro(PyFunctionObject *func)
938938
if (origin_depth==0) {
939939
((PyCoroObject*)coro)->cr_origin_or_finalizer=NULL;
940940
}else {
941-
_PyInterpreterFrame*frame=tstate->cframe->current_frame;
941+
_PyInterpreterFrame*frame=tstate->current_frame;
942942
assert(frame);
943943
assert(_PyFrame_IsIncomplete(frame));
944944
frame=_PyFrame_GetFirstComplete(frame->previous);

‎Objects/typevarobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ make_union(PyObject *self, PyObject *other)
107107
staticPyObject*
108108
caller(void)
109109
{
110-
_PyInterpreterFrame*f=_PyThreadState_GET()->cframe->current_frame;
110+
_PyInterpreterFrame*f=_PyThreadState_GET()->current_frame;
111111
if (f==NULL) {
112112
Py_RETURN_NONE;
113113
}

‎Python/bytecodes.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ dummy_func(
7272
_PyInterpreterFrame*frame,
7373
unsignedcharopcode,
7474
unsignedintoparg,
75-
_PyCFramecframe,
7675
_Py_CODEUNIT*next_instr,
7776
PyObject**stack_pointer,
7877
PyObject*kwnames,
@@ -134,8 +133,7 @@ dummy_func(
134133
}
135134

136135
inst(RESUME, (--)) {
137-
assert(tstate->cframe==&cframe);
138-
assert(frame==cframe.current_frame);
136+
assert(frame==tstate->current_frame);
139137
/* Possibly combine this with eval breaker */
140138
if (_PyFrame_GetCode(frame)->_co_instrumentation_version!=tstate->interp->monitoring_version) {
141139
interr=_Py_Instrument(_PyFrame_GetCode(frame),tstate->interp);
@@ -752,9 +750,8 @@ dummy_func(
752750
inst(INTERPRETER_EXIT, (retval--)) {
753751
assert(frame==&entry_frame);
754752
assert(_PyFrame_IsIncomplete(frame));
755-
/* Restore previous cframe and return. */
756-
tstate->cframe=cframe.previous;
757-
assert(tstate->cframe->current_frame==frame->previous);
753+
/* Restore previous frame and return. */
754+
tstate->current_frame=frame->previous;
758755
assert(!_PyErr_Occurred(tstate));
759756
tstate->c_recursion_remaining+=PY_EVAL_C_STACK_UNITS;
760757
returnretval;
@@ -768,7 +765,7 @@ dummy_func(
768765
assert(frame!=&entry_frame);
769766
// GH-99729: We need to unlink the frame *before* clearing it:
770767
_PyInterpreterFrame*dying=frame;
771-
frame=cframe.current_frame=dying->previous;
768+
frame=tstate->current_frame=dying->previous;
772769
_PyEvalFrameClearAndPop(tstate,dying);
773770
frame->prev_instr+=frame->return_offset;
774771
_PyFrame_StackPush(frame,retval);
@@ -787,7 +784,7 @@ dummy_func(
787784
assert(frame!=&entry_frame);
788785
// GH-99729: We need to unlink the frame *before* clearing it:
789786
_PyInterpreterFrame*dying=frame;
790-
frame=cframe.current_frame=dying->previous;
787+
frame=tstate->current_frame=dying->previous;
791788
_PyEvalFrameClearAndPop(tstate,dying);
792789
frame->prev_instr+=frame->return_offset;
793790
_PyFrame_StackPush(frame,retval);
@@ -803,7 +800,7 @@ dummy_func(
803800
assert(frame!=&entry_frame);
804801
// GH-99729: We need to unlink the frame *before* clearing it:
805802
_PyInterpreterFrame*dying=frame;
806-
frame=cframe.current_frame=dying->previous;
803+
frame=tstate->current_frame=dying->previous;
807804
_PyEvalFrameClearAndPop(tstate,dying);
808805
frame->prev_instr+=frame->return_offset;
809806
_PyFrame_StackPush(frame,retval);
@@ -823,7 +820,7 @@ dummy_func(
823820
assert(frame!=&entry_frame);
824821
// GH-99729: We need to unlink the frame *before* clearing it:
825822
_PyInterpreterFrame*dying=frame;
826-
frame=cframe.current_frame=dying->previous;
823+
frame=tstate->current_frame=dying->previous;
827824
_PyEvalFrameClearAndPop(tstate,dying);
828825
frame->prev_instr+=frame->return_offset;
829826
_PyFrame_StackPush(frame,retval);
@@ -1019,7 +1016,7 @@ dummy_func(
10191016
gen->gi_exc_state.previous_item=NULL;
10201017
_Py_LeaveRecursiveCallPy(tstate);
10211018
_PyInterpreterFrame*gen_frame=frame;
1022-
frame=cframe.current_frame=frame->previous;
1019+
frame=tstate->current_frame=frame->previous;
10231020
gen_frame->previous=NULL;
10241021
_PyFrame_StackPush(frame,retval);
10251022
gotoresume_frame;
@@ -1038,7 +1035,7 @@ dummy_func(
10381035
gen->gi_exc_state.previous_item=NULL;
10391036
_Py_LeaveRecursiveCallPy(tstate);
10401037
_PyInterpreterFrame*gen_frame=frame;
1041-
frame=cframe.current_frame=frame->previous;
1038+
frame=tstate->current_frame=frame->previous;
10421039
gen_frame->previous=NULL;
10431040
_PyFrame_StackPush(frame,retval);
10441041
gotoresume_frame;
@@ -2207,10 +2204,10 @@ dummy_func(
22072204
OBJECT_STAT_INC(optimization_attempts);
22082205
frame=_PyOptimizer_BackEdge(frame,here,next_instr,stack_pointer);
22092206
if (frame==NULL) {
2210-
frame=cframe.current_frame;
2207+
frame=tstate->current_frame;
22112208
gotoresume_with_error;
22122209
}
2213-
assert(frame==cframe.current_frame);
2210+
assert(frame==tstate->current_frame);
22142211
here[1].cache &= ((1 <<OPTIMIZER_BITS_IN_COUNTER)-1);
22152212
gotoresume_frame;
22162213
}
@@ -2238,7 +2235,7 @@ dummy_func(
22382235
Py_INCREF(executor);
22392236
frame=executor->execute(executor,frame,stack_pointer);
22402237
if (frame==NULL) {
2241-
frame=cframe.current_frame;
2238+
frame=tstate->current_frame;
22422239
gotoresume_with_error;
22432240
}
22442241
gotoresume_frame;
@@ -2993,12 +2990,11 @@ dummy_func(
29932990
_PyFrame_SetStackPointer(frame,stack_pointer);
29942991
new_frame->previous=frame;
29952992
CALL_STAT_INC(inlined_py_calls);
2993+
frame=tstate->current_frame=new_frame;
29962994
#ifTIER_ONE
2997-
frame=cframe.current_frame=new_frame;
29982995
gotostart_frame;
29992996
#endif
30002997
#ifTIER_TWO
3001-
frame=tstate->cframe->current_frame=new_frame;
30022998
ERROR_IF(_Py_EnterRecursivePy(tstate),exit_unwind);
30032999
stack_pointer=_PyFrame_GetStackPointer(frame);
30043000
ip_offset= (_Py_CODEUNIT*)_PyFrame_GetCode(frame)->co_code_adaptive;
@@ -3135,7 +3131,7 @@ dummy_func(
31353131
/* Link frames */
31363132
init_frame->previous=shim;
31373133
shim->previous=frame;
3138-
frame=cframe.current_frame=init_frame;
3134+
frame=tstate->current_frame=init_frame;
31393135
CALL_STAT_INC(inlined_py_calls);
31403136
/* Account for pushing the extra frame.
31413137
* We don't check recursion depth here,
@@ -3598,7 +3594,7 @@ dummy_func(
35983594
assert(frame!=&entry_frame);
35993595
_PyInterpreterFrame*prev=frame->previous;
36003596
_PyThreadState_PopFrame(tstate,frame);
3601-
frame=cframe.current_frame=prev;
3597+
frame=tstate->current_frame=prev;
36023598
_PyFrame_StackPush(frame, (PyObject*)gen);
36033599
gotoresume_frame;
36043600
}

‎Python/ceval.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -656,17 +656,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
656656
intlltrace=0;
657657
#endif
658658

659-
_PyCFramecframe;
660659
_PyInterpreterFrameentry_frame;
661660
PyObject*kwnames=NULL;// Borrowed reference. Reset by CALL instructions.
662661

663-
/* WARNING: Because the _PyCFrame lives on the C stack,
664-
* but can be accessed from a heap allocated object (tstate)
665-
* strict stack discipline must be maintained.
666-
*/
667-
_PyCFrame*prev_cframe=tstate->cframe;
668-
cframe.previous=prev_cframe;
669-
tstate->cframe=&cframe;
662+
670663

671664
#ifdefPy_DEBUG
672665
/* Set these to invalid but identifiable values for debugging. */
@@ -682,9 +675,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
682675
entry_frame.owner=FRAME_OWNED_BY_CSTACK;
683676
entry_frame.return_offset=0;
684677
/* Push frame */
685-
entry_frame.previous=prev_cframe->current_frame;
678+
entry_frame.previous=tstate->current_frame;
686679
frame->previous=&entry_frame;
687-
cframe.current_frame=frame;
680+
tstate->current_frame=frame;
688681

689682
tstate->c_recursion_remaining-= (PY_EVAL_C_STACK_UNITS-1);
690683
if (_Py_EnterRecursiveCallTstate(tstate,"")) {
@@ -924,13 +917,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
924917
assert(frame!=&entry_frame);
925918
// GH-99729: We need to unlink the frame *before* clearing it:
926919
_PyInterpreterFrame*dying=frame;
927-
frame=cframe.current_frame=dying->previous;
920+
frame=tstate->current_frame=dying->previous;
928921
_PyEvalFrameClearAndPop(tstate,dying);
929922
frame->return_offset=0;
930923
if (frame==&entry_frame) {
931-
/* Restore previous cframe and exit */
932-
tstate->cframe=cframe.previous;
933-
assert(tstate->cframe->current_frame==frame->previous);
924+
/* Restore previous frame and exit */
925+
tstate->current_frame=frame->previous;
934926
tstate->c_recursion_remaining+=PY_EVAL_C_STACK_UNITS;
935927
returnNULL;
936928
}
@@ -2297,7 +2289,7 @@ int
22972289
PyEval_MergeCompilerFlags(PyCompilerFlags*cf)
22982290
{
22992291
PyThreadState*tstate=_PyThreadState_GET();
2300-
_PyInterpreterFrame*current_frame=tstate->cframe->current_frame;
2292+
_PyInterpreterFrame*current_frame=tstate->current_frame;
23012293
intresult=cf->cf_flags!=0;
23022294

23032295
if (current_frame!=NULL) {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp