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
--- /dev/null
+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`.
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
// 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);
}
}
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();
}