11cb0ef41Sopenharmony_ci// Copyright 2018 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_citransitioning javascript builtin 71cb0ef41Sopenharmony_ciArrayFindIndexLoopEagerDeoptContinuation( 81cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)( 91cb0ef41Sopenharmony_ci callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny { 101cb0ef41Sopenharmony_ci // All continuation points in the optimized findIndex implementation are 111cb0ef41Sopenharmony_ci // after the ToObject(O) call that ensures we are dealing with a 121cb0ef41Sopenharmony_ci // JSReceiver. 131cb0ef41Sopenharmony_ci // 141cb0ef41Sopenharmony_ci // Also, this great mass of casts is necessary because the signature 151cb0ef41Sopenharmony_ci // of Torque javascript builtins requires JSAny type for all parameters 161cb0ef41Sopenharmony_ci // other than {context}. 171cb0ef41Sopenharmony_ci const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 181cb0ef41Sopenharmony_ci const callbackfn = Cast<Callable>(callback) otherwise unreachable; 191cb0ef41Sopenharmony_ci const numberK = Cast<Number>(initialK) otherwise unreachable; 201cb0ef41Sopenharmony_ci const numberLength = Cast<Number>(length) otherwise unreachable; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci return ArrayFindIndexLoopContinuation( 231cb0ef41Sopenharmony_ci jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength); 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_citransitioning javascript builtin 271cb0ef41Sopenharmony_ciArrayFindIndexLoopLazyDeoptContinuation( 281cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)( 291cb0ef41Sopenharmony_ci _callback: JSAny, _thisArg: JSAny, _initialK: JSAny, _length: JSAny, 301cb0ef41Sopenharmony_ci _result: JSAny): JSAny { 311cb0ef41Sopenharmony_ci // This deopt continuation point is never actually called, it just 321cb0ef41Sopenharmony_ci // exists to make stack traces correct from a ThrowTypeError if the 331cb0ef41Sopenharmony_ci // callback was found to be non-callable. 341cb0ef41Sopenharmony_ci unreachable; 351cb0ef41Sopenharmony_ci} 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci// Continuation that is called after a lazy deoptimization from TF that 381cb0ef41Sopenharmony_ci// happens right after the callback and it's returned value must be handled 391cb0ef41Sopenharmony_ci// before iteration continues. 401cb0ef41Sopenharmony_citransitioning javascript builtin 411cb0ef41Sopenharmony_ciArrayFindIndexLoopAfterCallbackLazyDeoptContinuation( 421cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)( 431cb0ef41Sopenharmony_ci callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny, 441cb0ef41Sopenharmony_ci foundValue: JSAny, isFound: JSAny): JSAny { 451cb0ef41Sopenharmony_ci // All continuation points in the optimized findIndex implementation are 461cb0ef41Sopenharmony_ci // after the ToObject(O) call that ensures we are dealing with a 471cb0ef41Sopenharmony_ci // JSReceiver. 481cb0ef41Sopenharmony_ci const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable; 491cb0ef41Sopenharmony_ci const callbackfn = Cast<Callable>(callback) otherwise unreachable; 501cb0ef41Sopenharmony_ci const numberK = Cast<Number>(initialK) otherwise unreachable; 511cb0ef41Sopenharmony_ci const numberLength = Cast<Number>(length) otherwise unreachable; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // This custom lazy deopt point is right after the callback. find() needs 541cb0ef41Sopenharmony_ci // to pick up at the next step, which is returning the element if the 551cb0ef41Sopenharmony_ci // callback value is truthy. Otherwise, continue the search by calling the 561cb0ef41Sopenharmony_ci // continuation. 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci if (ToBoolean(isFound)) { 591cb0ef41Sopenharmony_ci return foundValue; 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci return ArrayFindIndexLoopContinuation( 631cb0ef41Sopenharmony_ci jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength); 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_citransitioning builtin ArrayFindIndexLoopContinuation(implicit context: Context)( 671cb0ef41Sopenharmony_ci _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, o: JSReceiver, 681cb0ef41Sopenharmony_ci initialK: Number, length: Number): Number { 691cb0ef41Sopenharmony_ci // 5. Let k be 0. 701cb0ef41Sopenharmony_ci // 6. Repeat, while k < len 711cb0ef41Sopenharmony_ci for (let k: Number = initialK; k < length; k++) { 721cb0ef41Sopenharmony_ci // 6a. Let Pk be ! ToString(k). 731cb0ef41Sopenharmony_ci // k is guaranteed to be a positive integer, hence ToString is 741cb0ef41Sopenharmony_ci // side-effect free and HasProperty/GetProperty do the conversion inline. 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // 6b. i. Let kValue be ? Get(O, Pk). 771cb0ef41Sopenharmony_ci const value: JSAny = GetProperty(o, k); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci // 6c. Let testResult be ToBoolean(? Call(predicate, T, <<kValue, k, 801cb0ef41Sopenharmony_ci // O>>)). 811cb0ef41Sopenharmony_ci const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, o); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci // 6d. If testResult is true, return k. 841cb0ef41Sopenharmony_ci if (ToBoolean(testResult)) { 851cb0ef41Sopenharmony_ci return k; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci // 6e. Increase k by 1. (done by the loop). 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci return Convert<Smi>(-1); 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_citransitioning macro FastArrayFindIndex(implicit context: Context)( 941cb0ef41Sopenharmony_ci o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): Number 951cb0ef41Sopenharmony_ci labels Bailout(Smi) { 961cb0ef41Sopenharmony_ci let k: Smi = 0; 971cb0ef41Sopenharmony_ci const smiLen = Cast<Smi>(len) otherwise goto Bailout(k); 981cb0ef41Sopenharmony_ci const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k); 991cb0ef41Sopenharmony_ci let fastOW = NewFastJSArrayWitness(fastO); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci // Build a fast loop over the smi array. 1021cb0ef41Sopenharmony_ci for (; k < smiLen; k++) { 1031cb0ef41Sopenharmony_ci fastOW.Recheck() otherwise goto Bailout(k); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci // Ensure that we haven't walked beyond a possibly updated length. 1061cb0ef41Sopenharmony_ci if (k >= fastOW.Get().length) goto Bailout(k); 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci const value: JSAny = fastOW.LoadElementOrUndefined(k); 1091cb0ef41Sopenharmony_ci const testResult: JSAny = 1101cb0ef41Sopenharmony_ci Call(context, callbackfn, thisArg, value, k, fastOW.Get()); 1111cb0ef41Sopenharmony_ci if (ToBoolean(testResult)) { 1121cb0ef41Sopenharmony_ci return k; 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci return -1; 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex 1191cb0ef41Sopenharmony_citransitioning javascript builtin 1201cb0ef41Sopenharmony_ciArrayPrototypeFindIndex( 1211cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 1221cb0ef41Sopenharmony_ci try { 1231cb0ef41Sopenharmony_ci RequireObjectCoercible(receiver, 'Array.prototype.findIndex'); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci // 1. Let O be ? ToObject(this value). 1261cb0ef41Sopenharmony_ci const o: JSReceiver = ToObject_Inline(context, receiver); 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci // 2. Let len be ? ToLength(? Get(O, "length")). 1291cb0ef41Sopenharmony_ci const len: Number = GetLengthProperty(o); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. 1321cb0ef41Sopenharmony_ci if (arguments.length == 0) { 1331cb0ef41Sopenharmony_ci goto NotCallableError; 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci const callbackfn = Cast<Callable>(arguments[0]) otherwise NotCallableError; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci // 4. If thisArg is present, let T be thisArg; else let T be undefined. 1381cb0ef41Sopenharmony_ci const thisArg: JSAny = arguments[1]; 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci // Special cases. 1411cb0ef41Sopenharmony_ci try { 1421cb0ef41Sopenharmony_ci return FastArrayFindIndex(o, len, callbackfn, thisArg) 1431cb0ef41Sopenharmony_ci otherwise Bailout; 1441cb0ef41Sopenharmony_ci } label Bailout(k: Smi) deferred { 1451cb0ef41Sopenharmony_ci return ArrayFindIndexLoopContinuation(o, callbackfn, thisArg, o, k, len); 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci } label NotCallableError deferred { 1481cb0ef41Sopenharmony_ci ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci} 1511cb0ef41Sopenharmony_ci} 152