diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-08-23 17:56:06 +0200 |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-08-23 17:56:06 +0200 |
commit | 518c04ccd4d3b1d2b85d8ba7e62534cac0a2bbb7 (patch) | |
tree | e1cf927b82b54e402d0c968b5e0cd30496817cad /Python/bltinmodule.c | |
parent | 16eb9944497ad751f8cb55c8e6f56607fe1b07d7 (diff) | |
download | cpython-518c04ccd4d3b1d2b85d8ba7e62534cac0a2bbb7.tar.gz |
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.
Diffstat (limited to 'Python/bltinmodule.c')
-rw-r--r-- | Python/bltinmodule.c | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 00a85b5741..a77dfe84c1 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1156,27 +1156,43 @@ map_traverse(mapobject *lz, visitproc visit, void *arg) 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; + 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; + } + } - for (i=0 ; i<numargs ; i++) { + nargs = 0; + for (i=0; i < niters; i++) { PyObject *it = PyTuple_GET_ITEM(lz->iters, i); - val = Py_TYPE(it)->tp_iternext(it); + PyObject *val = Py_TYPE(it)->tp_iternext(it); if (val == NULL) { - Py_DECREF(argtuple); - return NULL; + goto exit; } - PyTuple_SET_ITEM(argtuple, i, val); + 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); } - result = PyObject_Call(lz->func, argtuple, NULL); - Py_DECREF(argtuple); return result; } |