diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index e6cdcfa3a301..d36e20f7dd8f 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -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()) { - Rooted arr(cx, &obj->as()); - 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() && !obj->as().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()) { + obj->as().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;