diff options
author | Pieter Eendebak <pieter.eendebak@gmail.com> | 2022-07-26 04:10:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-25 22:10:23 -0400 |
commit | 2ef73be891eb95064e268341e38e81d008add480 (patch) | |
tree | 895e2343dbbfc3c155d08301cf540deebd1bb259 /Objects/tupleobject.c | |
parent | 27055d766ab0ee5ddcfbd1fb51fb47419af1ddba (diff) | |
download | cpython-2ef73be891eb95064e268341e38e81d008add480.tar.gz cpython-2ef73be891eb95064e268341e38e81d008add480.zip |
gh-91247: Use memcpy for list and tuple repeat (#91482)
* Add _Py_memory_repeat function to pycore_list
* Add _Py_RefcntAdd function to pycore_object
* Use the new functions in tuplerepeat, list_repeat, and list_inplace_repeat
Diffstat (limited to 'Objects/tupleobject.c')
-rw-r--r-- | Objects/tupleobject.c | 41 |
1 files changed, 18 insertions, 23 deletions
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index dfb8597b876..240af0a9075 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -495,9 +495,8 @@ tupleconcat(PyTupleObject *a, PyObject *bb) static PyObject * tuplerepeat(PyTupleObject *a, Py_ssize_t n) { - Py_ssize_t size; - PyTupleObject *np; - if (Py_SIZE(a) == 0 || n == 1) { + const Py_ssize_t input_size = Py_SIZE(a); + if (input_size == 0 || n == 1) { if (PyTuple_CheckExact(a)) { /* Since tuples are immutable, we can return a shared copy in this case */ @@ -505,42 +504,38 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) return (PyObject *)a; } } - if (Py_SIZE(a) == 0 || n <= 0) { + if (input_size == 0 || n <= 0) { return tuple_get_empty(); } - if (n > PY_SSIZE_T_MAX / Py_SIZE(a)) + assert(n>0); + + if (input_size > PY_SSIZE_T_MAX / n) return PyErr_NoMemory(); - size = Py_SIZE(a) * n; - np = tuple_alloc(size); + Py_ssize_t output_size = input_size * n; + + PyTupleObject *np = tuple_alloc(output_size); if (np == NULL) return NULL; + PyObject **dest = np->ob_item; - PyObject **dest_end = dest + size; - if (Py_SIZE(a) == 1) { + if (input_size == 1) { PyObject *elem = a->ob_item[0]; - Py_SET_REFCNT(elem, Py_REFCNT(elem) + n); -#ifdef Py_REF_DEBUG - _Py_RefTotal += n; -#endif + _Py_RefcntAdd(elem, n); + PyObject **dest_end = dest + output_size; while (dest < dest_end) { *dest++ = elem; } } else { PyObject **src = a->ob_item; - PyObject **src_end = src + Py_SIZE(a); + PyObject **src_end = src + input_size; while (src < src_end) { - Py_SET_REFCNT(*src, Py_REFCNT(*src) + n); -#ifdef Py_REF_DEBUG - _Py_RefTotal += n; -#endif - *dest++ = *src++; - } - // Now src chases after dest in the same buffer - src = np->ob_item; - while (dest < dest_end) { + _Py_RefcntAdd(*src, n); *dest++ = *src++; } + + _Py_memory_repeat((char *)np->ob_item, sizeof(PyObject *)*output_size, + sizeof(PyObject *)*input_size); } _PyObject_GC_TRACK(np); return (PyObject *) np; |