diff options
author | Shantanu <12621235+hauntsaninja@users.noreply.github.com> | 2024-04-30 20:16:52 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-30 20:16:52 (GMT) |
commit | 6999d68d2878871493d85dc63599f3d44eada104 (patch) | |
tree | c62c4bb1f44bd899cad35103599a012b62bd9204 /Modules | |
parent | b568c2c1ff5c0b1922a6402dc95c588d7f9aa914 (diff) | |
download | cpython-6999d68d2878871493d85dc63599f3d44eada104.zip cpython-6999d68d2878871493d85dc63599f3d44eada104.tar.gz cpython-6999d68d2878871493d85dc63599f3d44eada104.tar.bz2 |
gh-118218: Reuse return tuple in itertools.pairwise (GH-118219)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/itertoolsmodule.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 6ee447e..21ce3ec 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -270,6 +270,7 @@ typedef struct { PyObject_HEAD PyObject *it; PyObject *old; + PyObject *result; } pairwiseobject; /*[clinic input] @@ -301,6 +302,11 @@ pairwise_new_impl(PyTypeObject *type, PyObject *iterable) } po->it = it; po->old = NULL; + po->result = PyTuple_Pack(2, Py_None, Py_None); + if (po->result == NULL) { + Py_DECREF(po); + return NULL; + } return (PyObject *)po; } @@ -311,6 +317,7 @@ pairwise_dealloc(pairwiseobject *po) PyObject_GC_UnTrack(po); Py_XDECREF(po->it); Py_XDECREF(po->old); + Py_XDECREF(po->result); tp->tp_free(po); Py_DECREF(tp); } @@ -321,6 +328,7 @@ pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg) Py_VISIT(Py_TYPE(po)); Py_VISIT(po->it); Py_VISIT(po->old); + Py_VISIT(po->result); return 0; } @@ -355,8 +363,30 @@ pairwise_next(pairwiseobject *po) Py_DECREF(old); return NULL; } - /* Future optimization: Reuse the result tuple as we do in enumerate() */ - result = PyTuple_Pack(2, old, new); + + result = po->result; + if (Py_REFCNT(result) == 1) { + Py_INCREF(result); + PyObject *last_old = PyTuple_GET_ITEM(result, 0); + PyObject *last_new = PyTuple_GET_ITEM(result, 1); + PyTuple_SET_ITEM(result, 0, Py_NewRef(old)); + PyTuple_SET_ITEM(result, 1, Py_NewRef(new)); + Py_DECREF(last_old); + Py_DECREF(last_new); + // bpo-42536: The GC may have untracked this result tuple. Since we're + // recycling it, make sure it's tracked again: + if (!_PyObject_GC_IS_TRACKED(result)) { + _PyObject_GC_TRACK(result); + } + } + else { + result = PyTuple_New(2); + if (result != NULL) { + PyTuple_SET_ITEM(result, 0, Py_NewRef(old)); + PyTuple_SET_ITEM(result, 1, Py_NewRef(new)); + } + } + Py_XSETREF(po->old, new); Py_DECREF(old); return result; |