summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_list.h2
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2022-12-09-13-18-42.gh-issue-100146.xLVKg0.rst4
-rw-r--r--Objects/listobject.c21
-rw-r--r--Python/bytecodes.c7
-rw-r--r--Python/generated_cases.c.h7
5 files changed, 31 insertions, 10 deletions
diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h
index 628267c..2fcbe12 100644
--- a/Include/internal/pycore_list.h
+++ b/Include/internal/pycore_list.h
@@ -75,6 +75,8 @@ typedef struct {
PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
} _PyListIterObject;
+extern PyObject *_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t n);
+
#ifdef __cplusplus
}
#endif
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-12-09-13-18-42.gh-issue-100146.xLVKg0.rst b/Misc/NEWS.d/next/Core and Builtins/2022-12-09-13-18-42.gh-issue-100146.xLVKg0.rst
new file mode 100644
index 0000000..8023a36
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-12-09-13-18-42.gh-issue-100146.xLVKg0.rst
@@ -0,0 +1,4 @@
+Improve ``BUILD_LIST`` opcode so that it works similarly to the
+``BUILD_TUPLE`` opcode, by stealing references from the stack rather than
+repeatedly using stack operations to set list elements. Implementation
+details are in a new private API :c:func:`_PyList_FromArraySteal`.
diff --git a/Objects/listobject.c b/Objects/listobject.c
index b093f88..6629775 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2565,6 +2565,27 @@ PyList_AsTuple(PyObject *v)
return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));
}
+PyObject *
+_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t n)
+{
+ if (n == 0) {
+ return PyList_New(0);
+ }
+
+ PyListObject *list = (PyListObject *)PyList_New(n);
+ if (list == NULL) {
+ for (Py_ssize_t i = 0; i < n; i++) {
+ Py_DECREF(src[i]);
+ }
+ return NULL;
+ }
+
+ PyObject **dst = list->ob_item;
+ memcpy(dst, src, n * sizeof(PyObject *));
+
+ return (PyObject *)list;
+}
+
/*[clinic input]
list.index
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index e1c73ab..839fac3 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1390,13 +1390,10 @@ dummy_func(
// stack effect: (__array[oparg] -- __0)
inst(BUILD_LIST) {
- PyObject *list = PyList_New(oparg);
+ STACK_SHRINK(oparg);
+ PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
if (list == NULL)
goto error;
- while (--oparg >= 0) {
- PyObject *item = POP();
- PyList_SET_ITEM(list, oparg, item);
- }
PUSH(list);
}
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 1179bdf..ed89e90 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -1608,13 +1608,10 @@
}
TARGET(BUILD_LIST) {
- PyObject *list = PyList_New(oparg);
+ STACK_SHRINK(oparg);
+ PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
if (list == NULL)
goto error;
- while (--oparg >= 0) {
- PyObject *item = POP();
- PyList_SET_ITEM(list, oparg, item);
- }
PUSH(list);
DISPATCH();
}