[Python-checkins] cpython: Issue #27809: map_next() uses fast call

victor.stinner python-checkins at python.org
Tue Aug 23 18:09:09 EDT 2016


https://hg.python.org/cpython/rev/70f88b097f60
changeset:   102873:70f88b097f60
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Aug 23 17:56:06 2016 +0200
summary:
  Issue #27809: map_next() uses fast call

Use a small stack allocated in the C stack for up to 5 iterator functions,
otherwise allocates a stack on the heap memory.

files:
  Python/bltinmodule.c |  50 +++++++++++++++++++++----------
  1 files changed, 33 insertions(+), 17 deletions(-)


diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1156,27 +1156,43 @@
 static PyObject *
 map_next(mapobject *lz)
 {
-    PyObject *val;
-    PyObject *argtuple;
-    PyObject *result;
-    Py_ssize_t numargs, i;
+    PyObject *small_stack[5];
+    PyObject **stack;
+    Py_ssize_t niters, nargs, i;
+    PyObject *result = NULL;
 
-    numargs = PyTuple_GET_SIZE(lz->iters);
-    argtuple = PyTuple_New(numargs);
-    if (argtuple == NULL)
-        return NULL;
-
-    for (i=0 ; i<numargs ; i++) {
-        PyObject *it = PyTuple_GET_ITEM(lz->iters, i);
-        val = Py_TYPE(it)->tp_iternext(it);
-        if (val == NULL) {
-            Py_DECREF(argtuple);
+    niters = PyTuple_GET_SIZE(lz->iters);
+    if (niters <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
+        stack = small_stack;
+    }
+    else {
+        stack = PyMem_Malloc(niters * sizeof(PyObject*));
+        if (stack == NULL) {
+            PyErr_NoMemory();
             return NULL;
         }
-        PyTuple_SET_ITEM(argtuple, i, val);
     }
-    result = PyObject_Call(lz->func, argtuple, NULL);
-    Py_DECREF(argtuple);
+
+    nargs = 0;
+    for (i=0; i < niters; i++) {
+        PyObject *it = PyTuple_GET_ITEM(lz->iters, i);
+        PyObject *val = Py_TYPE(it)->tp_iternext(it);
+        if (val == NULL) {
+            goto exit;
+        }
+        stack[i] = val;
+        nargs++;
+    }
+
+    result = _PyObject_FastCall(lz->func, stack, nargs);
+
+exit:
+    for (i=0; i < nargs; i++) {
+        Py_DECREF(stack[i]);
+    }
+    if (stack != small_stack) {
+        PyMem_Free(stack);
+    }
     return result;
 }
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list