diff --git a/Include/tupleobject.h b/Include/tupleobject.h index 8fe28a2394c..9897f6d135e 100644 --- a/Include/tupleobject.h +++ b/Include/tupleobject.h @@ -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]) diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 61863b63d08..0d03a3ba2b4 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -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; } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 0047a09c7e8..68fed9e45fa 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -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; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f4d7f47ae94..6069ae051f2 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1319,7 +1319,7 @@ filtertuple(func, tuple) } } - if (resizetuple(&result, j) < 0) + if (resizetuple(&result, j, 0) < 0) return NULL; if (shared)