Fix fixed slots invariant for slow arrays, bug 610592. r=brendan

This commit is contained in:
Brian Hackett 2010-11-15 17:21:58 -08:00
parent f9af2830e6
commit 3f497e1eae
2 changed files with 52 additions and 10 deletions

View File

@ -0,0 +1,29 @@
/* Don't confuse JIT code by making slow arrays that use inline slots inconsistently. */
function foo(a)
{
assertEq(a.x, 5);
}
function bar()
{
for (var i = 0; i < 50; i++) {
var a = [];
a[i] = 0;
delete a[i];
a.x = 5;
foo(a);
}
var b = [1,,2,,3,,4,,5];
assertEq(b.toString(), "1,,2,,3,,4,,5");
b.x = 0;
assertEq(b.toString(), "1,,2,,3,,4,,5");
delete b.x;
delete b[8];
delete b[6];
delete b[4];
assertEq(b.toString(), "1,,2,,,,,,");
}
bar();

View File

@ -1043,12 +1043,10 @@ JSObject::makeDenseArraySlow(JSContext *cx)
*/
JSObjectMap *oldMap = map;
/*
* Create a native scope. All slow arrays other than Array.prototype get
* the same initial shape.
*/
/* Create a native scope. */
JSObject *arrayProto = getProto();
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, arrayProto, FINALIZE_OBJECT0))
js::gc::FinalizeKind kind = js::gc::FinalizeKind(arena()->header()->thingKind);
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, arrayProto, kind))
return false;
uint32 capacity = getDenseArrayCapacity();
@ -1064,7 +1062,11 @@ JSObject::makeDenseArraySlow(JSContext *cx)
return false;
}
/* Create new properties pointing to existing elements. */
/*
* Create new properties pointing to existing elements. Pack the array to
* remove holes, so that shapes use successive slots (as for other objects).
*/
uint32 next = 0;
for (uint32 i = 0; i < capacity; i++) {
jsid id;
if (!ValueToId(cx, Int32Value(i), &id)) {
@ -1072,17 +1074,28 @@ JSObject::makeDenseArraySlow(JSContext *cx)
return false;
}
if (getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
setDenseArrayElement(i, UndefinedValue());
if (getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE))
continue;
}
if (!addDataProperty(cx, id, i, JSPROP_ENUMERATE)) {
setDenseArrayElement(next, getDenseArrayElement(i));
if (!addDataProperty(cx, id, next, JSPROP_ENUMERATE)) {
setMap(oldMap);
return false;
}
next++;
}
/*
* Dense arrays with different numbers of slots but the same number of fixed
* slots and the same non-hole indexes must use their fixed slots consistently.
*/
if (hasSlotsArray() && next <= numFixedSlots())
revertToFixedSlots(cx);
ClearValueRange(slots + next, this->capacity - next, false);
/*
* Finally, update class. If |this| is Array.prototype, then js_InitClass
* will create an emptyShape whose class is &js_SlowArrayClass, to ensure