Commit 2c84fa99 authored by Sjoerd Mullender's avatar Sjoerd Mullender

Fixed bugs in resizetuple and extended the interface.

Added ifdefs in stringobject.c for shared strings of length 1.
Renamed free_list in tupleobject.c to free_tuples.
parent a8aa7453
......@@ -58,7 +58,7 @@ extern int gettuplesize PROTO((object *));
extern object *gettupleitem PROTO((object *, int));
extern int settupleitem PROTO((object *, int, object *));
extern object *gettupleslice PROTO((object *, int, int));
extern int resizetuple PROTO((object **, int));
extern int resizetuple PROTO((object **, int, int));
/* Macro, trading safety for speed */
#define GETTUPLEITEM(op, i) ((op)->ob_item[i])
......
......@@ -39,7 +39,9 @@ int null_strings, one_strings;
#endif
static stringobject *characters[UCHAR_MAX + 1];
#ifndef DONT_SHARE_SHORT_STRINGS
static stringobject *nullstring;
#endif
/*
Newsizedstringobject() and newstringobject() try in certain cases
......@@ -62,6 +64,7 @@ newsizedstringobject(str, size)
int size;
{
register stringobject *op;
#ifndef DONT_SHARE_SHORT_STRINGS
if (size == 0 && (op = nullstring) != NULL) {
#ifdef COUNT_ALLOCS
null_strings++;
......@@ -76,6 +79,7 @@ newsizedstringobject(str, size)
INCREF(op);
return (object *)op;
}
#endif /* DONT_SHARE_SHORT_STRINGS */
op = (stringobject *)
malloc(sizeof(stringobject) + size * sizeof(char));
if (op == NULL)
......@@ -89,6 +93,7 @@ newsizedstringobject(str, size)
if (str != NULL)
memcpy(op->ob_sval, str, size);
op->ob_sval[size] = '\0';
#ifndef DONT_SHARE_SHORT_STRINGS
if (size == 0) {
nullstring = op;
INCREF(op);
......@@ -96,6 +101,7 @@ newsizedstringobject(str, size)
characters[*str & UCHAR_MAX] = op;
INCREF(op);
}
#endif
return (object *) op;
}
......@@ -105,6 +111,7 @@ newstringobject(str)
{
register unsigned int size = strlen(str);
register stringobject *op;
#ifndef DONT_SHARE_SHORT_STRINGS
if (size == 0 && (op = nullstring) != NULL) {
#ifdef COUNT_ALLOCS
null_strings++;
......@@ -119,6 +126,7 @@ newstringobject(str)
INCREF(op);
return (object *)op;
}
#endif /* DONT_SHARE_SHORT_STRINGS */
op = (stringobject *)
malloc(sizeof(stringobject) + size * sizeof(char));
if (op == NULL)
......@@ -130,6 +138,7 @@ newstringobject(str)
#endif
NEWREF(op);
strcpy(op->ob_sval, str);
#ifndef DONT_SHARE_SHORT_STRINGS
if (size == 0) {
nullstring = op;
INCREF(op);
......@@ -137,6 +146,7 @@ newstringobject(str)
characters[*str & UCHAR_MAX] = op;
INCREF(op);
}
#endif
return (object *) op;
}
......
......@@ -34,7 +34,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Entries 1 upto MAXSAVESIZE are free lists, entry 0 is the empty
tuple () of which at most one instance will be allocated.
*/
static tupleobject *free_list[MAXSAVESIZE];
static tupleobject *free_tuples[MAXSAVESIZE];
#endif
#ifdef COUNT_ALLOCS
int fast_tuple_allocs;
......@@ -52,16 +52,16 @@ newtupleobject(size)
return NULL;
}
#if MAXSAVESIZE > 0
if (size == 0 && free_list[0]) {
op = free_list[0];
if (size == 0 && free_tuples[0]) {
op = free_tuples[0];
INCREF(op);
#ifdef COUNT_ALLOCS
tuple_zero_allocs++;
#endif
return (object *) op;
}
if (0 < size && size < MAXSAVESIZE && (op = free_list[size]) != NULL) {
free_list[size] = (tupleobject *) op->ob_item[0];
if (0 < size && size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
free_tuples[size] = (tupleobject *) op->ob_item[0];
#ifdef COUNT_ALLOCS
fast_tuple_allocs++;
#endif
......@@ -80,7 +80,7 @@ newtupleobject(size)
NEWREF(op);
#if MAXSAVESIZE > 0
if (size == 0) {
free_list[0] = op;
free_tuples[0] = op;
INCREF(op); /* extra INCREF so that this is never freed */
}
#endif
......@@ -149,8 +149,8 @@ tupledealloc(op)
XDECREF(op->ob_item[i]);
#if MAXSAVESIZE > 0
if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
op->ob_item[0] = (object *) free_list[op->ob_size];
free_list[op->ob_size] = op;
op->ob_item[0] = (object *) free_tuples[op->ob_size];
free_tuples[op->ob_size] = op;
} else
#endif
free((ANY *)op);
......@@ -397,36 +397,67 @@ typeobject Tupletype = {
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
more efficiently. In any case, don't use this if the tuple may
already be known to some other part of the code... */
already be known to some other part of the code...
If last_is_sticky is set, the tuple will grow or shrink at the
front, otherwise it will grow or shrink at the end. */
int
resizetuple(pv, newsize)
resizetuple(pv, newsize, last_is_sticky)
object **pv;
int newsize;
int last_is_sticky;
{
register object *v;
register tupleobject *v;
register tupleobject *sv;
v = *pv;
int i;
int sizediff;
v = (tupleobject *) *pv;
sizediff = newsize - v->ob_size;
if (!is_tupleobject(v) || v->ob_refcnt != 1) {
*pv = 0;
DECREF(v);
err_badcall();
return -1;
}
if (sizediff == 0)
return 0;
/* XXX UNREF/NEWREF interface should be more symmetrical */
#ifdef REF_DEBUG
--ref_total;
#endif
UNREF(v);
*pv = (object *)
if (last_is_sticky && sizediff < 0) {
/* shrinking: move entries to the front and zero moved entries */
for (i = 0; i < newsize; i++) {
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++) {
XDECREF(v->ob_item[i]);
v->ob_item[i] = NULL;
}
sv = (tupleobject *)
realloc((char *)v,
sizeof(tupleobject) + newsize * sizeof(object *));
if (*pv == NULL) {
*pv = (object *) sv;
if (sv == NULL) {
DEL(v);
err_nomem();
return -1;
}
NEWREF(*pv);
((tupleobject *) *pv)->ob_size = newsize;
NEWREF(sv);
for (i = sv->ob_size; i < newsize; i++)
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;
}
}
sv->ob_size = newsize;
return 0;
}
......@@ -1319,7 +1319,7 @@ filtertuple(func, tuple)
}
}
if (resizetuple(&result, j) < 0)
if (resizetuple(&result, j, 0) < 0)
return NULL;
if (shared)
......
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