(original) (raw)

changeset: 102878:1b241e761f8f user: Victor Stinner victor.stinner@gmail.com date: Wed Aug 24 01:45:13 2016 +0200 files: Python/bltinmodule.c description: 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. diff -r 401f59a7020b -r 1b241e761f8f Python/bltinmodule.c --- a/Python/bltinmodule.c Wed Aug 24 01:14:54 2016 +0200 +++ b/Python/bltinmodule.c Wed Aug 24 01:45:13 2016 +0200 @@ -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 ; iiters, 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(stack[0])); + 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; }/victor.stinner@gmail.com