summaryrefslogtreecommitdiffstats
path: root/Objects/listobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r--Objects/listobject.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index fa26444..e85fa5c 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -76,6 +76,33 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
return 0;
}
+static int
+list_preallocate_exact(PyListObject *self, Py_ssize_t size)
+{
+ assert(self->ob_item == NULL);
+
+ PyObject **items;
+ size_t allocated;
+
+ allocated = (size_t)size;
+ if (allocated > (size_t)PY_SSIZE_T_MAX / sizeof(PyObject *)) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ if (size == 0) {
+ allocated = 0;
+ }
+ items = (PyObject **)PyMem_New(PyObject*, allocated);
+ if (items == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ self->ob_item = items;
+ self->allocated = allocated;
+ return 0;
+}
+
/* Debug statistic to compare allocations with reuse through the free list */
#undef SHOW_ALLOC_COUNT
#ifdef SHOW_ALLOC_COUNT
@@ -2683,6 +2710,19 @@ list___init___impl(PyListObject *self, PyObject *iterable)
(void)_list_clear(self);
}
if (iterable != NULL) {
+ if (_PyObject_HasLen(iterable)) {
+ Py_ssize_t iter_len = PyObject_Size(iterable);
+ if (iter_len == -1) {
+ if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
+ return -1;
+ }
+ PyErr_Clear();
+ }
+ if (iter_len > 0 && self->ob_item == NULL
+ && list_preallocate_exact(self, iter_len)) {
+ return -1;
+ }
+ }
PyObject *rv = list_extend(self, iterable);
if (rv == NULL)
return -1;