Fix net vs. gross botches from patch for 489899 (514112, r=gal).

This commit is contained in:
Brendan Eich 2009-09-01 22:54:02 -07:00
parent fb283f7442
commit 953fdff59e
3 changed files with 36 additions and 36 deletions

View File

@ -308,11 +308,11 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
}
static JSBool
ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldsize, uint32 size)
ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldlen, uint32 newlen)
{
jsval *slots, *newslots;
if (size == 0) {
if (newlen == 0) {
if (obj->dslots) {
cx->free(obj->dslots - 1);
obj->dslots = NULL;
@ -320,24 +320,20 @@ ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldsize, uint32 size)
return JS_TRUE;
}
/*
* MAX_DSLOTS_LENGTH is the maximum net capacity supported. Since we allocate
* one additional slot to hold the array length, we have to use >= here.
*/
if (size >= MAX_DSLOTS_LENGTH) {
if (newlen > MAX_DSLOTS_LENGTH) {
js_ReportAllocationOverflow(cx);
return JS_FALSE;
}
slots = obj->dslots ? obj->dslots - 1 : NULL;
newslots = (jsval *) cx->realloc(slots, (size + 1) * sizeof(jsval));
newslots = (jsval *) cx->realloc(slots, (newlen + 1) * sizeof(jsval));
if (!newslots)
return JS_FALSE;
obj->dslots = newslots + 1;
js_SetDenseArrayCapacity(obj, size);
js_SetDenseArrayCapacity(obj, newlen);
for (slots = obj->dslots + oldsize; slots < obj->dslots + size; slots++)
for (slots = obj->dslots + oldlen; slots < obj->dslots + newlen; slots++)
*slots = JSVAL_HOLE;
return JS_TRUE;
@ -359,31 +355,31 @@ ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldsize, uint32 size)
#define CAPACITY_CHUNK (1024 * 1024 / sizeof(jsval))
static JSBool
EnsureCapacity(JSContext *cx, JSObject *obj, uint32 capacity)
EnsureCapacity(JSContext *cx, JSObject *obj, uint32 newcap)
{
uint32 oldsize = js_DenseArrayCapacity(obj);
uint32 oldcap = js_DenseArrayCapacity(obj);
if (capacity > oldsize) {
if (newcap > oldcap) {
/*
* If this overflows uint32, capacity is very large. nextsize will end
* up being less than capacity, the code below will thus disregard it,
* If this overflows uint32, newcap is very large. nextsize will end
* up being less than newcap, the code below will thus disregard it,
* and ResizeSlots will fail.
*
* The way we use dslots[-1] forces a few +1s and -1s here. For
* example, (oldsize * 2 + 1) produces the sequence 7, 15, 31, 63, ...
* example, (oldcap * 2 + 1) produces the sequence 7, 15, 31, 63, ...
* which makes the total allocation size (with dslots[-1]) a power
* of two.
*/
uint32 nextsize = (oldsize <= CAPACITY_DOUBLING_MAX)
? oldsize * 2 + 1
: oldsize + (oldsize >> 3);
uint32 nextsize = (oldcap <= CAPACITY_DOUBLING_MAX)
? oldcap * 2 + 1
: oldcap + (oldcap >> 3);
capacity = JS_MAX(capacity, nextsize);
if (capacity >= CAPACITY_CHUNK)
capacity = JS_ROUNDUP(capacity + 1, CAPACITY_CHUNK) - 1; /* -1 for dslots[-1] */
else if (capacity < ARRAY_CAPACITY_MIN)
capacity = ARRAY_CAPACITY_MIN;
return ResizeSlots(cx, obj, oldsize, capacity);
newcap = JS_MAX(newcap, nextsize);
if (newcap >= CAPACITY_CHUNK)
newcap = JS_ROUNDUP(newcap + 1, CAPACITY_CHUNK) - 1; /* -1 for dslots[-1] */
else if (newcap < ARRAY_CAPACITY_MIN)
newcap = ARRAY_CAPACITY_MIN;
return ResizeSlots(cx, obj, oldcap, newcap);
}
return JS_TRUE;
}
@ -646,8 +642,8 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
/* Don't reallocate if we're not actually shrinking our slots. */
jsuint oldsize = js_DenseArrayCapacity(obj);
if (oldsize >= newlen && !ResizeSlots(cx, obj, oldsize, newlen))
jsuint capacity = js_DenseArrayCapacity(obj);
if (capacity > newlen && !ResizeSlots(cx, obj, capacity, newlen))
return JS_FALSE;
} else if (oldlen - newlen < (1 << 24)) {
do {
@ -898,8 +894,8 @@ dense_grow(JSContext* cx, JSObject* obj, jsint i, jsval v)
/*
* Let the interpreter worry about negative array indexes.
*/
JS_ASSERT((MAX_DSLOTS_LENGTH > JSVAL_INT_MAX) == (sizeof(jsval) != sizeof(uint32)));
if (MAX_DSLOTS_LENGTH > JSVAL_INT_MAX) {
JS_ASSERT((MAX_DSLOTS_LENGTH > MAX_DSLOTS_LENGTH32) == (sizeof(jsval) != sizeof(uint32)));
if (MAX_DSLOTS_LENGTH > MAX_DSLOTS_LENGTH32) {
/*
* Have to check for negative values bleeding through on 64-bit machines only,
* since we can't allocate large enough arrays for this on 32-bit machines.

View File

@ -308,10 +308,12 @@ struct JSObject {
+ JSCLASS_RESERVED_SLOTS(clasp))
/*
* Maximum net gross capacity of the obj->dslots vector, excluding the additional
* hidden slot used to store the length of the vector.
* Maximum capacity of the obj->dslots vector, net of the hidden slot at
* obj->dslots[-1] that is used to store the length of the vector biased by
* JS_INITIAL_NSLOTS (and again net of the slot at index -1).
*/
#define MAX_DSLOTS_LENGTH (JS_MAX(~(uint32)0, ~(size_t)0) / sizeof(jsval))
#define MAX_DSLOTS_LENGTH (JS_MAX(~uint32(0), ~size_t(0)) / sizeof(jsval) - 1)
#define MAX_DSLOTS_LENGTH32 (~uint32(0) / sizeof(jsval) - 1)
/*
* STOBJ prefix means Single Threaded Object. Use the following fast macros to

View File

@ -11303,8 +11303,9 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
if (!within) {
/* If idx < 0, stay on trace (and read value as undefined, since this is a dense array). */
LIns* br1 = NULL;
if (MAX_DSLOTS_LENGTH > JS_BITMASK(30) && !idx_ins->isconst()) {
JS_ASSERT(sizeof(jsval) == 8); // Only 64-bit machines support large enough arrays for this.
if (MAX_DSLOTS_LENGTH > MAX_DSLOTS_LENGTH32 && !idx_ins->isconst()) {
/* Only 64-bit machines support large enough arrays for this. */
JS_ASSERT(sizeof(jsval) == 8);
br1 = lir->insBranch(LIR_jt,
lir->ins2i(LIR_lt, idx_ins, 0),
NULL);
@ -11345,8 +11346,9 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
}
/* Guard against negative index */
if (MAX_DSLOTS_LENGTH > JS_BITMASK(30) && !idx_ins->isconst()) {
JS_ASSERT(sizeof(jsval) == 8); // Only 64-bit machines support large enough arrays for this.
if (MAX_DSLOTS_LENGTH > MAX_DSLOTS_LENGTH32 && !idx_ins->isconst()) {
/* Only 64-bit machines support large enough arrays for this. */
JS_ASSERT(sizeof(jsval) == 8);
guard(false,
lir->ins2i(LIR_lt, idx_ins, 0),
exit);