11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cinamespace array {
61cb0ef41Sopenharmony_ciextern builtin ArrayShift(Context, JSFunction, JSAny, int32): JSAny;
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_cimacro TryFastArrayShift(implicit context: Context)(receiver: JSAny): JSAny
91cb0ef41Sopenharmony_ci    labels Slow, Runtime {
101cb0ef41Sopenharmony_ci  const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow;
111cb0ef41Sopenharmony_ci  let witness = NewFastJSArrayWitness(array);
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci  witness.EnsureArrayPushable() otherwise Slow;
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci  if (array.length == 0) {
161cb0ef41Sopenharmony_ci    return Undefined;
171cb0ef41Sopenharmony_ci  }
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  const newLength = array.length - 1;
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  // Check that we're not supposed to right-trim the backing store, as
221cb0ef41Sopenharmony_ci  // implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
231cb0ef41Sopenharmony_ci  if ((newLength + newLength + kMinAddedElementsCapacity) <
241cb0ef41Sopenharmony_ci      array.elements.length) {
251cb0ef41Sopenharmony_ci    goto Runtime;
261cb0ef41Sopenharmony_ci  }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  // Check that we're not supposed to left-trim the backing store, as
291cb0ef41Sopenharmony_ci  // implemented in elements.cc:FastElementsAccessor::MoveElements.
301cb0ef41Sopenharmony_ci  if (newLength > kMaxCopyElements) goto Runtime;
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  const result = witness.LoadElementOrUndefined(0);
331cb0ef41Sopenharmony_ci  witness.ChangeLength(newLength);
341cb0ef41Sopenharmony_ci  witness.MoveElements(0, 1, Convert<intptr>(newLength));
351cb0ef41Sopenharmony_ci  witness.StoreHole(newLength);
361cb0ef41Sopenharmony_ci  return result;
371cb0ef41Sopenharmony_ci}
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_citransitioning macro GenericArrayShift(implicit context: Context)(
401cb0ef41Sopenharmony_ci    receiver: JSAny): JSAny {
411cb0ef41Sopenharmony_ci  // 1. Let O be ? ToObject(this value).
421cb0ef41Sopenharmony_ci  const object: JSReceiver = ToObject_Inline(context, receiver);
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  // 2. Let len be ? ToLength(? Get(O, "length")).
451cb0ef41Sopenharmony_ci  const length: Number = GetLengthProperty(object);
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  // 3. If len is zero, then
481cb0ef41Sopenharmony_ci  if (length == 0) {
491cb0ef41Sopenharmony_ci    // a. Perform ? Set(O, "length", 0, true).
501cb0ef41Sopenharmony_ci    SetProperty(object, kLengthString, Convert<Smi>(0));
511cb0ef41Sopenharmony_ci    // b. Return undefined.
521cb0ef41Sopenharmony_ci    return Undefined;
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // 4. Let first be ? Get(O, "0").
561cb0ef41Sopenharmony_ci  const first = GetProperty(object, Convert<Smi>(0));
571cb0ef41Sopenharmony_ci  // 5. Let k be 1.
581cb0ef41Sopenharmony_ci  let k: Number = 1;
591cb0ef41Sopenharmony_ci  // 6. Repeat, while k < len
601cb0ef41Sopenharmony_ci  while (k < length) {
611cb0ef41Sopenharmony_ci    // a. Let from be ! ToString(k).
621cb0ef41Sopenharmony_ci    const from: Number = k;
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci    // b. Let to be ! ToString(k - 1).
651cb0ef41Sopenharmony_ci    const to: Number = k - 1;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci    // c. Let fromPresent be ? HasProperty(O, from).
681cb0ef41Sopenharmony_ci    const fromPresent: Boolean = HasProperty(object, from);
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci    // d. If fromPresent is true, then
711cb0ef41Sopenharmony_ci    if (fromPresent == True) {
721cb0ef41Sopenharmony_ci      // i. Let fromVal be ? Get(O, from).
731cb0ef41Sopenharmony_ci      const fromValue: JSAny = GetProperty(object, from);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci      // ii. Perform ? Set(O, to, fromValue, true).
761cb0ef41Sopenharmony_ci      SetProperty(object, to, fromValue);
771cb0ef41Sopenharmony_ci    } else {
781cb0ef41Sopenharmony_ci      // i. Perform ? DeletePropertyOrThrow(O, to).
791cb0ef41Sopenharmony_ci      DeleteProperty(object, to, LanguageMode::kStrict);
801cb0ef41Sopenharmony_ci    }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci    // f. Increase k by 1.
831cb0ef41Sopenharmony_ci    k++;
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  // 7. Perform ? DeletePropertyOrThrow(O, ! ToString(len - 1)).
871cb0ef41Sopenharmony_ci  DeleteProperty(object, length - 1, LanguageMode::kStrict);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  // 8. Perform ? Set(O, "length", len - 1, true).
901cb0ef41Sopenharmony_ci  SetProperty(object, kLengthString, length - 1);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  // 9. Return first.
931cb0ef41Sopenharmony_ci  return first;
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci// https://tc39.github.io/ecma262/#sec-array.prototype.shift
971cb0ef41Sopenharmony_citransitioning javascript builtin ArrayPrototypeShift(
981cb0ef41Sopenharmony_ci    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
991cb0ef41Sopenharmony_ci  try {
1001cb0ef41Sopenharmony_ci    return TryFastArrayShift(receiver) otherwise Slow, Runtime;
1011cb0ef41Sopenharmony_ci  } label Slow {
1021cb0ef41Sopenharmony_ci    return GenericArrayShift(receiver);
1031cb0ef41Sopenharmony_ci  } label Runtime {
1041cb0ef41Sopenharmony_ci    tail ArrayShift(
1051cb0ef41Sopenharmony_ci        context, LoadTargetFromFrame(), Undefined,
1061cb0ef41Sopenharmony_ci        Convert<int32>(arguments.actual_count));
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci}
1091cb0ef41Sopenharmony_ci}
110