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