From 6ee879ffa1cbea78b0a0c4eff7e532fd6a2959ac Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 18 May 2026 08:37:12 +0200 Subject: [PATCH] gh-138325: steal list items in `INTRINSIC_LIST_TO_TUPLE` opcode (#149960) --- .../2026-05-17-12-00-00.gh-issue-138325.h2XSfe.rst | 3 +++ Python/intrinsics.c | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-05-17-12-00-00.gh-issue-138325.h2XSfe.rst 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 index 000000000000..0eb528c68d8d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-17-12-00-00.gh-issue-138325.h2XSfe.rst @@ -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. diff --git a/Python/intrinsics.c b/Python/intrinsics.c index 9cfc285c6a59..9f994950f272 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -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 * -- 2.47.3