blob: 4dd82d7b886d0a02ccb5c850a22d99a9cc1d520b [file] [log] [blame]
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace array_shift {
extern builtin ArrayShift(Context, JSFunction, Object, int32);
macro TryFastArrayShift(implicit context: Context)(
receiver: Object, arguments: Arguments): Object
labels Slow {
const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow;
let witness = NewFastJSArrayWitness(array);
witness.EnsureArrayPushable() otherwise Slow;
if (array.length == 0) {
return Undefined;
}
try {
const newLength = array.length - 1;
// Check that we're not supposed to right-trim the backing store, as
// implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
if ((newLength + newLength + kMinAddedElementsCapacity) <
array.elements.length) {
goto Runtime;
}
// Check that we're not supposed to left-trim the backing store, as
// implemented in elements.cc:FastElementsAccessor::MoveElements.
if (newLength > kMaxCopyElements) goto Runtime;
const result = witness.LoadElementOrUndefined(0);
witness.ChangeLength(newLength);
witness.MoveElements(0, 1, Convert<intptr>(newLength));
witness.StoreHole(newLength);
return result;
}
label Runtime {
tail ArrayShift(
context, LoadTargetFromFrame(), Undefined,
Convert<int32>(arguments.length));
}
}
transitioning macro GenericArrayShift(implicit context:
Context)(receiver: Object): Object {
// 1. Let O be ? ToObject(this value).
const object: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const length: Number = GetLengthProperty(object);
// 3. If len is zero, then
if (length == 0) {
// a. Perform ? Set(O, "length", 0, true).
SetProperty(object, kLengthString, Convert<Smi>(0));
// b. Return undefined.
return Undefined;
}
// 4. Let first be ? Get(O, "0").
const first = GetProperty(object, Convert<Smi>(0));
// 5. Let k be 1.
let k: Number = 1;
// 6. Repeat, while k < len
while (k < length) {
// a. Let from be ! ToString(k).
const from: Number = k;
// b. Let to be ! ToString(k - 1).
const to: Number = k - 1;
// c. Let fromPresent be ? HasProperty(O, from).
const fromPresent: Boolean = HasProperty(object, from);
// d. If fromPresent is true, then
if (fromPresent == True) {
// i. Let fromVal be ? Get(O, from).
const fromValue: Object = GetProperty(object, from);
// ii. Perform ? Set(O, to, fromValue, true).
SetProperty(object, to, fromValue);
} else {
// i. Perform ? DeletePropertyOrThrow(O, to).
DeleteProperty(object, to, kStrict);
}
// f. Increase k by 1.
k++;
}
// 7. Perform ? DeletePropertyOrThrow(O, ! ToString(len - 1)).
DeleteProperty(object, length - 1, kStrict);
// 8. Perform ? Set(O, "length", len - 1, true).
SetProperty(object, kLengthString, length - 1);
// 9. Return first.
return first;
}
// https://tc39.github.io/ecma262/#sec-array.prototype.shift
transitioning javascript builtin ArrayPrototypeShift(
js-implicit context: Context, receiver: Object)(...arguments): Object {
try {
return TryFastArrayShift(receiver, arguments) otherwise Slow;
}
label Slow {
return GenericArrayShift(receiver);
}
}
}