Simplify _PyTuple_Resize by not using the tuple free list and dropping

support for the last_is_sticky flag.  A few hard to find bugs may be
fixed by this patch since the old code was buggy.
This commit is contained in:
Neil Schemenauer 2000-10-05 19:36:49 +00:00
parent 98dc065c1b
commit 08b53e6a2a
1 changed files with 24 additions and 86 deletions

View File

@ -424,11 +424,10 @@ PyTypeObject PyTuple_Type = {
/* The following function breaks the notion that tuples are immutable: /* The following function breaks the notion that tuples are immutable:
it changes the size of a tuple. We get away with this only if there it changes the size of a tuple. We get away with this only if there
is only one module referencing the object. You can also think of it is only one module referencing the object. You can also think of it
as creating a new tuple object and destroying the old one, only as creating a new tuple object and destroying the old one, only more
more efficiently. In any case, don't use this if the tuple may efficiently. In any case, don't use this if the tuple may already be
already be known to some other part of the code... known to some other part of the code. The last_is_sticky is not used
If last_is_sticky is set, the tuple will grow or shrink at the and must always be false. */
front, otherwise it will grow or shrink at the end. */
int int
_PyTuple_Resize(PyObject **pv, int newsize, int last_is_sticky) _PyTuple_Resize(PyObject **pv, int newsize, int last_is_sticky)
@ -439,106 +438,45 @@ _PyTuple_Resize(PyObject **pv, int newsize, int last_is_sticky)
int sizediff; int sizediff;
v = (PyTupleObject *) *pv; v = (PyTupleObject *) *pv;
if (v == NULL || !PyTuple_Check(v) || v->ob_refcnt != 1) { if (v == NULL || !PyTuple_Check(v) || v->ob_refcnt != 1 ||
last_is_sticky) {
*pv = 0; *pv = 0;
Py_DECREF(v); Py_XDECREF(v);
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return -1; return -1;
} }
sizediff = newsize - v->ob_size; sizediff = newsize - v->ob_size;
if (sizediff == 0) if (sizediff == 0)
return 0; return 0;
/* XXX UNREF/NEWREF interface should be more symmetrical */ /* XXX UNREF/NEWREF interface should be more symmetrical */
#ifdef Py_REF_DEBUG #ifdef Py_REF_DEBUG
--_Py_RefTotal; --_Py_RefTotal;
#endif #endif
_Py_ForgetReference((PyObject *)v); _Py_ForgetReference((PyObject *) v);
if (last_is_sticky && sizediff < 0) {
/* shrinking:
move entries to the front and zero moved entries */
for (i = 0; i < newsize; i++) {
Py_XDECREF(v->ob_item[i]);
v->ob_item[i] = v->ob_item[i - sizediff];
v->ob_item[i - sizediff] = NULL;
}
}
for (i = newsize; i < v->ob_size; i++) { for (i = newsize; i < v->ob_size; i++) {
Py_XDECREF(v->ob_item[i]); Py_XDECREF(v->ob_item[i]);
v->ob_item[i] = NULL; v->ob_item[i] = NULL;
} }
#if MAXSAVESIZE > 0 PyObject_GC_Fini(v);
if (newsize == 0 && free_tuples[0]) { v = (PyTupleObject *) PyObject_AS_GC(v);
num_free_tuples[0]--; sv = (PyTupleObject *) PyObject_REALLOC((char *)v,
sv = free_tuples[0]; sizeof(PyTupleObject)
sv->ob_size = 0; + PyGC_HEAD_SIZE
Py_INCREF(sv); + newsize * sizeof(PyObject *));
#ifdef COUNT_ALLOCS if (sv == NULL) {
tuple_zero_allocs++; *pv = NULL;
#endif PyObject_DEL(v);
tupledealloc(v); PyErr_NoMemory();
*pv = (PyObject*) sv; return -1;
return 0;
} }
if (0 < newsize && newsize < MAXSAVESIZE && sv = (PyTupleObject *) PyObject_FROM_GC(sv);
(sv = free_tuples[newsize]) != NULL) _Py_NewReference((PyObject *) sv);
{
free_tuples[newsize] = (PyTupleObject *) sv->ob_item[0];
num_free_tuples[newsize]--;
#ifdef COUNT_ALLOCS
fast_tuple_allocs++;
#endif
#ifdef Py_TRACE_REFS
sv->ob_type = &PyTuple_Type;
#endif
for (i = 0; i < newsize; ++i){
sv->ob_item[i] = v->ob_item[i];
v->ob_item[i] = NULL;
}
sv->ob_size = v->ob_size;
tupledealloc(v);
*pv = (PyObject *) sv;
} else
#endif
{
#ifdef WITH_CYCLE_GC
PyGC_Head *g = PyObject_AS_GC((PyObject *)v);
PyObject_GC_Fini((PyObject *)v);
g = (PyGC_Head *)
PyObject_REALLOC((char *)g, sizeof(PyTupleObject)
+ PyGC_HEAD_SIZE
+ newsize * sizeof(PyObject *));
if (g == NULL) {
sv = NULL;
} else {
sv = (PyTupleObject *)PyObject_FROM_GC(g);
}
#else
sv = (PyTupleObject *)
PyObject_REALLOC((char *)v, sizeof(PyTupleObject)
+ PyGC_HEAD_SIZE
+ newsize * sizeof(PyObject *));
#endif
*pv = (PyObject *) sv;
if (sv == NULL) {
PyObject_GC_Init((PyObject *)v);
v = (PyTupleObject *) PyObject_AS_GC(v);
PyObject_DEL(v);
PyErr_NoMemory();
return -1;
}
}
_Py_NewReference((PyObject *)sv);
for (i = sv->ob_size; i < newsize; i++) for (i = sv->ob_size; i < newsize; i++)
sv->ob_item[i] = NULL; sv->ob_item[i] = NULL;
if (last_is_sticky && sizediff > 0) {
/* growing: move entries to the end and zero moved entries */
for (i = newsize - 1; i >= sizediff; i--) {
sv->ob_item[i] = sv->ob_item[i - sizediff];
sv->ob_item[i - sizediff] = NULL;
}
}
PyObject_GC_Init(sv);
sv->ob_size = newsize; sv->ob_size = newsize;
*pv = (PyObject *) sv;
PyObject_GC_Init(sv);
return 0; return 0;
} }