summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-08-23 23:45:13 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-08-23 23:45:13 (GMT)
commitcdb5cee9804a1cdc491c18118a92c4592218a894 (patch)
tree48e6e9355b37ab1f0defb8b5ff38d7d3ba33b77f /Python
parentdd69564c38de21f2ede269c55fce6db24bb27941 (diff)
downloadcpython-cdb5cee9804a1cdc491c18118a92c4592218a894.zip
cpython-cdb5cee9804a1cdc491c18118a92c4592218a894.tar.gz
cpython-cdb5cee9804a1cdc491c18118a92c4592218a894.tar.bz2
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')
-rw-r--r--Python/bltinmodule.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 00a85b5..121cbb7 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(stack[0]));
+ 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;
}