From ce997c2e27230bfea19921b5b34d9495e61c57e3 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Wed, 26 Aug 2026 19:22:10 +0500 Subject: [PATCH 1/4] Untrack tuples from _PyTuple_Concat and _PyTuple_Repeat - both used in flowgraph optimizations --- Objects/tupleobject.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index bb5e18cb790acf0..bac836457422dfa 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -593,7 +593,10 @@ _PyTuple_Concat(PyObject *aa, PyObject *bb) dest[i] = Py_NewRef(v); } - _PyObject_GC_TRACK(np); + if (_PyObject_GC_IS_TRACKED(aa) || _PyObject_GC_IS_TRACKED(bb)) + { + _PyObject_GC_TRACK(np); + } return (PyObject *)np; } @@ -642,7 +645,10 @@ _PyTuple_Repeat(PyObject *self, Py_ssize_t n) _Py_memory_repeat((char *)np->ob_item, sizeof(PyObject *)*output_size, sizeof(PyObject *)*input_size); } - _PyObject_GC_TRACK(np); + if (_PyObject_GC_IS_TRACKED(self)) + { + _PyObject_GC_TRACK(np); + } return (PyObject *) np; } From 5064e616b1b58a6a4ae3b58c7469158b0d267923 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Wed, 26 Aug 2026 19:23:28 +0500 Subject: [PATCH 2/4] Untrack from flowgraph optimizer --- Python/flowgraph.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Python/flowgraph.c b/Python/flowgraph.c index a5138d1a1fa2846..be56dd0bce14f6e 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -12,6 +12,7 @@ #include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_stackref.h" // PyStackRef_AsPyObjectBorrow() +#include "pycore_tuple.h" // _PyTuple_MaybeUntrack() #include @@ -1563,6 +1564,7 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, } PyTuple_SET_ITEM(const_tuple, i, element); } + _PyTuple_MaybeUntrack(const_tuple); nop_out(const_instrs, seq_size); return instr_make_load_const(instr, const_tuple, consts, const_cache, consts_index); @@ -1650,6 +1652,7 @@ fold_constant_seq_into_load_const(basicblock *bb, int i, } nop_out(&instr, 1); } + _PyTuple_MaybeUntrack(newconst); assert(consts_found == 0); if (build_op == BUILD_SET) { @@ -1737,6 +1740,7 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop, } PyTuple_SET_ITEM(const_result, i, element); } + _PyTuple_MaybeUntrack(const_result); if (instr->i_opcode == BUILD_SET) { PyObject *frozenset = PyFrozenSet_New(const_result); From cbf8feddcc59e6bc7e436305029d4e925eb24576 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Wed, 26 Aug 2026 19:23:41 +0500 Subject: [PATCH 3/4] Add tests --- Lib/test/test_tuple.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_tuple.py b/Lib/test/test_tuple.py index e533392b8cae94a..6564fa04f1bcbe2 100644 --- a/Lib/test/test_tuple.py +++ b/Lib/test/test_tuple.py @@ -319,10 +319,15 @@ def test_track_literals(self): self._not_tracked_instantly((1,)) self._not_tracked_instantly((1, 2)) self._not_tracked_instantly((1, 2, "a")) - self._not_tracked_instantly((1, 2) * 5) self._not_tracked_instantly((12, 10**10, 'a_' * 100)) self._not_tracked_instantly((object(),)) + # Test for _PyTuple_Concat + self._not_tracked_instantly((1, 2) + (2, 3)) + + # Test for _PyTuple_Repeat + self._not_tracked_instantly((1, 2) * 5) + self._not_tracked(((1, x), y, (2, 3))) self._not_tracked((1, 2, (None, True, False, ()), int)) self._not_tracked((object(), ())) From fee31fe55740e000871109f78e66c46638c1ca5f Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Wed, 26 Aug 2026 19:29:03 +0500 Subject: [PATCH 4/4] Add news --- .../2026-08-26-19-28-49.gh-issue-155728.LJIPeZ.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-08-26-19-28-49.gh-issue-155728.LJIPeZ.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-26-19-28-49.gh-issue-155728.LJIPeZ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-26-19-28-49.gh-issue-155728.LJIPeZ.rst new file mode 100644 index 000000000000000..5ef398285f6f37d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-26-19-28-49.gh-issue-155728.LJIPeZ.rst @@ -0,0 +1,2 @@ +The flowgraph optimizer now untracks tuples from the GC when possible. Patch +by Sergey Miryanov.