]> granicus.if.org Git - python/commitdiff
bpo-35582: Inline arguments tuple unpacking in handwritten code. (GH-11524)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 12 Jan 2019 06:25:41 +0000 (08:25 +0200)
committerGitHub <noreply@github.com>
Sat, 12 Jan 2019 06:25:41 +0000 (08:25 +0200)
Inline PyArg_UnpackTuple() and _PyArg_UnpackStack() in performance
sensitive code in the builtins and operator modules.

Modules/_operator.c
Python/bltinmodule.c

index d6c6a18d81b449c7538b735cde9aaba9cf002daa..d291ec1f920ed175c09f511a28a990ec86f2c672 100644 (file)
@@ -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;
index e19bc5604ba10932b5f7687849827ab9668bb54e..332142fc6ffc2ac37810eb9ce37e6b0f85d9d555 100644 (file)
@@ -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},