diff -r 8545624309f5 Objects/listobject.c --- a/Objects/listobject.c Wed Feb 25 20:48:01 2015 -0800 +++ b/Objects/listobject.c Thu Feb 26 12:40:08 2015 +0200 @@ -1956,6 +1956,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]; @@ -1966,16 +1967,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 8545624309f5 Python/bltinmodule.c --- a/Python/bltinmodule.c Wed Feb 25 20:48:01 2015 -0800 +++ b/Python/bltinmodule.c Thu Feb 26 12:40:08 2015 +0200 @@ -479,6 +479,7 @@ typedef struct { PyObject_HEAD PyObject *func; PyObject *it; + PyObject *argtuple; /* cached args tuple */ } filterobject; static PyObject * @@ -508,6 +509,7 @@ filter_new(PyTypeObject *type, PyObject Py_INCREF(func); lz->func = func; lz->it = it; + lz->argtuple = NULL; return (PyObject *)lz; } @@ -518,6 +520,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); } @@ -547,8 +551,35 @@ filter_next(filterobject *lz) ok = PyObject_IsTrue(item); } else { PyObject *good; - good = PyObject_CallFunctionObjArgs(lz->func, - item, NULL); + 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; @@ -1418,6 +1449,7 @@ typedef struct { PyObject_HEAD PyObject *iters; PyObject *func; + PyObject *argtuple; /* cached args tuple */ } mapobject; static PyObject * @@ -1461,6 +1493,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; } @@ -1471,6 +1504,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); } @@ -1487,23 +1522,47 @@ map_next(mapobject *lz) { PyObject *val; PyObject *argtuple; - PyObject *result; + PyObject *result = NULL; Py_ssize_t numargs, i; + argtuple = lz->argtuple; + lz->argtuple = NULL; numargs = PyTuple_Size(lz->iters); - argtuple = PyTuple_New(numargs); - if (argtuple == NULL) - return NULL; + 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)); 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; }