mirror of https://github.com/python/cpython
gh-100146: Steal references from stack when building a list (#100147)
When executing the BUILD_LIST opcode, steal the references from the stack, in a manner similar to the BUILD_TUPLE opcode. Implement this by offloading the logic to a new private API, _PyList_FromArraySteal(), that works similarly to _PyTuple_FromArraySteal(). This way, instead of performing multiple stack pointer adjustments while the list is being initialized, the stack is adjusted only once and a fast memory copy operation is performed in one fell swoop.
This commit is contained in:
parent
b3722ca058
commit
e6d4440782
|
@ -75,6 +75,8 @@ typedef struct {
|
||||||
PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
|
PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
|
||||||
} _PyListIterObject;
|
} _PyListIterObject;
|
||||||
|
|
||||||
|
extern PyObject *_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t n);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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`.
|
|
@ -2565,6 +2565,27 @@ PyList_AsTuple(PyObject *v)
|
||||||
return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(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]
|
/*[clinic input]
|
||||||
list.index
|
list.index
|
||||||
|
|
||||||
|
|
|
@ -1390,13 +1390,10 @@ dummy_func(
|
||||||
|
|
||||||
// stack effect: (__array[oparg] -- __0)
|
// stack effect: (__array[oparg] -- __0)
|
||||||
inst(BUILD_LIST) {
|
inst(BUILD_LIST) {
|
||||||
PyObject *list = PyList_New(oparg);
|
STACK_SHRINK(oparg);
|
||||||
|
PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
|
||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
while (--oparg >= 0) {
|
|
||||||
PyObject *item = POP();
|
|
||||||
PyList_SET_ITEM(list, oparg, item);
|
|
||||||
}
|
|
||||||
PUSH(list);
|
PUSH(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1608,13 +1608,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(BUILD_LIST) {
|
TARGET(BUILD_LIST) {
|
||||||
PyObject *list = PyList_New(oparg);
|
STACK_SHRINK(oparg);
|
||||||
|
PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
|
||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
while (--oparg >= 0) {
|
|
||||||
PyObject *item = POP();
|
|
||||||
PyList_SET_ITEM(list, oparg, item);
|
|
||||||
}
|
|
||||||
PUSH(list);
|
PUSH(list);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue