diff options
author | Mark Shannon <mark@hotpy.org> | 2022-03-22 12:57:19 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-22 12:57:19 (GMT) |
commit | 49daf6dba8178c5ae5d4d65408b20566d39c36a8 (patch) | |
tree | 4cb58165463cc7fd136337716f3af631c563a908 /Python | |
parent | 88872a29f19092d2fde27365af230abd6d301941 (diff) | |
download | cpython-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.c | 189 | ||||
-rw-r--r-- | Python/frame.c | 11 |
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; |