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