diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-08-10-50-42.bpo-46944.cnaIK3.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-08-10-50-42.bpo-46944.cnaIK3.rst new file mode 100644 index 00000000000..f940ebbbd1f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-08-10-50-42.bpo-46944.cnaIK3.rst @@ -0,0 +1 @@ +Speed up throwing exception in generator with :const:`METH_FASTCALL` calling convention. Patch by Kumar Aditya. diff --git a/Objects/genobject.c b/Objects/genobject.c index bfa1ea5c45f..4fac0ce241c 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -561,16 +561,23 @@ failed_throw: static PyObject * -gen_throw(PyGenObject *gen, PyObject *args) +gen_throw(PyGenObject *gen, PyObject *const *args, Py_ssize_t nargs) { PyObject *typ; PyObject *tb = NULL; PyObject *val = NULL; - if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) { + if (!_PyArg_CheckPositional("throw", nargs, 1, 3)) { return NULL; } - + typ = args[0]; + if (nargs == 3) { + val = args[1]; + tb = args[2]; + } + else if (nargs == 2) { + val = args[1]; + } return _gen_throw(gen, 1, typ, val, tb); } @@ -813,7 +820,7 @@ PyDoc_STRVAR(sizeof__doc__, static PyMethodDef gen_methods[] = { {"send",(PyCFunction)gen_send, METH_O, send_doc}, - {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc}, + {"throw",(PyCFunction)(void(*)(void))gen_throw, METH_FASTCALL, throw_doc}, {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc}, {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {NULL, NULL} /* Sentinel */ @@ -1159,7 +1166,7 @@ PyDoc_STRVAR(coro_close_doc, static PyMethodDef coro_methods[] = { {"send",(PyCFunction)gen_send, METH_O, coro_send_doc}, - {"throw",(PyCFunction)gen_throw, METH_VARARGS, coro_throw_doc}, + {"throw",(PyCFunction)(void(*)(void))gen_throw, METH_FASTCALL, coro_throw_doc}, {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc}, {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {NULL, NULL} /* Sentinel */ @@ -1246,9 +1253,9 @@ coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg) } static PyObject * -coro_wrapper_throw(PyCoroWrapper *cw, PyObject *args) +coro_wrapper_throw(PyCoroWrapper *cw, PyObject *const *args, Py_ssize_t nargs) { - return gen_throw((PyGenObject *)cw->cw_coroutine, args); + return gen_throw((PyGenObject *)cw->cw_coroutine, args, nargs); } static PyObject * @@ -1266,7 +1273,8 @@ coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg) static PyMethodDef coro_wrapper_methods[] = { {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc}, - {"throw",(PyCFunction)coro_wrapper_throw, METH_VARARGS, coro_throw_doc}, + {"throw",(PyCFunction)(void(*)(void))coro_wrapper_throw, + METH_FASTCALL, coro_throw_doc}, {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc}, {NULL, NULL} /* Sentinel */ }; @@ -1789,7 +1797,7 @@ async_gen_asend_iternext(PyAsyncGenASend *o) static PyObject * -async_gen_asend_throw(PyAsyncGenASend *o, PyObject *args) +async_gen_asend_throw(PyAsyncGenASend *o, PyObject *const *args, Py_ssize_t nargs) { PyObject *result; @@ -1800,7 +1808,7 @@ async_gen_asend_throw(PyAsyncGenASend *o, PyObject *args) return NULL; } - result = gen_throw((PyGenObject*)o->ags_gen, args); + result = gen_throw((PyGenObject*)o->ags_gen, args, nargs); result = async_gen_unwrap_value(o->ags_gen, result); if (result == NULL) { @@ -1821,7 +1829,7 @@ async_gen_asend_close(PyAsyncGenASend *o, PyObject *args) static PyMethodDef async_gen_asend_methods[] = { {"send", (PyCFunction)async_gen_asend_send, METH_O, send_doc}, - {"throw", (PyCFunction)async_gen_asend_throw, METH_VARARGS, throw_doc}, + {"throw", (PyCFunction)(void(*)(void))async_gen_asend_throw, METH_FASTCALL, throw_doc}, {"close", (PyCFunction)async_gen_asend_close, METH_NOARGS, close_doc}, {NULL, NULL} /* Sentinel */ }; @@ -2183,7 +2191,7 @@ check_error: static PyObject * -async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args) +async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t nargs) { PyObject *retval; @@ -2194,7 +2202,7 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args) return NULL; } - retval = gen_throw((PyGenObject*)o->agt_gen, args); + retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs); if (o->agt_args) { return async_gen_unwrap_value(o->agt_gen, retval); } else { @@ -2239,7 +2247,8 @@ async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args) static PyMethodDef async_gen_athrow_methods[] = { {"send", (PyCFunction)async_gen_athrow_send, METH_O, send_doc}, - {"throw", (PyCFunction)async_gen_athrow_throw, METH_VARARGS, throw_doc}, + {"throw", (PyCFunction)(void(*)(void))async_gen_athrow_throw, + METH_FASTCALL, throw_doc}, {"close", (PyCFunction)async_gen_athrow_close, METH_NOARGS, close_doc}, {NULL, NULL} /* Sentinel */ };