Commit 1dd04a02 authored by Armin Rigo's avatar Armin Rigo

This is a reorganization of list_ass_slice(). It should probably be reviewed,

though I tried to be very careful.  This is a slight simplification, and it
adds a new feature: a small stack-allocated "recycled" array for the cases
when we don't remove too many items.

It allows PyList_SetSlice() to never fail if:
* you are sure that the object is a list; and
* you either do not remove more than 8 items, or clear the list.

This makes a number of other places in the source code correct again -- there
are some places that delete a single item without checking for MemoryErrors
raised by PyList_SetSlice(), or that clear the whole list, and sometimes the
context doesn't allow an error to be propagated.
parent a37bbf2e
...@@ -517,6 +517,7 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -517,6 +517,7 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
we temporarily copy the items that are deleted from the we temporarily copy the items that are deleted from the
list. :-( */ list. :-( */
PyObject **recycle, **p; PyObject **recycle, **p;
PyObject *recycled[8];
PyObject **item; PyObject **item;
PyObject **vitem = NULL; PyObject **vitem = NULL;
PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */ PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */
...@@ -559,8 +560,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -559,8 +560,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
return list_clear(a); return list_clear(a);
} }
item = a->ob_item; item = a->ob_item;
if (ihigh > ilow) { /* recycle the ihigh-ilow items that we are about to remove */
p = recycle = PyMem_NEW(PyObject *, (ihigh-ilow)); s = (ihigh - ilow)*sizeof(PyObject *);
if (s > sizeof(recycled)) {
recycle = (PyObject **)PyMem_MALLOC(s);
if (recycle == NULL) { if (recycle == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
Py_XDECREF(v_as_SF); Py_XDECREF(v_as_SF);
...@@ -568,41 +571,36 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -568,41 +571,36 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
} }
} }
else else
p = recycle = NULL; recycle = recycled;
if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */ p = recycle + (ihigh - ilow);
memcpy(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *)); memcpy(recycle, &item[ilow], s);
p += ihigh - ilow; if (d < 0) { /* Delete -d items */
if (d < 0) {
memmove(&item[ihigh+d], &item[ihigh], memmove(&item[ihigh+d], &item[ihigh],
(a->ob_size - ihigh)*sizeof(PyObject *)); (a->ob_size - ihigh)*sizeof(PyObject *));
list_resize(a, a->ob_size + d); list_resize(a, a->ob_size + d);
item = a->ob_item; item = a->ob_item;
} }
} else if (d > 0) { /* Insert d items */
else { /* Insert d items; recycle ihigh-ilow items */
s = a->ob_size; s = a->ob_size;
if (list_resize(a, s+d) == -1) { if (list_resize(a, s+d) == -1) {
if (recycle != NULL) if (recycle != recycled)
PyMem_DEL(recycle); PyMem_FREE(recycle);
Py_XDECREF(v_as_SF); Py_XDECREF(v_as_SF);
return -1; return -1;
} }
item = a->ob_item; item = a->ob_item;
memmove(&item[ihigh+d], &item[ihigh], memmove(&item[ihigh+d], &item[ihigh],
(s - ihigh)*sizeof(PyObject *)); (s - ihigh)*sizeof(PyObject *));
memcpy(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *));
p += ihigh - ilow;
} }
for (k = 0; k < n; k++, ilow++) { for (k = 0; k < n; k++, ilow++) {
PyObject *w = vitem[k]; PyObject *w = vitem[k];
Py_XINCREF(w); Py_XINCREF(w);
item[ilow] = w; item[ilow] = w;
} }
if (recycle) {
while (--p >= recycle) while (--p >= recycle)
Py_XDECREF(*p); Py_XDECREF(*p);
PyMem_DEL(recycle); if (recycle != recycled)
} PyMem_FREE(recycle);
Py_XDECREF(v_as_SF); Py_XDECREF(v_as_SF);
return 0; return 0;
#undef b #undef b
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment