Bug 1364346 part 1 - Optimize Array.prototype.unshift fast path and use it more. r=anba

This commit is contained in:
Jan de Mooij 2017-05-27 23:39:55 +02:00
Родитель a24f22ae22
Коммит b37455bce0
1 изменённых файлов: 39 добавлений и 39 удалений

Просмотреть файл

@ -2485,41 +2485,41 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
// Steps 3-4. // Steps 3-4.
if (args.length() > 0) { if (args.length() > 0) {
/* Slide up the array to make room for all args at the bottom. */ // Only include a fast path for native objects. Unboxed arrays can't
if (length > 0) { // be optimized here because unshifting temporarily places holes at
// Only include a fast path for boxed arrays. Unboxed arrays can't // the start of the array.
// be optimized here because unshifting temporarily places holes at // TODO: Implement unboxed array optimization similar to the one in
// the start of the array. // array_splice_impl(), unshift() is a special version of splice():
// TODO: Implement unboxed array optimization similar to the one in // arr.unshift(...values) ~= arr.splice(0, 0, ...values).
// array_splice_impl(), unshift() is a special version of splice(): bool optimized = false;
// arr.unshift(...values) ~= arr.splice(0, 0, ...values). do {
bool optimized = false; if (length > UINT32_MAX)
do { break;
if (length > UINT32_MAX) if (!obj->isNative())
break; break;
if (!obj->is<ArrayObject>()) if (ObjectMayHaveExtraIndexedProperties(obj))
break; break;
if (ObjectMayHaveExtraIndexedProperties(obj)) if (MaybeInIteration(obj, cx))
break; break;
if (MaybeInIteration(obj, cx)) NativeObject* nobj = &obj->as<NativeObject>();
break; if (nobj->is<ArrayObject>() && !nobj->as<ArrayObject>().lengthIsWritable())
ArrayObject* aobj = &obj->as<ArrayObject>(); break;
if (!aobj->lengthIsWritable()) DenseElementResult result = nobj->ensureDenseElements(cx, uint32_t(length), args.length());
break; if (result != DenseElementResult::Success) {
DenseElementResult result = aobj->ensureDenseElements(cx, uint32_t(length), args.length()); if (result == DenseElementResult::Failure)
if (result != DenseElementResult::Success) { return false;
if (result == DenseElementResult::Failure) MOZ_ASSERT(result == DenseElementResult::Incomplete);
return false; break;
MOZ_ASSERT(result == DenseElementResult::Incomplete); }
break; if (length > 0)
} nobj->moveDenseElements(args.length(), 0, uint32_t(length));
aobj->moveDenseElements(args.length(), 0, uint32_t(length)); for (uint32_t i = 0; i < args.length(); i++)
for (uint32_t i = 0; i < args.length(); i++) nobj->setDenseElementWithType(cx, i, args[i]);
aobj->setDenseElement(i, MagicValue(JS_ELEMENTS_HOLE)); optimized = true;
optimized = true; } while (false);
} while (false);
if (!optimized) { if (!optimized) {
if (length > 0) {
uint64_t last = length; uint64_t last = length;
uint64_t upperIndex = last + args.length(); uint64_t upperIndex = last + args.length();
@ -2547,12 +2547,12 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
} }
} while (last != 0); } while (last != 0);
} }
}
// Steps 4.d-f. // Steps 4.d-f.
/* Copy from args to the bottom of the array. */ /* Copy from args to the bottom of the array. */
if (!SetArrayElements(cx, obj, 0, args.length(), args.array())) if (!SetArrayElements(cx, obj, 0, args.length(), args.array()))
return false; return false;
}
} }
// Step 5. // Step 5.