• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5namespace array {
6extern builtin ArrayShift(Context, JSFunction, JSAny, int32): JSAny;
7
8macro TryFastArrayShift(implicit context: Context)(receiver: JSAny): JSAny
9    labels Slow, Runtime {
10  const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow;
11  let witness = NewFastJSArrayWitness(array);
12
13  witness.EnsureArrayPushable() otherwise Slow;
14
15  if (array.length == 0) {
16    return Undefined;
17  }
18
19  const newLength = array.length - 1;
20
21  // Check that we're not supposed to right-trim the backing store, as
22  // implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
23  if ((newLength + newLength + kMinAddedElementsCapacity) <
24      array.elements.length) {
25    goto Runtime;
26  }
27
28  // Check that we're not supposed to left-trim the backing store, as
29  // implemented in elements.cc:FastElementsAccessor::MoveElements.
30  if (newLength > kMaxCopyElements) goto Runtime;
31
32  const result = witness.LoadElementOrUndefined(0);
33  witness.ChangeLength(newLength);
34  witness.MoveElements(0, 1, Convert<intptr>(newLength));
35  witness.StoreHole(newLength);
36  return result;
37}
38
39transitioning macro GenericArrayShift(implicit context: Context)(
40    receiver: JSAny): JSAny {
41  // 1. Let O be ? ToObject(this value).
42  const object: JSReceiver = ToObject_Inline(context, receiver);
43
44  // 2. Let len be ? ToLength(? Get(O, "length")).
45  const length: Number = GetLengthProperty(object);
46
47  // 3. If len is zero, then
48  if (length == 0) {
49    // a. Perform ? Set(O, "length", 0, true).
50    SetProperty(object, kLengthString, Convert<Smi>(0));
51    // b. Return undefined.
52    return Undefined;
53  }
54
55  // 4. Let first be ? Get(O, "0").
56  const first = GetProperty(object, Convert<Smi>(0));
57  // 5. Let k be 1.
58  let k: Number = 1;
59  // 6. Repeat, while k < len
60  while (k < length) {
61    // a. Let from be ! ToString(k).
62    const from: Number = k;
63
64    // b. Let to be ! ToString(k - 1).
65    const to: Number = k - 1;
66
67    // c. Let fromPresent be ? HasProperty(O, from).
68    const fromPresent: Boolean = HasProperty(object, from);
69
70    // d. If fromPresent is true, then
71    if (fromPresent == True) {
72      // i. Let fromVal be ? Get(O, from).
73      const fromValue: JSAny = GetProperty(object, from);
74
75      // ii. Perform ? Set(O, to, fromValue, true).
76      SetProperty(object, to, fromValue);
77    } else {
78      // i. Perform ? DeletePropertyOrThrow(O, to).
79      DeleteProperty(object, to, LanguageMode::kStrict);
80    }
81
82    // f. Increase k by 1.
83    k++;
84  }
85
86  // 7. Perform ? DeletePropertyOrThrow(O, ! ToString(len - 1)).
87  DeleteProperty(object, length - 1, LanguageMode::kStrict);
88
89  // 8. Perform ? Set(O, "length", len - 1, true).
90  SetProperty(object, kLengthString, length - 1);
91
92  // 9. Return first.
93  return first;
94}
95
96// https://tc39.github.io/ecma262/#sec-array.prototype.shift
97transitioning javascript builtin ArrayPrototypeShift(
98    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
99  try {
100    return TryFastArrayShift(receiver) otherwise Slow, Runtime;
101  } label Slow {
102    return GenericArrayShift(receiver);
103  } label Runtime {
104    tail ArrayShift(
105        context, LoadTargetFromFrame(), Undefined,
106        Convert<int32>(arguments.length));
107  }
108}
109}
110