summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-03-22 12:57:19 (GMT)
committerGitHub <noreply@github.com>2022-03-22 12:57:19 (GMT)
commit49daf6dba8178c5ae5d4d65408b20566d39c36a8 (patch)
tree4cb58165463cc7fd136337716f3af631c563a908 /Python
parent88872a29f19092d2fde27365af230abd6d301941 (diff)
downloadcpython-49daf6dba8178c5ae5d4d65408b20566d39c36a8.zip
cpython-49daf6dba8178c5ae5d4d65408b20566d39c36a8.tar.gz
cpython-49daf6dba8178c5ae5d4d65408b20566d39c36a8.tar.bz2
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.
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c189
-rw-r--r--Python/frame.c11
2 files changed, 104 insertions, 96 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 7c6bfd4..73179c8 100644
--- a/Python/ceval.c
+++ b/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));
-
- /* 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);
- frame->f_state = FRAME_RAISED;
- TRACE_FUNCTION_UNWIND();
- DTRACE_FUNCTION_EXIT();
- goto exit_unwind;
- }
+ {
+ /* 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);
+ }
+ assert(STACK_LEVEL() == 0);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ 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;
}
diff --git a/Python/frame.c b/Python/frame.c
index 20b4f81..3396ed8 100644
--- a/Python/frame.c
+++ b/Python/frame.c
@@ -37,7 +37,8 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
Py_XDECREF(error_traceback);
}
else {
- f->f_owns_frame = 0;
+ assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
+ assert(frame->owner != FRAME_CLEARED);
f->f_frame = frame;
frame->frame_obj = f;
PyErr_Restore(error_type, error_value, error_traceback);
@@ -57,12 +58,13 @@ _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
static void
take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
{
- assert(f->f_owns_frame == 0);
+ assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
+ assert(frame->owner != FRAME_CLEARED);
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
frame = (_PyInterpreterFrame *)f->_f_frame_data;
- f->f_owns_frame = 1;
f->f_frame = frame;
+ frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;
assert(f->f_back == NULL);
if (frame->previous != NULL) {
/* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */
@@ -88,7 +90,8 @@ _PyFrame_Clear(_PyInterpreterFrame *frame)
{
/* It is the responsibility of the owning generator/coroutine
* to have cleared the enclosing generator, if any. */
- assert(!frame->is_generator);
+ assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||
+ _PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED);
if (frame->frame_obj) {
PyFrameObject *f = frame->frame_obj;
frame->frame_obj = NULL;