mirror of
https://github.com/python/cpython.git
synced 2025-07-12 22:05:16 +00:00
bpo-47045: Remove f_state
field (GH-31963)
* Remove the f_state field from _PyInterpreterFrame * Make ownership of the frame explicit, replacing the is_generator field with an owner field.
This commit is contained in:
parent
88872a29f1
commit
49daf6dba8
9 changed files with 260 additions and 220 deletions
185
Python/ceval.c
185
Python/ceval.c
|
@ -1730,7 +1730,6 @@ handle_eval_breaker:
|
|||
PREDICTED(RESUME_QUICK);
|
||||
assert(tstate->cframe == &cframe);
|
||||
assert(frame == cframe.current_frame);
|
||||
frame->f_state = FRAME_EXECUTING;
|
||||
if (_Py_atomic_load_relaxed(eval_breaker) && oparg < 2) {
|
||||
goto handle_eval_breaker;
|
||||
}
|
||||
|
@ -2373,7 +2372,6 @@ handle_eval_breaker:
|
|||
TARGET(RETURN_VALUE) {
|
||||
PyObject *retval = POP();
|
||||
assert(EMPTY());
|
||||
frame->f_state = FRAME_RETURNED;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
TRACE_FUNCTION_EXIT();
|
||||
DTRACE_FUNCTION_EXIT();
|
||||
|
@ -2585,7 +2583,7 @@ handle_eval_breaker:
|
|||
TARGET(YIELD_VALUE) {
|
||||
assert(frame->is_entry);
|
||||
PyObject *retval = POP();
|
||||
frame->f_state = FRAME_SUSPENDED;
|
||||
_PyFrame_GetGenerator(frame)->gi_frame_state = FRAME_SUSPENDED;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
TRACE_FUNCTION_EXIT();
|
||||
DTRACE_FUNCTION_EXIT();
|
||||
|
@ -4068,7 +4066,6 @@ handle_eval_breaker:
|
|||
* generator or coroutine, so we deliberately do not check it here.
|
||||
* (see bpo-30039).
|
||||
*/
|
||||
frame->f_state = FRAME_EXECUTING;
|
||||
JUMPTO(oparg);
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -5253,9 +5250,8 @@ handle_eval_breaker:
|
|||
_PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
|
||||
_PyFrame_Copy(frame, gen_frame);
|
||||
assert(frame->frame_obj == NULL);
|
||||
gen->gi_frame_valid = 1;
|
||||
gen_frame->is_generator = true;
|
||||
gen_frame->f_state = FRAME_CREATED;
|
||||
gen->gi_frame_state = FRAME_CREATED;
|
||||
gen_frame->owner = FRAME_OWNED_BY_GENERATOR;
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
if (!frame->is_entry) {
|
||||
_PyInterpreterFrame *prev = frame->previous;
|
||||
|
@ -5429,41 +5425,47 @@ handle_eval_breaker:
|
|||
int instr_prev = frame->f_lasti;
|
||||
frame->f_lasti = INSTR_OFFSET();
|
||||
TRACING_NEXTOPARG();
|
||||
if (opcode == RESUME) {
|
||||
if (oparg < 2) {
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
/* Call tracing */
|
||||
TRACE_FUNCTION_ENTRY();
|
||||
DTRACE_FUNCTION_ENTRY();
|
||||
}
|
||||
else if (frame->f_state > FRAME_CREATED) {
|
||||
/* line-by-line tracing support */
|
||||
if (PyDTrace_LINE_ENABLED()) {
|
||||
maybe_dtrace_line(frame, &tstate->trace_info, instr_prev);
|
||||
}
|
||||
|
||||
if (cframe.use_tracing &&
|
||||
tstate->c_tracefunc != NULL && !tstate->tracing) {
|
||||
int err;
|
||||
/* see maybe_call_line_trace()
|
||||
for expository comments */
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
|
||||
err = maybe_call_line_trace(tstate->c_tracefunc,
|
||||
tstate->c_traceobj,
|
||||
tstate, frame, instr_prev);
|
||||
if (err) {
|
||||
/* trace function raised an exception */
|
||||
next_instr++;
|
||||
goto error;
|
||||
switch(opcode) {
|
||||
case COPY_FREE_VARS:
|
||||
case MAKE_CELL:
|
||||
case RETURN_GENERATOR:
|
||||
/* Frame not fully initialized */
|
||||
break;
|
||||
case RESUME:
|
||||
if (oparg < 2) {
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
/* Call tracing */
|
||||
TRACE_FUNCTION_ENTRY();
|
||||
DTRACE_FUNCTION_ENTRY();
|
||||
break;
|
||||
default:
|
||||
/* line-by-line tracing support */
|
||||
if (PyDTrace_LINE_ENABLED()) {
|
||||
maybe_dtrace_line(frame, &tstate->trace_info, instr_prev);
|
||||
}
|
||||
/* Reload possibly changed frame fields */
|
||||
JUMPTO(frame->f_lasti);
|
||||
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
frame->stacktop = -1;
|
||||
}
|
||||
if (cframe.use_tracing &&
|
||||
tstate->c_tracefunc != NULL && !tstate->tracing) {
|
||||
int err;
|
||||
/* see maybe_call_line_trace()
|
||||
for expository comments */
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
|
||||
err = maybe_call_line_trace(tstate->c_tracefunc,
|
||||
tstate->c_traceobj,
|
||||
tstate, frame, instr_prev);
|
||||
if (err) {
|
||||
/* trace function raised an exception */
|
||||
next_instr++;
|
||||
goto error;
|
||||
}
|
||||
/* Reload possibly changed frame fields */
|
||||
JUMPTO(frame->f_lasti);
|
||||
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
frame->stacktop = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACING_NEXTOPARG();
|
||||
|
@ -5558,65 +5560,63 @@ error:
|
|||
|
||||
if (tstate->c_tracefunc != NULL) {
|
||||
/* Make sure state is set to FRAME_UNWINDING for tracing */
|
||||
frame->f_state = FRAME_UNWINDING;
|
||||
call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj,
|
||||
tstate, frame);
|
||||
}
|
||||
|
||||
exception_unwind:
|
||||
frame->f_state = FRAME_UNWINDING;
|
||||
/* We can't use frame->f_lasti here, as RERAISE may have set it */
|
||||
int offset = INSTR_OFFSET()-1;
|
||||
int level, handler, lasti;
|
||||
if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) {
|
||||
// No handlers, so exit.
|
||||
assert(_PyErr_Occurred(tstate));
|
||||
{
|
||||
/* We can't use frame->f_lasti here, as RERAISE may have set it */
|
||||
int offset = INSTR_OFFSET()-1;
|
||||
int level, handler, lasti;
|
||||
if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) {
|
||||
// No handlers, so exit.
|
||||
assert(_PyErr_Occurred(tstate));
|
||||
|
||||
/* Pop remaining stack entries. */
|
||||
PyObject **stackbase = _PyFrame_Stackbase(frame);
|
||||
while (stack_pointer > stackbase) {
|
||||
PyObject *o = POP();
|
||||
Py_XDECREF(o);
|
||||
/* Pop remaining stack entries. */
|
||||
PyObject **stackbase = _PyFrame_Stackbase(frame);
|
||||
while (stack_pointer > stackbase) {
|
||||
PyObject *o = POP();
|
||||
Py_XDECREF(o);
|
||||
}
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
TRACE_FUNCTION_UNWIND();
|
||||
DTRACE_FUNCTION_EXIT();
|
||||
goto exit_unwind;
|
||||
}
|
||||
assert(STACK_LEVEL() == 0);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
frame->f_state = FRAME_RAISED;
|
||||
TRACE_FUNCTION_UNWIND();
|
||||
DTRACE_FUNCTION_EXIT();
|
||||
goto exit_unwind;
|
||||
}
|
||||
|
||||
assert(STACK_LEVEL() >= level);
|
||||
PyObject **new_top = _PyFrame_Stackbase(frame) + level;
|
||||
while (stack_pointer > new_top) {
|
||||
PyObject *v = POP();
|
||||
Py_XDECREF(v);
|
||||
}
|
||||
PyObject *exc, *val, *tb;
|
||||
if (lasti) {
|
||||
PyObject *lasti = PyLong_FromLong(frame->f_lasti);
|
||||
if (lasti == NULL) {
|
||||
goto exception_unwind;
|
||||
assert(STACK_LEVEL() >= level);
|
||||
PyObject **new_top = _PyFrame_Stackbase(frame) + level;
|
||||
while (stack_pointer > new_top) {
|
||||
PyObject *v = POP();
|
||||
Py_XDECREF(v);
|
||||
}
|
||||
PUSH(lasti);
|
||||
PyObject *exc, *val, *tb;
|
||||
if (lasti) {
|
||||
PyObject *lasti = PyLong_FromLong(frame->f_lasti);
|
||||
if (lasti == NULL) {
|
||||
goto exception_unwind;
|
||||
}
|
||||
PUSH(lasti);
|
||||
}
|
||||
_PyErr_Fetch(tstate, &exc, &val, &tb);
|
||||
/* Make the raw exception data
|
||||
available to the handler,
|
||||
so a program can emulate the
|
||||
Python main loop. */
|
||||
_PyErr_NormalizeException(tstate, &exc, &val, &tb);
|
||||
if (tb != NULL)
|
||||
PyException_SetTraceback(val, tb);
|
||||
else
|
||||
PyException_SetTraceback(val, Py_None);
|
||||
Py_XDECREF(tb);
|
||||
Py_XDECREF(exc);
|
||||
PUSH(val);
|
||||
JUMPTO(handler);
|
||||
/* Resume normal execution */
|
||||
DISPATCH();
|
||||
}
|
||||
_PyErr_Fetch(tstate, &exc, &val, &tb);
|
||||
/* Make the raw exception data
|
||||
available to the handler,
|
||||
so a program can emulate the
|
||||
Python main loop. */
|
||||
_PyErr_NormalizeException(tstate, &exc, &val, &tb);
|
||||
if (tb != NULL)
|
||||
PyException_SetTraceback(val, tb);
|
||||
else
|
||||
PyException_SetTraceback(val, Py_None);
|
||||
Py_XDECREF(tb);
|
||||
Py_XDECREF(exc);
|
||||
PUSH(val);
|
||||
JUMPTO(handler);
|
||||
/* Resume normal execution */
|
||||
frame->f_state = FRAME_EXECUTING;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
exit_unwind:
|
||||
|
@ -6180,6 +6180,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
|
|||
localsarray[i] = NULL;
|
||||
}
|
||||
if (initialize_locals(tstate, func, localsarray, args, argcount, kwnames)) {
|
||||
assert(frame->owner != FRAME_OWNED_BY_GENERATOR);
|
||||
_PyFrame_Clear(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -6203,7 +6204,8 @@ static void
|
|||
_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
|
||||
{
|
||||
tstate->recursion_remaining--;
|
||||
assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0);
|
||||
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
|
||||
assert(frame->owner == FRAME_OWNED_BY_THREAD);
|
||||
_PyFrame_Clear(frame);
|
||||
tstate->recursion_remaining++;
|
||||
_PyThreadState_PopFrame(tstate, frame);
|
||||
|
@ -6681,6 +6683,8 @@ call_trace(Py_tracefunc func, PyObject *obj,
|
|||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int old_what = tstate->tracing_what;
|
||||
tstate->tracing_what = what;
|
||||
PyThreadState_EnterTracing(tstate);
|
||||
assert (frame->f_lasti >= 0);
|
||||
initialize_trace_info(&tstate->trace_info, frame);
|
||||
|
@ -6688,6 +6692,7 @@ call_trace(Py_tracefunc func, PyObject *obj,
|
|||
result = func(obj, f, what, arg);
|
||||
f->f_lineno = 0;
|
||||
PyThreadState_LeaveTracing(tstate);
|
||||
tstate->tracing_what = old_what;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue