1// Copyright 2018 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 { 6transitioning javascript builtin 7ArrayReduceRightPreLoopEagerDeoptContinuation( 8 js-implicit context: NativeContext, receiver: JSAny)( 9 callback: JSAny, length: JSAny): JSAny { 10 // All continuation points in the optimized every implementation are 11 // after the ToObject(O) call that ensures we are dealing with a 12 // JSReceiver. 13 // 14 // Also, this great mass of casts is necessary because the signature 15 // of Torque javascript builtins requires JSAny type for all parameters 16 // other than {context}. 17 const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 18 const callbackfn = Cast<Callable>(callback) otherwise unreachable; 19 const numberLength = Cast<Number>(length) otherwise unreachable; 20 const initialK = numberLength - 1; 21 22 // Simulate starting the loop at {length - 1}, but ensuring that the 23 // accumulator is the hole. The continuation stub will search for the 24 // last non-hole element, rightly throwing an exception if not found. 25 return ArrayReduceRightLoopContinuation( 26 jsreceiver, callbackfn, TheHole, jsreceiver, initialK, numberLength); 27} 28 29transitioning javascript builtin 30ArrayReduceRightLoopEagerDeoptContinuation( 31 js-implicit context: NativeContext, receiver: JSAny)( 32 callback: JSAny, initialK: JSAny, length: JSAny, 33 accumulator: JSAny): JSAny { 34 // All continuation points in the optimized every implementation are 35 // after the ToObject(O) call that ensures we are dealing with a 36 // JSReceiver. 37 // 38 // Also, this great mass of casts is necessary because the signature 39 // of Torque javascript builtins requires JSAny type for all parameters 40 // other than {context}. 41 const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 42 const callbackfn = Cast<Callable>(callback) otherwise unreachable; 43 const numberK = Cast<Number>(initialK) otherwise unreachable; 44 const numberLength = Cast<Number>(length) otherwise unreachable; 45 46 return ArrayReduceRightLoopContinuation( 47 jsreceiver, callbackfn, accumulator, jsreceiver, numberK, numberLength); 48} 49 50transitioning javascript builtin 51ArrayReduceRightLoopLazyDeoptContinuation( 52 js-implicit context: NativeContext, receiver: JSAny)( 53 callback: JSAny, initialK: JSAny, length: JSAny, result: JSAny): JSAny { 54 // All continuation points in the optimized every implementation are 55 // after the ToObject(O) call that ensures we are dealing with a 56 // JSReceiver. 57 const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 58 const callbackfn = Cast<Callable>(callback) otherwise unreachable; 59 const numberK = Cast<Number>(initialK) otherwise unreachable; 60 const numberLength = Cast<Number>(length) otherwise unreachable; 61 62 // The accumulator is the result from the callback call which just occured. 63 const r = ArrayReduceRightLoopContinuation( 64 jsreceiver, callbackfn, result, jsreceiver, numberK, numberLength); 65 return r; 66} 67 68transitioning builtin ArrayReduceRightLoopContinuation( 69 implicit context: Context)( 70 _receiver: JSReceiver, callbackfn: Callable, 71 initialAccumulator: JSAny|TheHole, o: JSReceiver, initialK: Number, 72 _length: Number): JSAny { 73 let accumulator = initialAccumulator; 74 75 // 8b and 9. Repeat, while k >= 0 76 for (let k: Number = initialK; k >= 0; k--) { 77 // 8b i and 9a. Let Pk be ! ToString(k). 78 // k is guaranteed to be a positive integer, hence ToString is 79 // side-effect free and HasProperty/GetProperty do the conversion inline. 80 81 // 8b ii and 9b. Set kPresent to ? HasProperty(O, Pk). 82 const present: Boolean = HasProperty_Inline(o, k); 83 84 // 8b iii and 9c. If kPresent is true, then 85 if (present == True) { 86 // 8b iii and 9c i. Let kValue be ? Get(O, Pk). 87 const value: JSAny = GetProperty(o, k); 88 89 typeswitch (accumulator) { 90 case (TheHole): { 91 // 8b iii 1. 92 accumulator = value; 93 } 94 case (accumulatorNotHole: JSAny): { 95 // 9c. ii. Set accumulator to ? Call(callbackfn, undefined, 96 // <accumulator, kValue, k, O>). 97 accumulator = Call( 98 context, callbackfn, Undefined, accumulatorNotHole, value, k, o); 99 } 100 } 101 } 102 103 // 8b iv and 9d. Decrease k by 1. (done by the loop). 104 } 105 106 // 8c. if kPresent is false, throw a TypeError exception. 107 // If the accumulator is discovered with the sentinel hole value, 108 // this means kPresent is false. 109 typeswitch (accumulator) { 110 case (TheHole): { 111 ThrowTypeError( 112 MessageTemplate::kReduceNoInitial, 'Array.prototype.reduceRight'); 113 } 114 case (accumulator: JSAny): { 115 return accumulator; 116 } 117 } 118} 119 120transitioning macro FastArrayReduceRight(implicit context: Context)( 121 o: JSReceiver, len: Number, callbackfn: Callable, 122 initialAccumulator: JSAny|TheHole): JSAny 123 labels Bailout(Number, JSAny | TheHole) { 124 let accumulator = initialAccumulator; 125 const smiLen = Cast<Smi>(len) otherwise goto Bailout(len - 1, accumulator); 126 const fastO = Cast<FastJSArrayForRead>(o) 127 otherwise goto Bailout(len - 1, accumulator); 128 let fastOW = NewFastJSArrayForReadWitness(fastO); 129 130 // Build a fast loop over the array. 131 for (let k: Smi = smiLen - 1; k >= 0; k--) { 132 fastOW.Recheck() otherwise goto Bailout(k, accumulator); 133 134 // Ensure that we haven't walked beyond a possibly updated length. 135 if (k >= fastOW.Get().length) goto Bailout(k, accumulator); 136 137 const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue; 138 typeswitch (accumulator) { 139 case (TheHole): { 140 accumulator = value; 141 } 142 case (accumulatorNotHole: JSAny): { 143 accumulator = Call( 144 context, callbackfn, Undefined, accumulatorNotHole, value, k, 145 fastOW.Get()); 146 } 147 } 148 } 149 typeswitch (accumulator) { 150 case (TheHole): { 151 ThrowTypeError( 152 MessageTemplate::kReduceNoInitial, 'Array.prototype.reduceRight'); 153 } 154 case (accumulator: JSAny): { 155 return accumulator; 156 } 157 } 158} 159 160// https://tc39.github.io/ecma262/#sec-array.prototype.reduceRight 161transitioning javascript builtin 162ArrayReduceRight( 163 js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 164 try { 165 RequireObjectCoercible(receiver, 'Array.prototype.reduceRight'); 166 167 // 1. Let O be ? ToObject(this value). 168 const o: JSReceiver = ToObject_Inline(context, receiver); 169 170 // 2. Let len be ? ToLength(? Get(O, "length")). 171 const len: Number = GetLengthProperty(o); 172 173 // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. 174 if (arguments.length == 0) { 175 goto NoCallableError; 176 } 177 const callbackfn = Cast<Callable>(arguments[0]) otherwise NoCallableError; 178 179 // 4. If len is 0 and initialValue is not present, throw a TypeError 180 // exception. (This case is handled at the end of 181 // ArrayReduceRightLoopContinuation). 182 183 const initialValue: JSAny|TheHole = 184 arguments.length > 1 ? arguments[1] : TheHole; 185 186 try { 187 return FastArrayReduceRight(o, len, callbackfn, initialValue) 188 otherwise Bailout; 189 } label Bailout(value: Number, accumulator: JSAny|TheHole) { 190 return ArrayReduceRightLoopContinuation( 191 o, callbackfn, accumulator, o, value, len); 192 } 193 } label NoCallableError deferred { 194 ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); 195 } 196} 197} 198