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 /Objects/genobject.c | |
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 'Objects/genobject.c')
-rw-r--r-- | Objects/genobject.c | 98 |
1 files changed, 47 insertions, 51 deletions
diff --git a/Objects/genobject.c b/Objects/genobject.c index 3ad8dc1..f071390 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -35,9 +35,10 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) Py_VISIT(gen->gi_code); Py_VISIT(gen->gi_name); Py_VISIT(gen->gi_qualname); - if (gen->gi_frame_valid) { + if (gen->gi_frame_state < FRAME_CLEARED) { _PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe); - assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); + assert(frame->frame_obj == NULL || + frame->frame_obj->f_frame->owner == FRAME_OWNED_BY_GENERATOR); int err = _PyFrame_Traverse(frame, visit, arg); if (err) { return err; @@ -55,7 +56,7 @@ _PyGen_Finalize(PyObject *self) PyObject *res = NULL; PyObject *error_type, *error_value, *error_traceback; - if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted((_PyInterpreterFrame *)gen->gi_iframe)) { + if (gen->gi_frame_state >= FRAME_COMPLETED) { /* Generator isn't paused, so no need to close */ return; } @@ -87,7 +88,7 @@ _PyGen_Finalize(PyObject *self) issue a RuntimeWarning. */ if (gen->gi_code != NULL && ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE && - ((_PyInterpreterFrame *)gen->gi_iframe)->f_state == FRAME_CREATED) + gen->gi_frame_state == FRAME_CREATED) { _PyErr_WarnUnawaitedCoroutine((PyObject *)gen); } @@ -130,10 +131,9 @@ gen_dealloc(PyGenObject *gen) and GC_Del. */ Py_CLEAR(((PyAsyncGenObject*)gen)->ag_origin_or_finalizer); } - if (gen->gi_frame_valid) { + if (gen->gi_frame_state < FRAME_CLEARED) { _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - gen->gi_frame_valid = 0; - frame->is_generator = false; + gen->gi_frame_state = FRAME_CLEARED; frame->previous = NULL; _PyFrame_Clear(frame); } @@ -156,7 +156,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyObject *result; *presult = NULL; - if (frame->f_state == FRAME_CREATED && arg && arg != Py_None) { + if (gen->gi_frame_state == FRAME_CREATED && arg && arg != Py_None) { const char *msg = "can't send non-None value to a " "just-started generator"; if (PyCoro_CheckExact(gen)) { @@ -169,7 +169,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyErr_SetString(PyExc_TypeError, msg); return PYGEN_ERROR; } - if (gen->gi_frame_valid && _PyFrame_IsExecuting(frame)) { + if (gen->gi_frame_state == FRAME_EXECUTING) { const char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) { msg = "coroutine already executing"; @@ -180,7 +180,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyErr_SetString(PyExc_ValueError, msg); return PYGEN_ERROR; } - if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(frame)) { + if (gen->gi_frame_state >= FRAME_COMPLETED) { if (PyCoro_CheckExact(gen) && !closing) { /* `gen` is an exhausted coroutine: raise an error, except when called from gen_close(), which should @@ -199,8 +199,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, return PYGEN_ERROR; } - assert(gen->gi_frame_valid); - assert(_PyFrame_IsRunnable(frame)); + assert(gen->gi_frame_state < FRAME_EXECUTING); /* Push arg onto the frame's value stack */ result = arg ? arg : Py_None; Py_INCREF(result); @@ -216,7 +215,11 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, _PyErr_ChainStackItem(NULL); } + gen->gi_frame_state = FRAME_EXECUTING; result = _PyEval_EvalFrame(tstate, frame, exc); + if (gen->gi_frame_state == FRAME_EXECUTING) { + gen->gi_frame_state = FRAME_COMPLETED; + } tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; @@ -229,7 +232,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, /* If the generator just returned (as opposed to yielding), signal * that the generator is exhausted. */ if (result) { - if (!_PyFrameHasCompleted(frame)) { + if (gen->gi_frame_state == FRAME_SUSPENDED) { *presult = result; return PYGEN_NEXT; } @@ -265,8 +268,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, /* first clean reference cycle through stored exception traceback */ _PyErr_ClearExcState(&gen->gi_exc_state); - frame->is_generator = false; - gen->gi_frame_valid = 0; + gen->gi_frame_state = FRAME_CLEARED; _PyFrame_Clear(frame); *presult = result; return result ? PYGEN_RETURN : PYGEN_ERROR; @@ -347,7 +349,7 @@ _PyGen_yf(PyGenObject *gen) { PyObject *yf = NULL; - if (gen->gi_frame_valid) { + if (gen->gi_frame_state < FRAME_CLEARED) { _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; if (frame->f_lasti < 1) { @@ -378,11 +380,10 @@ gen_close(PyGenObject *gen, PyObject *args) int err = 0; if (yf) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = gen->gi_frame_state; + gen->gi_frame_state = FRAME_EXECUTING; err = gen_close_iter(yf); - frame->f_state = state; + gen->gi_frame_state = state; Py_DECREF(yf); } if (err == 0) @@ -429,10 +430,10 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, We have to allow some awaits to work it through, hence the `close_on_genexit` parameter here. */ - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = gen->gi_frame_state; + gen->gi_frame_state = FRAME_EXECUTING; err = gen_close_iter(yf); - frame->f_state = state; + gen->gi_frame_state = state; Py_DECREF(yf); if (err < 0) return gen_send_ex(gen, Py_None, 1, 0); @@ -451,11 +452,11 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, tstate->cframe->current_frame = frame; /* Close the generator that we are currently iterating with 'yield from' or awaiting on with 'await'. */ - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = gen->gi_frame_state; + gen->gi_frame_state = FRAME_EXECUTING; ret = _gen_throw((PyGenObject *)yf, close_on_genexit, typ, val, tb); - frame->f_state = state; + gen->gi_frame_state = state; tstate->cframe->current_frame = prev; frame->previous = NULL; } else { @@ -469,17 +470,17 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, Py_DECREF(yf); goto throw_here; } - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = gen->gi_frame_state; + gen->gi_frame_state = FRAME_EXECUTING; ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL); - frame->f_state = state; + gen->gi_frame_state = state; Py_DECREF(meth); } Py_DECREF(yf); if (!ret) { PyObject *val; /* Pop subiterator from stack */ - assert(gen->gi_frame_valid); + assert(gen->gi_frame_state < FRAME_CLEARED); ret = _PyFrame_StackPop((_PyInterpreterFrame *)gen->gi_iframe); assert(ret == yf); Py_DECREF(ret); @@ -756,19 +757,16 @@ gen_getyieldfrom(PyGenObject *gen, void *Py_UNUSED(ignored)) static PyObject * gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored)) { - if (gen->gi_frame_valid == 0) { - Py_RETURN_FALSE; + if (gen->gi_frame_state == FRAME_EXECUTING) { + Py_RETURN_TRUE; } - return PyBool_FromLong(_PyFrame_IsExecuting((_PyInterpreterFrame *)gen->gi_iframe)); + Py_RETURN_FALSE; } static PyObject * gen_getsuspended(PyGenObject *gen, void *Py_UNUSED(ignored)) { - if (gen->gi_frame_valid == 0) { - Py_RETURN_FALSE; - } - return PyBool_FromLong(((_PyInterpreterFrame *)gen->gi_iframe)->f_state == FRAME_SUSPENDED); + return PyBool_FromLong(gen->gi_frame_state == FRAME_SUSPENDED); } static PyObject * @@ -777,7 +775,7 @@ _gen_getframe(PyGenObject *gen, const char *const name) if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) { return NULL; } - if (gen->gi_frame_valid == 0) { + if (gen->gi_frame_state == FRAME_CLEARED) { Py_RETURN_NONE; } return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_PyInterpreterFrame *)gen->gi_iframe)); @@ -899,7 +897,7 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) if (gen == NULL) { return NULL; } - gen->gi_frame_valid = 0; + gen->gi_frame_state = FRAME_CLEARED; gen->gi_code = (PyCodeObject *)func->func_code; Py_INCREF(gen->gi_code); gen->gi_weakreflist = NULL; @@ -972,14 +970,13 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, } /* Copy the frame */ assert(f->f_frame->frame_obj == NULL); - assert(f->f_owns_frame); + assert(f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT); _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; _PyFrame_Copy((_PyInterpreterFrame *)f->_f_frame_data, frame); - gen->gi_frame_valid = 1; + gen->gi_frame_state = FRAME_CREATED; assert(frame->frame_obj == f); - f->f_owns_frame = 0; f->f_frame = frame; - frame->is_generator = true; + frame->owner = FRAME_OWNED_BY_GENERATOR; assert(PyObject_GC_IsTracked((PyObject *)f)); gen->gi_code = PyFrame_GetCode(f); Py_INCREF(gen->gi_code); @@ -1114,19 +1111,19 @@ coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored)) static PyObject * cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored)) { - if (coro->cr_frame_valid == 0) { - Py_RETURN_FALSE; + if (coro->cr_frame_state == FRAME_SUSPENDED) { + Py_RETURN_TRUE; } - return PyBool_FromLong(((_PyInterpreterFrame *)coro->cr_iframe)->f_state == FRAME_SUSPENDED); + Py_RETURN_FALSE; } static PyObject * cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored)) { - if (coro->cr_frame_valid == 0) { - Py_RETURN_FALSE; + if (coro->cr_frame_state == FRAME_EXECUTING) { + Py_RETURN_TRUE; } - return PyBool_FromLong(_PyFrame_IsExecuting((_PyInterpreterFrame *)coro->cr_iframe)); + Py_RETURN_FALSE; } static PyObject * @@ -2063,7 +2060,6 @@ static PyObject * async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) { PyGenObject *gen = (PyGenObject*)o->agt_gen; - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; PyObject *retval; if (o->agt_state == AWAITABLE_STATE_CLOSED) { @@ -2073,7 +2069,7 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) return NULL; } - if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(frame)) { + if (gen->gi_frame_state >= FRAME_COMPLETED) { o->agt_state = AWAITABLE_STATE_CLOSED; PyErr_SetNone(PyExc_StopIteration); return NULL; |