mirror of https://github.com/python/cpython
GH-108035: Remove the `_PyCFrame` struct as it is no longer needed for performance. (GH-108036)
This commit is contained in:
parent
33e6e3fec0
commit
006e44f950
|
@ -29,24 +29,6 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);
|
||||||
#define PyTrace_C_RETURN 6
|
#define PyTrace_C_RETURN 6
|
||||||
#define PyTrace_OPCODE 7
|
#define PyTrace_OPCODE 7
|
||||||
|
|
||||||
// Internal structure: you should not use it directly, but use public functions
|
|
||||||
// like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing().
|
|
||||||
typedef struct _PyCFrame {
|
|
||||||
/* This struct will be threaded through the C stack
|
|
||||||
* allowing fast access to per-thread state that needs
|
|
||||||
* to be accessed quickly by the interpreter, but can
|
|
||||||
* be modified outside of the interpreter.
|
|
||||||
*
|
|
||||||
* WARNING: This makes data on the C stack accessible from
|
|
||||||
* heap objects. Care must be taken to maintain stack
|
|
||||||
* discipline and make sure that instances of this struct cannot
|
|
||||||
* accessed outside of their lifetime.
|
|
||||||
*/
|
|
||||||
/* Pointer to the currently executing frame (it can be NULL) */
|
|
||||||
struct _PyInterpreterFrame *current_frame;
|
|
||||||
struct _PyCFrame *previous;
|
|
||||||
} _PyCFrame;
|
|
||||||
|
|
||||||
typedef struct _err_stackitem {
|
typedef struct _err_stackitem {
|
||||||
/* This struct represents a single execution context where we might
|
/* This struct represents a single execution context where we might
|
||||||
* be currently handling an exception. It is a per-coroutine state
|
* be currently handling an exception. It is a per-coroutine state
|
||||||
|
@ -123,9 +105,8 @@ struct _ts {
|
||||||
int tracing;
|
int tracing;
|
||||||
int what_event; /* The event currently being monitored, if any. */
|
int what_event; /* The event currently being monitored, if any. */
|
||||||
|
|
||||||
/* Pointer to current _PyCFrame in the C stack frame of the currently,
|
/* Pointer to currently executing frame. */
|
||||||
* or most recently, executing _PyEval_EvalFrameDefault. */
|
struct _PyInterpreterFrame *current_frame;
|
||||||
_PyCFrame *cframe;
|
|
||||||
|
|
||||||
Py_tracefunc c_profilefunc;
|
Py_tracefunc c_profilefunc;
|
||||||
Py_tracefunc c_tracefunc;
|
Py_tracefunc c_tracefunc;
|
||||||
|
@ -211,8 +192,6 @@ struct _ts {
|
||||||
/* The thread's exception stack entry. (Always the last entry.) */
|
/* The thread's exception stack entry. (Always the last entry.) */
|
||||||
_PyErr_StackItem exc_state;
|
_PyErr_StackItem exc_state;
|
||||||
|
|
||||||
/* The bottom-most frame on the stack. */
|
|
||||||
_PyCFrame root_cframe;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* WASI has limited call stack. Python's recursion limit depends on code
|
/* WASI has limited call stack. Python's recursion limit depends on code
|
||||||
|
|
|
@ -196,7 +196,7 @@ _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
|
||||||
static inline _PyInterpreterFrame *
|
static inline _PyInterpreterFrame *
|
||||||
_PyThreadState_GetFrame(PyThreadState *tstate)
|
_PyThreadState_GetFrame(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
return _PyFrame_GetFirstComplete(tstate->cframe->current_frame);
|
return _PyFrame_GetFirstComplete(tstate->current_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For use by _PyFrame_GetFrameObject
|
/* For use by _PyFrame_GetFrameObject
|
||||||
|
|
|
@ -80,7 +80,7 @@ typedef struct _Py_DebugOffsets {
|
||||||
off_t prev;
|
off_t prev;
|
||||||
off_t next;
|
off_t next;
|
||||||
off_t interp;
|
off_t interp;
|
||||||
off_t cframe;
|
off_t current_frame;
|
||||||
off_t thread_id;
|
off_t thread_id;
|
||||||
off_t native_thread_id;
|
off_t native_thread_id;
|
||||||
} thread_state;
|
} thread_state;
|
||||||
|
|
|
@ -45,7 +45,7 @@ extern PyTypeObject _PyExc_MemoryError;
|
||||||
.prev = offsetof(PyThreadState, prev), \
|
.prev = offsetof(PyThreadState, prev), \
|
||||||
.next = offsetof(PyThreadState, next), \
|
.next = offsetof(PyThreadState, next), \
|
||||||
.interp = offsetof(PyThreadState, interp), \
|
.interp = offsetof(PyThreadState, interp), \
|
||||||
.cframe = offsetof(PyThreadState, cframe), \
|
.current_frame = offsetof(PyThreadState, current_frame), \
|
||||||
.thread_id = offsetof(PyThreadState, thread_id), \
|
.thread_id = offsetof(PyThreadState, thread_id), \
|
||||||
.native_thread_id = offsetof(PyThreadState, native_thread_id), \
|
.native_thread_id = offsetof(PyThreadState, native_thread_id), \
|
||||||
}, \
|
}, \
|
||||||
|
@ -56,10 +56,6 @@ extern PyTypeObject _PyExc_MemoryError;
|
||||||
.localsplus = offsetof(_PyInterpreterFrame, localsplus), \
|
.localsplus = offsetof(_PyInterpreterFrame, localsplus), \
|
||||||
.owner = offsetof(_PyInterpreterFrame, owner), \
|
.owner = offsetof(_PyInterpreterFrame, owner), \
|
||||||
}, \
|
}, \
|
||||||
.cframe = { \
|
|
||||||
.current_frame = offsetof(_PyCFrame, current_frame), \
|
|
||||||
.previous = offsetof(_PyCFrame, previous), \
|
|
||||||
}, \
|
|
||||||
.code_object = { \
|
.code_object = { \
|
||||||
.filename = offsetof(PyCodeObject, co_filename), \
|
.filename = offsetof(PyCodeObject, co_filename), \
|
||||||
.name = offsetof(PyCodeObject, co_name), \
|
.name = offsetof(PyCodeObject, co_name), \
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Remove the ``_PyCFrame`` struct, moving the pointer to the current intepreter frame
|
||||||
|
back to the threadstate, as it was for 3.10 and earlier. The ``_PyCFrame``
|
||||||
|
existed as a performance optimization for tracing. Since PEP 669 has been
|
||||||
|
implemented, this optimization no longer applies.
|
|
@ -369,7 +369,7 @@ _is_running(PyInterpreterState *interp)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!PyErr_Occurred());
|
assert(!PyErr_Occurred());
|
||||||
struct _PyInterpreterFrame *frame = tstate->cframe->current_frame;
|
struct _PyInterpreterFrame *frame = tstate->current_frame;
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,9 +476,9 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
|
||||||
will be reported correctly to the user. */
|
will be reported correctly to the user. */
|
||||||
/* XXX We should probably be updating the current frame
|
/* XXX We should probably be updating the current frame
|
||||||
somewhere in ceval.c. */
|
somewhere in ceval.c. */
|
||||||
_PyInterpreterFrame *prev = tstate->cframe->current_frame;
|
_PyInterpreterFrame *prev = tstate->current_frame;
|
||||||
frame->previous = prev;
|
frame->previous = prev;
|
||||||
tstate->cframe->current_frame = frame;
|
tstate->current_frame = frame;
|
||||||
/* Close the generator that we are currently iterating with
|
/* Close the generator that we are currently iterating with
|
||||||
'yield from' or awaiting on with 'await'. */
|
'yield from' or awaiting on with 'await'. */
|
||||||
PyFrameState state = gen->gi_frame_state;
|
PyFrameState state = gen->gi_frame_state;
|
||||||
|
@ -486,7 +486,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
|
||||||
ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
|
ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
|
||||||
typ, val, tb);
|
typ, val, tb);
|
||||||
gen->gi_frame_state = state;
|
gen->gi_frame_state = state;
|
||||||
tstate->cframe->current_frame = prev;
|
tstate->current_frame = prev;
|
||||||
frame->previous = NULL;
|
frame->previous = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* `yf` is an iterator or a coroutine-like object. */
|
/* `yf` is an iterator or a coroutine-like object. */
|
||||||
|
@ -938,7 +938,7 @@ _Py_MakeCoro(PyFunctionObject *func)
|
||||||
if (origin_depth == 0) {
|
if (origin_depth == 0) {
|
||||||
((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
|
((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
|
||||||
} else {
|
} else {
|
||||||
_PyInterpreterFrame *frame = tstate->cframe->current_frame;
|
_PyInterpreterFrame *frame = tstate->current_frame;
|
||||||
assert(frame);
|
assert(frame);
|
||||||
assert(_PyFrame_IsIncomplete(frame));
|
assert(_PyFrame_IsIncomplete(frame));
|
||||||
frame = _PyFrame_GetFirstComplete(frame->previous);
|
frame = _PyFrame_GetFirstComplete(frame->previous);
|
||||||
|
|
|
@ -107,7 +107,7 @@ make_union(PyObject *self, PyObject *other)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
caller(void)
|
caller(void)
|
||||||
{
|
{
|
||||||
_PyInterpreterFrame *f = _PyThreadState_GET()->cframe->current_frame;
|
_PyInterpreterFrame *f = _PyThreadState_GET()->current_frame;
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,6 @@ dummy_func(
|
||||||
_PyInterpreterFrame *frame,
|
_PyInterpreterFrame *frame,
|
||||||
unsigned char opcode,
|
unsigned char opcode,
|
||||||
unsigned int oparg,
|
unsigned int oparg,
|
||||||
_PyCFrame cframe,
|
|
||||||
_Py_CODEUNIT *next_instr,
|
_Py_CODEUNIT *next_instr,
|
||||||
PyObject **stack_pointer,
|
PyObject **stack_pointer,
|
||||||
PyObject *kwnames,
|
PyObject *kwnames,
|
||||||
|
@ -134,8 +133,7 @@ dummy_func(
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(RESUME, (--)) {
|
inst(RESUME, (--)) {
|
||||||
assert(tstate->cframe == &cframe);
|
assert(frame == tstate->current_frame);
|
||||||
assert(frame == cframe.current_frame);
|
|
||||||
/* Possibly combine this with eval breaker */
|
/* Possibly combine this with eval breaker */
|
||||||
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
||||||
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
|
@ -752,9 +750,8 @@ dummy_func(
|
||||||
inst(INTERPRETER_EXIT, (retval --)) {
|
inst(INTERPRETER_EXIT, (retval --)) {
|
||||||
assert(frame == &entry_frame);
|
assert(frame == &entry_frame);
|
||||||
assert(_PyFrame_IsIncomplete(frame));
|
assert(_PyFrame_IsIncomplete(frame));
|
||||||
/* Restore previous cframe and return. */
|
/* Restore previous frame and return. */
|
||||||
tstate->cframe = cframe.previous;
|
tstate->current_frame = frame->previous;
|
||||||
assert(tstate->cframe->current_frame == frame->previous);
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
|
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -768,7 +765,7 @@ dummy_func(
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -787,7 +784,7 @@ dummy_func(
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -803,7 +800,7 @@ dummy_func(
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -823,7 +820,7 @@ dummy_func(
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -1019,7 +1016,7 @@ dummy_func(
|
||||||
gen->gi_exc_state.previous_item = NULL;
|
gen->gi_exc_state.previous_item = NULL;
|
||||||
_Py_LeaveRecursiveCallPy(tstate);
|
_Py_LeaveRecursiveCallPy(tstate);
|
||||||
_PyInterpreterFrame *gen_frame = frame;
|
_PyInterpreterFrame *gen_frame = frame;
|
||||||
frame = cframe.current_frame = frame->previous;
|
frame = tstate->current_frame = frame->previous;
|
||||||
gen_frame->previous = NULL;
|
gen_frame->previous = NULL;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
|
@ -1038,7 +1035,7 @@ dummy_func(
|
||||||
gen->gi_exc_state.previous_item = NULL;
|
gen->gi_exc_state.previous_item = NULL;
|
||||||
_Py_LeaveRecursiveCallPy(tstate);
|
_Py_LeaveRecursiveCallPy(tstate);
|
||||||
_PyInterpreterFrame *gen_frame = frame;
|
_PyInterpreterFrame *gen_frame = frame;
|
||||||
frame = cframe.current_frame = frame->previous;
|
frame = tstate->current_frame = frame->previous;
|
||||||
gen_frame->previous = NULL;
|
gen_frame->previous = NULL;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
|
@ -2207,10 +2204,10 @@ dummy_func(
|
||||||
OBJECT_STAT_INC(optimization_attempts);
|
OBJECT_STAT_INC(optimization_attempts);
|
||||||
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
frame = cframe.current_frame;
|
frame = tstate->current_frame;
|
||||||
goto resume_with_error;
|
goto resume_with_error;
|
||||||
}
|
}
|
||||||
assert(frame == cframe.current_frame);
|
assert(frame == tstate->current_frame);
|
||||||
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
|
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
}
|
}
|
||||||
|
@ -2238,7 +2235,7 @@ dummy_func(
|
||||||
Py_INCREF(executor);
|
Py_INCREF(executor);
|
||||||
frame = executor->execute(executor, frame, stack_pointer);
|
frame = executor->execute(executor, frame, stack_pointer);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
frame = cframe.current_frame;
|
frame = tstate->current_frame;
|
||||||
goto resume_with_error;
|
goto resume_with_error;
|
||||||
}
|
}
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
|
@ -2993,12 +2990,11 @@ dummy_func(
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
|
frame = tstate->current_frame = new_frame;
|
||||||
#if TIER_ONE
|
#if TIER_ONE
|
||||||
frame = cframe.current_frame = new_frame;
|
|
||||||
goto start_frame;
|
goto start_frame;
|
||||||
#endif
|
#endif
|
||||||
#if TIER_TWO
|
#if TIER_TWO
|
||||||
frame = tstate->cframe->current_frame = new_frame;
|
|
||||||
ERROR_IF(_Py_EnterRecursivePy(tstate), exit_unwind);
|
ERROR_IF(_Py_EnterRecursivePy(tstate), exit_unwind);
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
|
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
|
||||||
|
@ -3135,7 +3131,7 @@ dummy_func(
|
||||||
/* Link frames */
|
/* Link frames */
|
||||||
init_frame->previous = shim;
|
init_frame->previous = shim;
|
||||||
shim->previous = frame;
|
shim->previous = frame;
|
||||||
frame = cframe.current_frame = init_frame;
|
frame = tstate->current_frame = init_frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
/* Account for pushing the extra frame.
|
/* Account for pushing the extra frame.
|
||||||
* We don't check recursion depth here,
|
* We don't check recursion depth here,
|
||||||
|
@ -3598,7 +3594,7 @@ dummy_func(
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
_PyInterpreterFrame *prev = frame->previous;
|
_PyInterpreterFrame *prev = frame->previous;
|
||||||
_PyThreadState_PopFrame(tstate, frame);
|
_PyThreadState_PopFrame(tstate, frame);
|
||||||
frame = cframe.current_frame = prev;
|
frame = tstate->current_frame = prev;
|
||||||
_PyFrame_StackPush(frame, (PyObject *)gen);
|
_PyFrame_StackPush(frame, (PyObject *)gen);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,17 +656,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
int lltrace = 0;
|
int lltrace = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_PyCFrame cframe;
|
|
||||||
_PyInterpreterFrame entry_frame;
|
_PyInterpreterFrame entry_frame;
|
||||||
PyObject *kwnames = NULL; // Borrowed reference. Reset by CALL instructions.
|
PyObject *kwnames = NULL; // Borrowed reference. Reset by CALL instructions.
|
||||||
|
|
||||||
/* WARNING: Because the _PyCFrame lives on the C stack,
|
|
||||||
* but can be accessed from a heap allocated object (tstate)
|
|
||||||
* strict stack discipline must be maintained.
|
|
||||||
*/
|
|
||||||
_PyCFrame *prev_cframe = tstate->cframe;
|
|
||||||
cframe.previous = prev_cframe;
|
|
||||||
tstate->cframe = &cframe;
|
|
||||||
|
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
/* Set these to invalid but identifiable values for debugging. */
|
/* Set these to invalid but identifiable values for debugging. */
|
||||||
|
@ -682,9 +675,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
|
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
|
||||||
entry_frame.return_offset = 0;
|
entry_frame.return_offset = 0;
|
||||||
/* Push frame */
|
/* Push frame */
|
||||||
entry_frame.previous = prev_cframe->current_frame;
|
entry_frame.previous = tstate->current_frame;
|
||||||
frame->previous = &entry_frame;
|
frame->previous = &entry_frame;
|
||||||
cframe.current_frame = frame;
|
tstate->current_frame = frame;
|
||||||
|
|
||||||
tstate->c_recursion_remaining -= (PY_EVAL_C_STACK_UNITS - 1);
|
tstate->c_recursion_remaining -= (PY_EVAL_C_STACK_UNITS - 1);
|
||||||
if (_Py_EnterRecursiveCallTstate(tstate, "")) {
|
if (_Py_EnterRecursiveCallTstate(tstate, "")) {
|
||||||
|
@ -924,13 +917,12 @@ exit_unwind:
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->return_offset = 0;
|
frame->return_offset = 0;
|
||||||
if (frame == &entry_frame) {
|
if (frame == &entry_frame) {
|
||||||
/* Restore previous cframe and exit */
|
/* Restore previous frame and exit */
|
||||||
tstate->cframe = cframe.previous;
|
tstate->current_frame = frame->previous;
|
||||||
assert(tstate->cframe->current_frame == frame->previous);
|
|
||||||
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
|
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2297,7 +2289,7 @@ int
|
||||||
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
|
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
_PyInterpreterFrame *current_frame = tstate->cframe->current_frame;
|
_PyInterpreterFrame *current_frame = tstate->current_frame;
|
||||||
int result = cf->cf_flags != 0;
|
int result = cf->cf_flags != 0;
|
||||||
|
|
||||||
if (current_frame != NULL) {
|
if (current_frame != NULL) {
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer); \
|
_PyFrame_SetStackPointer(frame, stack_pointer); \
|
||||||
frame->prev_instr = next_instr - 1; \
|
frame->prev_instr = next_instr - 1; \
|
||||||
(NEW_FRAME)->previous = frame; \
|
(NEW_FRAME)->previous = frame; \
|
||||||
frame = cframe.current_frame = (NEW_FRAME); \
|
frame = tstate->current_frame = (NEW_FRAME); \
|
||||||
CALL_STAT_INC(inlined_py_calls); \
|
CALL_STAT_INC(inlined_py_calls); \
|
||||||
goto start_frame; \
|
goto start_frame; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -111,7 +111,7 @@ pop_1_exit_unwind:
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
error:
|
error:
|
||||||
// On ERROR_IF we return NULL as the frame.
|
// On ERROR_IF we return NULL as the frame.
|
||||||
// The caller recovers the frame from cframe.current_frame.
|
// The caller recovers the frame from tstate->current_frame.
|
||||||
DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
|
DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
Py_DECREF(self);
|
Py_DECREF(self);
|
||||||
|
|
|
@ -2212,12 +2212,11 @@
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
|
frame = tstate->current_frame = new_frame;
|
||||||
#if TIER_ONE
|
#if TIER_ONE
|
||||||
frame = cframe.current_frame = new_frame;
|
|
||||||
goto start_frame;
|
goto start_frame;
|
||||||
#endif
|
#endif
|
||||||
#if TIER_TWO
|
#if TIER_TWO
|
||||||
frame = tstate->cframe->current_frame = new_frame;
|
|
||||||
if (_Py_EnterRecursivePy(tstate)) goto pop_1_exit_unwind;
|
if (_Py_EnterRecursivePy(tstate)) goto pop_1_exit_unwind;
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
|
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
|
||||||
|
|
|
@ -124,7 +124,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
|
||||||
_PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED);
|
_PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED);
|
||||||
// GH-99729: Clearing this frame can expose the stack (via finalizers). It's
|
// GH-99729: Clearing this frame can expose the stack (via finalizers). It's
|
||||||
// crucial that this frame has been unlinked, and is no longer visible:
|
// crucial that this frame has been unlinked, and is no longer visible:
|
||||||
assert(_PyThreadState_GET()->cframe->current_frame != frame);
|
assert(_PyThreadState_GET()->current_frame != frame);
|
||||||
if (frame->frame_obj) {
|
if (frame->frame_obj) {
|
||||||
PyFrameObject *f = frame->frame_obj;
|
PyFrameObject *f = frame->frame_obj;
|
||||||
frame->frame_obj = NULL;
|
frame->frame_obj = NULL;
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(RESUME) {
|
TARGET(RESUME) {
|
||||||
assert(tstate->cframe == &cframe);
|
assert(frame == tstate->current_frame);
|
||||||
assert(frame == cframe.current_frame);
|
|
||||||
/* Possibly combine this with eval breaker */
|
/* Possibly combine this with eval breaker */
|
||||||
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
||||||
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
|
@ -961,9 +960,8 @@
|
||||||
retval = stack_pointer[-1];
|
retval = stack_pointer[-1];
|
||||||
assert(frame == &entry_frame);
|
assert(frame == &entry_frame);
|
||||||
assert(_PyFrame_IsIncomplete(frame));
|
assert(_PyFrame_IsIncomplete(frame));
|
||||||
/* Restore previous cframe and return. */
|
/* Restore previous frame and return. */
|
||||||
tstate->cframe = cframe.previous;
|
tstate->current_frame = frame->previous;
|
||||||
assert(tstate->cframe->current_frame == frame->previous);
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
|
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -980,7 +978,7 @@
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -1002,7 +1000,7 @@
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -1019,7 +1017,7 @@
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -1039,7 +1037,7 @@
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
// GH-99729: We need to unlink the frame *before* clearing it:
|
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||||
_PyInterpreterFrame *dying = frame;
|
_PyInterpreterFrame *dying = frame;
|
||||||
frame = cframe.current_frame = dying->previous;
|
frame = tstate->current_frame = dying->previous;
|
||||||
_PyEvalFrameClearAndPop(tstate, dying);
|
_PyEvalFrameClearAndPop(tstate, dying);
|
||||||
frame->prev_instr += frame->return_offset;
|
frame->prev_instr += frame->return_offset;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
|
@ -1263,7 +1261,7 @@
|
||||||
gen->gi_exc_state.previous_item = NULL;
|
gen->gi_exc_state.previous_item = NULL;
|
||||||
_Py_LeaveRecursiveCallPy(tstate);
|
_Py_LeaveRecursiveCallPy(tstate);
|
||||||
_PyInterpreterFrame *gen_frame = frame;
|
_PyInterpreterFrame *gen_frame = frame;
|
||||||
frame = cframe.current_frame = frame->previous;
|
frame = tstate->current_frame = frame->previous;
|
||||||
gen_frame->previous = NULL;
|
gen_frame->previous = NULL;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
|
@ -1284,7 +1282,7 @@
|
||||||
gen->gi_exc_state.previous_item = NULL;
|
gen->gi_exc_state.previous_item = NULL;
|
||||||
_Py_LeaveRecursiveCallPy(tstate);
|
_Py_LeaveRecursiveCallPy(tstate);
|
||||||
_PyInterpreterFrame *gen_frame = frame;
|
_PyInterpreterFrame *gen_frame = frame;
|
||||||
frame = cframe.current_frame = frame->previous;
|
frame = tstate->current_frame = frame->previous;
|
||||||
gen_frame->previous = NULL;
|
gen_frame->previous = NULL;
|
||||||
_PyFrame_StackPush(frame, retval);
|
_PyFrame_StackPush(frame, retval);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
|
@ -2911,10 +2909,10 @@
|
||||||
OBJECT_STAT_INC(optimization_attempts);
|
OBJECT_STAT_INC(optimization_attempts);
|
||||||
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
frame = cframe.current_frame;
|
frame = tstate->current_frame;
|
||||||
goto resume_with_error;
|
goto resume_with_error;
|
||||||
}
|
}
|
||||||
assert(frame == cframe.current_frame);
|
assert(frame == tstate->current_frame);
|
||||||
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
|
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
}
|
}
|
||||||
|
@ -2933,7 +2931,7 @@
|
||||||
Py_INCREF(executor);
|
Py_INCREF(executor);
|
||||||
frame = executor->execute(executor, frame, stack_pointer);
|
frame = executor->execute(executor, frame, stack_pointer);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
frame = cframe.current_frame;
|
frame = tstate->current_frame;
|
||||||
goto resume_with_error;
|
goto resume_with_error;
|
||||||
}
|
}
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
|
@ -3830,12 +3828,11 @@
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
|
frame = tstate->current_frame = new_frame;
|
||||||
#if TIER_ONE
|
#if TIER_ONE
|
||||||
frame = cframe.current_frame = new_frame;
|
|
||||||
goto start_frame;
|
goto start_frame;
|
||||||
#endif
|
#endif
|
||||||
#if TIER_TWO
|
#if TIER_TWO
|
||||||
frame = tstate->cframe->current_frame = new_frame;
|
|
||||||
if (_Py_EnterRecursivePy(tstate)) goto pop_1_exit_unwind;
|
if (_Py_EnterRecursivePy(tstate)) goto pop_1_exit_unwind;
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
|
ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
|
||||||
|
@ -4014,7 +4011,7 @@
|
||||||
/* Link frames */
|
/* Link frames */
|
||||||
init_frame->previous = shim;
|
init_frame->previous = shim;
|
||||||
shim->previous = frame;
|
shim->previous = frame;
|
||||||
frame = cframe.current_frame = init_frame;
|
frame = tstate->current_frame = init_frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
/* Account for pushing the extra frame.
|
/* Account for pushing the extra frame.
|
||||||
* We don't check recursion depth here,
|
* We don't check recursion depth here,
|
||||||
|
@ -4636,7 +4633,7 @@
|
||||||
assert(frame != &entry_frame);
|
assert(frame != &entry_frame);
|
||||||
_PyInterpreterFrame *prev = frame->previous;
|
_PyInterpreterFrame *prev = frame->previous;
|
||||||
_PyThreadState_PopFrame(tstate, frame);
|
_PyThreadState_PopFrame(tstate, frame);
|
||||||
frame = cframe.current_frame = prev;
|
frame = tstate->current_frame = prev;
|
||||||
_PyFrame_StackPush(frame, (PyObject *)gen);
|
_PyFrame_StackPush(frame, (PyObject *)gen);
|
||||||
goto resume_frame;
|
goto resume_frame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1677,7 +1677,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) {
|
||||||
PyThreadState* ts = PyInterpreterState_ThreadHead(interp);
|
PyThreadState* ts = PyInterpreterState_ThreadHead(interp);
|
||||||
HEAD_UNLOCK(runtime);
|
HEAD_UNLOCK(runtime);
|
||||||
while (ts) {
|
while (ts) {
|
||||||
_PyInterpreterFrame *frame = ts->cframe->current_frame;
|
_PyInterpreterFrame *frame = ts->current_frame;
|
||||||
while (frame) {
|
while (frame) {
|
||||||
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
|
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
|
||||||
if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) {
|
||||||
|
|
|
@ -120,7 +120,7 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
import_star(PyThreadState* tstate, PyObject *from)
|
import_star(PyThreadState* tstate, PyObject *from)
|
||||||
{
|
{
|
||||||
_PyInterpreterFrame *frame = tstate->cframe->current_frame;
|
_PyInterpreterFrame *frame = tstate->current_frame;
|
||||||
if (_PyFrame_FastToLocalsWithError(frame) < 0) {
|
if (_PyFrame_FastToLocalsWithError(frame) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ import_star(PyThreadState* tstate, PyObject *from)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
stopiteration_error(PyThreadState* tstate, PyObject *exc)
|
stopiteration_error(PyThreadState* tstate, PyObject *exc)
|
||||||
{
|
{
|
||||||
_PyInterpreterFrame *frame = tstate->cframe->current_frame;
|
_PyInterpreterFrame *frame = tstate->current_frame;
|
||||||
assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
|
assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
|
||||||
assert(PyExceptionInstance_Check(exc));
|
assert(PyExceptionInstance_Check(exc));
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
|
|
|
@ -2147,7 +2147,7 @@ Py_EndInterpreter(PyThreadState *tstate)
|
||||||
if (tstate != _PyThreadState_GET()) {
|
if (tstate != _PyThreadState_GET()) {
|
||||||
Py_FatalError("thread is not current");
|
Py_FatalError("thread is not current");
|
||||||
}
|
}
|
||||||
if (tstate->cframe->current_frame != NULL) {
|
if (tstate->current_frame != NULL) {
|
||||||
Py_FatalError("thread still has a frame");
|
Py_FatalError("thread still has a frame");
|
||||||
}
|
}
|
||||||
interp->finalizing = 1;
|
interp->finalizing = 1;
|
||||||
|
|
|
@ -1310,7 +1310,7 @@ init_threadstate(PyThreadState *tstate,
|
||||||
// This is cleared when PyGILState_Ensure() creates the thread state.
|
// This is cleared when PyGILState_Ensure() creates the thread state.
|
||||||
tstate->gilstate_counter = 1;
|
tstate->gilstate_counter = 1;
|
||||||
|
|
||||||
tstate->cframe = &tstate->root_cframe;
|
tstate->current_frame = NULL;
|
||||||
tstate->datastack_chunk = NULL;
|
tstate->datastack_chunk = NULL;
|
||||||
tstate->datastack_top = NULL;
|
tstate->datastack_top = NULL;
|
||||||
tstate->datastack_limit = NULL;
|
tstate->datastack_limit = NULL;
|
||||||
|
@ -1452,7 +1452,7 @@ PyThreadState_Clear(PyThreadState *tstate)
|
||||||
|
|
||||||
int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;
|
int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;
|
||||||
|
|
||||||
if (verbose && tstate->cframe->current_frame != NULL) {
|
if (verbose && tstate->current_frame != NULL) {
|
||||||
/* bpo-20526: After the main thread calls
|
/* bpo-20526: After the main thread calls
|
||||||
_PyInterpreterState_SetFinalizing() in Py_FinalizeEx()
|
_PyInterpreterState_SetFinalizing() in Py_FinalizeEx()
|
||||||
(or in Py_EndInterpreter() for subinterpreters),
|
(or in Py_EndInterpreter() for subinterpreters),
|
||||||
|
@ -1953,7 +1953,7 @@ _PyThread_CurrentFrames(void)
|
||||||
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
|
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
|
||||||
PyThreadState *t;
|
PyThreadState *t;
|
||||||
for (t = i->threads.head; t != NULL; t = t->next) {
|
for (t = i->threads.head; t != NULL; t = t->next) {
|
||||||
_PyInterpreterFrame *frame = t->cframe->current_frame;
|
_PyInterpreterFrame *frame = t->current_frame;
|
||||||
frame = _PyFrame_GetFirstComplete(frame);
|
frame = _PyFrame_GetFirstComplete(frame);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1954,7 +1954,7 @@ sys__getframe_impl(PyObject *module, int depth)
|
||||||
/*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/
|
/*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
_PyInterpreterFrame *frame = tstate->cframe->current_frame;
|
_PyInterpreterFrame *frame = tstate->current_frame;
|
||||||
|
|
||||||
if (frame != NULL) {
|
if (frame != NULL) {
|
||||||
while (depth > 0) {
|
while (depth > 0) {
|
||||||
|
@ -2270,7 +2270,7 @@ sys__getframemodulename_impl(PyObject *module, int depth)
|
||||||
if (PySys_Audit("sys._getframemodulename", "i", depth) < 0) {
|
if (PySys_Audit("sys._getframemodulename", "i", depth) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_PyInterpreterFrame *f = _PyThreadState_GET()->cframe->current_frame;
|
_PyInterpreterFrame *f = _PyThreadState_GET()->current_frame;
|
||||||
while (f && (_PyFrame_IsIncomplete(f) || depth-- > 0)) {
|
while (f && (_PyFrame_IsIncomplete(f) || depth-- > 0)) {
|
||||||
f = f->previous;
|
f = f->previous;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1207,7 +1207,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
|
||||||
PUTS(fd, "Stack (most recent call first):\n");
|
PUTS(fd, "Stack (most recent call first):\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
frame = tstate->cframe->current_frame;
|
frame = tstate->current_frame;
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
PUTS(fd, " <no Python frame>\n");
|
PUTS(fd, " <no Python frame>\n");
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue