summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2004-07-30 11:38:22 (GMT)
committerArmin Rigo <arigo@tunes.org>2004-07-30 11:38:22 (GMT)
commit1dd04a02e03e1765d9f2096d979de92927337dcb (patch)
tree5bbc0038acb57ed18f360cd01b482c1c3ac685f6
parenta37bbf2e5bf9d0854a774cdd1a972d0b7cc9e733 (diff)
downloadcpython-1dd04a02e03e1765d9f2096d979de92927337dcb.zip
cpython-1dd04a02e03e1765d9f2096d979de92927337dcb.tar.gz
cpython-1dd04a02e03e1765d9f2096d979de92927337dcb.tar.bz2
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.
-rw-r--r--Objects/listobject.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index bd5b95a..2adc4f4 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -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
list. :-( */
PyObject **recycle, **p;
+ PyObject *recycled[8];
PyObject **item;
PyObject **vitem = NULL;
PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */
@@ -559,8 +560,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
return list_clear(a);
}
item = a->ob_item;
- if (ihigh > ilow) {
- p = recycle = PyMem_NEW(PyObject *, (ihigh-ilow));
+ /* recycle the ihigh-ilow items that we are about to remove */
+ s = (ihigh - ilow)*sizeof(PyObject *);
+ if (s > sizeof(recycled)) {
+ recycle = (PyObject **)PyMem_MALLOC(s);
if (recycle == NULL) {
PyErr_NoMemory();
Py_XDECREF(v_as_SF);
@@ -568,41 +571,36 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
}
}
else
- p = recycle = NULL;
- if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */
- memcpy(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *));
- p += ihigh - ilow;
- if (d < 0) {
- memmove(&item[ihigh+d], &item[ihigh],
- (a->ob_size - ihigh)*sizeof(PyObject *));
- list_resize(a, a->ob_size + d);
- item = a->ob_item;
- }
+ recycle = recycled;
+ p = recycle + (ihigh - ilow);
+ memcpy(recycle, &item[ilow], s);
+ if (d < 0) { /* Delete -d items */
+ memmove(&item[ihigh+d], &item[ihigh],
+ (a->ob_size - ihigh)*sizeof(PyObject *));
+ list_resize(a, a->ob_size + d);
+ item = a->ob_item;
}
- else { /* Insert d items; recycle ihigh-ilow items */
+ else if (d > 0) { /* Insert d items */
s = a->ob_size;
if (list_resize(a, s+d) == -1) {
- if (recycle != NULL)
- PyMem_DEL(recycle);
+ if (recycle != recycled)
+ PyMem_FREE(recycle);
Py_XDECREF(v_as_SF);
return -1;
}
item = a->ob_item;
memmove(&item[ihigh+d], &item[ihigh],
(s - ihigh)*sizeof(PyObject *));
- memcpy(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *));
- p += ihigh - ilow;
}
for (k = 0; k < n; k++, ilow++) {
PyObject *w = vitem[k];
Py_XINCREF(w);
item[ilow] = w;
}
- if (recycle) {
- while (--p >= recycle)
- Py_XDECREF(*p);
- PyMem_DEL(recycle);
- }
+ while (--p >= recycle)
+ Py_XDECREF(*p);
+ if (recycle != recycled)
+ PyMem_FREE(recycle);
Py_XDECREF(v_as_SF);
return 0;
#undef b