diff options
author | Mark Shannon <mark@hotpy.org> | 2022-11-07 14:49:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-07 14:49:51 (GMT) |
commit | 4a1c58d504a49eeb9be7beef3ca861a9d6b28ede (patch) | |
tree | 8c5245a6a3a19a311d0d5a31723da1225a2c6795 /Python/ceval.c | |
parent | 80c08d1cd67afdd1336c65ba23a044b6ac490f33 (diff) | |
download | cpython-4a1c58d504a49eeb9be7beef3ca861a9d6b28ede.zip cpython-4a1c58d504a49eeb9be7beef3ca861a9d6b28ede.tar.gz cpython-4a1c58d504a49eeb9be7beef3ca861a9d6b28ede.tar.bz2 |
GH-96793: Specialize FOR_ITER for generators. (GH-98772)
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 85011af..46fad97 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1360,6 +1360,11 @@ exit_unwind: assert(_PyErr_Occurred(tstate)); _Py_LeaveRecursiveCallPy(tstate); if (frame->is_entry) { + if (frame->owner == FRAME_OWNED_BY_GENERATOR) { + PyGenObject *gen = _PyFrame_GetGenerator(frame); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + } /* Restore previous cframe and exit */ tstate->cframe = cframe.previous; tstate->cframe->use_tracing = cframe.use_tracing; @@ -1930,20 +1935,48 @@ fail: } static void -_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame) +clear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame) { + assert(frame->owner == FRAME_OWNED_BY_THREAD); // Make sure that this is, indeed, the top frame. We can't check this in // _PyThreadState_PopFrame, since f_code is already cleared at that point: assert((PyObject **)frame + frame->f_code->co_framesize == - tstate->datastack_top); + tstate->datastack_top); tstate->c_recursion_remaining--; assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame); - assert(frame->owner == FRAME_OWNED_BY_THREAD); _PyFrame_Clear(frame); tstate->c_recursion_remaining++; _PyThreadState_PopFrame(tstate, frame); } +static void +clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame) +{ + assert(frame->owner == FRAME_OWNED_BY_GENERATOR); + PyGenObject *gen = _PyFrame_GetGenerator(frame); + gen->gi_frame_state = FRAME_CLEARED; + assert(tstate->exc_info == &gen->gi_exc_state); + tstate->exc_info = gen->gi_exc_state.previous_item; + gen->gi_exc_state.previous_item = NULL; + tstate->c_recursion_remaining--; + assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame); + _PyFrame_Clear(frame); + tstate->c_recursion_remaining++; + frame->previous = NULL; +} + +static void +_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame) +{ + if (frame->owner == FRAME_OWNED_BY_THREAD) { + clear_thread_frame(tstate, frame); + } + else { + clear_gen_frame(tstate, frame); + } +} + + PyObject * _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, |