From 793426687509be24a42663a27e568cc92dcc07f6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 12 Jan 2019 08:25:41 +0200 Subject: [PATCH] bpo-35582: Inline arguments tuple unpacking in handwritten code. (GH-11524) Inline PyArg_UnpackTuple() and _PyArg_UnpackStack() in performance sensitive code in the builtins and operator modules. --- Modules/_operator.c | 21 ++++++++++----------- Python/bltinmodule.c | 31 ++++++++++++++++++------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Modules/_operator.c b/Modules/_operator.c index d6c6a18d81b..d291ec1f920 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -1011,15 +1011,12 @@ itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw) Py_ssize_t i, nitems=ig->nitems; assert(PyTuple_CheckExact(args)); - if (kw == NULL && PyTuple_GET_SIZE(args) == 1) { - obj = PyTuple_GET_ITEM(args, 0); - } - else { - if (!_PyArg_NoKeywords("itemgetter", kw)) - return NULL; - if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj)) - return NULL; - } + if (!_PyArg_NoKeywords("itemgetter", kw)) + return NULL; + if (!_PyArg_CheckPositional("itemgetter", PyTuple_GET_SIZE(args), 1, 1)) + return NULL; + + obj = PyTuple_GET_ITEM(args, 0); if (nitems == 1) { if (ig->index >= 0 && PyTuple_CheckExact(obj) @@ -1317,8 +1314,9 @@ attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw) if (!_PyArg_NoKeywords("attrgetter", kw)) return NULL; - if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj)) + if (!_PyArg_CheckPositional("attrgetter", PyTuple_GET_SIZE(args), 1, 1)) return NULL; + obj = PyTuple_GET_ITEM(args, 0); if (ag->nattrs == 1) /* ag->attr is always a tuple */ return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0)); @@ -1561,8 +1559,9 @@ methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw) if (!_PyArg_NoKeywords("methodcaller", kw)) return NULL; - if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj)) + if (!_PyArg_CheckPositional("methodcaller", PyTuple_GET_SIZE(args), 1, 1)) return NULL; + obj = PyTuple_GET_ITEM(args, 0); method = PyObject_GetAttr(obj, mc->name); if (method == NULL) return NULL; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index e19bc5604ba..332142fc6ff 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1067,19 +1067,21 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals, static PyObject * builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - PyObject *v, *result, *dflt = NULL; - PyObject *name; + PyObject *v, *name, *result; - if (!_PyArg_UnpackStack(args, nargs, "getattr", 2, 3, &v, &name, &dflt)) + if (!_PyArg_CheckPositional("getattr", nargs, 2, 3)) return NULL; + v = args[0]; + name = args[1]; if (!PyUnicode_Check(name)) { PyErr_SetString(PyExc_TypeError, "getattr(): attribute name must be string"); return NULL; } - if (dflt != NULL) { + if (nargs > 2) { if (_PyObject_LookupAttr(v, name, &result) == 0) { + PyObject *dflt = args[2]; Py_INCREF(dflt); return dflt; } @@ -1372,11 +1374,11 @@ static PyObject * builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *it, *res; - PyObject *def = NULL; - if (!_PyArg_UnpackStack(args, nargs, "next", 1, 2, &it, &def)) + if (!_PyArg_CheckPositional("next", nargs, 1, 2)) return NULL; + it = args[0]; if (!PyIter_Check(it)) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not an iterator", @@ -1387,7 +1389,8 @@ builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs) res = (*it->ob_type->tp_iternext)(it); if (res != NULL) { return res; - } else if (def != NULL) { + } else if (nargs > 1) { + PyObject *def = args[1]; if (PyErr_Occurred()) { if(!PyErr_ExceptionMatches(PyExc_StopIteration)) return NULL; @@ -1503,20 +1506,22 @@ builtin_hex(PyObject *module, PyObject *number) /* AC: cannot convert yet, as needs PEP 457 group support in inspect */ static PyObject * -builtin_iter(PyObject *self, PyObject *args) +builtin_iter(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - PyObject *v, *w = NULL; + PyObject *v; - if (!PyArg_UnpackTuple(args, "iter", 1, 2, &v, &w)) + if (!_PyArg_CheckPositional("iter", nargs, 1, 2)) return NULL; - if (w == NULL) + v = args[0]; + if (nargs == 1) return PyObject_GetIter(v); if (!PyCallable_Check(v)) { PyErr_SetString(PyExc_TypeError, "iter(v, w): v must be callable"); return NULL; } - return PyCallIter_New(v, w); + PyObject *sentinel = args[1]; + return PyCallIter_New(v, sentinel); } PyDoc_STRVAR(iter_doc, @@ -2718,7 +2723,7 @@ static PyMethodDef builtin_methods[] = { BUILTIN_INPUT_METHODDEF BUILTIN_ISINSTANCE_METHODDEF BUILTIN_ISSUBCLASS_METHODDEF - {"iter", builtin_iter, METH_VARARGS, iter_doc}, + {"iter", (PyCFunction)(void(*)(void))builtin_iter, METH_FASTCALL, iter_doc}, BUILTIN_LEN_METHODDEF BUILTIN_LOCALS_METHODDEF {"max", (PyCFunction)(void(*)(void))builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},