Bug 933475 - Rewrite Array.prototype.push fast path to work on all native objects with dense elements. r=Waldo

This commit is contained in:
Jan de Mooij 2013-11-02 11:54:07 +01:00
parent 6e5310720b
commit ac08cd69cc

View File

@ -2043,33 +2043,42 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp)
if (!obj)
return false;
/* Fast path for the fully-dense case. */
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (arr->lengthIsWritable() && !ObjectMayHaveExtraIndexedProperties(arr)) {
uint32_t length = arr->length();
uint32_t argCount = args.length();
JSObject::EnsureDenseResult result = arr->ensureDenseElements(cx, length, argCount);
if (result == JSObject::ED_FAILED)
return false;
if (result == JSObject::ED_OK) {
arr->setLengthInt32(length + argCount);
for (uint32_t i = 0, index = length; i < argCount; index++, i++)
JSObject::setDenseElementWithType(cx, arr, index, args[i]);
args.rval().setNumber(arr->length());
return true;
}
MOZ_ASSERT(result == JSObject::ED_SPARSE);
}
}
/* Steps 2-3. */
uint32_t length;
if (!GetLengthProperty(cx, obj, &length))
return false;
/* Fast path for native objects with dense elements. */
do {
if (!obj->isNative())
break;
if (obj->is<ArrayObject>() && !obj->as<ArrayObject>().lengthIsWritable())
break;
if (ObjectMayHaveExtraIndexedProperties(obj))
break;
uint32_t argCount = args.length();
JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, length, argCount);
if (result == JSObject::ED_FAILED)
return false;
if (result == JSObject::ED_OK) {
for (uint32_t i = 0, index = length; i < argCount; index++, i++)
JSObject::setDenseElementWithType(cx, obj, index, args[i]);
uint32_t newlength = length + argCount;
args.rval().setNumber(newlength);
if (obj->is<ArrayObject>()) {
obj->as<ArrayObject>().setLengthInt32(newlength);
return true;
}
return SetLengthProperty(cx, obj, newlength);
}
MOZ_ASSERT(result == JSObject::ED_SPARSE);
} while (false);
/* Steps 4-5. */
if (!InitArrayElements(cx, obj, length, args.length(), args.array(), UpdateTypes))
return false;