[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 ab5e595c8e
commit c9f6465be0
5 changed files with 46 additions and 20 deletions

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;
obj->setDenseArrayInitializedLength(length);
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();
}
if (cx->typeInferenceEnabled())
obj->setDenseArrayInitializedLength(length + 1);
obj->setDenseArrayLength(length + 1);
obj->setDenseArrayInitializedLength(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 (index == obj->getDenseArrayInitializedLength() - 1)
obj->setDenseArrayInitializedLength(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,23 +2312,24 @@ 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) {
*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 {
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;
}
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))
return JS_FALSE;