[INFER] Fix cases where dense arrays have initialized length < capacity with disabled inference, bug 648357.

This commit is contained in:
Brian Hackett 2011-04-07 17:14:15 -07:00
parent 52950bca44
commit 814665de9f
5 changed files with 46 additions and 20 deletions

View File

@ -0,0 +1,3 @@
var x = [1, 2, 3, 4, 5, 6, 7, 8];
x.pop();
x.push(9);

View File

@ -1509,7 +1509,12 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const Value *vector
/* Avoid ensureDenseArrayElements to skip sparse array checks there. */
if (!obj->ensureSlots(cx, length))
return false;
if (cx->typeInferenceEnabled())
obj->setDenseArrayInitializedLength(length);
else
obj->backfillDenseArrayHoles();
bool hole = false;
for (jsuint i = 0; i < length; i++) {
obj->setDenseArrayElement(i, vector[i]);
@ -1517,6 +1522,7 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const Value *vector
}
if (hole && !obj->setDenseArrayNotPacked(cx))
return false;
return true;
}
@ -1583,6 +1589,7 @@ array_reverse(JSContext *cx, uintN argc, Value *vp)
/* Fill out the array's initialized length to its proper length. */
jsuint initlen = obj->getDenseArrayInitializedLength();
if (len > initlen) {
JS_ASSERT(cx->typeInferenceEnabled());
if (!obj->setDenseArrayNotPacked(cx))
return false;
ClearValueRange(obj->getDenseArrayElements() + initlen, len - initlen, true);
@ -2169,9 +2176,13 @@ ArrayCompPushImpl(JSContext *cx, JSObject *obj, const Value &v)
*/
if (!obj->ensureSlots(cx, length + 1))
return false;
if (!cx->typeInferenceEnabled())
obj->backfillDenseArrayHoles();
}
obj->setDenseArrayLength(length + 1);
if (cx->typeInferenceEnabled())
obj->setDenseArrayInitializedLength(length + 1);
obj->setDenseArrayLength(length + 1);
obj->setDenseArrayElement(length, v);
return true;
}
@ -2259,9 +2270,16 @@ array_pop_dense(JSContext *cx, JSObject* obj, Value *vp)
return JS_FALSE;
if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
return JS_FALSE;
obj->setDenseArrayLength(index);
if (cx->typeInferenceEnabled()) {
JS_ASSERT(!obj->isPackedDenseArray());
if (index == obj->getDenseArrayInitializedLength() - 1)
obj->setDenseArrayInitializedLength(index);
if (!cx->markTypeArrayShrank(obj->getType()))
return JS_FALSE;
}
return JS_TRUE;
}
@ -2294,22 +2312,23 @@ array_shift(JSContext *cx, uintN argc, Value *vp)
} else {
length--;
if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj)) {
Value *elems = obj->getDenseArrayElements();
jsuint initlen = obj->getDenseArrayInitializedLength();
if (initlen > 0) {
if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) &&
length < obj->getDenseArrayCapacity() &&
0 < obj->getDenseArrayInitializedLength()) {
*vp = obj->getDenseArrayElement(0);
if (vp->isMagic(JS_ARRAY_HOLE)) {
vp->setUndefined();
if (!cx->markTypeCallerUnexpected(TYPE_UNDEFINED))
return JS_FALSE;
}
memmove(elems, elems + 1, (initlen - 1) * sizeof(jsval));
obj->setDenseArrayInitializedLength(initlen - 1);
} else {
vp->setUndefined();
if (!cx->markTypeCallerUnexpected(TYPE_UNDEFINED))
Value *elems = obj->getDenseArrayElements();
memmove(elems, elems + 1, length * sizeof(jsval));
if (cx->typeInferenceEnabled()) {
obj->setDenseArrayInitializedLength(obj->getDenseArrayInitializedLength() - 1);
if (!cx->markTypeArrayShrank(obj->getType()))
return JS_FALSE;
} else {
obj->setDenseArrayElement(length, MagicValue(JS_ARRAY_HOLE));
}
JS_ALWAYS_TRUE(obj->setArrayLength(cx, length));
if (!js_SuppressDeletedIndexProperties(cx, obj, length, length + 1))

View File

@ -105,6 +105,7 @@ JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
if (index < initLength)
return ED_OK;
if (index < currentCapacity) {
JS_ASSERT(cx->typeInferenceEnabled());
if (index > initLength) {
if (!setDenseArrayNotPacked(cx))
return ED_FAILED;
@ -127,6 +128,7 @@ JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
if (requiredCapacity <= initLength)
return ED_OK;
if (requiredCapacity <= currentCapacity) {
JS_ASSERT(cx->typeInferenceEnabled());
if (index > initLength) {
ClearValueRange(getSlots() + initLength, index - initLength, true);
if (!setDenseArrayNotPacked(cx))

View File

@ -4224,8 +4224,10 @@ JSObject::growSlots(JSContext *cx, size_t newcap)
slots = tmpslots;
capacity = actualCapacity;
/* Initialize the additional slots we added. */
ClearValueRange(slots + oldcap, actualCapacity - oldcap, isDenseArray());
if (!isDenseArray()) {
/* Initialize the additional slots we added. This is not required for dense arrays. */
ClearValueRange(slots + oldcap, actualCapacity - oldcap, false);
}
return true;
}

View File

@ -747,7 +747,7 @@ FrameState::computeAllocation(jsbytecode *target)
continue;
if (fe >= spBase && !isTemporary(fe))
continue;
if (isTemporary(fe) && target - script->code > loop->backedgeOffset())
if (isTemporary(fe) && uint32(target - script->code) > loop->backedgeOffset())
continue;
alloc->set(reg, indexOfFe(fe), fe->data.synced());
}