[INFER] Use both inline and dynamic slots for objects other than dense arrays, bug 648321.

This commit is contained in:
Brian Hackett
2011-04-08 19:51:40 -07:00
parent eac99c4620
commit 5f992cdd2c
23 changed files with 547 additions and 346 deletions

View File

@@ -972,7 +972,7 @@ array_trace(JSTracer *trc, JSObject *obj)
JS_ASSERT(obj->isDenseArray());
uint32 capacity = obj->getDenseArrayInitializedLength();
MarkValueRange(trc, capacity, obj->slots, "element");
MarkValueRange(trc, capacity, obj->getDenseArrayElements(), "element");
}
static JSBool
@@ -1075,7 +1075,24 @@ JSObject::makeDenseArraySlow(JSContext *cx)
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, getType(), kind))
return false;
uint32 initlen = getDenseArrayInitializedLength();
backfillDenseArrayHoles();
uint32 arrayCapacity = getDenseArrayCapacity();
/*
* Adjust the slots to account for the different layout between dense
* arrays and other objects. The slots must be dynamic, and the fixed slots
* are now available for newly added properties.
*/
if (denseArrayHasInlineSlots()) {
if (!allocSlots(cx, numSlots())) {
setMap(oldMap);
return false;
}
JS_ASSERT(!denseArrayHasInlineSlots());
}
capacity = numFixedSlots() + arrayCapacity;
clasp = &js_SlowArrayClass;
/*
* Begin with the length property to share more of the property tree.
@@ -1083,6 +1100,8 @@ JSObject::makeDenseArraySlow(JSContext *cx)
*/
if (!AddLengthProperty(cx, this)) {
setMap(oldMap);
capacity = arrayCapacity;
clasp = &js_ArrayClass;
return false;
}
@@ -1091,46 +1110,38 @@ JSObject::makeDenseArraySlow(JSContext *cx)
* remove holes, so that shapes use successive slots (as for other objects).
*/
uint32 next = 0;
for (uint32 i = 0; i < initlen; i++) {
for (uint32 i = 0; i < arrayCapacity; i++) {
/* Dense array indexes can always fit in a jsid. */
jsid id;
if (!ValueToId(cx, Int32Value(i), &id)) {
setMap(oldMap);
return false;
}
JS_ALWAYS_TRUE(ValueToId(cx, Int32Value(i), &id));
if (getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE))
if (slots[i].isMagic(JS_ARRAY_HOLE))
continue;
setDenseArrayElement(next, getDenseArrayElement(i));
setSlot(next, slots[i]);
if (!addDataProperty(cx, id, next, JSPROP_ENUMERATE)) {
setMap(oldMap);
capacity = arrayCapacity;
clasp = &js_ArrayClass;
return false;
}
next++;
}
clearSlotRange(next, capacity - next);
/* initialized length is not used anymore. */
initializedLength = 0;
JS_ASSERT(newType == NULL);
/*
* 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
* that delegating instances can share shapes in the tree rooted at the
* proto's empty shape.
*/
clasp = &js_SlowArrayClass;
return true;
}