LCOV - code coverage report
Current view: top level - src/builtins - builtins-array-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1509 1520 99.3 %
Date: 2019-01-20 Functions: 202 222 91.0 %

          Line data    Source code
       1             : // Copyright 2017 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             : 
       5             : #include "src/builtins/builtins-array-gen.h"
       6             : 
       7             : #include "src/builtins/builtins-iterator-gen.h"
       8             : #include "src/builtins/builtins-string-gen.h"
       9             : #include "src/builtins/builtins-typed-array-gen.h"
      10             : #include "src/builtins/builtins-utils-gen.h"
      11             : #include "src/builtins/builtins.h"
      12             : #include "src/code-stub-assembler.h"
      13             : #include "src/frame-constants.h"
      14             : #include "src/heap/factory-inl.h"
      15             : #include "src/objects/arguments-inl.h"
      16             : #include "src/objects/property-cell.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : using Node = compiler::Node;
      22             : using IteratorRecord = IteratorBuiltinsFromDSLAssembler::IteratorRecord;
      23             : 
      24        3752 : ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
      25             :     compiler::CodeAssemblerState* state)
      26             :     : CodeStubAssembler(state),
      27             :       k_(this, MachineRepresentation::kTagged),
      28             :       a_(this, MachineRepresentation::kTagged),
      29             :       to_(this, MachineRepresentation::kTagged, SmiConstant(0)),
      30       18760 :       fully_spec_compliant_(this, {&k_, &a_, &to_}) {}
      31             : 
      32         112 : void ArrayBuiltinsAssembler::FindResultGenerator() {
      33         224 :   a_.Bind(UndefinedConstant());
      34         112 : }
      35             : 
      36         784 : Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
      37             :   Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      38        1568 :                        this_arg(), k_value, k, o());
      39         784 :   Label false_continue(this), return_true(this);
      40         784 :   BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
      41         784 :   BIND(&return_true);
      42         784 :   ReturnFromBuiltin(k_value);
      43         784 :   BIND(&false_continue);
      44         784 :   return a();
      45             :   }
      46             : 
      47         112 :   void ArrayBuiltinsAssembler::FindIndexResultGenerator() {
      48         224 :     a_.Bind(SmiConstant(-1));
      49         112 :   }
      50             : 
      51         784 :   Node* ArrayBuiltinsAssembler::FindIndexProcessor(Node* k_value, Node* k) {
      52             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      53        1568 :                          this_arg(), k_value, k, o());
      54         784 :     Label false_continue(this), return_true(this);
      55         784 :     BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
      56         784 :     BIND(&return_true);
      57         784 :     ReturnFromBuiltin(k);
      58         784 :     BIND(&false_continue);
      59         784 :     return a();
      60             :   }
      61             : 
      62          56 :   void ArrayBuiltinsAssembler::ForEachResultGenerator() {
      63         112 :     a_.Bind(UndefinedConstant());
      64          56 :   }
      65             : 
      66         616 :   Node* ArrayBuiltinsAssembler::ForEachProcessor(Node* k_value, Node* k) {
      67             :     CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(),
      68        1232 :            k_value, k, o());
      69         616 :     return a();
      70             :   }
      71             : 
      72         112 :   void ArrayBuiltinsAssembler::SomeResultGenerator() {
      73         224 :     a_.Bind(FalseConstant());
      74         112 :   }
      75             : 
      76         784 :   Node* ArrayBuiltinsAssembler::SomeProcessor(Node* k_value, Node* k) {
      77             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      78        1568 :                          this_arg(), k_value, k, o());
      79         784 :     Label false_continue(this), return_true(this);
      80         784 :     BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
      81         784 :     BIND(&return_true);
      82        1568 :     ReturnFromBuiltin(TrueConstant());
      83         784 :     BIND(&false_continue);
      84         784 :     return a();
      85             :   }
      86             : 
      87         112 :   void ArrayBuiltinsAssembler::EveryResultGenerator() {
      88         224 :     a_.Bind(TrueConstant());
      89         112 :   }
      90             : 
      91         784 :   Node* ArrayBuiltinsAssembler::EveryProcessor(Node* k_value, Node* k) {
      92             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      93        1568 :                          this_arg(), k_value, k, o());
      94         784 :     Label true_continue(this), return_false(this);
      95         784 :     BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
      96         784 :     BIND(&return_false);
      97        1568 :     ReturnFromBuiltin(FalseConstant());
      98         784 :     BIND(&true_continue);
      99         784 :     return a();
     100             :   }
     101             : 
     102         224 :   void ArrayBuiltinsAssembler::ReduceResultGenerator() {
     103         224 :     return a_.Bind(this_arg());
     104             :   }
     105             : 
     106        3136 :   Node* ArrayBuiltinsAssembler::ReduceProcessor(Node* k_value, Node* k) {
     107        1568 :     VARIABLE(result, MachineRepresentation::kTagged);
     108        4704 :     Label done(this, {&result}), initial(this);
     109        3136 :     GotoIf(WordEqual(a(), TheHoleConstant()), &initial);
     110             :     result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
     111        4704 :                        UndefinedConstant(), a(), k_value, k, o()));
     112        1568 :     Goto(&done);
     113             : 
     114        1568 :     BIND(&initial);
     115        1568 :     result.Bind(k_value);
     116        1568 :     Goto(&done);
     117             : 
     118        1568 :     BIND(&done);
     119        3136 :     return result.value();
     120             :   }
     121             : 
     122        1568 :   void ArrayBuiltinsAssembler::ReducePostLoopAction() {
     123        1568 :     Label ok(this);
     124        3136 :     GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok);
     125        1568 :     ThrowTypeError(context(), MessageTemplate::kReduceNoInitial);
     126        1568 :     BIND(&ok);
     127        1568 :   }
     128             : 
     129          56 :   void ArrayBuiltinsAssembler::MapResultGenerator() {
     130          56 :     GenerateArraySpeciesCreate(len_);
     131          56 :   }
     132             : 
     133          56 :   void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() {
     134             :     // 6. Let A be ? TypedArraySpeciesCreate(O, len).
     135             :     TNode<JSTypedArray> original_array = CAST(o());
     136          56 :     TNode<Smi> length = CAST(len_);
     137             :     const char* method_name = "%TypedArray%.prototype.map";
     138             : 
     139             :     TypedArrayBuiltinsAssembler typedarray_asm(state());
     140             :     TNode<JSTypedArray> a = typedarray_asm.TypedArraySpeciesCreateByLength(
     141          56 :         context(), original_array, length, method_name);
     142             :     // In the Spec and our current implementation, the length check is already
     143             :     // performed in TypedArraySpeciesCreate.
     144             :     CSA_ASSERT(this, SmiLessThanOrEqual(CAST(len_), LoadJSTypedArrayLength(a)));
     145         112 :     fast_typed_array_target_ =
     146          56 :         Word32Equal(LoadInstanceType(LoadElements(original_array)),
     147         336 :                     LoadInstanceType(LoadElements(a)));
     148          56 :     a_.Bind(a);
     149          56 :   }
     150             : 
     151          56 :   Node* ArrayBuiltinsAssembler::SpecCompliantMapProcessor(Node* k_value,
     152          56 :                                                           Node* k) {
     153             :     //  i. Let kValue be ? Get(O, Pk). Performed by the caller of
     154             :     //  SpecCompliantMapProcessor.
     155             :     // ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O).
     156             :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
     157         112 :                                 callbackfn(), this_arg(), k_value, k, o());
     158             : 
     159             :     // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     160             :     CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mapped_value);
     161          56 :     return a();
     162             :   }
     163             : 
     164         112 :   Node* ArrayBuiltinsAssembler::FastMapProcessor(Node* k_value, Node* k) {
     165             :     //  i. Let kValue be ? Get(O, Pk). Performed by the caller of
     166             :     //  FastMapProcessor.
     167             :     // ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O).
     168             :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
     169         224 :                                 callbackfn(), this_arg(), k_value, k, o());
     170             : 
     171             :     // mode is SMI_PARAMETERS because k has tagged representation.
     172             :     ParameterMode mode = SMI_PARAMETERS;
     173         112 :     Label runtime(this), finished(this);
     174         112 :     Label transition_pre(this), transition_smi_fast(this),
     175         112 :         transition_smi_double(this);
     176         112 :     Label array_not_smi(this), array_fast(this), array_double(this);
     177             : 
     178         112 :     TNode<Int32T> kind = LoadElementsKind(a());
     179             :     Node* elements = LoadElements(a());
     180         224 :     GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), &array_not_smi);
     181             :     TryStoreArrayElement(HOLEY_SMI_ELEMENTS, mode, &transition_pre, elements, k,
     182         112 :                          mapped_value);
     183         112 :     Goto(&finished);
     184             : 
     185         112 :     BIND(&transition_pre);
     186             :     {
     187             :       // array is smi. Value is either tagged or a heap number.
     188             :       CSA_ASSERT(this, TaggedIsNotSmi(mapped_value));
     189         336 :       GotoIf(IsHeapNumberMap(LoadMap(mapped_value)), &transition_smi_double);
     190         112 :       Goto(&transition_smi_fast);
     191             :     }
     192             : 
     193         112 :     BIND(&array_not_smi);
     194             :     {
     195             :       Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &array_double,
     196         224 :              &array_fast);
     197             :     }
     198             : 
     199         112 :     BIND(&transition_smi_fast);
     200             :     {
     201             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     202         224 :       Node* const native_context = LoadNativeContext(context());
     203             :       Node* const fast_map = LoadContextElement(
     204         224 :           native_context, Context::JS_ARRAY_HOLEY_ELEMENTS_MAP_INDEX);
     205             : 
     206             :       // Since this transition is only a map change, just do it right here.
     207             :       // Since a() doesn't have an allocation site, it's safe to do the
     208             :       // map store directly, otherwise I'd call TransitionElementsKind().
     209         112 :       StoreMap(a(), fast_map);
     210         112 :       Goto(&array_fast);
     211             :     }
     212             : 
     213         112 :     BIND(&array_fast);
     214             :     {
     215             :       TryStoreArrayElement(HOLEY_ELEMENTS, mode, &runtime, elements, k,
     216         112 :                            mapped_value);
     217         112 :       Goto(&finished);
     218             :     }
     219             : 
     220         112 :     BIND(&transition_smi_double);
     221             :     {
     222             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     223         224 :       Node* const native_context = LoadNativeContext(context());
     224             :       Node* const double_map = LoadContextElement(
     225         224 :           native_context, Context::JS_ARRAY_HOLEY_DOUBLE_ELEMENTS_MAP_INDEX);
     226             : 
     227             :       const ElementsKind kFromKind = HOLEY_SMI_ELEMENTS;
     228             :       const ElementsKind kToKind = HOLEY_DOUBLE_ELEMENTS;
     229             : 
     230             :       Label transition_in_runtime(this, Label::kDeferred);
     231             :       TransitionElementsKind(a(), double_map, kFromKind, kToKind,
     232         112 :                              &transition_in_runtime);
     233         112 :       Goto(&array_double);
     234             : 
     235         112 :       BIND(&transition_in_runtime);
     236             :       CallRuntime(Runtime::kTransitionElementsKind, context(), a(), double_map);
     237         112 :       Goto(&array_double);
     238             :     }
     239             : 
     240         112 :     BIND(&array_double);
     241             :     {
     242             :       // TODO(mvstanton): If we use a variable for elements and bind it
     243             :       // appropriately, we can avoid an extra load of elements by binding the
     244             :       // value only after a transition from smi to double.
     245             :       elements = LoadElements(a());
     246             :       // If the mapped_value isn't a number, this will bail out to the runtime
     247             :       // to make the transition.
     248             :       TryStoreArrayElement(HOLEY_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
     249         112 :                            mapped_value);
     250         112 :       Goto(&finished);
     251             :     }
     252             : 
     253         112 :     BIND(&runtime);
     254             :     {
     255             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     256             :       CallRuntime(Runtime::kCreateDataProperty, context(), a(), k,
     257             :                   mapped_value);
     258         112 :       Goto(&finished);
     259             :     }
     260             : 
     261         112 :     BIND(&finished);
     262         112 :     return a();
     263             :   }
     264             : 
     265             :   // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map.
     266         616 :   Node* ArrayBuiltinsAssembler::TypedArrayMapProcessor(Node* k_value, Node* k) {
     267             :     // 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »).
     268             :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
     269        1232 :                                 callbackfn(), this_arg(), k_value, k, o());
     270         616 :     Label fast(this), slow(this), done(this), detached(this, Label::kDeferred);
     271             : 
     272             :     // 8. d. Perform ? Set(A, Pk, mapped_value, true).
     273             :     // Since we know that A is a TypedArray, this always ends up in
     274             :     // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then
     275             :     // tc39.github.io/ecma262/#sec-integerindexedelementset .
     276        1232 :     Branch(fast_typed_array_target_, &fast, &slow);
     277             : 
     278         616 :     BIND(&fast);
     279             :     // #sec-integerindexedelementset
     280             :     // 5. If arrayTypeName is "BigUint64Array" or "BigInt64Array", let
     281             :     // numValue be ? ToBigInt(v).
     282             :     // 6. Otherwise, let numValue be ? ToNumber(value).
     283             :     Node* num_value;
     284         616 :     if (source_elements_kind_ == BIGINT64_ELEMENTS ||
     285             :         source_elements_kind_ == BIGUINT64_ELEMENTS) {
     286         224 :       num_value = ToBigInt(context(), mapped_value);
     287             :     } else {
     288        1008 :       num_value = ToNumber_Inline(context(), mapped_value);
     289             :     }
     290             :     // The only way how this can bailout is because of a detached buffer.
     291             :     EmitElementStore(a(), k, num_value, source_elements_kind_,
     292             :                      KeyedAccessStoreMode::STANDARD_STORE, &detached,
     293        1232 :                      context());
     294         616 :     Goto(&done);
     295             : 
     296         616 :     BIND(&slow);
     297             :     SetPropertyStrict(context(), CAST(a()), CAST(k), CAST(mapped_value));
     298         616 :     Goto(&done);
     299             : 
     300         616 :     BIND(&detached);
     301             :     // tc39.github.io/ecma262/#sec-integerindexedelementset
     302             :     // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
     303        1232 :     ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_);
     304             : 
     305         616 :     BIND(&done);
     306         616 :     return a();
     307             :   }
     308             : 
     309        4536 :   void ArrayBuiltinsAssembler::NullPostLoopAction() {}
     310             : 
     311           0 :   void ArrayBuiltinsAssembler::FillFixedArrayWithSmiZero(
     312             :       TNode<FixedArray> array, TNode<Smi> smi_length) {
     313             :     CSA_ASSERT(this, Word32BinaryNot(IsFixedDoubleArray(array)));
     314             : 
     315           0 :     TNode<IntPtrT> length = SmiToIntPtr(smi_length);
     316             :     TNode<WordT> byte_length = TimesTaggedSize(length);
     317             :     CSA_ASSERT(this, UintPtrLessThan(length, byte_length));
     318             : 
     319             :     static const int32_t fa_base_data_offset =
     320             :         FixedArray::kHeaderSize - kHeapObjectTag;
     321             :     TNode<IntPtrT> backing_store = IntPtrAdd(
     322           0 :         BitcastTaggedToWord(array), IntPtrConstant(fa_base_data_offset));
     323             : 
     324             :     // Call out to memset to perform initialization.
     325             :     TNode<ExternalReference> memset =
     326           0 :         ExternalConstant(ExternalReference::libc_memset_function());
     327             :     STATIC_ASSERT(kSizetSize == kIntptrSize);
     328             :     CallCFunction3(MachineType::Pointer(), MachineType::Pointer(),
     329             :                    MachineType::IntPtr(), MachineType::UintPtr(), memset,
     330           0 :                    backing_store, IntPtrConstant(0), byte_length);
     331           0 :   }
     332             : 
     333        9240 :   void ArrayBuiltinsAssembler::ReturnFromBuiltin(Node* value) {
     334        9240 :     if (argc_ == nullptr) {
     335         224 :       Return(value);
     336             :     } else {
     337             :       // argc_ doesn't include the receiver, so it has to be added back in
     338             :       // manually.
     339       18032 :       PopAndReturn(IntPtrAdd(argc_, IntPtrConstant(1)), value);
     340             :     }
     341        9240 :   }
     342             : 
     343           0 :   void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinBody(
     344             :       TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
     345             :       Node* this_arg, TNode<IntPtrT> argc) {
     346             :     context_ = context;
     347             :     receiver_ = receiver;
     348         840 :     callbackfn_ = callbackfn;
     349         840 :     this_arg_ = this_arg;
     350             :     argc_ = argc;
     351           0 :   }
     352             : 
     353         392 :   void ArrayBuiltinsAssembler::GenerateIteratingArrayBuiltinBody(
     354             :       const char* name, const BuiltinResultGenerator& generator,
     355             :       const CallResultProcessor& processor, const PostLoopAction& action,
     356             :       const Callable& slow_case_continuation,
     357        1568 :       MissingPropertyMode missing_property_mode, ForEachDirection direction) {
     358        1568 :     Label non_array(this), array_changes(this, {&k_, &a_, &to_});
     359             : 
     360             :     // TODO(danno): Seriously? Do we really need to throw the exact error
     361             :     // message on null and undefined so that the webkit tests pass?
     362         392 :     Label throw_null_undefined_exception(this, Label::kDeferred);
     363         784 :     GotoIf(IsNullOrUndefined(receiver()), &throw_null_undefined_exception);
     364             : 
     365             :     // By the book: taken directly from the ECMAScript 2015 specification
     366             : 
     367             :     // 1. Let O be ToObject(this value).
     368             :     // 2. ReturnIfAbrupt(O)
     369         392 :     o_ = ToObject_Inline(context(), receiver());
     370             : 
     371             :     // 3. Let len be ToLength(Get(O, "length")).
     372             :     // 4. ReturnIfAbrupt(len).
     373             :     TVARIABLE(Number, merged_length);
     374         392 :     Label has_length(this, &merged_length), not_js_array(this);
     375         784 :     GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), &not_js_array);
     376         392 :     merged_length = LoadJSArrayLength(CAST(o()));
     377         392 :     Goto(&has_length);
     378             : 
     379         392 :     BIND(&not_js_array);
     380             :     {
     381             :       Node* len_property =
     382        1176 :           GetProperty(context(), o(), isolate()->factory()->length_string());
     383         784 :       merged_length = ToLength_Inline(context(), len_property);
     384         392 :       Goto(&has_length);
     385             :     }
     386         392 :     BIND(&has_length);
     387             :     {
     388             :       len_ = merged_length.value();
     389             : 
     390             :       // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
     391             :       Label type_exception(this, Label::kDeferred);
     392         392 :       Label done(this);
     393         784 :       GotoIf(TaggedIsSmi(callbackfn()), &type_exception);
     394        1176 :       Branch(IsCallableMap(LoadMap(callbackfn())), &done, &type_exception);
     395             : 
     396         392 :       BIND(&throw_null_undefined_exception);
     397             :       ThrowTypeError(context(), MessageTemplate::kCalledOnNullOrUndefined,
     398         392 :                      name);
     399             : 
     400         392 :       BIND(&type_exception);
     401             :       ThrowTypeError(context(), MessageTemplate::kCalledNonCallable,
     402         392 :                      callbackfn());
     403             : 
     404         784 :       BIND(&done);
     405             :     }
     406             : 
     407             :     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
     408             :     // [Already done by the arguments adapter]
     409             : 
     410         392 :     if (direction == ForEachDirection::kForward) {
     411             :       // 7. Let k be 0.
     412         672 :       k_.Bind(SmiConstant(0));
     413             :     } else {
     414         112 :       k_.Bind(NumberDec(len()));
     415             :     }
     416             : 
     417         392 :     generator(this);
     418             : 
     419             :     HandleFastElements(processor, action, &fully_spec_compliant_, direction,
     420         392 :                        missing_property_mode);
     421             : 
     422         392 :     BIND(&fully_spec_compliant_);
     423             : 
     424             :     Node* result =
     425             :         CallStub(slow_case_continuation, context(), receiver(), callbackfn(),
     426        1176 :                  this_arg(), a_.value(), o(), k_.value(), len(), to_.value());
     427         784 :     ReturnFromBuiltin(result);
     428         392 :   }
     429             : 
     430           0 :   void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinLoopContinuation(
     431             :       TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
     432             :       Node* this_arg, Node* a, TNode<JSReceiver> o, Node* initial_k,
     433             :       TNode<Number> len, Node* to) {
     434             :     context_ = context;
     435         392 :     this_arg_ = this_arg;
     436         392 :     callbackfn_ = callbackfn;
     437         392 :     a_.Bind(a);
     438         392 :     k_.Bind(initial_k);
     439             :     o_ = o;
     440             :     len_ = len;
     441         392 :     to_.Bind(to);
     442           0 :   }
     443             : 
     444         448 :   void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody(
     445             :       const char* name, const BuiltinResultGenerator& generator,
     446             :       const CallResultProcessor& processor, const PostLoopAction& action,
     447             :       ForEachDirection direction) {
     448         448 :     name_ = name;
     449             : 
     450             :     // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
     451             : 
     452         448 :     Label throw_not_typed_array(this, Label::kDeferred);
     453             : 
     454         896 :     GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
     455             :     GotoIfNot(HasInstanceType(CAST(receiver_), JS_TYPED_ARRAY_TYPE),
     456         896 :               &throw_not_typed_array);
     457             : 
     458             :     TNode<JSTypedArray> typed_array = CAST(receiver_);
     459             :     o_ = typed_array;
     460             : 
     461             :     TNode<JSArrayBuffer> array_buffer =
     462         448 :         LoadJSArrayBufferViewBuffer(typed_array);
     463         896 :     ThrowIfArrayBufferIsDetached(context_, array_buffer, name_);
     464             : 
     465         896 :     len_ = LoadJSTypedArrayLength(typed_array);
     466             : 
     467         448 :     Label throw_not_callable(this, Label::kDeferred);
     468         448 :     Label distinguish_types(this);
     469        1344 :     GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable);
     470        1344 :     Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types,
     471         896 :            &throw_not_callable);
     472             : 
     473         448 :     BIND(&throw_not_typed_array);
     474         448 :     ThrowTypeError(context_, MessageTemplate::kNotTypedArray);
     475             : 
     476         448 :     BIND(&throw_not_callable);
     477         896 :     ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_);
     478             : 
     479         448 :     Label unexpected_instance_type(this);
     480         448 :     BIND(&unexpected_instance_type);
     481         448 :     Unreachable();
     482             : 
     483             :     std::vector<int32_t> instance_types = {
     484             : #define INSTANCE_TYPE(Type, type, TYPE, ctype) FIXED_##TYPE##_ARRAY_TYPE,
     485             :         TYPED_ARRAYS(INSTANCE_TYPE)
     486             : #undef INSTANCE_TYPE
     487             :     };
     488         448 :     std::vector<Label> labels;
     489       10752 :     for (size_t i = 0; i < instance_types.size(); ++i) {
     490        4928 :       labels.push_back(Label(this));
     491             :     }
     492             :     std::vector<Label*> label_ptrs;
     493        5824 :     for (Label& label : labels) {
     494        9856 :       label_ptrs.push_back(&label);
     495             :     }
     496             : 
     497         448 :     BIND(&distinguish_types);
     498             : 
     499         448 :     generator(this);
     500             : 
     501         448 :     if (direction == ForEachDirection::kForward) {
     502         784 :       k_.Bind(SmiConstant(0));
     503             :     } else {
     504         112 :       k_.Bind(NumberDec(len()));
     505             :     }
     506             :     CSA_ASSERT(this, IsSafeInteger(k()));
     507         896 :     Node* instance_type = LoadInstanceType(LoadElements(typed_array));
     508             :     Switch(instance_type, &unexpected_instance_type, instance_types.data(),
     509         896 :            label_ptrs.data(), labels.size());
     510             : 
     511       10752 :     for (size_t i = 0; i < labels.size(); ++i) {
     512        4928 :       BIND(&labels[i]);
     513             :       Label done(this);
     514             :       source_elements_kind_ = ElementsKindForInstanceType(
     515        9856 :           static_cast<InstanceType>(instance_types[i]));
     516             :       // TODO(tebbi): Silently cancelling the loop on buffer detachment is a
     517             :       // spec violation. Should go to &throw_detached and throw a TypeError
     518             :       // instead.
     519             :       VisitAllTypedArrayElements(array_buffer, processor, &done, direction,
     520        4928 :                                  typed_array);
     521        4928 :       Goto(&done);
     522             :       // No exception, return success
     523        4928 :       BIND(&done);
     524        4928 :       action(this);
     525        4928 :       ReturnFromBuiltin(a_.value());
     526        5376 :     }
     527         448 :   }
     528             : 
     529         392 :   void ArrayBuiltinsAssembler::GenerateIteratingArrayBuiltinLoopContinuation(
     530             :       const CallResultProcessor& processor, const PostLoopAction& action,
     531             :       MissingPropertyMode missing_property_mode, ForEachDirection direction) {
     532         784 :     Label loop(this, {&k_, &a_, &to_});
     533         392 :     Label after_loop(this);
     534         392 :     Goto(&loop);
     535         392 :     BIND(&loop);
     536             :     {
     537         392 :       if (direction == ForEachDirection::kForward) {
     538             :         // 8. Repeat, while k < len
     539         336 :         GotoIfNumberGreaterThanOrEqual(k(), len_, &after_loop);
     540             :       } else {
     541             :         // OR
     542             :         // 10. Repeat, while k >= 0
     543         112 :         GotoIfNumberGreaterThanOrEqual(SmiConstant(-1), k(), &after_loop);
     544             :       }
     545             : 
     546             :       Label done_element(this, &to_);
     547             :       // a. Let Pk be ToString(k).
     548             :       // k() is guaranteed to be a positive integer, hence ToString is
     549             :       // side-effect free and HasProperty/GetProperty do the conversion inline.
     550             :       CSA_ASSERT(this, IsSafeInteger(k()));
     551             : 
     552         392 :       if (missing_property_mode == MissingPropertyMode::kSkip) {
     553             :         // b. Let kPresent be HasProperty(O, Pk).
     554             :         // c. ReturnIfAbrupt(kPresent).
     555             :         TNode<Oddball> k_present =
     556         280 :             HasProperty(context(), o(), k(), kHasProperty);
     557             : 
     558             :         // d. If kPresent is true, then
     559         560 :         GotoIf(IsFalse(k_present), &done_element);
     560             :       }
     561             : 
     562             :       // i. Let kValue be Get(O, Pk).
     563             :       // ii. ReturnIfAbrupt(kValue).
     564             :       Node* k_value = GetProperty(context(), o(), k());
     565             : 
     566             :       // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
     567             :       // iv. ReturnIfAbrupt(funcResult).
     568         392 :       a_.Bind(processor(this, k_value, k()));
     569         392 :       Goto(&done_element);
     570             : 
     571         392 :       BIND(&done_element);
     572             : 
     573         392 :       if (direction == ForEachDirection::kForward) {
     574             :         // e. Increase k by 1.
     575         672 :         k_.Bind(NumberInc(k()));
     576             :       } else {
     577             :         // e. Decrease k by 1.
     578         112 :         k_.Bind(NumberDec(k()));
     579             :       }
     580         392 :       Goto(&loop);
     581             :     }
     582         392 :     BIND(&after_loop);
     583             : 
     584         392 :     action(this);
     585        1176 :     Return(a_.value());
     586         392 :   }
     587             : 
     588        4928 :   ElementsKind ArrayBuiltinsAssembler::ElementsKindForInstanceType(
     589             :       InstanceType type) {
     590        4928 :     switch (type) {
     591             : #define INSTANCE_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype) \
     592             :   case FIXED_##TYPE##_ARRAY_TYPE:                               \
     593             :     return TYPE##_ELEMENTS;
     594             : 
     595         448 :       TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
     596             : #undef INSTANCE_TYPE_TO_ELEMENTS_KIND
     597             : 
     598             :       default:
     599           0 :         UNREACHABLE();
     600             :     }
     601             :   }
     602             : 
     603        4928 :   void ArrayBuiltinsAssembler::VisitAllTypedArrayElements(
     604             :       Node* array_buffer, const CallResultProcessor& processor, Label* detached,
     605             :       ForEachDirection direction, TNode<JSTypedArray> typed_array) {
     606        9856 :     VariableList list({&a_, &k_, &to_}, zone());
     607             : 
     608        4928 :     FastLoopBody body = [&](Node* index) {
     609        9856 :       GotoIf(IsDetachedBuffer(array_buffer), detached);
     610        9856 :       Node* elements = LoadElements(typed_array);
     611             :       Node* base_ptr =
     612        4928 :           LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
     613             :       Node* external_ptr =
     614             :           LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
     615        4928 :                           MachineType::Pointer());
     616       14784 :       Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
     617             :       Node* value = LoadFixedTypedArrayElementAsTagged(
     618        4928 :           data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
     619        4928 :       k_.Bind(index);
     620        4928 :       a_.Bind(processor(this, value, index));
     621        4928 :     };
     622        9856 :     Node* start = SmiConstant(0);
     623             :     Node* end = len_;
     624             :     IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
     625             :     int incr = 1;
     626        4928 :     if (direction == ForEachDirection::kReverse) {
     627             :       std::swap(start, end);
     628             :       advance_mode = IndexAdvanceMode::kPre;
     629             :       incr = -1;
     630             :     }
     631             :     BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS,
     632        4928 :                   advance_mode);
     633        4928 :   }
     634             : 
     635         784 :   void ArrayBuiltinsAssembler::VisitAllFastElementsOneKind(
     636             :       ElementsKind kind, const CallResultProcessor& processor,
     637             :       Label* array_changed, ParameterMode mode, ForEachDirection direction,
     638             :       MissingPropertyMode missing_property_mode, TNode<Smi> length) {
     639         784 :     Comment("begin VisitAllFastElementsOneKind");
     640             :     // We only use this kind of processing if the no-elements protector is
     641             :     // in place at the start. We'll continue checking during array iteration.
     642             :     CSA_ASSERT(this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
     643         784 :     VARIABLE(original_map, MachineRepresentation::kTagged);
     644        1568 :     original_map.Bind(LoadMap(o()));
     645        1568 :     VariableList list({&original_map, &a_, &k_, &to_}, zone());
     646         784 :     Node* start = IntPtrOrSmiConstant(0, mode);
     647             :     Node* end = TaggedToParameter(length, mode);
     648             :     IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse
     649             :                                         ? IndexAdvanceMode::kPre
     650         784 :                                         : IndexAdvanceMode::kPost;
     651         784 :     if (direction == ForEachDirection::kReverse) std::swap(start, end);
     652             :     BuildFastLoop(
     653             :         list, start, end,
     654        2352 :         [=, &original_map](Node* index) {
     655        1568 :           k_.Bind(ParameterToTagged(index, mode));
     656        2352 :           Label one_element_done(this), hole_element(this),
     657        1568 :               process_element(this);
     658             : 
     659             :           // Check if o's map has changed during the callback. If so, we have to
     660             :           // fall back to the slower spec implementation for the rest of the
     661             :           // iteration.
     662        2352 :           Node* o_map = LoadMap(o());
     663        2352 :           GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
     664             : 
     665         784 :           TNode<JSArray> o_array = CAST(o());
     666             :           // Check if o's length has changed during the callback and if the
     667             :           // index is now out of range of the new length.
     668         784 :           GotoIf(SmiGreaterThanOrEqual(CAST(k_.value()),
     669        2352 :                                        CAST(LoadJSArrayLength(o_array))),
     670        2352 :                  array_changed);
     671             : 
     672             :           // Re-load the elements array. If may have been resized.
     673         784 :           Node* elements = LoadElements(o_array);
     674             : 
     675             :           // Fast case: load the element directly from the elements FixedArray
     676             :           // and call the callback if the element is not the hole.
     677             :           DCHECK(kind == PACKED_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS);
     678         784 :           int base_size = kind == PACKED_ELEMENTS
     679             :                               ? FixedArray::kHeaderSize
     680         784 :                               : (FixedArray::kHeaderSize - kHeapObjectTag);
     681        1568 :           Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
     682        1568 :           VARIABLE(value, MachineRepresentation::kTagged);
     683         784 :           if (kind == PACKED_ELEMENTS) {
     684         784 :             value.Bind(LoadObjectField(elements, offset));
     685        1176 :             GotoIf(WordEqual(value.value(), TheHoleConstant()), &hole_element);
     686             :           } else {
     687             :             Node* double_value =
     688         784 :                 LoadDoubleWithHoleCheck(elements, offset, &hole_element);
     689         784 :             value.Bind(AllocateHeapNumberWithValue(double_value));
     690             :           }
     691         784 :           Goto(&process_element);
     692             : 
     693         784 :           BIND(&hole_element);
     694         784 :           if (missing_property_mode == MissingPropertyMode::kSkip) {
     695             :             // The NoElementsProtectorCell could go invalid during callbacks.
     696         560 :             Branch(IsNoElementsProtectorCellInvalid(), array_changed,
     697        1680 :                    &one_element_done);
     698             :           } else {
     699         448 :             value.Bind(UndefinedConstant());
     700         224 :             Goto(&process_element);
     701             :           }
     702         784 :           BIND(&process_element);
     703             :           {
     704        1568 :             a_.Bind(processor(this, value.value(), k()));
     705         784 :             Goto(&one_element_done);
     706             :           }
     707         784 :           BIND(&one_element_done);
     708         784 :         },
     709        3136 :         1, mode, advance_mode);
     710         784 :     Comment("end VisitAllFastElementsOneKind");
     711         784 :   }
     712             : 
     713         392 :   void ArrayBuiltinsAssembler::HandleFastElements(
     714             :       const CallResultProcessor& processor, const PostLoopAction& action,
     715             :       Label* slow, ForEachDirection direction,
     716             :       MissingPropertyMode missing_property_mode) {
     717         784 :     Label switch_on_elements_kind(this), fast_elements(this),
     718         392 :         maybe_double_elements(this), fast_double_elements(this);
     719             : 
     720         392 :     Comment("begin HandleFastElements");
     721             :     // Non-smi lengths must use the slow path.
     722         784 :     GotoIf(TaggedIsNotSmi(len()), slow);
     723             : 
     724             :     BranchIfFastJSArray(o(), context(),
     725         392 :                         &switch_on_elements_kind, slow);
     726             : 
     727         392 :     BIND(&switch_on_elements_kind);
     728         392 :     TNode<Smi> smi_len = CAST(len());
     729             :     // Select by ElementsKind
     730         784 :     Node* kind = LoadElementsKind(o());
     731             :     Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
     732         784 :            &maybe_double_elements, &fast_elements);
     733             : 
     734             :     ParameterMode mode = OptimalParameterMode();
     735         392 :     BIND(&fast_elements);
     736             :     {
     737             :       VisitAllFastElementsOneKind(PACKED_ELEMENTS, processor, slow, mode,
     738         392 :                                   direction, missing_property_mode, smi_len);
     739             : 
     740         392 :       action(this);
     741             : 
     742             :       // No exception, return success
     743         392 :       ReturnFromBuiltin(a_.value());
     744             :     }
     745             : 
     746         392 :     BIND(&maybe_double_elements);
     747             :     Branch(IsElementsKindGreaterThan(kind, HOLEY_DOUBLE_ELEMENTS), slow,
     748         784 :            &fast_double_elements);
     749             : 
     750         392 :     BIND(&fast_double_elements);
     751             :     {
     752             :       VisitAllFastElementsOneKind(PACKED_DOUBLE_ELEMENTS, processor, slow, mode,
     753         392 :                                   direction, missing_property_mode, smi_len);
     754             : 
     755         392 :       action(this);
     756             : 
     757             :       // No exception, return success
     758         392 :       ReturnFromBuiltin(a_.value());
     759         392 :     }
     760         392 :   }
     761             : 
     762             :   // Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
     763          56 :   void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate(TNode<Number> len) {
     764         112 :     Label runtime(this, Label::kDeferred), done(this);
     765             : 
     766         112 :     Node* const original_map = LoadMap(o());
     767             :     GotoIfNot(
     768         112 :         InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE),
     769         112 :         &runtime);
     770             : 
     771          56 :     GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
     772         112 :               &runtime);
     773             : 
     774         112 :     Node* species_protector = ArraySpeciesProtectorConstant();
     775             :     Node* value =
     776             :         LoadObjectField(species_protector, PropertyCell::kValueOffset);
     777         112 :     Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
     778         112 :     GotoIf(WordEqual(value, protector_invalid), &runtime);
     779             : 
     780         112 :     GotoIfNot(TaggedIsPositiveSmi(len), &runtime);
     781             :     GotoIfNot(
     782             :         IsValidFastJSArrayCapacity(len, CodeStubAssembler::SMI_PARAMETERS),
     783         112 :         &runtime);
     784             : 
     785             :     // We need to be conservative and start with holey because the builtins
     786             :     // that create output arrays aren't guaranteed to be called for every
     787             :     // element in the input array (maybe the callback deletes an element).
     788             :     const ElementsKind elements_kind =
     789             :         GetHoleyElementsKind(GetInitialFastElementsKind());
     790          56 :     TNode<Context> native_context = LoadNativeContext(context());
     791             :     TNode<Map> array_map =
     792          56 :         LoadJSArrayElementsMap(elements_kind, native_context);
     793             :     a_.Bind(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, len, CAST(len),
     794             :                             nullptr, CodeStubAssembler::SMI_PARAMETERS,
     795         112 :                             kAllowLargeObjectAllocation));
     796             : 
     797          56 :     Goto(&done);
     798             : 
     799          56 :     BIND(&runtime);
     800             :     {
     801             :       // 5. Let A be ? ArraySpeciesCreate(O, len).
     802             :       TNode<JSReceiver> constructor =
     803          56 :           CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()));
     804         112 :       a_.Bind(Construct(context(), constructor, len));
     805          56 :       Goto(&fully_spec_compliant_);
     806             :     }
     807             : 
     808         112 :     BIND(&done);
     809          56 :   }
     810             : 
     811         168 : TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) {
     812             :   TNode<Int32T> argc =
     813             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
     814             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     815             :   CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
     816             : 
     817         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     818          56 :   TNode<Object> receiver = args.GetReceiver();
     819             : 
     820             :   Label runtime(this, Label::kDeferred);
     821          56 :   Label fast(this);
     822             : 
     823             :   // Only pop in this stub if
     824             :   // 1) the array has fast elements
     825             :   // 2) the length is writable,
     826             :   // 3) the elements backing store isn't copy-on-write,
     827             :   // 4) we aren't supposed to shrink the backing store.
     828             : 
     829             :   // 1) Check that the array has fast elements.
     830          56 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
     831             : 
     832          56 :   BIND(&fast);
     833             :   {
     834             :     TNode<JSArray> array_receiver = CAST(receiver);
     835             :     CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
     836             :     TNode<IntPtrT> length =
     837          56 :         LoadAndUntagObjectField(array_receiver, JSArray::kLengthOffset);
     838          56 :     Label return_undefined(this), fast_elements(this);
     839         168 :     GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
     840             : 
     841             :     // 2) Ensure that the length is writable.
     842          56 :     EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime);
     843             : 
     844             :     // 3) Check that the elements backing store isn't copy-on-write.
     845             :     TNode<FixedArrayBase> elements = LoadElements(array_receiver);
     846         168 :     GotoIf(WordEqual(LoadMap(elements), LoadRoot(RootIndex::kFixedCOWArrayMap)),
     847          56 :            &runtime);
     848             : 
     849          56 :     TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1));
     850             : 
     851             :     // 4) Check that we're not supposed to shrink the backing store, as
     852             :     //    implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
     853         112 :     TNode<IntPtrT> capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
     854             :     GotoIf(IntPtrLessThan(
     855             :                IntPtrAdd(IntPtrAdd(new_length, new_length),
     856          56 :                          IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
     857          56 :                capacity),
     858         112 :            &runtime);
     859             : 
     860             :     StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
     861         112 :                                    SmiTag(new_length));
     862             : 
     863          56 :     TNode<Int32T> elements_kind = LoadElementsKind(array_receiver);
     864             :     GotoIf(Int32LessThanOrEqual(elements_kind,
     865         112 :                                 Int32Constant(TERMINAL_FAST_ELEMENTS_KIND)),
     866         112 :            &fast_elements);
     867             : 
     868             :     Node* value = LoadFixedDoubleArrayElement(CAST(elements), new_length,
     869          56 :                                               &return_undefined);
     870             : 
     871          56 :     StoreFixedDoubleArrayHole(CAST(elements), new_length);
     872         112 :     args.PopAndReturn(AllocateHeapNumberWithValue(value));
     873             : 
     874          56 :     BIND(&fast_elements);
     875             :     {
     876             :       Node* value = LoadFixedArrayElement(CAST(elements), new_length);
     877         112 :       StoreFixedArrayElement(CAST(elements), new_length, TheHoleConstant());
     878         112 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
     879          56 :       args.PopAndReturn(value);
     880             :     }
     881             : 
     882          56 :     BIND(&return_undefined);
     883         168 :     { args.PopAndReturn(UndefinedConstant()); }
     884             :   }
     885             : 
     886          56 :   BIND(&runtime);
     887             :   {
     888             :     // We are not using Parameter(Descriptor::kJSTarget) and loading the value
     889             :     // from the current frame here in order to reduce register pressure on the
     890             :     // fast path.
     891          56 :     TNode<JSFunction> target = LoadTargetFromFrame();
     892             :     TailCallBuiltin(Builtins::kArrayPop, context, target, UndefinedConstant(),
     893         112 :                     argc);
     894          56 :   }
     895          56 : }
     896             : 
     897         224 : TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) {
     898          56 :   TVARIABLE(IntPtrT, arg_index);
     899          56 :   Label default_label(this, &arg_index);
     900          56 :   Label smi_transition(this);
     901          56 :   Label object_push_pre(this);
     902          56 :   Label object_push(this, &arg_index);
     903          56 :   Label double_push(this, &arg_index);
     904          56 :   Label double_transition(this);
     905          56 :   Label runtime(this, Label::kDeferred);
     906             : 
     907             :   // TODO(ishell): use constants from Descriptor once the JSFunction linkage
     908             :   // arguments are reordered.
     909             :   TNode<Int32T> argc =
     910             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
     911             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     912             :   CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
     913             : 
     914         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     915          56 :   TNode<Object> receiver = args.GetReceiver();
     916             :   TNode<JSArray> array_receiver;
     917             :   Node* kind = nullptr;
     918             : 
     919          56 :   Label fast(this);
     920          56 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
     921             : 
     922          56 :   BIND(&fast);
     923             :   {
     924             :     array_receiver = CAST(receiver);
     925          56 :     arg_index = IntPtrConstant(0);
     926         112 :     kind = EnsureArrayPushable(LoadMap(array_receiver), &runtime);
     927             :     GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
     928         112 :            &object_push_pre);
     929             : 
     930             :     Node* new_length = BuildAppendJSArray(PACKED_SMI_ELEMENTS, array_receiver,
     931         112 :                                           &args, &arg_index, &smi_transition);
     932          56 :     args.PopAndReturn(new_length);
     933             :   }
     934             : 
     935             :   // If the argument is not a smi, then use a heavyweight SetProperty to
     936             :   // transition the array for only the single next element. If the argument is
     937             :   // a smi, the failure is due to some other reason and we should fall back on
     938             :   // the most generic implementation for the rest of the array.
     939          56 :   BIND(&smi_transition);
     940             :   {
     941         112 :     Node* arg = args.AtIndex(arg_index.value());
     942         112 :     GotoIf(TaggedIsSmi(arg), &default_label);
     943         112 :     Node* length = LoadJSArrayLength(array_receiver);
     944             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
     945             :     // calling into the runtime to do the elements transition is overkill.
     946             :     SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
     947          56 :     Increment(&arg_index);
     948             :     // The runtime SetProperty call could have converted the array to dictionary
     949             :     // mode, which must be detected to abort the fast-path.
     950         112 :     Node* kind = LoadElementsKind(array_receiver);
     951         112 :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
     952         112 :            &default_label);
     953             : 
     954          56 :     GotoIfNotNumber(arg, &object_push);
     955          56 :     Goto(&double_push);
     956             :   }
     957             : 
     958          56 :   BIND(&object_push_pre);
     959             :   {
     960             :     Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &double_push,
     961         112 :            &object_push);
     962             :   }
     963             : 
     964          56 :   BIND(&object_push);
     965             :   {
     966             :     Node* new_length = BuildAppendJSArray(PACKED_ELEMENTS, array_receiver,
     967         112 :                                           &args, &arg_index, &default_label);
     968          56 :     args.PopAndReturn(new_length);
     969             :   }
     970             : 
     971          56 :   BIND(&double_push);
     972             :   {
     973             :     Node* new_length =
     974             :         BuildAppendJSArray(PACKED_DOUBLE_ELEMENTS, array_receiver, &args,
     975         112 :                            &arg_index, &double_transition);
     976          56 :     args.PopAndReturn(new_length);
     977             :   }
     978             : 
     979             :   // If the argument is not a double, then use a heavyweight SetProperty to
     980             :   // transition the array for only the single next element. If the argument is
     981             :   // a double, the failure is due to some other reason and we should fall back
     982             :   // on the most generic implementation for the rest of the array.
     983          56 :   BIND(&double_transition);
     984             :   {
     985         112 :     Node* arg = args.AtIndex(arg_index.value());
     986          56 :     GotoIfNumber(arg, &default_label);
     987         112 :     Node* length = LoadJSArrayLength(array_receiver);
     988             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
     989             :     // calling into the runtime to do the elements transition is overkill.
     990             :     SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
     991          56 :     Increment(&arg_index);
     992             :     // The runtime SetProperty call could have converted the array to dictionary
     993             :     // mode, which must be detected to abort the fast-path.
     994         112 :     Node* kind = LoadElementsKind(array_receiver);
     995         112 :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
     996         112 :            &default_label);
     997          56 :     Goto(&object_push);
     998             :   }
     999             : 
    1000             :   // Fallback that stores un-processed arguments using the full, heavyweight
    1001             :   // SetProperty machinery.
    1002          56 :   BIND(&default_label);
    1003             :   {
    1004             :     args.ForEach(
    1005          56 :         [this, array_receiver, context](Node* arg) {
    1006         112 :           Node* length = LoadJSArrayLength(array_receiver);
    1007          56 :           SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
    1008          56 :         },
    1009         112 :         arg_index.value());
    1010         112 :     args.PopAndReturn(LoadJSArrayLength(array_receiver));
    1011             :   }
    1012             : 
    1013          56 :   BIND(&runtime);
    1014             :   {
    1015             :     // We are not using Parameter(Descriptor::kJSTarget) and loading the value
    1016             :     // from the current frame here in order to reduce register pressure on the
    1017             :     // fast path.
    1018          56 :     TNode<JSFunction> target = LoadTargetFromFrame();
    1019             :     TailCallBuiltin(Builtins::kArrayPush, context, target, UndefinedConstant(),
    1020         112 :                     argc);
    1021             :   }
    1022          56 : }
    1023             : 
    1024         168 : TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
    1025             :   TNode<Int32T> argc =
    1026             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
    1027             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1028             :   CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
    1029             : 
    1030         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
    1031          56 :   TNode<Object> receiver = args.GetReceiver();
    1032             : 
    1033             :   Label runtime(this, Label::kDeferred);
    1034          56 :   Label fast(this);
    1035             : 
    1036             :   // Only shift in this stub if
    1037             :   // 1) the array has fast elements
    1038             :   // 2) the length is writable,
    1039             :   // 3) the elements backing store isn't copy-on-write,
    1040             :   // 4) we aren't supposed to shrink the backing store,
    1041             :   // 5) we aren't supposed to left-trim the backing store.
    1042             : 
    1043             :   // 1) Check that the array has fast elements.
    1044          56 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
    1045             : 
    1046          56 :   BIND(&fast);
    1047             :   {
    1048             :     TNode<JSArray> array_receiver = CAST(receiver);
    1049             :     CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
    1050             : 
    1051             :     // 2) Ensure that the length is writable.
    1052             :     //    This check needs to happen before the check for length zero.
    1053             :     //    The spec requires a "SetProperty(array, 'length', 0)" call when
    1054             :     //    the length is zero. This must throw an exception in the case of a
    1055             :     //    read-only length.
    1056          56 :     EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime);
    1057             : 
    1058             :     TNode<IntPtrT> length =
    1059          56 :         LoadAndUntagObjectField(array_receiver, JSArray::kLengthOffset);
    1060          56 :     Label return_undefined(this), fast_elements_tagged(this),
    1061          56 :         fast_elements_smi(this);
    1062         168 :     GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
    1063             : 
    1064             :     // 3) Check that the elements backing store isn't copy-on-write.
    1065             :     TNode<FixedArrayBase> elements = LoadElements(array_receiver);
    1066         168 :     GotoIf(WordEqual(LoadMap(elements), LoadRoot(RootIndex::kFixedCOWArrayMap)),
    1067          56 :            &runtime);
    1068             : 
    1069          56 :     TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1));
    1070             : 
    1071             :     // 4) Check that we're not supposed to right-trim the backing store, as
    1072             :     //    implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
    1073         168 :     Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
    1074             :     GotoIf(IntPtrLessThan(
    1075             :                IntPtrAdd(IntPtrAdd(new_length, new_length),
    1076          56 :                          IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
    1077          56 :                capacity),
    1078         112 :            &runtime);
    1079             : 
    1080             :     // 5) Check that we're not supposed to left-trim the backing store, as
    1081             :     //    implemented in elements.cc:FastElementsAccessor::MoveElements.
    1082             :     GotoIf(IntPtrGreaterThan(new_length,
    1083         112 :                              IntPtrConstant(JSArray::kMaxCopyElements)),
    1084         112 :            &runtime);
    1085             : 
    1086             :     StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
    1087         112 :                                    SmiTag(new_length));
    1088             : 
    1089          56 :     TNode<IntPtrT> element_zero = IntPtrConstant(0);
    1090          56 :     TNode<IntPtrT> element_one = IntPtrConstant(1);
    1091          56 :     TNode<Int32T> elements_kind = LoadElementsKind(array_receiver);
    1092             :     GotoIf(
    1093         112 :         Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_SMI_ELEMENTS)),
    1094         112 :         &fast_elements_smi);
    1095         112 :     GotoIf(Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
    1096         112 :            &fast_elements_tagged);
    1097             : 
    1098             :     // Fast double elements kind:
    1099             :     {
    1100             :       CSA_ASSERT(this,
    1101             :                  Int32LessThanOrEqual(elements_kind,
    1102             :                                       Int32Constant(HOLEY_DOUBLE_ELEMENTS)));
    1103             : 
    1104         112 :       VARIABLE(result, MachineRepresentation::kTagged, UndefinedConstant());
    1105             : 
    1106          56 :       Label move_elements(this);
    1107             :       result.Bind(AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement(
    1108         168 :           CAST(elements), element_zero, &move_elements)));
    1109          56 :       Goto(&move_elements);
    1110          56 :       BIND(&move_elements);
    1111             : 
    1112             :       MoveElements(HOLEY_DOUBLE_ELEMENTS, elements, element_zero, element_one,
    1113          56 :                    new_length);
    1114          56 :       StoreFixedDoubleArrayHole(CAST(elements), new_length);
    1115         112 :       args.PopAndReturn(result.value());
    1116             :     }
    1117             : 
    1118          56 :     BIND(&fast_elements_tagged);
    1119             :     {
    1120          56 :       TNode<FixedArray> elements_fixed_array = CAST(elements);
    1121         112 :       Node* value = LoadFixedArrayElement(elements_fixed_array, 0);
    1122             :       MoveElements(HOLEY_ELEMENTS, elements, element_zero, element_one,
    1123          56 :                    new_length);
    1124             :       StoreFixedArrayElement(elements_fixed_array, new_length,
    1125         112 :                              TheHoleConstant());
    1126         112 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
    1127          56 :       args.PopAndReturn(value);
    1128             :     }
    1129             : 
    1130          56 :     BIND(&fast_elements_smi);
    1131             :     {
    1132          56 :       TNode<FixedArray> elements_fixed_array = CAST(elements);
    1133         112 :       Node* value = LoadFixedArrayElement(elements_fixed_array, 0);
    1134             :       MoveElements(HOLEY_SMI_ELEMENTS, elements, element_zero, element_one,
    1135          56 :                    new_length);
    1136             :       StoreFixedArrayElement(elements_fixed_array, new_length,
    1137         112 :                              TheHoleConstant());
    1138         112 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
    1139          56 :       args.PopAndReturn(value);
    1140             :     }
    1141             : 
    1142          56 :     BIND(&return_undefined);
    1143         168 :     { args.PopAndReturn(UndefinedConstant()); }
    1144             :   }
    1145             : 
    1146          56 :   BIND(&runtime);
    1147             :   {
    1148             :     // We are not using Parameter(Descriptor::kJSTarget) and loading the value
    1149             :     // from the current frame here in order to reduce register pressure on the
    1150             :     // fast path.
    1151          56 :     TNode<JSFunction> target = LoadTargetFromFrame();
    1152             :     TailCallBuiltin(Builtins::kArrayShift, context, target, UndefinedConstant(),
    1153         112 :                     argc);
    1154          56 :   }
    1155          56 : }
    1156             : 
    1157         224 : TF_BUILTIN(ExtractFastJSArray, ArrayBuiltinsAssembler) {
    1158             :   ParameterMode mode = OptimalParameterMode();
    1159             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1160             :   Node* array = Parameter(Descriptor::kSource);
    1161          56 :   Node* begin = TaggedToParameter(Parameter(Descriptor::kBegin), mode);
    1162             :   Node* count = TaggedToParameter(Parameter(Descriptor::kCount), mode);
    1163             : 
    1164             :   CSA_ASSERT(this, IsJSArray(array));
    1165             :   CSA_ASSERT(this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
    1166             : 
    1167         112 :   Return(ExtractFastJSArray(context, array, begin, count, mode));
    1168          56 : }
    1169             : 
    1170         112 : TF_BUILTIN(CloneFastJSArray, ArrayBuiltinsAssembler) {
    1171             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1172             :   TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
    1173             : 
    1174             :   CSA_ASSERT(this,
    1175             :              Word32Or(Word32BinaryNot(
    1176             :                           IsHoleyFastElementsKind(LoadElementsKind(array))),
    1177             :                       Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
    1178             : 
    1179             :   ParameterMode mode = OptimalParameterMode();
    1180         112 :   Return(CloneFastJSArray(context, array, mode));
    1181          56 : }
    1182             : 
    1183             : // This builtin copies the backing store of fast arrays, while converting any
    1184             : // holes to undefined.
    1185             : // - If there are no holes in the source, its ElementsKind will be preserved. In
    1186             : // that case, this builtin should perform as fast as CloneFastJSArray. (In fact,
    1187             : // for fast packed arrays, the behavior is equivalent to CloneFastJSArray.)
    1188             : // - If there are holes in the source, the ElementsKind of the "copy" will be
    1189             : // PACKED_ELEMENTS (such that undefined can be stored).
    1190         112 : TF_BUILTIN(CloneFastJSArrayFillingHoles, ArrayBuiltinsAssembler) {
    1191             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1192             :   TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
    1193             : 
    1194             :   CSA_ASSERT(this,
    1195             :              Word32Or(Word32BinaryNot(
    1196             :                           IsHoleyFastElementsKind(LoadElementsKind(array))),
    1197             :                       Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
    1198             : 
    1199             :   ParameterMode mode = OptimalParameterMode();
    1200             :   Return(CloneFastJSArray(context, array, mode, nullptr,
    1201         112 :                           HoleConversionMode::kConvertToUndefined));
    1202          56 : }
    1203             : 
    1204         112 : TF_BUILTIN(ArrayFindLoopContinuation, ArrayBuiltinsAssembler) {
    1205             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1206             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1207             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1208             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1209             :   Node* array = Parameter(Descriptor::kArray);
    1210             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    1211             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1212             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1213             :   Node* to = Parameter(Descriptor::kTo);
    1214             : 
    1215             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1216             :                                             this_arg, array, object, initial_k,
    1217             :                                             len, to);
    1218             : 
    1219             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1220             :       &ArrayBuiltinsAssembler::FindProcessor,
    1221             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    1222         168 :       MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
    1223          56 : }
    1224             : 
    1225             : // Continuation that is called after an eager deoptimization from TF (ex. the
    1226             : // array changes during iteration).
    1227         168 : TF_BUILTIN(ArrayFindLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    1228             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1229          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1230             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1231             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1232             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1233          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1234             : 
    1235             :   Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
    1236             :                      callbackfn, this_arg, UndefinedConstant(), receiver,
    1237         168 :                      initial_k, len, UndefinedConstant()));
    1238          56 : }
    1239             : 
    1240             : // Continuation that is called after a lazy deoptimization from TF (ex. the
    1241             : // callback function is no longer callable).
    1242         168 : TF_BUILTIN(ArrayFindLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    1243             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1244          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1245             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1246             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1247             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1248          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1249             : 
    1250             :   Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
    1251             :                      callbackfn, this_arg, UndefinedConstant(), receiver,
    1252         168 :                      initial_k, len, UndefinedConstant()));
    1253          56 : }
    1254             : 
    1255             : // Continuation that is called after a lazy deoptimization from TF that happens
    1256             : // right after the callback and it's returned value must be handled before
    1257             : // iteration continues.
    1258         224 : TF_BUILTIN(ArrayFindLoopAfterCallbackLazyDeoptContinuation,
    1259             :            ArrayBuiltinsAssembler) {
    1260             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1261          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1262             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1263             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1264             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1265          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1266             :   Node* found_value = Parameter(Descriptor::kFoundValue);
    1267             :   Node* is_found = Parameter(Descriptor::kIsFound);
    1268             : 
    1269             :   // This custom lazy deopt point is right after the callback. find() needs
    1270             :   // to pick up at the next step, which is returning the element if the callback
    1271             :   // value is truthy.  Otherwise, continue the search by calling the
    1272             :   // continuation.
    1273          56 :   Label if_true(this), if_false(this);
    1274          56 :   BranchIfToBooleanIsTrue(is_found, &if_true, &if_false);
    1275          56 :   BIND(&if_true);
    1276          56 :   Return(found_value);
    1277          56 :   BIND(&if_false);
    1278             :   Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
    1279             :                      callbackfn, this_arg, UndefinedConstant(), receiver,
    1280         224 :                      initial_k, len, UndefinedConstant()));
    1281          56 : }
    1282             : 
    1283             : // ES #sec-get-%typedarray%.prototype.find
    1284         168 : TF_BUILTIN(ArrayPrototypeFind, ArrayBuiltinsAssembler) {
    1285             :   TNode<IntPtrT> argc =
    1286          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1287          56 :   CodeStubArguments args(this, argc);
    1288             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1289          56 :   TNode<Object> receiver = args.GetReceiver();
    1290         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1291         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1292             : 
    1293             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1294             : 
    1295             :   GenerateIteratingArrayBuiltinBody(
    1296             :       "Array.prototype.find", &ArrayBuiltinsAssembler::FindResultGenerator,
    1297             :       &ArrayBuiltinsAssembler::FindProcessor,
    1298             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    1299             :       Builtins::CallableFor(isolate(), Builtins::kArrayFindLoopContinuation),
    1300         280 :       MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
    1301          56 : }
    1302             : 
    1303         112 : TF_BUILTIN(ArrayFindIndexLoopContinuation, ArrayBuiltinsAssembler) {
    1304             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1305             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1306             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1307             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1308             :   Node* array = Parameter(Descriptor::kArray);
    1309             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    1310             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1311             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1312             :   Node* to = Parameter(Descriptor::kTo);
    1313             : 
    1314             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1315             :                                             this_arg, array, object, initial_k,
    1316             :                                             len, to);
    1317             : 
    1318             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1319             :       &ArrayBuiltinsAssembler::FindIndexProcessor,
    1320             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    1321         168 :       MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
    1322          56 : }
    1323             : 
    1324         168 : TF_BUILTIN(ArrayFindIndexLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    1325             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1326          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1327             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1328             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1329             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1330          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1331             : 
    1332             :   Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
    1333             :                      receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
    1334         168 :                      initial_k, len, UndefinedConstant()));
    1335          56 : }
    1336             : 
    1337         168 : TF_BUILTIN(ArrayFindIndexLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    1338             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1339          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1340             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1341             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1342             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1343          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1344             : 
    1345             :   Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
    1346             :                      receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
    1347         168 :                      initial_k, len, UndefinedConstant()));
    1348          56 : }
    1349             : 
    1350         224 : TF_BUILTIN(ArrayFindIndexLoopAfterCallbackLazyDeoptContinuation,
    1351             :            ArrayBuiltinsAssembler) {
    1352             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1353          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1354             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1355             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1356             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1357          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1358             :   Node* found_value = Parameter(Descriptor::kFoundValue);
    1359             :   Node* is_found = Parameter(Descriptor::kIsFound);
    1360             : 
    1361             :   // This custom lazy deopt point is right after the callback. find() needs
    1362             :   // to pick up at the next step, which is returning the element if the callback
    1363             :   // value is truthy.  Otherwise, continue the search by calling the
    1364             :   // continuation.
    1365          56 :   Label if_true(this), if_false(this);
    1366          56 :   BranchIfToBooleanIsTrue(is_found, &if_true, &if_false);
    1367          56 :   BIND(&if_true);
    1368          56 :   Return(found_value);
    1369          56 :   BIND(&if_false);
    1370             :   Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
    1371             :                      receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
    1372         224 :                      initial_k, len, UndefinedConstant()));
    1373          56 : }
    1374             : 
    1375             : // ES #sec-get-%typedarray%.prototype.findIndex
    1376         168 : TF_BUILTIN(ArrayPrototypeFindIndex, ArrayBuiltinsAssembler) {
    1377             :   TNode<IntPtrT> argc =
    1378          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1379          56 :   CodeStubArguments args(this, argc);
    1380             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1381          56 :   TNode<Object> receiver = args.GetReceiver();
    1382         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1383         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1384             : 
    1385             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1386             : 
    1387             :   GenerateIteratingArrayBuiltinBody(
    1388             :       "Array.prototype.findIndex",
    1389             :       &ArrayBuiltinsAssembler::FindIndexResultGenerator,
    1390             :       &ArrayBuiltinsAssembler::FindIndexProcessor,
    1391             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    1392             :       Builtins::CallableFor(isolate(),
    1393             :                             Builtins::kArrayFindIndexLoopContinuation),
    1394         280 :       MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
    1395          56 : }
    1396             : 
    1397             : class ArrayPopulatorAssembler : public CodeStubAssembler {
    1398             :  public:
    1399             :   explicit ArrayPopulatorAssembler(compiler::CodeAssemblerState* state)
    1400          56 :       : CodeStubAssembler(state) {}
    1401             : 
    1402          56 :   TNode<Object> ConstructArrayLike(TNode<Context> context,
    1403             :                                    TNode<Object> receiver) {
    1404          56 :     TVARIABLE(Object, array);
    1405          56 :     Label is_constructor(this), is_not_constructor(this), done(this);
    1406         112 :     GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
    1407         112 :     Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
    1408             : 
    1409          56 :     BIND(&is_constructor);
    1410             :     {
    1411         112 :       array = Construct(context, CAST(receiver));
    1412          56 :       Goto(&done);
    1413             :     }
    1414             : 
    1415          56 :     BIND(&is_not_constructor);
    1416             :     {
    1417             :       Label allocate_js_array(this);
    1418             : 
    1419          56 :       TNode<Map> array_map = CAST(LoadContextElement(
    1420             :           context, Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX));
    1421             : 
    1422         112 :       array = AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, SmiConstant(0),
    1423             :                               SmiConstant(0), nullptr,
    1424         112 :                               ParameterMode::SMI_PARAMETERS);
    1425          56 :       Goto(&done);
    1426             :     }
    1427             : 
    1428          56 :     BIND(&done);
    1429          56 :     return array.value();
    1430             :   }
    1431             : 
    1432          56 :   TNode<Object> ConstructArrayLike(TNode<Context> context,
    1433             :                                    TNode<Object> receiver,
    1434             :                                    TNode<Number> length) {
    1435          56 :     TVARIABLE(Object, array);
    1436          56 :     Label is_constructor(this), is_not_constructor(this), done(this);
    1437             :     CSA_ASSERT(this, IsNumberNormalized(length));
    1438         112 :     GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
    1439         112 :     Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
    1440             : 
    1441          56 :     BIND(&is_constructor);
    1442             :     {
    1443         112 :       array = Construct(context, CAST(receiver), length);
    1444          56 :       Goto(&done);
    1445             :     }
    1446             : 
    1447          56 :     BIND(&is_not_constructor);
    1448             :     {
    1449         112 :       array = ArrayCreate(context, length);
    1450          56 :       Goto(&done);
    1451             :     }
    1452             : 
    1453          56 :     BIND(&done);
    1454          56 :     return array.value();
    1455             :   }
    1456             : };
    1457             : 
    1458             : // ES #sec-array.from
    1459         224 : TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) {
    1460             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1461             :   TNode<Int32T> argc =
    1462             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
    1463             : 
    1464         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
    1465          56 :   TNode<Object> items = args.GetOptionalArgumentValue(0);
    1466          56 :   TNode<Object> receiver = args.GetReceiver();
    1467             : 
    1468          56 :   Label fast_iterate(this), normal_iterate(this);
    1469             : 
    1470             :   // Use fast path if:
    1471             :   // * |items| is the only argument, and
    1472             :   // * the receiver is the Array function.
    1473         168 :   GotoIfNot(Word32Equal(argc, Int32Constant(1)), &normal_iterate);
    1474             :   TNode<Object> array_function = LoadContextElement(
    1475         112 :       LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
    1476          56 :   Branch(WordEqual(array_function, receiver), &fast_iterate, &normal_iterate);
    1477             : 
    1478          56 :   BIND(&fast_iterate);
    1479             :   {
    1480             :     IteratorBuiltinsAssembler iterator_assembler(state());
    1481             :     TVARIABLE(Object, var_fast_result);
    1482             :     iterator_assembler.FastIterableToList(context, items, &var_fast_result,
    1483          56 :                                           &normal_iterate);
    1484         112 :     args.PopAndReturn(var_fast_result.value());
    1485             :   }
    1486             : 
    1487          56 :   BIND(&normal_iterate);
    1488          56 :   TNode<Object> map_function = args.GetOptionalArgumentValue(1);
    1489             : 
    1490             :   // If map_function is not undefined, then ensure it's callable else throw.
    1491             :   {
    1492          56 :     Label no_error(this), error(this);
    1493         112 :     GotoIf(IsUndefined(map_function), &no_error);
    1494         112 :     GotoIf(TaggedIsSmi(map_function), &error);
    1495         112 :     Branch(IsCallable(CAST(map_function)), &no_error, &error);
    1496             : 
    1497          56 :     BIND(&error);
    1498          56 :     ThrowTypeError(context, MessageTemplate::kCalledNonCallable, map_function);
    1499             : 
    1500         112 :     BIND(&no_error);
    1501             :   }
    1502             : 
    1503          56 :   Label iterable(this), not_iterable(this), finished(this), if_exception(this);
    1504             : 
    1505          56 :   TNode<Object> this_arg = args.GetOptionalArgumentValue(2);
    1506             :   // The spec doesn't require ToObject to be called directly on the iterable
    1507             :   // branch, but it's part of GetMethod that is in the spec.
    1508          56 :   TNode<JSReceiver> array_like = ToObject_Inline(context, items);
    1509             : 
    1510             :   TVARIABLE(Object, array);
    1511             :   TVARIABLE(Number, length);
    1512             : 
    1513             :   // Determine whether items[Symbol.iterator] is defined:
    1514          56 :   IteratorBuiltinsAssembler iterator_assembler(state());
    1515             :   Node* iterator_method =
    1516         112 :       iterator_assembler.GetIteratorMethod(context, array_like);
    1517         112 :   Branch(IsNullOrUndefined(iterator_method), &not_iterable, &iterable);
    1518             : 
    1519          56 :   BIND(&iterable);
    1520             :   {
    1521         112 :     TVARIABLE(Number, index, SmiConstant(0));
    1522             :     TVARIABLE(Object, var_exception);
    1523          56 :     Label loop(this, &index), loop_done(this),
    1524          56 :         on_exception(this, Label::kDeferred),
    1525          56 :         index_overflow(this, Label::kDeferred);
    1526             : 
    1527             :     // Check that the method is callable.
    1528             :     {
    1529          56 :       Label get_method_not_callable(this, Label::kDeferred), next(this);
    1530         112 :       GotoIf(TaggedIsSmi(iterator_method), &get_method_not_callable);
    1531         112 :       GotoIfNot(IsCallable(CAST(iterator_method)), &get_method_not_callable);
    1532          56 :       Goto(&next);
    1533             : 
    1534          56 :       BIND(&get_method_not_callable);
    1535             :       ThrowTypeError(context, MessageTemplate::kCalledNonCallable,
    1536          56 :                      iterator_method);
    1537             : 
    1538         112 :       BIND(&next);
    1539             :     }
    1540             : 
    1541             :     // Construct the output array with empty length.
    1542          56 :     array = ConstructArrayLike(context, receiver);
    1543             : 
    1544             :     // Actually get the iterator and throw if the iterator method does not yield
    1545             :     // one.
    1546             :     IteratorRecord iterator_record =
    1547          56 :         iterator_assembler.GetIterator(context, items, iterator_method);
    1548             : 
    1549          56 :     TNode<Context> native_context = LoadNativeContext(context);
    1550             :     TNode<Object> fast_iterator_result_map =
    1551          56 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    1552             : 
    1553          56 :     Goto(&loop);
    1554             : 
    1555          56 :     BIND(&loop);
    1556             :     {
    1557             :       // Loop while iterator is not done.
    1558             :       TNode<Object> next = iterator_assembler.IteratorStep(
    1559          56 :           context, iterator_record, &loop_done, fast_iterator_result_map);
    1560          56 :       TVARIABLE(Object, value,
    1561             :                 CAST(iterator_assembler.IteratorValue(
    1562             :                     context, next, fast_iterator_result_map)));
    1563             : 
    1564             :       // If a map_function is supplied then call it (using this_arg as
    1565             :       // receiver), on the value returned from the iterator. Exceptions are
    1566             :       // caught so the iterator can be closed.
    1567             :       {
    1568             :         Label next(this);
    1569         112 :         GotoIf(IsUndefined(map_function), &next);
    1570             : 
    1571             :         CSA_ASSERT(this, IsCallable(CAST(map_function)));
    1572             :         Node* v = CallJS(CodeFactory::Call(isolate()), context, map_function,
    1573         112 :                          this_arg, value.value(), index.value());
    1574          56 :         GotoIfException(v, &on_exception, &var_exception);
    1575             :         value = CAST(v);
    1576          56 :         Goto(&next);
    1577          56 :         BIND(&next);
    1578             :       }
    1579             : 
    1580             :       // Store the result in the output object (catching any exceptions so the
    1581             :       // iterator can be closed).
    1582             :       Node* define_status =
    1583             :           CallRuntime(Runtime::kCreateDataProperty, context, array.value(),
    1584             :                       index.value(), value.value());
    1585          56 :       GotoIfException(define_status, &on_exception, &var_exception);
    1586             : 
    1587         112 :       index = NumberInc(index.value());
    1588             : 
    1589             :       // The spec requires that we throw an exception if index reaches 2^53-1,
    1590             :       // but an empty loop would take >100 days to do this many iterations. To
    1591             :       // actually run for that long would require an iterator that never set
    1592             :       // done to true and a target array which somehow never ran out of memory,
    1593             :       // e.g. a proxy that discarded the values. Ignoring this case just means
    1594             :       // we would repeatedly call CreateDataProperty with index = 2^53.
    1595             :       CSA_ASSERT_BRANCH(this, [&](Label* ok, Label* not_ok) {
    1596             :         BranchIfNumberRelationalComparison(Operation::kLessThan, index.value(),
    1597             :                                            NumberConstant(kMaxSafeInteger), ok,
    1598             :                                            not_ok);
    1599             :       });
    1600          56 :       Goto(&loop);
    1601             :     }
    1602             : 
    1603          56 :     BIND(&loop_done);
    1604             :     {
    1605             :       length = index;
    1606          56 :       Goto(&finished);
    1607             :     }
    1608             : 
    1609          56 :     BIND(&on_exception);
    1610             :     {
    1611             :       // Close the iterator, rethrowing either the passed exception or
    1612             :       // exceptions thrown during the close.
    1613             :       iterator_assembler.IteratorCloseOnException(context, iterator_record,
    1614          56 :                                                   var_exception.value());
    1615             :     }
    1616             :   }
    1617             : 
    1618          56 :   BIND(&not_iterable);
    1619             :   {
    1620             :     // Treat array_like as an array and try to get its length.
    1621         168 :     length = ToLength_Inline(
    1622         112 :         context, GetProperty(context, array_like, factory()->length_string()));
    1623             : 
    1624             :     // Construct an array using the receiver as constructor with the same length
    1625             :     // as the input array.
    1626          56 :     array = ConstructArrayLike(context, receiver, length.value());
    1627             : 
    1628         112 :     TVARIABLE(Number, index, SmiConstant(0));
    1629             : 
    1630             :     // TODO(ishell): remove <Object, Object>
    1631         112 :     GotoIf(WordEqual<Object, Object>(length.value(), SmiConstant(0)),
    1632          56 :            &finished);
    1633             : 
    1634             :     // Loop from 0 to length-1.
    1635             :     {
    1636             :       Label loop(this, &index);
    1637          56 :       Goto(&loop);
    1638          56 :       BIND(&loop);
    1639             :       TVARIABLE(Object, value);
    1640             : 
    1641             :       value = GetProperty(context, array_like, index.value());
    1642             : 
    1643             :       // If a map_function is supplied then call it (using this_arg as
    1644             :       // receiver), on the value retrieved from the array.
    1645             :       {
    1646             :         Label next(this);
    1647         112 :         GotoIf(IsUndefined(map_function), &next);
    1648             : 
    1649             :         CSA_ASSERT(this, IsCallable(CAST(map_function)));
    1650         112 :         value = CAST(CallJS(CodeFactory::Call(isolate()), context, map_function,
    1651             :                             this_arg, value.value(), index.value()));
    1652          56 :         Goto(&next);
    1653          56 :         BIND(&next);
    1654             :       }
    1655             : 
    1656             :       // Store the result in the output object.
    1657             :       CallRuntime(Runtime::kCreateDataProperty, context, array.value(),
    1658             :                   index.value(), value.value());
    1659         112 :       index = NumberInc(index.value());
    1660             :       BranchIfNumberRelationalComparison(Operation::kLessThan, index.value(),
    1661         112 :                                          length.value(), &loop, &finished);
    1662             :     }
    1663             :   }
    1664             : 
    1665          56 :   BIND(&finished);
    1666             : 
    1667             :   // Finally set the length on the output and return it.
    1668          56 :   SetPropertyLength(context, array.value(), length.value());
    1669         112 :   args.PopAndReturn(array.value());
    1670          56 : }
    1671             : 
    1672             : // ES #sec-get-%typedarray%.prototype.find
    1673         168 : TF_BUILTIN(TypedArrayPrototypeFind, ArrayBuiltinsAssembler) {
    1674             :   TNode<IntPtrT> argc =
    1675          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1676          56 :   CodeStubArguments args(this, argc);
    1677             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1678          56 :   TNode<Object> receiver = args.GetReceiver();
    1679         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1680         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1681             : 
    1682             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1683             : 
    1684             :   GenerateIteratingTypedArrayBuiltinBody(
    1685             :       "%TypedArray%.prototype.find",
    1686             :       &ArrayBuiltinsAssembler::FindResultGenerator,
    1687             :       &ArrayBuiltinsAssembler::FindProcessor,
    1688         224 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
    1689          56 : }
    1690             : 
    1691             : // ES #sec-get-%typedarray%.prototype.findIndex
    1692         168 : TF_BUILTIN(TypedArrayPrototypeFindIndex, ArrayBuiltinsAssembler) {
    1693             :   TNode<IntPtrT> argc =
    1694          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1695          56 :   CodeStubArguments args(this, argc);
    1696             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1697          56 :   TNode<Object> receiver = args.GetReceiver();
    1698         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1699         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1700             : 
    1701             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1702             : 
    1703             :   GenerateIteratingTypedArrayBuiltinBody(
    1704             :       "%TypedArray%.prototype.findIndex",
    1705             :       &ArrayBuiltinsAssembler::FindIndexResultGenerator,
    1706             :       &ArrayBuiltinsAssembler::FindIndexProcessor,
    1707         224 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
    1708          56 : }
    1709             : 
    1710         168 : TF_BUILTIN(TypedArrayPrototypeForEach, ArrayBuiltinsAssembler) {
    1711             :   TNode<IntPtrT> argc =
    1712          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1713          56 :   CodeStubArguments args(this, argc);
    1714             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1715          56 :   TNode<Object> receiver = args.GetReceiver();
    1716         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1717         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1718             : 
    1719             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1720             : 
    1721             :   GenerateIteratingTypedArrayBuiltinBody(
    1722             :       "%TypedArray%.prototype.forEach",
    1723             :       &ArrayBuiltinsAssembler::ForEachResultGenerator,
    1724             :       &ArrayBuiltinsAssembler::ForEachProcessor,
    1725         224 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
    1726          56 : }
    1727             : 
    1728         224 : TF_BUILTIN(ArraySomeLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    1729             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1730          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1731             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1732             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1733             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1734          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1735             :   Node* result = Parameter(Descriptor::kResult);
    1736             : 
    1737             :   // This custom lazy deopt point is right after the callback. every() needs
    1738             :   // to pick up at the next step, which is either continuing to the next
    1739             :   // array element or returning false if {result} is false.
    1740          56 :   Label true_continue(this), false_continue(this);
    1741             : 
    1742             :   // iii. If selected is true, then...
    1743          56 :   BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
    1744          56 :   BIND(&true_continue);
    1745         112 :   { Return(TrueConstant()); }
    1746          56 :   BIND(&false_continue);
    1747             :   {
    1748             :     // Increment k.
    1749         112 :     initial_k = NumberInc(initial_k);
    1750             : 
    1751             :     Return(CallBuiltin(Builtins::kArraySomeLoopContinuation, context, receiver,
    1752             :                        callbackfn, this_arg, FalseConstant(), receiver,
    1753         168 :                        initial_k, len, UndefinedConstant()));
    1754          56 :   }
    1755          56 : }
    1756             : 
    1757         168 : TF_BUILTIN(ArraySomeLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    1758             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1759          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1760             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1761             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1762             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1763          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1764             : 
    1765             :   Return(CallBuiltin(Builtins::kArraySomeLoopContinuation, context, receiver,
    1766             :                      callbackfn, this_arg, FalseConstant(), receiver, initial_k,
    1767         168 :                      len, UndefinedConstant()));
    1768          56 : }
    1769             : 
    1770         112 : TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinsAssembler) {
    1771             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1772             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1773             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1774             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1775             :   Node* array = Parameter(Descriptor::kArray);
    1776             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    1777             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1778             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1779             :   Node* to = Parameter(Descriptor::kTo);
    1780             : 
    1781             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1782             :                                             this_arg, array, object, initial_k,
    1783             :                                             len, to);
    1784             : 
    1785             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1786             :       &ArrayBuiltinsAssembler::SomeProcessor,
    1787         168 :       &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
    1788          56 : }
    1789             : 
    1790         168 : TF_BUILTIN(ArraySome, ArrayBuiltinsAssembler) {
    1791             :   TNode<IntPtrT> argc =
    1792          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1793          56 :   CodeStubArguments args(this, argc);
    1794             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1795          56 :   TNode<Object> receiver = args.GetReceiver();
    1796         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1797         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1798             : 
    1799             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1800             : 
    1801             :   GenerateIteratingArrayBuiltinBody(
    1802             :       "Array.prototype.some", &ArrayBuiltinsAssembler::SomeResultGenerator,
    1803             :       &ArrayBuiltinsAssembler::SomeProcessor,
    1804             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    1805             :       Builtins::CallableFor(isolate(), Builtins::kArraySomeLoopContinuation),
    1806         280 :       MissingPropertyMode::kSkip);
    1807          56 : }
    1808             : 
    1809         168 : TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinsAssembler) {
    1810             :   TNode<IntPtrT> argc =
    1811          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1812          56 :   CodeStubArguments args(this, argc);
    1813             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1814          56 :   TNode<Object> receiver = args.GetReceiver();
    1815         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1816         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1817             : 
    1818             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1819             : 
    1820             :   GenerateIteratingTypedArrayBuiltinBody(
    1821             :       "%TypedArray%.prototype.some",
    1822             :       &ArrayBuiltinsAssembler::SomeResultGenerator,
    1823             :       &ArrayBuiltinsAssembler::SomeProcessor,
    1824         224 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
    1825          56 : }
    1826             : 
    1827         224 : TF_BUILTIN(ArrayEveryLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    1828             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1829          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1830             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1831             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1832             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1833          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1834             :   Node* result = Parameter(Descriptor::kResult);
    1835             : 
    1836             :   // This custom lazy deopt point is right after the callback. every() needs
    1837             :   // to pick up at the next step, which is either continuing to the next
    1838             :   // array element or returning false if {result} is false.
    1839          56 :   Label true_continue(this), false_continue(this);
    1840             : 
    1841             :   // iii. If selected is true, then...
    1842          56 :   BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
    1843          56 :   BIND(&true_continue);
    1844             :   {
    1845             :     // Increment k.
    1846         112 :     initial_k = NumberInc(initial_k);
    1847             : 
    1848             :     Return(CallBuiltin(Builtins::kArrayEveryLoopContinuation, context, receiver,
    1849             :                        callbackfn, this_arg, TrueConstant(), receiver,
    1850         168 :                        initial_k, len, UndefinedConstant()));
    1851             :   }
    1852          56 :   BIND(&false_continue);
    1853         168 :   { Return(FalseConstant()); }
    1854          56 : }
    1855             : 
    1856         168 : TF_BUILTIN(ArrayEveryLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    1857             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1858          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1859             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1860             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1861             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1862          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1863             : 
    1864             :   Return(CallBuiltin(Builtins::kArrayEveryLoopContinuation, context, receiver,
    1865             :                      callbackfn, this_arg, TrueConstant(), receiver, initial_k,
    1866         168 :                      len, UndefinedConstant()));
    1867          56 : }
    1868             : 
    1869         112 : TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinsAssembler) {
    1870             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1871             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1872             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1873             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1874             :   Node* array = Parameter(Descriptor::kArray);
    1875             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    1876             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1877             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1878             :   Node* to = Parameter(Descriptor::kTo);
    1879             : 
    1880             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1881             :                                             this_arg, array, object, initial_k,
    1882             :                                             len, to);
    1883             : 
    1884             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1885             :       &ArrayBuiltinsAssembler::EveryProcessor,
    1886         168 :       &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
    1887          56 : }
    1888             : 
    1889         168 : TF_BUILTIN(ArrayEvery, ArrayBuiltinsAssembler) {
    1890             :   TNode<IntPtrT> argc =
    1891          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1892          56 :   CodeStubArguments args(this, argc);
    1893             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1894          56 :   TNode<Object> receiver = args.GetReceiver();
    1895         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1896         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1897             : 
    1898             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1899             : 
    1900             :   GenerateIteratingArrayBuiltinBody(
    1901             :       "Array.prototype.every", &ArrayBuiltinsAssembler::EveryResultGenerator,
    1902             :       &ArrayBuiltinsAssembler::EveryProcessor,
    1903             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    1904             :       Builtins::CallableFor(isolate(), Builtins::kArrayEveryLoopContinuation),
    1905         280 :       MissingPropertyMode::kSkip);
    1906          56 : }
    1907             : 
    1908         168 : TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinsAssembler) {
    1909             :   TNode<IntPtrT> argc =
    1910          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1911          56 :   CodeStubArguments args(this, argc);
    1912             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1913          56 :   TNode<Object> receiver = args.GetReceiver();
    1914         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1915         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1916             : 
    1917             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    1918             : 
    1919             :   GenerateIteratingTypedArrayBuiltinBody(
    1920             :       "%TypedArray%.prototype.every",
    1921             :       &ArrayBuiltinsAssembler::EveryResultGenerator,
    1922             :       &ArrayBuiltinsAssembler::EveryProcessor,
    1923         224 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
    1924          56 : }
    1925             : 
    1926         112 : TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinsAssembler) {
    1927             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1928             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1929             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1930             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1931             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    1932             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    1933             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1934             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1935             :   Node* to = Parameter(Descriptor::kTo);
    1936             : 
    1937             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1938             :                                             this_arg, accumulator, object,
    1939             :                                             initial_k, len, to);
    1940             : 
    1941             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1942             :       &ArrayBuiltinsAssembler::ReduceProcessor,
    1943             :       &ArrayBuiltinsAssembler::ReducePostLoopAction,
    1944         168 :       MissingPropertyMode::kSkip);
    1945          56 : }
    1946             : 
    1947         168 : TF_BUILTIN(ArrayReducePreLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    1948             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1949          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1950             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1951          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1952             : 
    1953             :   // Simulate starting the loop at 0, but ensuring that the accumulator is
    1954             :   // the hole. The continuation stub will search for the initial non-hole
    1955             :   // element, rightly throwing an exception if not found.
    1956             :   Return(CallBuiltin(Builtins::kArrayReduceLoopContinuation, context, receiver,
    1957             :                      callbackfn, UndefinedConstant(), TheHoleConstant(),
    1958         168 :                      receiver, SmiConstant(0), len, UndefinedConstant()));
    1959          56 : }
    1960             : 
    1961         168 : TF_BUILTIN(ArrayReduceLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    1962             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1963          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1964             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1965             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    1966             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1967          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1968             : 
    1969             :   Return(CallBuiltin(Builtins::kArrayReduceLoopContinuation, context, receiver,
    1970             :                      callbackfn, UndefinedConstant(), accumulator, receiver,
    1971         168 :                      initial_k, len, UndefinedConstant()));
    1972          56 : }
    1973             : 
    1974         224 : TF_BUILTIN(ArrayReduceLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    1975             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1976          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1977             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1978             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1979          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    1980             :   Node* result = Parameter(Descriptor::kResult);
    1981             : 
    1982             :   Return(CallBuiltin(Builtins::kArrayReduceLoopContinuation, context, receiver,
    1983             :                      callbackfn, UndefinedConstant(), result, receiver,
    1984         168 :                      initial_k, len, UndefinedConstant()));
    1985          56 : }
    1986             : 
    1987         168 : TF_BUILTIN(ArrayReduce, ArrayBuiltinsAssembler) {
    1988             :   TNode<IntPtrT> argc =
    1989          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1990          56 :   CodeStubArguments args(this, argc);
    1991             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1992          56 :   TNode<Object> receiver = args.GetReceiver();
    1993         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1994         168 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    1995             : 
    1996             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1997             :                                 argc);
    1998             : 
    1999             :   GenerateIteratingArrayBuiltinBody(
    2000             :       "Array.prototype.reduce", &ArrayBuiltinsAssembler::ReduceResultGenerator,
    2001             :       &ArrayBuiltinsAssembler::ReduceProcessor,
    2002             :       &ArrayBuiltinsAssembler::ReducePostLoopAction,
    2003             :       Builtins::CallableFor(isolate(), Builtins::kArrayReduceLoopContinuation),
    2004         280 :       MissingPropertyMode::kSkip);
    2005          56 : }
    2006             : 
    2007         168 : TF_BUILTIN(TypedArrayPrototypeReduce, ArrayBuiltinsAssembler) {
    2008             :   TNode<IntPtrT> argc =
    2009          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2010          56 :   CodeStubArguments args(this, argc);
    2011             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2012          56 :   TNode<Object> receiver = args.GetReceiver();
    2013         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    2014         168 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    2015             : 
    2016             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    2017             :                                 argc);
    2018             : 
    2019             :   GenerateIteratingTypedArrayBuiltinBody(
    2020             :       "%TypedArray%.prototype.reduce",
    2021             :       &ArrayBuiltinsAssembler::ReduceResultGenerator,
    2022             :       &ArrayBuiltinsAssembler::ReduceProcessor,
    2023         224 :       &ArrayBuiltinsAssembler::ReducePostLoopAction);
    2024          56 : }
    2025             : 
    2026         112 : TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinsAssembler) {
    2027             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2028             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2029             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2030             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    2031             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    2032             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    2033             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    2034             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    2035             :   Node* to = Parameter(Descriptor::kTo);
    2036             : 
    2037             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    2038             :                                             this_arg, accumulator, object,
    2039             :                                             initial_k, len, to);
    2040             : 
    2041             :   GenerateIteratingArrayBuiltinLoopContinuation(
    2042             :       &ArrayBuiltinsAssembler::ReduceProcessor,
    2043             :       &ArrayBuiltinsAssembler::ReducePostLoopAction, MissingPropertyMode::kSkip,
    2044         168 :       ForEachDirection::kReverse);
    2045          56 : }
    2046             : 
    2047         168 : TF_BUILTIN(ArrayReduceRightPreLoopEagerDeoptContinuation,
    2048             :            ArrayBuiltinsAssembler) {
    2049             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2050          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2051             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2052          56 :   TNode<Smi> len = CAST(Parameter(Descriptor::kLength));
    2053             : 
    2054             :   // Simulate starting the loop at 0, but ensuring that the accumulator is
    2055             :   // the hole. The continuation stub will search for the initial non-hole
    2056             :   // element, rightly throwing an exception if not found.
    2057             :   Return(CallBuiltin(Builtins::kArrayReduceRightLoopContinuation, context,
    2058             :                      receiver, callbackfn, UndefinedConstant(),
    2059             :                      TheHoleConstant(), receiver, SmiSub(len, SmiConstant(1)),
    2060         168 :                      len, UndefinedConstant()));
    2061          56 : }
    2062             : 
    2063         168 : TF_BUILTIN(ArrayReduceRightLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    2064             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2065          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2066             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2067             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    2068             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    2069          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    2070             : 
    2071             :   Return(CallBuiltin(Builtins::kArrayReduceRightLoopContinuation, context,
    2072             :                      receiver, callbackfn, UndefinedConstant(), accumulator,
    2073         168 :                      receiver, initial_k, len, UndefinedConstant()));
    2074          56 : }
    2075             : 
    2076         224 : TF_BUILTIN(ArrayReduceRightLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    2077             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2078          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2079             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2080             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    2081          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    2082             :   Node* result = Parameter(Descriptor::kResult);
    2083             : 
    2084             :   Return(CallBuiltin(Builtins::kArrayReduceRightLoopContinuation, context,
    2085             :                      receiver, callbackfn, UndefinedConstant(), result,
    2086         168 :                      receiver, initial_k, len, UndefinedConstant()));
    2087          56 : }
    2088             : 
    2089         168 : TF_BUILTIN(ArrayReduceRight, ArrayBuiltinsAssembler) {
    2090             :   TNode<IntPtrT> argc =
    2091          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2092          56 :   CodeStubArguments args(this, argc);
    2093             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2094          56 :   TNode<Object> receiver = args.GetReceiver();
    2095         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    2096         168 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    2097             : 
    2098             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    2099             :                                 argc);
    2100             : 
    2101             :   GenerateIteratingArrayBuiltinBody(
    2102             :       "Array.prototype.reduceRight",
    2103             :       &ArrayBuiltinsAssembler::ReduceResultGenerator,
    2104             :       &ArrayBuiltinsAssembler::ReduceProcessor,
    2105             :       &ArrayBuiltinsAssembler::ReducePostLoopAction,
    2106             :       Builtins::CallableFor(isolate(),
    2107             :                             Builtins::kArrayReduceRightLoopContinuation),
    2108         280 :       MissingPropertyMode::kSkip, ForEachDirection::kReverse);
    2109          56 : }
    2110             : 
    2111         168 : TF_BUILTIN(TypedArrayPrototypeReduceRight, ArrayBuiltinsAssembler) {
    2112             :   TNode<IntPtrT> argc =
    2113          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2114          56 :   CodeStubArguments args(this, argc);
    2115             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2116          56 :   TNode<Object> receiver = args.GetReceiver();
    2117         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    2118         168 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    2119             : 
    2120             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    2121             :                                 argc);
    2122             : 
    2123             :   GenerateIteratingTypedArrayBuiltinBody(
    2124             :       "%TypedArray%.prototype.reduceRight",
    2125             :       &ArrayBuiltinsAssembler::ReduceResultGenerator,
    2126             :       &ArrayBuiltinsAssembler::ReduceProcessor,
    2127             :       &ArrayBuiltinsAssembler::ReducePostLoopAction,
    2128         224 :       ForEachDirection::kReverse);
    2129          56 : }
    2130             : 
    2131         112 : TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinsAssembler) {
    2132             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2133             :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2134             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2135             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    2136             :   Node* array = Parameter(Descriptor::kArray);
    2137             :   TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
    2138             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    2139             :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    2140             :   Node* to = Parameter(Descriptor::kTo);
    2141             : 
    2142             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    2143             :                                             this_arg, array, object, initial_k,
    2144             :                                             len, to);
    2145             : 
    2146             :   GenerateIteratingArrayBuiltinLoopContinuation(
    2147             :       &ArrayBuiltinsAssembler::SpecCompliantMapProcessor,
    2148         168 :       &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
    2149          56 : }
    2150             : 
    2151         168 : TF_BUILTIN(ArrayMapLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
    2152             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2153          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2154             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2155             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    2156             :   Node* array = Parameter(Descriptor::kArray);
    2157             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    2158          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    2159             : 
    2160             :   Return(CallBuiltin(Builtins::kArrayMapLoopContinuation, context, receiver,
    2161             :                      callbackfn, this_arg, array, receiver, initial_k, len,
    2162         168 :                      UndefinedConstant()));
    2163          56 : }
    2164             : 
    2165         224 : TF_BUILTIN(ArrayMapLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
    2166             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2167          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2168             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    2169             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    2170             :   Node* array = Parameter(Descriptor::kArray);
    2171             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    2172          56 :   TNode<Number> len = CAST(Parameter(Descriptor::kLength));
    2173             :   Node* result = Parameter(Descriptor::kResult);
    2174             : 
    2175             :   // This custom lazy deopt point is right after the callback. map() needs
    2176             :   // to pick up at the next step, which is setting the callback result in
    2177             :   // the output array. After incrementing k, we can glide into the loop
    2178             :   // continuation builtin.
    2179             : 
    2180             :   // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
    2181             :   CallRuntime(Runtime::kCreateDataProperty, context, array, initial_k, result);
    2182             :   // Then we have to increment k before going on.
    2183         112 :   initial_k = NumberInc(initial_k);
    2184             : 
    2185             :   Return(CallBuiltin(Builtins::kArrayMapLoopContinuation, context, receiver,
    2186             :                      callbackfn, this_arg, array, receiver, initial_k, len,
    2187         168 :                      UndefinedConstant()));
    2188          56 : }
    2189             : 
    2190         168 : TF_BUILTIN(ArrayMap, ArrayBuiltinsAssembler) {
    2191             :   TNode<IntPtrT> argc =
    2192          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2193          56 :   CodeStubArguments args(this, argc);
    2194             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2195          56 :   TNode<Object> receiver = args.GetReceiver();
    2196         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    2197         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    2198             : 
    2199             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    2200             : 
    2201             :   GenerateIteratingArrayBuiltinBody(
    2202             :       "Array.prototype.map", &ArrayBuiltinsAssembler::MapResultGenerator,
    2203             :       &ArrayBuiltinsAssembler::FastMapProcessor,
    2204             :       &ArrayBuiltinsAssembler::NullPostLoopAction,
    2205             :       Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation),
    2206         280 :       MissingPropertyMode::kSkip);
    2207          56 : }
    2208             : 
    2209         168 : TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinsAssembler) {
    2210             :   TNode<IntPtrT> argc =
    2211          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2212          56 :   CodeStubArguments args(this, argc);
    2213             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2214          56 :   TNode<Object> receiver = args.GetReceiver();
    2215         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    2216         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    2217             : 
    2218             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
    2219             : 
    2220             :   GenerateIteratingTypedArrayBuiltinBody(
    2221             :       "%TypedArray%.prototype.map",
    2222             :       &ArrayBuiltinsAssembler::TypedArrayMapResultGenerator,
    2223             :       &ArrayBuiltinsAssembler::TypedArrayMapProcessor,
    2224         224 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
    2225          56 : }
    2226             : 
    2227         168 : TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
    2228             :   TNode<Object> object = CAST(Parameter(Descriptor::kArg));
    2229             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2230             : 
    2231          56 :   Label call_runtime(this), return_true(this), return_false(this);
    2232             : 
    2233         112 :   GotoIf(TaggedIsSmi(object), &return_false);
    2234          56 :   TNode<Int32T> instance_type = LoadInstanceType(CAST(object));
    2235             : 
    2236         112 :   GotoIf(InstanceTypeEqual(instance_type, JS_ARRAY_TYPE), &return_true);
    2237             : 
    2238             :   // TODO(verwaest): Handle proxies in-place.
    2239          56 :   Branch(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), &call_runtime,
    2240         112 :          &return_false);
    2241             : 
    2242          56 :   BIND(&return_true);
    2243         112 :   Return(TrueConstant());
    2244             : 
    2245          56 :   BIND(&return_false);
    2246         112 :   Return(FalseConstant());
    2247             : 
    2248          56 :   BIND(&call_runtime);
    2249         112 :   Return(CallRuntime(Runtime::kArrayIsArray, context, object));
    2250          56 : }
    2251             : 
    2252             : class ArrayIncludesIndexofAssembler : public CodeStubAssembler {
    2253             :  public:
    2254             :   explicit ArrayIncludesIndexofAssembler(compiler::CodeAssemblerState* state)
    2255         448 :       : CodeStubAssembler(state) {}
    2256             : 
    2257             :   enum SearchVariant { kIncludes, kIndexOf };
    2258             : 
    2259             :   void Generate(SearchVariant variant, TNode<IntPtrT> argc,
    2260             :                 TNode<Context> context);
    2261             :   void GenerateSmiOrObject(SearchVariant variant, Node* context, Node* elements,
    2262             :                            Node* search_element, Node* array_length,
    2263             :                            Node* from_index);
    2264             :   void GeneratePackedDoubles(SearchVariant variant, Node* elements,
    2265             :                              Node* search_element, Node* array_length,
    2266             :                              Node* from_index);
    2267             :   void GenerateHoleyDoubles(SearchVariant variant, Node* elements,
    2268             :                             Node* search_element, Node* array_length,
    2269             :                             Node* from_index);
    2270             : };
    2271             : 
    2272         112 : void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant,
    2273             :                                              TNode<IntPtrT> argc,
    2274             :                                              TNode<Context> context) {
    2275             :   const int kSearchElementArg = 0;
    2276             :   const int kFromIndexArg = 1;
    2277             : 
    2278         112 :   CodeStubArguments args(this, argc);
    2279             : 
    2280         112 :   TNode<Object> receiver = args.GetReceiver();
    2281             :   TNode<Object> search_element =
    2282         112 :       args.GetOptionalArgumentValue(kSearchElementArg);
    2283             : 
    2284         224 :   Node* intptr_zero = IntPtrConstant(0);
    2285             : 
    2286         112 :   Label init_index(this), return_not_found(this), call_runtime(this);
    2287             : 
    2288             :   // Take slow path if not a JSArray, if retrieving elements requires
    2289             :   // traversing prototype, or if access checks are required.
    2290         112 :   BranchIfFastJSArray(receiver, context, &init_index, &call_runtime);
    2291             : 
    2292         112 :   BIND(&init_index);
    2293         224 :   VARIABLE(index_var, MachineType::PointerRepresentation(), intptr_zero);
    2294             :   TNode<JSArray> array = CAST(receiver);
    2295             : 
    2296             :   // JSArray length is always a positive Smi for fast arrays.
    2297             :   CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array)));
    2298         224 :   Node* array_length = LoadFastJSArrayLength(array);
    2299         224 :   Node* array_length_untagged = SmiUntag(array_length);
    2300             : 
    2301             :   {
    2302             :     // Initialize fromIndex.
    2303         112 :     Label is_smi(this), is_nonsmi(this), done(this);
    2304             : 
    2305             :     // If no fromIndex was passed, default to 0.
    2306         336 :     GotoIf(IntPtrLessThanOrEqual(argc, IntPtrConstant(kFromIndexArg)), &done);
    2307             : 
    2308         224 :     Node* start_from = args.AtIndex(kFromIndexArg);
    2309             :     // Handle Smis and undefined here and everything else in runtime.
    2310             :     // We must be very careful with side effects from the ToInteger conversion,
    2311             :     // as the side effects might render previously checked assumptions about
    2312             :     // the receiver being a fast JSArray and its length invalid.
    2313         224 :     Branch(TaggedIsSmi(start_from), &is_smi, &is_nonsmi);
    2314             : 
    2315         112 :     BIND(&is_nonsmi);
    2316             :     {
    2317         224 :       GotoIfNot(IsUndefined(start_from), &call_runtime);
    2318         112 :       Goto(&done);
    2319             :     }
    2320         112 :     BIND(&is_smi);
    2321             :     {
    2322         224 :       Node* intptr_start_from = SmiUntag(start_from);
    2323         112 :       index_var.Bind(intptr_start_from);
    2324             : 
    2325         336 :       GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
    2326             :       // The fromIndex is negative: add it to the array's length.
    2327         336 :       index_var.Bind(IntPtrAdd(array_length_untagged, index_var.value()));
    2328             :       // Clamp negative results at zero.
    2329         336 :       GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
    2330         112 :       index_var.Bind(intptr_zero);
    2331         112 :       Goto(&done);
    2332             :     }
    2333         224 :     BIND(&done);
    2334             :   }
    2335             : 
    2336             :   // Fail early if startIndex >= array.length.
    2337         224 :   GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), array_length_untagged),
    2338         224 :          &return_not_found);
    2339             : 
    2340         112 :   Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this);
    2341             : 
    2342         112 :   TNode<Int32T> elements_kind = LoadElementsKind(array);
    2343             :   Node* elements = LoadElements(array);
    2344             :   STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
    2345             :   STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
    2346             :   STATIC_ASSERT(PACKED_ELEMENTS == 2);
    2347             :   STATIC_ASSERT(HOLEY_ELEMENTS == 3);
    2348         224 :   GotoIf(Uint32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
    2349         224 :          &if_smiorobjects);
    2350         224 :   GotoIf(Word32Equal(elements_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
    2351         224 :          &if_packed_doubles);
    2352         224 :   GotoIf(Word32Equal(elements_kind, Int32Constant(HOLEY_DOUBLE_ELEMENTS)),
    2353         224 :          &if_holey_doubles);
    2354         112 :   Goto(&return_not_found);
    2355             : 
    2356         112 :   BIND(&if_smiorobjects);
    2357             :   {
    2358             :     Callable callable =
    2359             :         (variant == kIncludes)
    2360             :             ? Builtins::CallableFor(isolate(),
    2361             :                                     Builtins::kArrayIncludesSmiOrObject)
    2362             :             : Builtins::CallableFor(isolate(),
    2363         112 :                                     Builtins::kArrayIndexOfSmiOrObject);
    2364             :     Node* result = CallStub(callable, context, elements, search_element,
    2365         448 :                             array_length, SmiTag(index_var.value()));
    2366         112 :     args.PopAndReturn(result);
    2367             :   }
    2368             : 
    2369         112 :   BIND(&if_packed_doubles);
    2370             :   {
    2371             :     Callable callable =
    2372             :         (variant == kIncludes)
    2373             :             ? Builtins::CallableFor(isolate(),
    2374             :                                     Builtins::kArrayIncludesPackedDoubles)
    2375             :             : Builtins::CallableFor(isolate(),
    2376         112 :                                     Builtins::kArrayIndexOfPackedDoubles);
    2377             :     Node* result = CallStub(callable, context, elements, search_element,
    2378         448 :                             array_length, SmiTag(index_var.value()));
    2379         112 :     args.PopAndReturn(result);
    2380             :   }
    2381             : 
    2382         112 :   BIND(&if_holey_doubles);
    2383             :   {
    2384             :     Callable callable =
    2385             :         (variant == kIncludes)
    2386             :             ? Builtins::CallableFor(isolate(),
    2387             :                                     Builtins::kArrayIncludesHoleyDoubles)
    2388             :             : Builtins::CallableFor(isolate(),
    2389         112 :                                     Builtins::kArrayIndexOfHoleyDoubles);
    2390             :     Node* result = CallStub(callable, context, elements, search_element,
    2391         448 :                             array_length, SmiTag(index_var.value()));
    2392         112 :     args.PopAndReturn(result);
    2393             :   }
    2394             : 
    2395         112 :   BIND(&return_not_found);
    2396         112 :   if (variant == kIncludes) {
    2397         112 :     args.PopAndReturn(FalseConstant());
    2398             :   } else {
    2399         112 :     args.PopAndReturn(NumberConstant(-1));
    2400             :   }
    2401             : 
    2402         112 :   BIND(&call_runtime);
    2403             :   {
    2404             :     Node* start_from =
    2405         336 :         args.GetOptionalArgumentValue(kFromIndexArg, UndefinedConstant());
    2406             :     Runtime::FunctionId function = variant == kIncludes
    2407             :                                        ? Runtime::kArrayIncludes_Slow
    2408         112 :                                        : Runtime::kArrayIndexOf;
    2409             :     args.PopAndReturn(
    2410         112 :         CallRuntime(function, context, array, search_element, start_from));
    2411         112 :   }
    2412         112 : }
    2413             : 
    2414         112 : void ArrayIncludesIndexofAssembler::GenerateSmiOrObject(
    2415             :     SearchVariant variant, Node* context, Node* elements, Node* search_element,
    2416             :     Node* array_length, Node* from_index) {
    2417         224 :   VARIABLE(index_var, MachineType::PointerRepresentation(),
    2418             :            SmiUntag(from_index));
    2419         224 :   VARIABLE(search_num, MachineRepresentation::kFloat64);
    2420         224 :   Node* array_length_untagged = SmiUntag(array_length);
    2421             : 
    2422         112 :   Label ident_loop(this, &index_var), heap_num_loop(this, &search_num),
    2423         112 :       string_loop(this), bigint_loop(this, &index_var),
    2424         112 :       undef_loop(this, &index_var), not_smi(this), not_heap_num(this),
    2425         112 :       return_found(this), return_not_found(this);
    2426             : 
    2427         224 :   GotoIfNot(TaggedIsSmi(search_element), &not_smi);
    2428         224 :   search_num.Bind(SmiToFloat64(search_element));
    2429         112 :   Goto(&heap_num_loop);
    2430             : 
    2431         112 :   BIND(&not_smi);
    2432         112 :   if (variant == kIncludes) {
    2433         112 :     GotoIf(IsUndefined(search_element), &undef_loop);
    2434             :   }
    2435         224 :   Node* map = LoadMap(search_element);
    2436         224 :   GotoIfNot(IsHeapNumberMap(map), &not_heap_num);
    2437         224 :   search_num.Bind(LoadHeapNumberValue(search_element));
    2438         112 :   Goto(&heap_num_loop);
    2439             : 
    2440         112 :   BIND(&not_heap_num);
    2441         224 :   Node* search_type = LoadMapInstanceType(map);
    2442         224 :   GotoIf(IsStringInstanceType(search_type), &string_loop);
    2443         224 :   GotoIf(IsBigIntInstanceType(search_type), &bigint_loop);
    2444         112 :   Goto(&ident_loop);
    2445             : 
    2446         112 :   BIND(&ident_loop);
    2447             :   {
    2448         224 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2449         224 :               &return_not_found);
    2450         224 :     Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
    2451         224 :     GotoIf(WordEqual(element_k, search_element), &return_found);
    2452             : 
    2453         112 :     Increment(&index_var);
    2454         112 :     Goto(&ident_loop);
    2455             :   }
    2456             : 
    2457         112 :   if (variant == kIncludes) {
    2458          56 :     BIND(&undef_loop);
    2459             : 
    2460         112 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2461         112 :               &return_not_found);
    2462         112 :     Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
    2463         112 :     GotoIf(IsUndefined(element_k), &return_found);
    2464         112 :     GotoIf(IsTheHole(element_k), &return_found);
    2465             : 
    2466          56 :     Increment(&index_var);
    2467          56 :     Goto(&undef_loop);
    2468             :   }
    2469             : 
    2470         112 :   BIND(&heap_num_loop);
    2471             :   {
    2472         112 :     Label nan_loop(this, &index_var), not_nan_loop(this, &index_var);
    2473         112 :     Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    2474         112 :     BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    2475             : 
    2476         112 :     BIND(&not_nan_loop);
    2477             :     {
    2478         112 :       Label continue_loop(this), not_smi(this);
    2479         224 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2480         224 :                 &return_not_found);
    2481             :       Node* element_k =
    2482         224 :           LoadFixedArrayElement(CAST(elements), index_var.value());
    2483         224 :       GotoIfNot(TaggedIsSmi(element_k), &not_smi);
    2484         336 :       Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)),
    2485         224 :              &return_found, &continue_loop);
    2486             : 
    2487         112 :       BIND(&not_smi);
    2488         224 :       GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    2489         336 :       Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)),
    2490         224 :              &return_found, &continue_loop);
    2491             : 
    2492         112 :       BIND(&continue_loop);
    2493         112 :       Increment(&index_var);
    2494         224 :       Goto(&not_nan_loop);
    2495             :     }
    2496             : 
    2497             :     // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    2498         112 :     if (variant == kIncludes) {
    2499          56 :       BIND(&nan_loop);
    2500             :       Label continue_loop(this);
    2501         112 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2502         112 :                 &return_not_found);
    2503             :       Node* element_k =
    2504         112 :           LoadFixedArrayElement(CAST(elements), index_var.value());
    2505         112 :       GotoIf(TaggedIsSmi(element_k), &continue_loop);
    2506         112 :       GotoIfNot(IsHeapNumber(CAST(element_k)), &continue_loop);
    2507          56 :       BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_found,
    2508         112 :                            &continue_loop);
    2509             : 
    2510          56 :       BIND(&continue_loop);
    2511          56 :       Increment(&index_var);
    2512          56 :       Goto(&nan_loop);
    2513         112 :     }
    2514             :   }
    2515             : 
    2516         112 :   BIND(&string_loop);
    2517             :   {
    2518             :     TNode<String> search_element_string = CAST(search_element);
    2519         112 :     Label continue_loop(this), next_iteration(this, &index_var),
    2520         112 :         slow_compare(this), runtime(this, Label::kDeferred);
    2521             :     TNode<IntPtrT> search_length =
    2522         112 :         LoadStringLengthAsWord(search_element_string);
    2523         112 :     Goto(&next_iteration);
    2524         112 :     BIND(&next_iteration);
    2525         224 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2526         224 :               &return_not_found);
    2527         224 :     Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
    2528         224 :     GotoIf(TaggedIsSmi(element_k), &continue_loop);
    2529         112 :     GotoIf(WordEqual(search_element_string, element_k), &return_found);
    2530         224 :     Node* element_k_type = LoadInstanceType(element_k);
    2531         224 :     GotoIfNot(IsStringInstanceType(element_k_type), &continue_loop);
    2532         224 :     Branch(WordEqual(search_length, LoadStringLengthAsWord(element_k)),
    2533         224 :            &slow_compare, &continue_loop);
    2534             : 
    2535         112 :     BIND(&slow_compare);
    2536             :     StringBuiltinsAssembler string_asm(state());
    2537             :     string_asm.StringEqual_Core(context, search_element_string, search_type,
    2538             :                                 element_k, element_k_type, search_length,
    2539         112 :                                 &return_found, &continue_loop, &runtime);
    2540         112 :     BIND(&runtime);
    2541             :     TNode<Object> result = CallRuntime(Runtime::kStringEqual, context,
    2542             :                                        search_element_string, element_k);
    2543         224 :     Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop);
    2544             : 
    2545         112 :     BIND(&continue_loop);
    2546         112 :     Increment(&index_var);
    2547         224 :     Goto(&next_iteration);
    2548             :   }
    2549             : 
    2550         112 :   BIND(&bigint_loop);
    2551             :   {
    2552         224 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2553         224 :               &return_not_found);
    2554             : 
    2555         224 :     Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
    2556             :     Label continue_loop(this);
    2557         224 :     GotoIf(TaggedIsSmi(element_k), &continue_loop);
    2558         224 :     GotoIfNot(IsBigInt(CAST(element_k)), &continue_loop);
    2559             :     TNode<Object> result = CallRuntime(Runtime::kBigIntEqualToBigInt, context,
    2560             :                                        search_element, element_k);
    2561         224 :     Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop);
    2562             : 
    2563         112 :     BIND(&continue_loop);
    2564         112 :     Increment(&index_var);
    2565         112 :     Goto(&bigint_loop);
    2566             :   }
    2567         112 :   BIND(&return_found);
    2568         112 :   if (variant == kIncludes) {
    2569         112 :     Return(TrueConstant());
    2570             :   } else {
    2571         168 :     Return(SmiTag(index_var.value()));
    2572             :   }
    2573             : 
    2574         112 :   BIND(&return_not_found);
    2575         112 :   if (variant == kIncludes) {
    2576         112 :     Return(FalseConstant());
    2577             :   } else {
    2578         112 :     Return(NumberConstant(-1));
    2579         112 :   }
    2580         112 : }
    2581             : 
    2582         112 : void ArrayIncludesIndexofAssembler::GeneratePackedDoubles(SearchVariant variant,
    2583             :                                                           Node* elements,
    2584             :                                                           Node* search_element,
    2585             :                                                           Node* array_length,
    2586             :                                                           Node* from_index) {
    2587         224 :   VARIABLE(index_var, MachineType::PointerRepresentation(),
    2588             :            SmiUntag(from_index));
    2589         224 :   Node* array_length_untagged = SmiUntag(array_length);
    2590             : 
    2591         112 :   Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    2592         112 :       hole_loop(this, &index_var), search_notnan(this), return_found(this),
    2593         112 :       return_not_found(this);
    2594         224 :   VARIABLE(search_num, MachineRepresentation::kFloat64);
    2595         224 :   search_num.Bind(Float64Constant(0));
    2596             : 
    2597         224 :   GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    2598         224 :   search_num.Bind(SmiToFloat64(search_element));
    2599         112 :   Goto(&not_nan_loop);
    2600             : 
    2601         112 :   BIND(&search_notnan);
    2602         224 :   GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    2603             : 
    2604         224 :   search_num.Bind(LoadHeapNumberValue(search_element));
    2605             : 
    2606         112 :   Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    2607         112 :   BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    2608             : 
    2609         112 :   BIND(&not_nan_loop);
    2610             :   {
    2611             :     Label continue_loop(this);
    2612         224 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2613         224 :               &return_not_found);
    2614             :     Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    2615         336 :                                                   MachineType::Float64());
    2616         224 :     Branch(Float64Equal(element_k, search_num.value()), &return_found,
    2617         224 :            &continue_loop);
    2618         112 :     BIND(&continue_loop);
    2619         112 :     Increment(&index_var);
    2620         112 :     Goto(&not_nan_loop);
    2621             :   }
    2622             : 
    2623             :   // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    2624         112 :   if (variant == kIncludes) {
    2625          56 :     BIND(&nan_loop);
    2626             :     Label continue_loop(this);
    2627         112 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2628         112 :               &return_not_found);
    2629             :     Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    2630         168 :                                                   MachineType::Float64());
    2631          56 :     BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
    2632          56 :     BIND(&continue_loop);
    2633          56 :     Increment(&index_var);
    2634          56 :     Goto(&nan_loop);
    2635             :   }
    2636             : 
    2637         112 :   BIND(&return_found);
    2638         112 :   if (variant == kIncludes) {
    2639         112 :     Return(TrueConstant());
    2640             :   } else {
    2641         168 :     Return(SmiTag(index_var.value()));
    2642             :   }
    2643             : 
    2644         112 :   BIND(&return_not_found);
    2645         112 :   if (variant == kIncludes) {
    2646         112 :     Return(FalseConstant());
    2647             :   } else {
    2648         112 :     Return(NumberConstant(-1));
    2649         112 :   }
    2650         112 : }
    2651             : 
    2652         112 : void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant,
    2653             :                                                          Node* elements,
    2654             :                                                          Node* search_element,
    2655             :                                                          Node* array_length,
    2656             :                                                          Node* from_index) {
    2657         224 :   VARIABLE(index_var, MachineType::PointerRepresentation(),
    2658             :            SmiUntag(from_index));
    2659         224 :   Node* array_length_untagged = SmiUntag(array_length);
    2660             : 
    2661         112 :   Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    2662         112 :       hole_loop(this, &index_var), search_notnan(this), return_found(this),
    2663         112 :       return_not_found(this);
    2664         224 :   VARIABLE(search_num, MachineRepresentation::kFloat64);
    2665         224 :   search_num.Bind(Float64Constant(0));
    2666             : 
    2667         224 :   GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    2668         224 :   search_num.Bind(SmiToFloat64(search_element));
    2669         112 :   Goto(&not_nan_loop);
    2670             : 
    2671         112 :   BIND(&search_notnan);
    2672         112 :   if (variant == kIncludes) {
    2673         112 :     GotoIf(IsUndefined(search_element), &hole_loop);
    2674             :   }
    2675         224 :   GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    2676             : 
    2677         224 :   search_num.Bind(LoadHeapNumberValue(search_element));
    2678             : 
    2679         112 :   Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    2680         112 :   BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    2681             : 
    2682         112 :   BIND(&not_nan_loop);
    2683             :   {
    2684             :     Label continue_loop(this);
    2685         224 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2686         224 :               &return_not_found);
    2687             : 
    2688             :     // No need for hole checking here; the following Float64Equal will
    2689             :     // return 'not equal' for holes anyway.
    2690             :     Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    2691         336 :                                                   MachineType::Float64());
    2692             : 
    2693         224 :     Branch(Float64Equal(element_k, search_num.value()), &return_found,
    2694         224 :            &continue_loop);
    2695         112 :     BIND(&continue_loop);
    2696         112 :     Increment(&index_var);
    2697         112 :     Goto(&not_nan_loop);
    2698             :   }
    2699             : 
    2700             :   // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    2701         112 :   if (variant == kIncludes) {
    2702          56 :     BIND(&nan_loop);
    2703             :     Label continue_loop(this);
    2704         112 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2705         112 :               &return_not_found);
    2706             : 
    2707             :     // Load double value or continue if it's the hole NaN.
    2708             :     Node* element_k = LoadFixedDoubleArrayElement(
    2709             :         elements, index_var.value(), MachineType::Float64(), 0,
    2710         168 :         INTPTR_PARAMETERS, &continue_loop);
    2711             : 
    2712          56 :     BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
    2713          56 :     BIND(&continue_loop);
    2714          56 :     Increment(&index_var);
    2715          56 :     Goto(&nan_loop);
    2716             :   }
    2717             : 
    2718             :   // Array.p.includes treats the hole as undefined.
    2719         112 :   if (variant == kIncludes) {
    2720          56 :     BIND(&hole_loop);
    2721         112 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    2722         112 :               &return_not_found);
    2723             : 
    2724             :     // Check if the element is a double hole, but don't load it.
    2725             :     LoadFixedDoubleArrayElement(elements, index_var.value(),
    2726             :                                 MachineType::None(), 0, INTPTR_PARAMETERS,
    2727         112 :                                 &return_found);
    2728             : 
    2729          56 :     Increment(&index_var);
    2730          56 :     Goto(&hole_loop);
    2731             :   }
    2732             : 
    2733         112 :   BIND(&return_found);
    2734         112 :   if (variant == kIncludes) {
    2735         112 :     Return(TrueConstant());
    2736             :   } else {
    2737         168 :     Return(SmiTag(index_var.value()));
    2738             :   }
    2739             : 
    2740         112 :   BIND(&return_not_found);
    2741         112 :   if (variant == kIncludes) {
    2742         112 :     Return(FalseConstant());
    2743             :   } else {
    2744         112 :     Return(NumberConstant(-1));
    2745         112 :   }
    2746         112 : }
    2747             : 
    2748         280 : TF_BUILTIN(ArrayIncludes, ArrayIncludesIndexofAssembler) {
    2749             :   TNode<IntPtrT> argc =
    2750          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2751          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2752             : 
    2753          56 :   Generate(kIncludes, argc, context);
    2754          56 : }
    2755             : 
    2756         224 : TF_BUILTIN(ArrayIncludesSmiOrObject, ArrayIncludesIndexofAssembler) {
    2757             :   Node* context = Parameter(Descriptor::kContext);
    2758             :   Node* elements = Parameter(Descriptor::kElements);
    2759             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    2760             :   Node* array_length = Parameter(Descriptor::kLength);
    2761             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    2762             : 
    2763             :   GenerateSmiOrObject(kIncludes, context, elements, search_element,
    2764          56 :                       array_length, from_index);
    2765          56 : }
    2766             : 
    2767         224 : TF_BUILTIN(ArrayIncludesPackedDoubles, ArrayIncludesIndexofAssembler) {
    2768             :   Node* elements = Parameter(Descriptor::kElements);
    2769             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    2770             :   Node* array_length = Parameter(Descriptor::kLength);
    2771             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    2772             : 
    2773             :   GeneratePackedDoubles(kIncludes, elements, search_element, array_length,
    2774          56 :                         from_index);
    2775          56 : }
    2776             : 
    2777         224 : TF_BUILTIN(ArrayIncludesHoleyDoubles, ArrayIncludesIndexofAssembler) {
    2778             :   Node* elements = Parameter(Descriptor::kElements);
    2779             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    2780             :   Node* array_length = Parameter(Descriptor::kLength);
    2781             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    2782             : 
    2783             :   GenerateHoleyDoubles(kIncludes, elements, search_element, array_length,
    2784          56 :                        from_index);
    2785          56 : }
    2786             : 
    2787         280 : TF_BUILTIN(ArrayIndexOf, ArrayIncludesIndexofAssembler) {
    2788             :   TNode<IntPtrT> argc =
    2789          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    2790          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2791             : 
    2792          56 :   Generate(kIndexOf, argc, context);
    2793          56 : }
    2794             : 
    2795         224 : TF_BUILTIN(ArrayIndexOfSmiOrObject, ArrayIncludesIndexofAssembler) {
    2796             :   Node* context = Parameter(Descriptor::kContext);
    2797             :   Node* elements = Parameter(Descriptor::kElements);
    2798             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    2799             :   Node* array_length = Parameter(Descriptor::kLength);
    2800             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    2801             : 
    2802             :   GenerateSmiOrObject(kIndexOf, context, elements, search_element, array_length,
    2803          56 :                       from_index);
    2804          56 : }
    2805             : 
    2806         224 : TF_BUILTIN(ArrayIndexOfPackedDoubles, ArrayIncludesIndexofAssembler) {
    2807             :   Node* elements = Parameter(Descriptor::kElements);
    2808             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    2809             :   Node* array_length = Parameter(Descriptor::kLength);
    2810             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    2811             : 
    2812             :   GeneratePackedDoubles(kIndexOf, elements, search_element, array_length,
    2813          56 :                         from_index);
    2814          56 : }
    2815             : 
    2816         224 : TF_BUILTIN(ArrayIndexOfHoleyDoubles, ArrayIncludesIndexofAssembler) {
    2817             :   Node* elements = Parameter(Descriptor::kElements);
    2818             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    2819             :   Node* array_length = Parameter(Descriptor::kLength);
    2820             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    2821             : 
    2822             :   GenerateHoleyDoubles(kIndexOf, elements, search_element, array_length,
    2823          56 :                        from_index);
    2824          56 : }
    2825             : 
    2826             : // ES #sec-array.prototype.values
    2827         224 : TF_BUILTIN(ArrayPrototypeValues, CodeStubAssembler) {
    2828          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2829          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2830          56 :   Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
    2831         168 :                              IterationKind::kValues));
    2832          56 : }
    2833             : 
    2834             : // ES #sec-array.prototype.entries
    2835         224 : TF_BUILTIN(ArrayPrototypeEntries, CodeStubAssembler) {
    2836          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2837          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2838          56 :   Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
    2839         168 :                              IterationKind::kEntries));
    2840          56 : }
    2841             : 
    2842             : // ES #sec-array.prototype.keys
    2843         224 : TF_BUILTIN(ArrayPrototypeKeys, CodeStubAssembler) {
    2844          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2845          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    2846          56 :   Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
    2847         168 :                              IterationKind::kKeys));
    2848          56 : }
    2849             : 
    2850             : // ES #sec-%arrayiteratorprototype%.next
    2851         168 : TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
    2852             :   const char* method_name = "Array Iterator.prototype.next";
    2853             : 
    2854             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2855             :   Node* iterator = Parameter(Descriptor::kReceiver);
    2856             : 
    2857         112 :   VARIABLE(var_done, MachineRepresentation::kTagged, TrueConstant());
    2858         168 :   VARIABLE(var_value, MachineRepresentation::kTagged, UndefinedConstant());
    2859             : 
    2860          56 :   Label allocate_entry_if_needed(this);
    2861          56 :   Label allocate_iterator_result(this);
    2862          56 :   Label if_typedarray(this), if_other(this, Label::kDeferred), if_array(this),
    2863          56 :       if_generic(this, Label::kDeferred);
    2864          56 :   Label set_done(this, Label::kDeferred);
    2865             : 
    2866             :   // If O does not have all of the internal slots of an Array Iterator Instance
    2867             :   // (22.1.5.3), throw a TypeError exception
    2868             :   ThrowIfNotInstanceType(context, iterator, JS_ARRAY_ITERATOR_TYPE,
    2869          56 :                          method_name);
    2870             : 
    2871             :   // Let a be O.[[IteratedObject]].
    2872             :   TNode<JSReceiver> array =
    2873             :       CAST(LoadObjectField(iterator, JSArrayIterator::kIteratedObjectOffset));
    2874             : 
    2875             :   // Let index be O.[[ArrayIteratorNextIndex]].
    2876             :   TNode<Number> index =
    2877             :       CAST(LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset));
    2878             :   CSA_ASSERT(this, IsNumberNonNegativeSafeInteger(index));
    2879             : 
    2880             :   // Dispatch based on the type of the {array}.
    2881          56 :   TNode<Map> array_map = LoadMap(array);
    2882          56 :   TNode<Int32T> array_type = LoadMapInstanceType(array_map);
    2883         112 :   GotoIf(InstanceTypeEqual(array_type, JS_ARRAY_TYPE), &if_array);
    2884          56 :   Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_typedarray,
    2885         112 :          &if_other);
    2886             : 
    2887          56 :   BIND(&if_array);
    2888             :   {
    2889             :     // If {array} is a JSArray, then the {index} must be in Unsigned32 range.
    2890             :     CSA_ASSERT(this, IsNumberArrayIndex(index));
    2891             : 
    2892             :     // Check that the {index} is within range for the {array}. We handle all
    2893             :     // kinds of JSArray's here, so we do the computation on Uint32.
    2894          56 :     TNode<Uint32T> index32 = ChangeNumberToUint32(index);
    2895             :     TNode<Uint32T> length32 =
    2896          56 :         ChangeNumberToUint32(LoadJSArrayLength(CAST(array)));
    2897         112 :     GotoIfNot(Uint32LessThan(index32, length32), &set_done);
    2898             :     StoreObjectField(
    2899             :         iterator, JSArrayIterator::kNextIndexOffset,
    2900         224 :         ChangeUint32ToTagged(Unsigned(Int32Add(index32, Int32Constant(1)))));
    2901             : 
    2902         112 :     var_done.Bind(FalseConstant());
    2903          56 :     var_value.Bind(index);
    2904             : 
    2905             :     GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
    2906             :                            iterator, JSArrayIterator::kKindOffset),
    2907         168 :                        Int32Constant(static_cast<int>(IterationKind::kKeys))),
    2908         112 :            &allocate_iterator_result);
    2909             : 
    2910             :     Label if_hole(this, Label::kDeferred);
    2911          56 :     TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
    2912          56 :     TNode<FixedArrayBase> elements = LoadElements(CAST(array));
    2913          56 :     GotoIfForceSlowPath(&if_generic);
    2914             :     var_value.Bind(LoadFixedArrayBaseElementAsTagged(
    2915          56 :         elements, Signed(ChangeUint32ToWord(index32)), elements_kind,
    2916         168 :         &if_generic, &if_hole));
    2917          56 :     Goto(&allocate_entry_if_needed);
    2918             : 
    2919          56 :     BIND(&if_hole);
    2920             :     {
    2921         112 :       GotoIf(IsNoElementsProtectorCellInvalid(), &if_generic);
    2922          56 :       GotoIfNot(IsPrototypeInitialArrayPrototype(context, array_map),
    2923         112 :                 &if_generic);
    2924         112 :       var_value.Bind(UndefinedConstant());
    2925          56 :       Goto(&allocate_entry_if_needed);
    2926          56 :     }
    2927             :   }
    2928             : 
    2929          56 :   BIND(&if_other);
    2930             :   {
    2931             :     // We cannot enter here with either JSArray's or JSTypedArray's.
    2932             :     CSA_ASSERT(this, Word32BinaryNot(IsJSArray(array)));
    2933             :     CSA_ASSERT(this, Word32BinaryNot(IsJSTypedArray(array)));
    2934             : 
    2935             :     // Check that the {index} is within the bounds of the {array}s "length".
    2936         168 :     TNode<Number> length = CAST(
    2937             :         CallBuiltin(Builtins::kToLength, context,
    2938             :                     GetProperty(context, array, factory()->length_string())));
    2939          56 :     GotoIfNumberGreaterThanOrEqual(index, length, &set_done);
    2940             :     StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset,
    2941         112 :                      NumberInc(index));
    2942             : 
    2943         112 :     var_done.Bind(FalseConstant());
    2944          56 :     var_value.Bind(index);
    2945             : 
    2946             :     Branch(Word32Equal(LoadAndUntagToWord32ObjectField(
    2947             :                            iterator, JSArrayIterator::kKindOffset),
    2948         168 :                        Int32Constant(static_cast<int>(IterationKind::kKeys))),
    2949         112 :            &allocate_iterator_result, &if_generic);
    2950             :   }
    2951             : 
    2952          56 :   BIND(&set_done);
    2953             :   {
    2954             :     // Change the [[ArrayIteratorNextIndex]] such that the {iterator} will
    2955             :     // never produce values anymore, because it will always fail the bounds
    2956             :     // check. Note that this is different from what the specification does,
    2957             :     // which is changing the [[IteratedObject]] to undefined, because leaving
    2958             :     // [[IteratedObject]] alone helps TurboFan to generate better code with
    2959             :     // the inlining in JSCallReducer::ReduceArrayIteratorPrototypeNext().
    2960             :     //
    2961             :     // The terminal value we chose here depends on the type of the {array},
    2962             :     // for JSArray's we use kMaxUInt32 so that TurboFan can always use
    2963             :     // Word32 representation for fast-path indices (and this is safe since
    2964             :     // the "length" of JSArray's is limited to Unsigned32 range). For other
    2965             :     // JSReceiver's we have to use kMaxSafeInteger, since the "length" can
    2966             :     // be any arbitrary value in the safe integer range.
    2967             :     //
    2968             :     // Note specifically that JSTypedArray's will never take this path, so
    2969             :     // we don't need to worry about their maximum value.
    2970             :     CSA_ASSERT(this, Word32BinaryNot(IsJSTypedArray(array)));
    2971             :     TNode<Number> max_length =
    2972             :         SelectConstant(IsJSArray(array), NumberConstant(kMaxUInt32),
    2973         112 :                        NumberConstant(kMaxSafeInteger));
    2974          56 :     StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset, max_length);
    2975          56 :     Goto(&allocate_iterator_result);
    2976             :   }
    2977             : 
    2978          56 :   BIND(&if_generic);
    2979             :   {
    2980          56 :     var_value.Bind(GetProperty(context, array, index));
    2981          56 :     Goto(&allocate_entry_if_needed);
    2982             :   }
    2983             : 
    2984          56 :   BIND(&if_typedarray);
    2985             :   {
    2986             :     // If {array} is a JSTypedArray, the {index} must always be a Smi.
    2987             :     CSA_ASSERT(this, TaggedIsSmi(index));
    2988             : 
    2989             :     // Check that the {array}s buffer wasn't detached.
    2990          56 :     ThrowIfArrayBufferViewBufferIsDetached(context, CAST(array), method_name);
    2991             : 
    2992             :     // If we go outside of the {length}, we don't need to update the
    2993             :     // [[ArrayIteratorNextIndex]] anymore, since a JSTypedArray's
    2994             :     // length cannot change anymore, so this {iterator} will never
    2995             :     // produce values again anyways.
    2996          56 :     TNode<Smi> length = LoadJSTypedArrayLength(CAST(array));
    2997         112 :     GotoIfNot(SmiBelow(CAST(index), length), &allocate_iterator_result);
    2998             :     StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
    2999         112 :                                    SmiInc(CAST(index)));
    3000             : 
    3001         112 :     var_done.Bind(FalseConstant());
    3002          56 :     var_value.Bind(index);
    3003             : 
    3004             :     GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
    3005             :                            iterator, JSArrayIterator::kKindOffset),
    3006         168 :                        Int32Constant(static_cast<int>(IterationKind::kKeys))),
    3007         112 :            &allocate_iterator_result);
    3008             : 
    3009          56 :     TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
    3010             :     Node* elements = LoadElements(CAST(array));
    3011             :     Node* base_ptr =
    3012             :         LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
    3013             :     Node* external_ptr =
    3014             :         LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
    3015          56 :                         MachineType::Pointer());
    3016             :     TNode<WordT> data_ptr =
    3017         112 :         IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
    3018             :     var_value.Bind(LoadFixedTypedArrayElementAsTagged(data_ptr, CAST(index),
    3019         112 :                                                       elements_kind));
    3020          56 :     Goto(&allocate_entry_if_needed);
    3021             :   }
    3022             : 
    3023          56 :   BIND(&allocate_entry_if_needed);
    3024             :   {
    3025             :     GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
    3026             :                            iterator, JSArrayIterator::kKindOffset),
    3027         168 :                        Int32Constant(static_cast<int>(IterationKind::kValues))),
    3028         112 :            &allocate_iterator_result);
    3029             : 
    3030             :     Node* result =
    3031          56 :         AllocateJSIteratorResultForEntry(context, index, var_value.value());
    3032          56 :     Return(result);
    3033             :   }
    3034             : 
    3035          56 :   BIND(&allocate_iterator_result);
    3036             :   {
    3037             :     Node* result =
    3038          56 :         AllocateJSIteratorResult(context, var_value.value(), var_done.value());
    3039          56 :     Return(result);
    3040          56 :   }
    3041          56 : }
    3042             : 
    3043             : class ArrayFlattenAssembler : public CodeStubAssembler {
    3044             :  public:
    3045             :   explicit ArrayFlattenAssembler(compiler::CodeAssemblerState* state)
    3046         112 :       : CodeStubAssembler(state) {}
    3047             : 
    3048             :   // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
    3049         112 :   Node* FlattenIntoArray(Node* context, Node* target, Node* source,
    3050             :                          Node* source_length, Node* start, Node* depth,
    3051             :                          Node* mapper_function = nullptr,
    3052             :                          Node* this_arg = nullptr) {
    3053             :     CSA_ASSERT(this, IsJSReceiver(target));
    3054             :     CSA_ASSERT(this, IsJSReceiver(source));
    3055             :     CSA_ASSERT(this, IsNumberPositive(source_length));
    3056             :     CSA_ASSERT(this, IsNumberPositive(start));
    3057             :     CSA_ASSERT(this, IsNumber(depth));
    3058             : 
    3059             :     // 1. Let targetIndex be start.
    3060         112 :     VARIABLE(var_target_index, MachineRepresentation::kTagged, start);
    3061             : 
    3062             :     // 2. Let sourceIndex be 0.
    3063         336 :     VARIABLE(var_source_index, MachineRepresentation::kTagged, SmiConstant(0));
    3064             : 
    3065             :     // 3. Repeat...
    3066         336 :     Label loop(this, {&var_target_index, &var_source_index}), done_loop(this);
    3067         112 :     Goto(&loop);
    3068         112 :     BIND(&loop);
    3069             :     {
    3070         112 :       Node* const source_index = var_source_index.value();
    3071         112 :       Node* const target_index = var_target_index.value();
    3072             : 
    3073             :       // ...while sourceIndex < sourceLen
    3074         112 :       GotoIfNumberGreaterThanOrEqual(source_index, source_length, &done_loop);
    3075             : 
    3076             :       // a. Let P be ! ToString(sourceIndex).
    3077             :       // b. Let exists be ? HasProperty(source, P).
    3078             :       CSA_ASSERT(this,
    3079             :                  SmiGreaterThanOrEqual(CAST(source_index), SmiConstant(0)));
    3080             :       Node* const exists =
    3081         224 :           HasProperty(context, source, source_index, kHasProperty);
    3082             : 
    3083             :       // c. If exists is true, then
    3084             :       Label next(this);
    3085         224 :       GotoIfNot(IsTrue(exists), &next);
    3086             :       {
    3087             :         // i. Let element be ? Get(source, P).
    3088             :         Node* element = GetProperty(context, source, source_index);
    3089             : 
    3090             :         // ii. If mapperFunction is present, then
    3091         112 :         if (mapper_function != nullptr) {
    3092             :           CSA_ASSERT(this, Word32Or(IsUndefined(mapper_function),
    3093             :                                     IsCallable(mapper_function)));
    3094             :           DCHECK_NOT_NULL(this_arg);
    3095             : 
    3096             :           // 1. Set element to ? Call(mapperFunction, thisArg , « element,
    3097             :           //                          sourceIndex, source »).
    3098             :           element =
    3099             :               CallJS(CodeFactory::Call(isolate()), context, mapper_function,
    3100         112 :                      this_arg, element, source_index, source);
    3101             :         }
    3102             : 
    3103             :         // iii. Let shouldFlatten be false.
    3104         112 :         Label if_flatten_array(this), if_flatten_proxy(this, Label::kDeferred),
    3105         112 :             if_noflatten(this);
    3106             :         // iv. If depth > 0, then
    3107         224 :         GotoIfNumberGreaterThanOrEqual(SmiConstant(0), depth, &if_noflatten);
    3108             :         // 1. Set shouldFlatten to ? IsArray(element).
    3109         224 :         GotoIf(TaggedIsSmi(element), &if_noflatten);
    3110         224 :         GotoIf(IsJSArray(element), &if_flatten_array);
    3111         224 :         GotoIfNot(IsJSProxy(element), &if_noflatten);
    3112         112 :         Branch(IsTrue(CallRuntime(Runtime::kArrayIsArray, context, element)),
    3113         224 :                &if_flatten_proxy, &if_noflatten);
    3114             : 
    3115         112 :         BIND(&if_flatten_array);
    3116             :         {
    3117             :           CSA_ASSERT(this, IsJSArray(element));
    3118             : 
    3119             :           // 1. Let elementLen be ? ToLength(? Get(element, "length")).
    3120             :           Node* const element_length =
    3121             :               LoadObjectField(element, JSArray::kLengthOffset);
    3122             : 
    3123             :           // 2. Set targetIndex to ? FlattenIntoArray(target, element,
    3124             :           //                                          elementLen, targetIndex,
    3125             :           //                                          depth - 1).
    3126             :           var_target_index.Bind(
    3127             :               CallBuiltin(Builtins::kFlattenIntoArray, context, target, element,
    3128         336 :                           element_length, target_index, NumberDec(depth)));
    3129         112 :           Goto(&next);
    3130             :         }
    3131             : 
    3132         112 :         BIND(&if_flatten_proxy);
    3133             :         {
    3134             :           CSA_ASSERT(this, IsJSProxy(element));
    3135             : 
    3136             :           // 1. Let elementLen be ? ToLength(? Get(element, "length")).
    3137             :           Node* const element_length = ToLength_Inline(
    3138         336 :               context, GetProperty(context, element, LengthStringConstant()));
    3139             : 
    3140             :           // 2. Set targetIndex to ? FlattenIntoArray(target, element,
    3141             :           //                                          elementLen, targetIndex,
    3142             :           //                                          depth - 1).
    3143             :           var_target_index.Bind(
    3144             :               CallBuiltin(Builtins::kFlattenIntoArray, context, target, element,
    3145         336 :                           element_length, target_index, NumberDec(depth)));
    3146         112 :           Goto(&next);
    3147             :         }
    3148             : 
    3149         112 :         BIND(&if_noflatten);
    3150             :         {
    3151             :           // 1. If targetIndex >= 2^53-1, throw a TypeError exception.
    3152             :           Label throw_error(this, Label::kDeferred);
    3153             :           GotoIfNumberGreaterThanOrEqual(
    3154         224 :               target_index, NumberConstant(kMaxSafeInteger), &throw_error);
    3155             : 
    3156             :           // 2. Perform ? CreateDataPropertyOrThrow(target,
    3157             :           //                                        ! ToString(targetIndex),
    3158             :           //                                        element).
    3159             :           CallRuntime(Runtime::kCreateDataProperty, context, target,
    3160             :                       target_index, element);
    3161             : 
    3162             :           // 3. Increase targetIndex by 1.
    3163         224 :           var_target_index.Bind(NumberInc(target_index));
    3164         112 :           Goto(&next);
    3165             : 
    3166         112 :           BIND(&throw_error);
    3167             :           ThrowTypeError(context, MessageTemplate::kFlattenPastSafeLength,
    3168         112 :                          source_length, target_index);
    3169         112 :         }
    3170             :       }
    3171         112 :       BIND(&next);
    3172             : 
    3173             :       // d. Increase sourceIndex by 1.
    3174         224 :       var_source_index.Bind(NumberInc(source_index));
    3175         112 :       Goto(&loop);
    3176             :     }
    3177             : 
    3178         112 :     BIND(&done_loop);
    3179         224 :     return var_target_index.value();
    3180             :   }
    3181             : };
    3182             : 
    3183             : // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
    3184         224 : TF_BUILTIN(FlattenIntoArray, ArrayFlattenAssembler) {
    3185             :   Node* const context = Parameter(Descriptor::kContext);
    3186             :   Node* const target = Parameter(Descriptor::kTarget);
    3187             :   Node* const source = Parameter(Descriptor::kSource);
    3188             :   Node* const source_length = Parameter(Descriptor::kSourceLength);
    3189             :   Node* const start = Parameter(Descriptor::kStart);
    3190             :   Node* const depth = Parameter(Descriptor::kDepth);
    3191             : 
    3192             :   Return(
    3193         112 :       FlattenIntoArray(context, target, source, source_length, start, depth));
    3194          56 : }
    3195             : 
    3196             : // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
    3197         224 : TF_BUILTIN(FlatMapIntoArray, ArrayFlattenAssembler) {
    3198             :   Node* const context = Parameter(Descriptor::kContext);
    3199             :   Node* const target = Parameter(Descriptor::kTarget);
    3200             :   Node* const source = Parameter(Descriptor::kSource);
    3201             :   Node* const source_length = Parameter(Descriptor::kSourceLength);
    3202             :   Node* const start = Parameter(Descriptor::kStart);
    3203             :   Node* const depth = Parameter(Descriptor::kDepth);
    3204             :   Node* const mapper_function = Parameter(Descriptor::kMapperFunction);
    3205             :   Node* const this_arg = Parameter(Descriptor::kThisArg);
    3206             : 
    3207             :   Return(FlattenIntoArray(context, target, source, source_length, start, depth,
    3208         112 :                           mapper_function, this_arg));
    3209          56 : }
    3210             : 
    3211             : // https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flat
    3212         224 : TF_BUILTIN(ArrayPrototypeFlat, CodeStubAssembler) {
    3213             :   TNode<IntPtrT> const argc =
    3214          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    3215          56 :   CodeStubArguments args(this, argc);
    3216             :   TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
    3217          56 :   TNode<Object> const receiver = args.GetReceiver();
    3218          56 :   TNode<Object> const depth = args.GetOptionalArgumentValue(0);
    3219             : 
    3220             :   // 1. Let O be ? ToObject(this value).
    3221          56 :   TNode<JSReceiver> const o = ToObject_Inline(context, receiver);
    3222             : 
    3223             :   // 2. Let sourceLen be ? ToLength(? Get(O, "length")).
    3224             :   TNode<Number> const source_length =
    3225         112 :       ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
    3226             : 
    3227             :   // 3. Let depthNum be 1.
    3228         112 :   TVARIABLE(Number, var_depth_num, SmiConstant(1));
    3229             : 
    3230             :   // 4. If depth is not undefined, then
    3231          56 :   Label done(this);
    3232         112 :   GotoIf(IsUndefined(depth), &done);
    3233             :   {
    3234             :     // a. Set depthNum to ? ToInteger(depth).
    3235         112 :     var_depth_num = ToInteger_Inline(context, depth);
    3236          56 :     Goto(&done);
    3237             :   }
    3238          56 :   BIND(&done);
    3239             : 
    3240             :   // 5. Let A be ? ArraySpeciesCreate(O, 0).
    3241             :   TNode<JSReceiver> const constructor =
    3242          56 :       CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
    3243         112 :   Node* const a = Construct(context, constructor, SmiConstant(0));
    3244             : 
    3245             :   // 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, depthNum).
    3246             :   CallBuiltin(Builtins::kFlattenIntoArray, context, a, o, source_length,
    3247         112 :               SmiConstant(0), var_depth_num.value());
    3248             : 
    3249             :   // 7. Return A.
    3250          56 :   args.PopAndReturn(a);
    3251          56 : }
    3252             : 
    3253             : // https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap
    3254         224 : TF_BUILTIN(ArrayPrototypeFlatMap, CodeStubAssembler) {
    3255             :   TNode<IntPtrT> const argc =
    3256          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    3257          56 :   CodeStubArguments args(this, argc);
    3258             :   TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
    3259          56 :   TNode<Object> const receiver = args.GetReceiver();
    3260          56 :   TNode<Object> const mapper_function = args.GetOptionalArgumentValue(0);
    3261             : 
    3262             :   // 1. Let O be ? ToObject(this value).
    3263          56 :   TNode<JSReceiver> const o = ToObject_Inline(context, receiver);
    3264             : 
    3265             :   // 2. Let sourceLen be ? ToLength(? Get(O, "length")).
    3266             :   TNode<Number> const source_length =
    3267         112 :       ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
    3268             : 
    3269             :   // 3. If IsCallable(mapperFunction) is false, throw a TypeError exception.
    3270             :   Label if_not_callable(this, Label::kDeferred);
    3271         112 :   GotoIf(TaggedIsSmi(mapper_function), &if_not_callable);
    3272         112 :   GotoIfNot(IsCallable(CAST(mapper_function)), &if_not_callable);
    3273             : 
    3274             :   // 4. If thisArg is present, let T be thisArg; else let T be undefined.
    3275          56 :   TNode<Object> const t = args.GetOptionalArgumentValue(1);
    3276             : 
    3277             :   // 5. Let A be ? ArraySpeciesCreate(O, 0).
    3278             :   TNode<JSReceiver> const constructor =
    3279          56 :       CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
    3280          56 :   TNode<JSReceiver> const a = Construct(context, constructor, SmiConstant(0));
    3281             : 
    3282             :   // 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T).
    3283             :   CallBuiltin(Builtins::kFlatMapIntoArray, context, a, o, source_length,
    3284         112 :               SmiConstant(0), SmiConstant(1), mapper_function, t);
    3285             : 
    3286             :   // 7. Return A.
    3287          56 :   args.PopAndReturn(a);
    3288             : 
    3289          56 :   BIND(&if_not_callable);
    3290          56 :   { ThrowTypeError(context, MessageTemplate::kMapperFunctionNonCallable); }
    3291          56 : }
    3292             : 
    3293         112 : TF_BUILTIN(ArrayConstructor, ArrayBuiltinsAssembler) {
    3294             :   // This is a trampoline to ArrayConstructorImpl which just adds
    3295             :   // allocation_site parameter value and sets new_target if necessary.
    3296             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    3297             :   TNode<JSFunction> function = CAST(Parameter(Descriptor::kTarget));
    3298             :   TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
    3299             :   TNode<Int32T> argc =
    3300          56 :       UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
    3301             : 
    3302             :   // If new_target is undefined, then this is the 'Call' case, so set new_target
    3303             :   // to function.
    3304          56 :   new_target =
    3305             :       SelectConstant<Object>(IsUndefined(new_target), function, new_target);
    3306             : 
    3307             :   // Run the native code for the Array function called as a normal function.
    3308         112 :   TNode<Object> no_allocation_site = UndefinedConstant();
    3309             :   TailCallBuiltin(Builtins::kArrayConstructorImpl, context, function,
    3310          56 :                   new_target, argc, no_allocation_site);
    3311          56 : }
    3312             : 
    3313         784 : void ArrayBuiltinsAssembler::TailCallArrayConstructorStub(
    3314             :     const Callable& callable, TNode<Context> context, TNode<JSFunction> target,
    3315             :     TNode<HeapObject> allocation_site_or_undefined, TNode<Int32T> argc) {
    3316         784 :   TNode<Code> code = HeapConstant(callable.code());
    3317             : 
    3318             :   // We are going to call here ArrayNoArgumentsConstructor or
    3319             :   // ArraySingleArgumentsConstructor which in addition to the register arguments
    3320             :   // also expect some number of arguments on the expression stack.
    3321             :   // Since
    3322             :   // 1) incoming JS arguments are still on the stack,
    3323             :   // 2) the ArrayNoArgumentsConstructor, ArraySingleArgumentsConstructor and
    3324             :   //    ArrayNArgumentsConstructor are defined so that the register arguments
    3325             :   //    are passed on the same registers,
    3326             :   // in order to be able to generate a tail call to those builtins we do the
    3327             :   // following trick here: we tail call to the constructor builtin using
    3328             :   // ArrayNArgumentsConstructorDescriptor, so the tail call instruction
    3329             :   // pops the current frame but leaves all the incoming JS arguments on the
    3330             :   // expression stack so that the target builtin can still find them where it
    3331             :   // expects.
    3332             :   TailCallStub(ArrayNArgumentsConstructorDescriptor{}, code, context, target,
    3333         784 :                allocation_site_or_undefined, argc);
    3334         784 : }
    3335             : 
    3336         112 : void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
    3337             :     TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
    3338             :     AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
    3339         112 :   if (mode == DISABLE_ALLOCATION_SITES) {
    3340             :     Callable callable = CodeFactory::ArrayNoArgumentConstructor(
    3341          56 :         isolate(), GetInitialFastElementsKind(), mode);
    3342             : 
    3343          56 :     TailCallArrayConstructorStub(callable, context, target, UndefinedConstant(),
    3344         112 :                                  argc);
    3345             :   } else {
    3346             :     DCHECK_EQ(mode, DONT_OVERRIDE);
    3347          56 :     TNode<Int32T> elements_kind = LoadElementsKind(allocation_site);
    3348             : 
    3349             :     // TODO(ishell): Compute the builtin index dynamically instead of
    3350             :     // iterating over all expected elements kinds.
    3351             :     int last_index =
    3352          56 :         GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
    3353         392 :     for (int i = 0; i <= last_index; ++i) {
    3354         336 :       Label next(this);
    3355         336 :       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
    3356        1008 :       GotoIfNot(Word32Equal(elements_kind, Int32Constant(kind)), &next);
    3357             : 
    3358             :       Callable callable =
    3359         336 :           CodeFactory::ArrayNoArgumentConstructor(isolate(), kind, mode);
    3360             : 
    3361             :       TailCallArrayConstructorStub(callable, context, target, allocation_site,
    3362         336 :                                    argc);
    3363             : 
    3364         336 :       BIND(&next);
    3365         336 :     }
    3366             : 
    3367             :     // If we reached this point there is a problem.
    3368          56 :     Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
    3369             :   }
    3370         112 : }
    3371             : 
    3372         112 : void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
    3373             :     TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
    3374             :     AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
    3375         112 :   if (mode == DISABLE_ALLOCATION_SITES) {
    3376             :     ElementsKind initial = GetInitialFastElementsKind();
    3377             :     ElementsKind holey_initial = GetHoleyElementsKind(initial);
    3378             :     Callable callable = CodeFactory::ArraySingleArgumentConstructor(
    3379          56 :         isolate(), holey_initial, mode);
    3380             : 
    3381          56 :     TailCallArrayConstructorStub(callable, context, target, UndefinedConstant(),
    3382         112 :                                  argc);
    3383             :   } else {
    3384             :     DCHECK_EQ(mode, DONT_OVERRIDE);
    3385          56 :     TNode<Smi> transition_info = LoadTransitionInfo(allocation_site);
    3386             : 
    3387             :     // Least significant bit in fast array elements kind means holeyness.
    3388             :     STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
    3389             :     STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
    3390             :     STATIC_ASSERT(PACKED_ELEMENTS == 2);
    3391             :     STATIC_ASSERT(HOLEY_ELEMENTS == 3);
    3392             :     STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
    3393             :     STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
    3394             : 
    3395          56 :     Label normal_sequence(this);
    3396         112 :     TVARIABLE(Int32T, var_elements_kind,
    3397             :               Signed(DecodeWord32<AllocationSite::ElementsKindBits>(
    3398             :                   SmiToInt32(transition_info))));
    3399             :     // Is the low bit set? If so, we are holey and that is good.
    3400             :     int fast_elements_kind_holey_mask =
    3401             :         AllocationSite::ElementsKindBits::encode(static_cast<ElementsKind>(1));
    3402          56 :     GotoIf(IsSetSmi(transition_info, fast_elements_kind_holey_mask),
    3403         112 :            &normal_sequence);
    3404             :     {
    3405             :       // Make elements kind holey and update elements kind in the type info.
    3406         168 :       var_elements_kind =
    3407             :           Signed(Word32Or(var_elements_kind.value(), Int32Constant(1)));
    3408             :       StoreObjectFieldNoWriteBarrier(
    3409             :           allocation_site, AllocationSite::kTransitionInfoOrBoilerplateOffset,
    3410         112 :           SmiOr(transition_info, SmiConstant(fast_elements_kind_holey_mask)));
    3411          56 :       Goto(&normal_sequence);
    3412             :     }
    3413          56 :     BIND(&normal_sequence);
    3414             : 
    3415             :     // TODO(ishell): Compute the builtin index dynamically instead of
    3416             :     // iterating over all expected elements kinds.
    3417             :     // TODO(ishell): Given that the code above ensures that the elements kind
    3418             :     // is holey we can skip checking with non-holey elements kinds.
    3419             :     int last_index =
    3420          56 :         GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
    3421         392 :     for (int i = 0; i <= last_index; ++i) {
    3422             :       Label next(this);
    3423         336 :       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
    3424         672 :       GotoIfNot(Word32Equal(var_elements_kind.value(), Int32Constant(kind)),
    3425         672 :                 &next);
    3426             : 
    3427             :       Callable callable =
    3428         336 :           CodeFactory::ArraySingleArgumentConstructor(isolate(), kind, mode);
    3429             : 
    3430             :       TailCallArrayConstructorStub(callable, context, target, allocation_site,
    3431         336 :                                    argc);
    3432             : 
    3433         336 :       BIND(&next);
    3434         336 :     }
    3435             : 
    3436             :     // If we reached this point there is a problem.
    3437         112 :     Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
    3438             :   }
    3439         112 : }
    3440             : 
    3441         112 : void ArrayBuiltinsAssembler::GenerateDispatchToArrayStub(
    3442             :     TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
    3443             :     AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
    3444         224 :   Label check_one_case(this), fallthrough(this);
    3445         336 :   GotoIfNot(Word32Equal(argc, Int32Constant(0)), &check_one_case);
    3446         112 :   CreateArrayDispatchNoArgument(context, target, argc, mode, allocation_site);
    3447             : 
    3448         112 :   BIND(&check_one_case);
    3449         336 :   GotoIfNot(Word32Equal(argc, Int32Constant(1)), &fallthrough);
    3450             :   CreateArrayDispatchSingleArgument(context, target, argc, mode,
    3451         112 :                                     allocation_site);
    3452             : 
    3453         224 :   BIND(&fallthrough);
    3454         112 : }
    3455             : 
    3456         168 : TF_BUILTIN(ArrayConstructorImpl, ArrayBuiltinsAssembler) {
    3457             :   TNode<JSFunction> target = CAST(Parameter(Descriptor::kTarget));
    3458             :   TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
    3459             :   TNode<Int32T> argc =
    3460          56 :       UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
    3461             :   TNode<HeapObject> maybe_allocation_site =
    3462             :       CAST(Parameter(Descriptor::kAllocationSite));
    3463             : 
    3464             :   // Initial map for the builtin Array functions should be Map.
    3465             :   CSA_ASSERT(this, IsMap(CAST(LoadObjectField(
    3466             :                        target, JSFunction::kPrototypeOrInitialMapOffset))));
    3467             : 
    3468             :   // We should either have undefined or a valid AllocationSite
    3469             :   CSA_ASSERT(this, Word32Or(IsUndefined(maybe_allocation_site),
    3470             :                             IsAllocationSite(maybe_allocation_site)));
    3471             : 
    3472             :   // "Enter" the context of the Array function.
    3473             :   TNode<Context> context =
    3474         112 :       CAST(LoadObjectField(target, JSFunction::kContextOffset));
    3475             : 
    3476             :   Label runtime(this, Label::kDeferred);
    3477          56 :   GotoIf(WordNotEqual(target, new_target), &runtime);
    3478             : 
    3479          56 :   Label no_info(this);
    3480             :   // If the feedback vector is the undefined value call an array constructor
    3481             :   // that doesn't use AllocationSites.
    3482         112 :   GotoIf(IsUndefined(maybe_allocation_site), &no_info);
    3483             : 
    3484             :   GenerateDispatchToArrayStub(context, target, argc, DONT_OVERRIDE,
    3485          56 :                               CAST(maybe_allocation_site));
    3486          56 :   Goto(&runtime);
    3487             : 
    3488          56 :   BIND(&no_info);
    3489          56 :   GenerateDispatchToArrayStub(context, target, argc, DISABLE_ALLOCATION_SITES);
    3490          56 :   Goto(&runtime);
    3491             : 
    3492          56 :   BIND(&runtime);
    3493             :   GenerateArrayNArgumentsConstructor(context, target, new_target, argc,
    3494         112 :                                      maybe_allocation_site);
    3495          56 : }
    3496             : 
    3497         448 : void ArrayBuiltinsAssembler::GenerateConstructor(
    3498             :     Node* context, Node* array_function, Node* array_map, Node* array_size,
    3499             :     Node* allocation_site, ElementsKind elements_kind,
    3500             :     AllocationSiteMode mode) {
    3501         448 :   Label ok(this);
    3502         448 :   Label smi_size(this);
    3503         448 :   Label small_smi_size(this);
    3504         448 :   Label call_runtime(this, Label::kDeferred);
    3505             : 
    3506         896 :   Branch(TaggedIsSmi(array_size), &smi_size, &call_runtime);
    3507             : 
    3508         448 :   BIND(&smi_size);
    3509             : 
    3510         448 :   if (IsFastPackedElementsKind(elements_kind)) {
    3511             :     Label abort(this, Label::kDeferred);
    3512         448 :     Branch(SmiEqual(CAST(array_size), SmiConstant(0)), &small_smi_size, &abort);
    3513             : 
    3514         224 :     BIND(&abort);
    3515             :     Node* reason = SmiConstant(AbortReason::kAllocatingNonEmptyPackedArray);
    3516         224 :     TailCallRuntime(Runtime::kAbort, context, reason);
    3517             :   } else {
    3518             :     int element_size =
    3519             :         IsDoubleElementsKind(elements_kind) ? kDoubleSize : kTaggedSize;
    3520             :     int max_fast_elements =
    3521             :         (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - JSArray::kSize -
    3522             :          AllocationMemento::kSize) /
    3523             :         element_size;
    3524         224 :     Branch(SmiAboveOrEqual(CAST(array_size), SmiConstant(max_fast_elements)),
    3525         448 :            &call_runtime, &small_smi_size);
    3526             :   }
    3527             : 
    3528         448 :   BIND(&small_smi_size);
    3529             :   {
    3530             :     TNode<JSArray> array = AllocateJSArray(
    3531             :         elements_kind, CAST(array_map), array_size, CAST(array_size),
    3532             :         mode == DONT_TRACK_ALLOCATION_SITE ? nullptr : allocation_site,
    3533         448 :         CodeStubAssembler::SMI_PARAMETERS);
    3534         448 :     Return(array);
    3535             :   }
    3536             : 
    3537         448 :   BIND(&call_runtime);
    3538             :   {
    3539             :     TailCallRuntime(Runtime::kNewArray, context, array_function, array_size,
    3540         448 :                     array_function, allocation_site);
    3541         448 :   }
    3542         448 : }
    3543             : 
    3544         448 : void ArrayBuiltinsAssembler::GenerateArrayNoArgumentConstructor(
    3545             :     ElementsKind kind, AllocationSiteOverrideMode mode) {
    3546             :   typedef ArrayNoArgumentConstructorDescriptor Descriptor;
    3547             :   Node* native_context = LoadObjectField(Parameter(Descriptor::kFunction),
    3548         448 :                                          JSFunction::kContextOffset);
    3549             :   bool track_allocation_site =
    3550         448 :       AllocationSite::ShouldTrack(kind) && mode != DISABLE_ALLOCATION_SITES;
    3551             :   Node* allocation_site =
    3552         448 :       track_allocation_site ? Parameter(Descriptor::kAllocationSite) : nullptr;
    3553         448 :   TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context);
    3554             :   TNode<JSArray> array = AllocateJSArray(
    3555             :       kind, array_map, IntPtrConstant(JSArray::kPreallocatedArrayElements),
    3556         896 :       SmiConstant(0), allocation_site);
    3557         448 :   Return(array);
    3558         448 : }
    3559             : 
    3560         448 : void ArrayBuiltinsAssembler::GenerateArraySingleArgumentConstructor(
    3561             :     ElementsKind kind, AllocationSiteOverrideMode mode) {
    3562             :   typedef ArraySingleArgumentConstructorDescriptor Descriptor;
    3563         448 :   Node* context = Parameter(Descriptor::kContext);
    3564         448 :   Node* function = Parameter(Descriptor::kFunction);
    3565         448 :   Node* native_context = LoadObjectField(function, JSFunction::kContextOffset);
    3566         896 :   Node* array_map = LoadJSArrayElementsMap(kind, native_context);
    3567             : 
    3568             :   AllocationSiteMode allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
    3569         448 :   if (mode == DONT_OVERRIDE) {
    3570             :     allocation_site_mode = AllocationSite::ShouldTrack(kind)
    3571             :                                ? TRACK_ALLOCATION_SITE
    3572         112 :                                : DONT_TRACK_ALLOCATION_SITE;
    3573             :   }
    3574             : 
    3575         448 :   Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
    3576         448 :   Node* allocation_site = Parameter(Descriptor::kAllocationSite);
    3577             : 
    3578             :   GenerateConstructor(context, function, array_map, array_size, allocation_site,
    3579         448 :                       kind, allocation_site_mode);
    3580         448 : }
    3581             : 
    3582         112 : void ArrayBuiltinsAssembler::GenerateArrayNArgumentsConstructor(
    3583             :     TNode<Context> context, TNode<JSFunction> target, TNode<Object> new_target,
    3584             :     TNode<Int32T> argc, TNode<HeapObject> maybe_allocation_site) {
    3585             :   // Replace incoming JS receiver argument with the target.
    3586             :   // TODO(ishell): Avoid replacing the target on the stack and just add it
    3587             :   // as another additional parameter for Runtime::kNewArray.
    3588         336 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
    3589         112 :   args.SetReceiver(target);
    3590             : 
    3591             :   // Adjust arguments count for the runtime call: +1 for implicit receiver
    3592             :   // and +2 for new_target and maybe_allocation_site.
    3593         112 :   argc = Int32Add(argc, Int32Constant(3));
    3594             :   TailCallRuntime(Runtime::kNewArray, argc, context, new_target,
    3595             :                   maybe_allocation_site);
    3596         112 : }
    3597             : 
    3598         224 : TF_BUILTIN(ArrayNArgumentsConstructor, ArrayBuiltinsAssembler) {
    3599          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    3600             :   TNode<JSFunction> target = CAST(Parameter(Descriptor::kFunction));
    3601             :   TNode<Int32T> argc =
    3602          56 :       UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
    3603             :   TNode<HeapObject> maybe_allocation_site =
    3604          56 :       CAST(Parameter(Descriptor::kAllocationSite));
    3605             : 
    3606             :   GenerateArrayNArgumentsConstructor(context, target, target, argc,
    3607          56 :                                      maybe_allocation_site);
    3608          56 : }
    3609             : 
    3610             : #define GENERATE_ARRAY_CTOR(name, kind_camel, kind_caps, mode_camel, \
    3611             :                             mode_caps)                               \
    3612             :   TF_BUILTIN(Array##name##Constructor_##kind_camel##_##mode_camel,   \
    3613             :              ArrayBuiltinsAssembler) {                               \
    3614             :     GenerateArray##name##Constructor(kind_caps, mode_caps);          \
    3615             :   }
    3616             : 
    3617             : // The ArrayNoArgumentConstructor builtin family.
    3618          56 : GENERATE_ARRAY_CTOR(NoArgument, PackedSmi, PACKED_SMI_ELEMENTS, DontOverride,
    3619             :                     DONT_OVERRIDE);
    3620          56 : GENERATE_ARRAY_CTOR(NoArgument, HoleySmi, HOLEY_SMI_ELEMENTS, DontOverride,
    3621             :                     DONT_OVERRIDE);
    3622          56 : GENERATE_ARRAY_CTOR(NoArgument, PackedSmi, PACKED_SMI_ELEMENTS,
    3623             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3624          56 : GENERATE_ARRAY_CTOR(NoArgument, HoleySmi, HOLEY_SMI_ELEMENTS,
    3625             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3626          56 : GENERATE_ARRAY_CTOR(NoArgument, Packed, PACKED_ELEMENTS, DisableAllocationSites,
    3627             :                     DISABLE_ALLOCATION_SITES);
    3628          56 : GENERATE_ARRAY_CTOR(NoArgument, Holey, HOLEY_ELEMENTS, DisableAllocationSites,
    3629             :                     DISABLE_ALLOCATION_SITES);
    3630          56 : GENERATE_ARRAY_CTOR(NoArgument, PackedDouble, PACKED_DOUBLE_ELEMENTS,
    3631             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3632          56 : GENERATE_ARRAY_CTOR(NoArgument, HoleyDouble, HOLEY_DOUBLE_ELEMENTS,
    3633             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3634             : 
    3635             : // The ArraySingleArgumentConstructor builtin family.
    3636          56 : GENERATE_ARRAY_CTOR(SingleArgument, PackedSmi, PACKED_SMI_ELEMENTS,
    3637             :                     DontOverride, DONT_OVERRIDE);
    3638          56 : GENERATE_ARRAY_CTOR(SingleArgument, HoleySmi, HOLEY_SMI_ELEMENTS, DontOverride,
    3639             :                     DONT_OVERRIDE);
    3640          56 : GENERATE_ARRAY_CTOR(SingleArgument, PackedSmi, PACKED_SMI_ELEMENTS,
    3641             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3642          56 : GENERATE_ARRAY_CTOR(SingleArgument, HoleySmi, HOLEY_SMI_ELEMENTS,
    3643             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3644          56 : GENERATE_ARRAY_CTOR(SingleArgument, Packed, PACKED_ELEMENTS,
    3645             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3646          56 : GENERATE_ARRAY_CTOR(SingleArgument, Holey, HOLEY_ELEMENTS,
    3647             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3648          56 : GENERATE_ARRAY_CTOR(SingleArgument, PackedDouble, PACKED_DOUBLE_ELEMENTS,
    3649             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3650          56 : GENERATE_ARRAY_CTOR(SingleArgument, HoleyDouble, HOLEY_DOUBLE_ELEMENTS,
    3651             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES);
    3652             : 
    3653             : #undef GENERATE_ARRAY_CTOR
    3654             : 
    3655         112 : TF_BUILTIN(InternalArrayNoArgumentConstructor_Packed, ArrayBuiltinsAssembler) {
    3656             :   typedef ArrayNoArgumentConstructorDescriptor Descriptor;
    3657             :   TNode<Map> array_map =
    3658          56 :       CAST(LoadObjectField(Parameter(Descriptor::kFunction),
    3659             :                            JSFunction::kPrototypeOrInitialMapOffset));
    3660             :   TNode<JSArray> array = AllocateJSArray(
    3661             :       PACKED_ELEMENTS, array_map,
    3662          56 :       IntPtrConstant(JSArray::kPreallocatedArrayElements), SmiConstant(0));
    3663          56 :   Return(array);
    3664          56 : }
    3665             : 
    3666             : }  // namespace internal
    3667       94089 : }  // namespace v8

Generated by: LCOV version 1.10