diff -r 68b2a43d8653 Objects/listobject.c --- a/Objects/listobject.c Fri Apr 22 16:26:23 2016 +0200 +++ b/Objects/listobject.c Fri Apr 22 18:21:57 2016 +0200 @@ -1950,6 +1950,7 @@ listsort(PyListObject *self, PyObject *a lo.values = NULL; } else { + PyObject *argtuple = NULL; if (saved_ob_size < MERGESTATE_TEMP_SIZE/2) /* Leverage stack space we allocated but won't otherwise use */ keys = &ms.temparray[saved_ob_size+1]; @@ -1962,16 +1963,41 @@ listsort(PyListObject *self, PyObject *a } for (i = 0; i < saved_ob_size ; i++) { - keys[i] = PyObject_CallFunctionObjArgs(keyfunc, saved_ob_item[i], - NULL); + if (argtuple == NULL) { + argtuple = PyTuple_New(1); + if (argtuple == NULL) { + goto cleanup; + } + Py_INCREF(argtuple); + } + assert(Py_REFCNT(argtuple) == 2); + assert(Py_SIZE(argtuple) == 1); + assert(PyTuple_GET_ITEM(argtuple, 0) == NULL); + Py_INCREF(saved_ob_item[i]); + PyTuple_SET_ITEM(argtuple, 0, saved_ob_item[i]); + keys[i] = PyObject_Call(keyfunc, argtuple, NULL); + if (Py_REFCNT(argtuple) == 2) { + PyTuple_SET_ITEM(argtuple, 0, NULL); + Py_DECREF(saved_ob_item[i]); + } + else { + Py_DECREF(argtuple); + Py_DECREF(argtuple); + argtuple = NULL; + } if (keys[i] == NULL) { +cleanup: for (i=i-1 ; i>=0 ; i--) Py_DECREF(keys[i]); if (saved_ob_size >= MERGESTATE_TEMP_SIZE/2) PyMem_FREE(keys); + Py_XDECREF(argtuple); + Py_XDECREF(argtuple); goto keyfunc_fail; } } + Py_XDECREF(argtuple); + Py_XDECREF(argtuple); lo.keys = keys; lo.values = saved_ob_item; diff -r 68b2a43d8653 Python/bltinmodule.c --- a/Python/bltinmodule.c Fri Apr 22 16:26:23 2016 +0200 +++ b/Python/bltinmodule.c Fri Apr 22 18:21:57 2016 +0200 @@ -412,6 +412,7 @@ typedef struct { PyObject_HEAD PyObject *func; PyObject *it; + PyObject *argtuple; /* cached args tuple */ } filterobject; static PyObject * @@ -441,6 +442,7 @@ filter_new(PyTypeObject *type, PyObject Py_INCREF(func); lz->func = func; lz->it = it; + lz->argtuple = NULL; return (PyObject *)lz; } @@ -451,6 +453,8 @@ filter_dealloc(filterobject *lz) PyObject_GC_UnTrack(lz); Py_XDECREF(lz->func); Py_XDECREF(lz->it); + Py_XDECREF(lz->argtuple); + Py_XDECREF(lz->argtuple); Py_TYPE(lz)->tp_free(lz); } @@ -480,9 +484,37 @@ filter_next(filterobject *lz) if (checktrue) { ok = PyObject_IsTrue(item); } else { - PyObject *good; - good = PyObject_CallFunctionObjArgs(lz->func, item, NULL); - if (good == NULL) { + PyObject *good; + PyObject *argtuple = lz->argtuple; + lz->argtuple = NULL; + if (argtuple == NULL) { + argtuple = PyTuple_New(1); + if (argtuple == NULL) { + Py_DECREF(item); + return NULL; + } + Py_INCREF(argtuple); + } + assert(Py_REFCNT(argtuple) == 2); + assert(Py_SIZE(argtuple) == 1); + assert(PyTuple_GET_ITEM(argtuple, 0) == NULL); + PyTuple_SET_ITEM(argtuple, 0, item); + good = PyObject_Call(lz->func, argtuple, NULL); + if (Py_REFCNT(argtuple) == 2) { + PyTuple_SET_ITEM(argtuple, 0, NULL); + if (lz->argtuple == NULL) + lz->argtuple = argtuple; + else { + Py_DECREF(argtuple); + Py_DECREF(argtuple); + } + } + else { + Py_INCREF(item); + Py_DECREF(argtuple); + Py_DECREF(argtuple); + } + if (good == NULL) { Py_DECREF(item); return NULL; } @@ -1102,6 +1134,7 @@ typedef struct { PyObject_HEAD PyObject *iters; PyObject *func; + PyObject *argtuple; /* cached args tuple */ } mapobject; static PyObject * @@ -1145,6 +1178,7 @@ map_new(PyTypeObject *type, PyObject *ar func = PyTuple_GET_ITEM(args, 0); Py_INCREF(func); lz->func = func; + lz->argtuple = NULL; return (PyObject *)lz; } @@ -1155,6 +1189,8 @@ map_dealloc(mapobject *lz) PyObject_GC_UnTrack(lz); Py_XDECREF(lz->iters); Py_XDECREF(lz->func); + Py_XDECREF(lz->argtuple); + Py_XDECREF(lz->argtuple); Py_TYPE(lz)->tp_free(lz); } @@ -1171,24 +1207,47 @@ map_next(mapobject *lz) { PyObject *val; PyObject *argtuple; - PyObject *result; + PyObject *result = NULL; Py_ssize_t numargs, i; - numargs = PyTuple_GET_SIZE(lz->iters); - argtuple = PyTuple_New(numargs); - if (argtuple == NULL) - return NULL; + argtuple = lz->argtuple; + lz->argtuple = NULL; + numargs = PyTuple_Size(lz->iters); + if (argtuple == NULL) { + argtuple = PyTuple_New(numargs); + if (argtuple == NULL) + return NULL; + Py_INCREF(argtuple); + } + assert(Py_REFCNT(argtuple) == 2); + assert(Py_SIZE(argtuple) == numargs); +#ifndef NDEBUG + for (i = 0; i < numargs; i++) + assert(PyTuple_GET_ITEM(argtuple, i) == NULL); +#endif for (i=0 ; iiters, i); - val = Py_TYPE(it)->tp_iternext(it); + val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i)); if (val == NULL) { - Py_DECREF(argtuple); - return NULL; + numargs = i; + goto cleanup; } PyTuple_SET_ITEM(argtuple, i, val); } result = PyObject_Call(lz->func, argtuple, NULL); +cleanup: + if (Py_REFCNT(argtuple) == 2) { + for (i = 0; i < numargs; i++) { + val = PyTuple_GET_ITEM(argtuple, i); + PyTuple_SET_ITEM(argtuple, i, NULL); + Py_DECREF(val); + } + if (lz->argtuple == NULL) { + lz->argtuple = argtuple; + return result; + } + } + Py_DECREF(argtuple); Py_DECREF(argtuple); return result; }