diff options
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r-- | Objects/listobject.c | 40 |
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; |