]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-138325: steal list items in `INTRINSIC_LIST_TO_TUPLE` opcode (#149960)
authorPieter Eendebak <pieter.eendebak@gmail.com>
Mon, 18 May 2026 06:37:12 +0000 (08:37 +0200)
committerGitHub <noreply@github.com>
Mon, 18 May 2026 06:37:12 +0000 (12:07 +0530)
Misc/NEWS.d/next/Core_and_Builtins/2026-05-17-12-00-00.gh-issue-138325.h2XSfe.rst [new file with mode: 0644]
Python/intrinsics.c

diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-17-12-00-00.gh-issue-138325.h2XSfe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-17-12-00-00.gh-issue-138325.h2XSfe.rst
new file mode 100644 (file)
index 0000000..0eb528c
--- /dev/null
@@ -0,0 +1,3 @@
+Speed up converting a list to a tuple in the ``tuple(genexpr)`` fast path
+and in starred tuple displays (e.g. ``(*a, *b)``) by stealing the list's
+items into the tuple instead of copying them.
index 9cfc285c6a5925963ffd9f808d1b40d6ac9c3d56..9f994950f2721db7312ec39d4b6dd3b6e5a4a526 100644 (file)
@@ -7,6 +7,8 @@
 #include "pycore_genobject.h"     // _PyAsyncGenValueWrapperNew
 #include "pycore_interpframe.h"   // _PyFrame_GetLocals()
 #include "pycore_intrinsics.h"    // INTRINSIC_PRINT
+#include "pycore_list.h"          // _PyList_AsTupleAndClear()
+#include "pycore_object.h"        // _PyObject_IsUniquelyReferenced()
 #include "pycore_pyerrors.h"      // _PyErr_SetString()
 #include "pycore_runtime.h"       // _Py_ID()
 #include "pycore_typevarobject.h" // _Py_make_typevar()
@@ -190,8 +192,12 @@ unary_pos(PyThreadState* unused, PyObject *value)
 static PyObject *
 list_to_tuple(PyThreadState* unused, PyObject *v)
 {
-    assert(PyList_Check(v));
-    return PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));
+    /* INTRINSIC_LIST_TO_TUPLE is only emitted by the compiler for a
+       freshly-built, uniquely-referenced temporary list, so steal its items
+       into the tuple instead of copying them. */
+    assert(PyList_CheckExact(v));
+    assert(_PyObject_IsUniquelyReferenced(v));
+    return _PyList_AsTupleAndClear((PyListObject *)v);
 }
 
 static PyObject *