// 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 { extern builtin ArrayShift(Context, JSFunction, JSAny, int32): JSAny; macro TryFastArrayShift(implicit context: Context)(receiver: JSAny): JSAny labels Slow, Runtime { const array: FastJSArray = Cast(receiver) otherwise Slow; let witness = NewFastJSArrayWitness(array); witness.EnsureArrayPushable() otherwise Slow; if (array.length == 0) { return Undefined; } 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(newLength)); witness.StoreHole(newLength); return result; } transitioning macro GenericArrayShift(implicit context: Context)( receiver: JSAny): JSAny { // 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(0)); // b. Return undefined. return Undefined; } // 4. Let first be ? Get(O, "0"). const first = GetProperty(object, Convert(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: JSAny = GetProperty(object, from); // ii. Perform ? Set(O, to, fromValue, true). SetProperty(object, to, fromValue); } else { // i. Perform ? DeletePropertyOrThrow(O, to). DeleteProperty(object, to, LanguageMode::kStrict); } // f. Increase k by 1. k++; } // 7. Perform ? DeletePropertyOrThrow(O, ! ToString(len - 1)). DeleteProperty(object, length - 1, LanguageMode::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: NativeContext, receiver: JSAny)(...arguments): JSAny { try { return TryFastArrayShift(receiver) otherwise Slow, Runtime; } label Slow { return GenericArrayShift(receiver); } label Runtime { tail ArrayShift( context, LoadTargetFromFrame(), Undefined, Convert(arguments.actual_count)); } } }