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 7ArrayForEachLoopEagerDeoptContinuation( 8 js-implicit context: NativeContext, receiver: JSAny)( 9 callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { 10 // All continuation points in the optimized forEach implementation are 11 // after the ToObject(O) call that ensures we are dealing with a 12 // JSReceiver. 13 const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 14 const callbackfn = Cast<Callable>(callback) otherwise unreachable; 15 const numberK = Cast<Number>(initialK) otherwise unreachable; 16 const numberLength = Cast<Number>(length) otherwise unreachable; 17 18 return ArrayForEachLoopContinuation( 19 jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK, 20 numberLength, Undefined); 21} 22 23transitioning javascript builtin 24ArrayForEachLoopLazyDeoptContinuation( 25 js-implicit context: NativeContext, receiver: JSAny)( 26 callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, 27 _result: JSAny): JSAny { 28 // All continuation points in the optimized forEach implementation are 29 // after the ToObject(O) call that ensures we are dealing with a 30 // JSReceiver. 31 const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 32 const callbackfn = Cast<Callable>(callback) otherwise unreachable; 33 const numberK = Cast<Number>(initialK) otherwise unreachable; 34 const numberLength = Cast<Number>(length) otherwise unreachable; 35 36 return ArrayForEachLoopContinuation( 37 jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK, 38 numberLength, Undefined); 39} 40 41transitioning builtin ArrayForEachLoopContinuation(implicit context: Context)( 42 _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, _array: JSAny, 43 o: JSReceiver, initialK: Number, len: Number, _to: JSAny): JSAny { 44 // variables {array} and {to} are ignored. 45 46 // 5. Let k be 0. 47 // 6. Repeat, while k < len 48 for (let k: Number = initialK; k < len; k = k + 1) { 49 // 6a. Let Pk be ! ToString(k). 50 // k is guaranteed to be a positive integer, hence ToString is 51 // side-effect free and HasProperty/GetProperty do the conversion inline. 52 53 // 6b. Let kPresent be ? HasProperty(O, Pk). 54 const kPresent: Boolean = HasProperty_Inline(o, k); 55 56 // 6c. If kPresent is true, then 57 if (kPresent == True) { 58 // 6c. i. Let kValue be ? Get(O, Pk). 59 const kValue: JSAny = GetProperty(o, k); 60 61 // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>). 62 Call(context, callbackfn, thisArg, kValue, k, o); 63 } 64 65 // 6d. Increase k by 1. (done by the loop). 66 } 67 return Undefined; 68} 69 70transitioning macro FastArrayForEach(implicit context: Context)( 71 o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny 72 labels Bailout(Smi) { 73 let k: Smi = 0; 74 const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); 75 const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k); 76 let fastOW = NewFastJSArrayWitness(fastO); 77 78 // Build a fast loop over the smi array. 79 for (; k < smiLen; k++) { 80 fastOW.Recheck() otherwise goto Bailout(k); 81 82 // Ensure that we haven't walked beyond a possibly updated length. 83 if (k >= fastOW.Get().length) goto Bailout(k); 84 const value: JSAny = fastOW.LoadElementNoHole(k) 85 otherwise continue; 86 Call(context, callbackfn, thisArg, value, k, fastOW.Get()); 87 } 88 return Undefined; 89} 90 91// https://tc39.github.io/ecma262/#sec-array.prototype.foreach 92transitioning javascript builtin 93ArrayForEach( 94 js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 95 try { 96 RequireObjectCoercible(receiver, 'Array.prototype.forEach'); 97 98 // 1. Let O be ? ToObject(this value). 99 const o: JSReceiver = ToObject_Inline(context, receiver); 100 101 // 2. Let len be ? ToLength(? Get(O, "length")). 102 const len: Number = GetLengthProperty(o); 103 104 // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. 105 if (arguments.length == 0) { 106 goto TypeError; 107 } 108 const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError; 109 110 // 4. If thisArg is present, let T be thisArg; else let T be undefined. 111 const thisArg: JSAny = arguments[1]; 112 113 // Special cases. 114 let k: Number = 0; 115 try { 116 return FastArrayForEach(o, len, callbackfn, thisArg) 117 otherwise Bailout; 118 } label Bailout(kValue: Smi) deferred { 119 k = kValue; 120 } 121 122 return ArrayForEachLoopContinuation( 123 o, callbackfn, thisArg, Undefined, o, k, len, Undefined); 124 } label TypeError deferred { 125 ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); 126 } 127} 128} 129