From 028ddff5b6962e0d298ea69aa706c9e5fe404ebb Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 25 Jan 2023 11:10:08 +0000 Subject: [PATCH 1/2] Add news item. --- .../2023-01-25-11-09-56.gh-issue-100762.VuArrB.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-25-11-09-56.gh-issue-100762.VuArrB.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-25-11-09-56.gh-issue-100762.VuArrB.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-25-11-09-56.gh-issue-100762.VuArrB.rst new file mode 100644 index 00000000000000..043b65d1f74a78 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-25-11-09-56.gh-issue-100762.VuArrB.rst @@ -0,0 +1,2 @@ +Avoid expensive ``gen.throw()`` call when closing generators (and +coroutines) that can be closed trivially. From f67b210bdf5bd386326922bc1cff6c5c83daeb72 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 25 Jan 2023 11:13:18 +0000 Subject: [PATCH 2/2] Don't call gen.throw() from gen.close() unless necessary. --- Objects/genobject.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Objects/genobject.c b/Objects/genobject.c index b9a0c30c411a00..c964d3924e84a8 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -376,6 +376,13 @@ static PyObject * gen_close(PyGenObject *gen, PyObject *args) { PyObject *retval; + if (gen->gi_frame_state == FRAME_CREATED) { + gen->gi_frame_state = FRAME_COMPLETED; + Py_RETURN_NONE; + } + if (gen->gi_frame_state >= FRAME_COMPLETED) { + Py_RETURN_NONE; + } PyObject *yf = _PyGen_yf(gen); int err = 0; @@ -386,6 +393,11 @@ gen_close(PyGenObject *gen, PyObject *args) gen->gi_frame_state = state; Py_DECREF(yf); } + _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; + assert(PyBytes_CheckExact(frame->f_code->co_exceptiontable)); + if (err == 0 && PyBytes_GET_SIZE(frame->f_code->co_exceptiontable) == 0) { + Py_RETURN_NONE; + } if (err == 0) PyErr_SetNone(PyExc_GeneratorExit); retval = gen_send_ex(gen, Py_None, 1, 1);