LCOV - code coverage report
Current view: top level - src/builtins - builtins-array-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1002 1039 96.4 %
Date: 2019-04-17 Functions: 98 117 83.8 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-array-gen.h"
       6             : 
       7             : #include "src/builtins/builtins-iterator-gen.h"
       8             : #include "src/builtins/builtins-string-gen.h"
       9             : #include "src/builtins/builtins-typed-array-gen.h"
      10             : #include "src/builtins/builtins-utils-gen.h"
      11             : #include "src/builtins/builtins.h"
      12             : #include "src/code-stub-assembler.h"
      13             : #include "src/frame-constants.h"
      14             : #include "src/heap/factory-inl.h"
      15             : #include "src/objects/allocation-site-inl.h"
      16             : #include "src/objects/arguments-inl.h"
      17             : #include "src/objects/property-cell.h"
      18             : #include "torque-generated/builtins-typed-array-createtypedarray-from-dsl-gen.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23             : using Node = compiler::Node;
      24             : using IteratorRecord = IteratorBuiltinsFromDSLAssembler::IteratorRecord;
      25             : 
      26        1568 : ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
      27             :     compiler::CodeAssemblerState* state)
      28             :     : CodeStubAssembler(state),
      29             :       k_(this, MachineRepresentation::kTagged),
      30             :       a_(this, MachineRepresentation::kTagged),
      31        3136 :       to_(this, MachineRepresentation::kTagged, SmiConstant(0)),
      32        9408 :       fully_spec_compliant_(this, {&k_, &a_, &to_}) {}
      33             : 
      34          56 :   void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() {
      35             :     // 6. Let A be ? TypedArraySpeciesCreate(O, len).
      36             :     TNode<JSTypedArray> original_array = CAST(o());
      37          56 :     TNode<Smi> length = CAST(len_);
      38             :     const char* method_name = "%TypedArray%.prototype.map";
      39             : 
      40             :     TypedArrayCreatetypedarrayBuiltinsFromDSLAssembler typedarray_asm(state());
      41             :     TNode<JSTypedArray> a = typedarray_asm.TypedArraySpeciesCreateByLength(
      42          56 :         context(), method_name, original_array, length);
      43             :     // In the Spec and our current implementation, the length check is already
      44             :     // performed in TypedArraySpeciesCreate.
      45             :     CSA_ASSERT(this, SmiLessThanOrEqual(CAST(len_), LoadJSTypedArrayLength(a)));
      46             :     fast_typed_array_target_ =
      47         224 :         Word32Equal(LoadInstanceType(LoadElements(original_array)),
      48         280 :                     LoadInstanceType(LoadElements(a)));
      49          56 :     a_.Bind(a);
      50          56 :   }
      51             : 
      52             :   // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map.
      53         616 :   Node* ArrayBuiltinsAssembler::TypedArrayMapProcessor(Node* k_value, Node* k) {
      54             :     // 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »).
      55        1232 :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
      56         616 :                                 callbackfn(), this_arg(), k_value, k, o());
      57         616 :     Label fast(this), slow(this), done(this), detached(this, Label::kDeferred);
      58             : 
      59             :     // 8. d. Perform ? Set(A, Pk, mapped_value, true).
      60             :     // Since we know that A is a TypedArray, this always ends up in
      61             :     // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then
      62             :     // tc39.github.io/ecma262/#sec-integerindexedelementset .
      63        1232 :     Branch(fast_typed_array_target_, &fast, &slow);
      64             : 
      65         616 :     BIND(&fast);
      66             :     // #sec-integerindexedelementset
      67             :     // 5. If arrayTypeName is "BigUint64Array" or "BigInt64Array", let
      68             :     // numValue be ? ToBigInt(v).
      69             :     // 6. Otherwise, let numValue be ? ToNumber(value).
      70             :     Node* num_value;
      71         616 :     if (source_elements_kind_ == BIGINT64_ELEMENTS ||
      72             :         source_elements_kind_ == BIGUINT64_ELEMENTS) {
      73         224 :       num_value = ToBigInt(context(), mapped_value);
      74             :     } else {
      75        1008 :       num_value = ToNumber_Inline(context(), mapped_value);
      76             :     }
      77             :     // The only way how this can bailout is because of a detached buffer.
      78         616 :     EmitElementStore(a(), k, num_value, source_elements_kind_,
      79             :                      KeyedAccessStoreMode::STANDARD_STORE, &detached,
      80         616 :                      context());
      81         616 :     Goto(&done);
      82             : 
      83         616 :     BIND(&slow);
      84             :     SetPropertyStrict(context(), CAST(a()), CAST(k), CAST(mapped_value));
      85         616 :     Goto(&done);
      86             : 
      87         616 :     BIND(&detached);
      88             :     // tc39.github.io/ecma262/#sec-integerindexedelementset
      89             :     // 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
      90        1232 :     ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_);
      91             : 
      92         616 :     BIND(&done);
      93         616 :     return a();
      94             :   }
      95             : 
      96         616 :   void ArrayBuiltinsAssembler::NullPostLoopAction() {}
      97             : 
      98           0 :   void ArrayBuiltinsAssembler::FillFixedArrayWithSmiZero(
      99             :       TNode<FixedArray> array, TNode<Smi> smi_length) {
     100             :     CSA_ASSERT(this, Word32BinaryNot(IsFixedDoubleArray(array)));
     101             : 
     102           0 :     TNode<IntPtrT> length = SmiToIntPtr(smi_length);
     103             :     TNode<WordT> byte_length = TimesTaggedSize(length);
     104             :     CSA_ASSERT(this, UintPtrLessThan(length, byte_length));
     105             : 
     106             :     static const int32_t fa_base_data_offset =
     107             :         FixedArray::kHeaderSize - kHeapObjectTag;
     108             :     TNode<IntPtrT> backing_store = IntPtrAdd(
     109           0 :         BitcastTaggedToWord(array), IntPtrConstant(fa_base_data_offset));
     110             : 
     111             :     // Call out to memset to perform initialization.
     112             :     TNode<ExternalReference> memset =
     113           0 :         ExternalConstant(ExternalReference::libc_memset_function());
     114             :     STATIC_ASSERT(kSizetSize == kIntptrSize);
     115             :     CallCFunction(memset, MachineType::Pointer(),
     116             :                   std::make_pair(MachineType::Pointer(), backing_store),
     117           0 :                   std::make_pair(MachineType::IntPtr(), IntPtrConstant(0)),
     118           0 :                   std::make_pair(MachineType::UintPtr(), byte_length));
     119           0 :   }
     120             : 
     121         616 :   void ArrayBuiltinsAssembler::ReturnFromBuiltin(Node* value) {
     122         616 :     if (argc_ == nullptr) {
     123           0 :       Return(value);
     124             :     } else {
     125             :       // argc_ doesn't include the receiver, so it has to be added back in
     126             :       // manually.
     127        1232 :       PopAndReturn(IntPtrAdd(argc_, IntPtrConstant(1)), value);
     128             :     }
     129         616 :   }
     130             : 
     131           0 :   void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinBody(
     132             :       TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
     133             :       Node* this_arg, TNode<IntPtrT> argc) {
     134             :     context_ = context;
     135             :     receiver_ = receiver;
     136          56 :     callbackfn_ = callbackfn;
     137          56 :     this_arg_ = this_arg;
     138             :     argc_ = argc;
     139           0 :   }
     140             : 
     141          56 :   void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody(
     142             :       const char* name, const BuiltinResultGenerator& generator,
     143             :       const CallResultProcessor& processor, const PostLoopAction& action,
     144             :       ForEachDirection direction) {
     145          56 :     name_ = name;
     146             : 
     147             :     // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
     148             : 
     149         112 :     Label throw_not_typed_array(this, Label::kDeferred);
     150             : 
     151         112 :     GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
     152         112 :     GotoIfNot(HasInstanceType(CAST(receiver_), JS_TYPED_ARRAY_TYPE),
     153          56 :               &throw_not_typed_array);
     154             : 
     155             :     TNode<JSTypedArray> typed_array = CAST(receiver_);
     156             :     o_ = typed_array;
     157             : 
     158             :     TNode<JSArrayBuffer> array_buffer =
     159          56 :         LoadJSArrayBufferViewBuffer(typed_array);
     160         112 :     ThrowIfArrayBufferIsDetached(context_, array_buffer, name_);
     161             : 
     162         112 :     len_ = LoadJSTypedArrayLength(typed_array);
     163             : 
     164          56 :     Label throw_not_callable(this, Label::kDeferred);
     165          56 :     Label distinguish_types(this);
     166         168 :     GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable);
     167         224 :     Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types,
     168          56 :            &throw_not_callable);
     169             : 
     170          56 :     BIND(&throw_not_typed_array);
     171          56 :     ThrowTypeError(context_, MessageTemplate::kNotTypedArray);
     172             : 
     173          56 :     BIND(&throw_not_callable);
     174         112 :     ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_);
     175             : 
     176          56 :     Label unexpected_instance_type(this);
     177          56 :     BIND(&unexpected_instance_type);
     178          56 :     Unreachable();
     179             : 
     180             :     std::vector<int32_t> instance_types = {
     181             : #define INSTANCE_TYPE(Type, type, TYPE, ctype) FIXED_##TYPE##_ARRAY_TYPE,
     182             :         TYPED_ARRAYS(INSTANCE_TYPE)
     183             : #undef INSTANCE_TYPE
     184             :     };
     185             :     std::list<Label> labels;
     186        1288 :     for (size_t i = 0; i < instance_types.size(); ++i) {
     187        1232 :       labels.emplace_back(this);
     188             :     }
     189             :     std::vector<Label*> label_ptrs;
     190         672 :     for (Label& label : labels) {
     191        1232 :       label_ptrs.push_back(&label);
     192             :     }
     193             : 
     194          56 :     BIND(&distinguish_types);
     195             : 
     196             :     generator(this);
     197             : 
     198          56 :     if (direction == ForEachDirection::kForward) {
     199         112 :       k_.Bind(SmiConstant(0));
     200             :     } else {
     201           0 :       k_.Bind(NumberDec(len()));
     202             :     }
     203             :     CSA_ASSERT(this, IsSafeInteger(k()));
     204         112 :     Node* instance_type = LoadInstanceType(LoadElements(typed_array));
     205             :     Switch(instance_type, &unexpected_instance_type, instance_types.data(),
     206          56 :            label_ptrs.data(), labels.size());
     207             : 
     208             :     size_t i = 0;
     209        1288 :     for (auto it = labels.begin(); it != labels.end(); ++i, ++it) {
     210         616 :       BIND(&*it);
     211         616 :       Label done(this);
     212         616 :       source_elements_kind_ = ElementsKindForInstanceType(
     213         616 :           static_cast<InstanceType>(instance_types[i]));
     214             :       // TODO(tebbi): Silently cancelling the loop on buffer detachment is a
     215             :       // spec violation. Should go to &throw_detached and throw a TypeError
     216             :       // instead.
     217             :       VisitAllTypedArrayElements(array_buffer, processor, &done, direction,
     218         616 :                                  typed_array);
     219         616 :       Goto(&done);
     220             :       // No exception, return success
     221         616 :       BIND(&done);
     222             :       action(this);
     223         616 :       ReturnFromBuiltin(a_.value());
     224             :     }
     225          56 :   }
     226             : 
     227         616 :   ElementsKind ArrayBuiltinsAssembler::ElementsKindForInstanceType(
     228             :       InstanceType type) {
     229         616 :     switch (type) {
     230             : #define INSTANCE_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype) \
     231             :   case FIXED_##TYPE##_ARRAY_TYPE:                               \
     232             :     return TYPE##_ELEMENTS;
     233             : 
     234          56 :       TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
     235             : #undef INSTANCE_TYPE_TO_ELEMENTS_KIND
     236             : 
     237             :       default:
     238           0 :         UNREACHABLE();
     239             :     }
     240             :   }
     241             : 
     242         616 :   void ArrayBuiltinsAssembler::VisitAllTypedArrayElements(
     243             :       Node* array_buffer, const CallResultProcessor& processor, Label* detached,
     244             :       ForEachDirection direction, TNode<JSTypedArray> typed_array) {
     245        1232 :     VariableList list({&a_, &k_, &to_}, zone());
     246             : 
     247         616 :     FastLoopBody body = [&](Node* index) {
     248        6776 :       GotoIf(IsDetachedBuffer(array_buffer), detached);
     249         616 :       Node* elements = LoadElements(typed_array);
     250             :       Node* base_ptr =
     251         616 :           LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
     252             :       Node* external_ptr =
     253        1232 :           LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
     254         616 :                           MachineType::Pointer());
     255        1848 :       Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
     256         616 :       Node* value = LoadFixedTypedArrayElementAsTagged(
     257        1232 :           data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
     258         616 :       k_.Bind(index);
     259        1232 :       a_.Bind(processor(this, value, index));
     260         616 :     };
     261        1232 :     Node* start = SmiConstant(0);
     262             :     Node* end = len_;
     263             :     IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
     264             :     int incr = 1;
     265         616 :     if (direction == ForEachDirection::kReverse) {
     266             :       std::swap(start, end);
     267             :       advance_mode = IndexAdvanceMode::kPre;
     268             :       incr = -1;
     269             :     }
     270         616 :     BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS,
     271         616 :                   advance_mode);
     272         616 :   }
     273             : 
     274             :   // Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
     275           0 :   void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate(TNode<Number> len) {
     276           0 :     Label runtime(this, Label::kDeferred), done(this);
     277             : 
     278           0 :     Node* const original_map = LoadMap(o());
     279           0 :     GotoIfNot(
     280           0 :         InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE),
     281           0 :         &runtime);
     282             : 
     283           0 :     GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
     284           0 :               &runtime);
     285             : 
     286           0 :     Node* species_protector = ArraySpeciesProtectorConstant();
     287             :     Node* value =
     288             :         LoadObjectField(species_protector, PropertyCell::kValueOffset);
     289           0 :     Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
     290           0 :     GotoIf(WordEqual(value, protector_invalid), &runtime);
     291             : 
     292           0 :     GotoIfNot(TaggedIsPositiveSmi(len), &runtime);
     293           0 :     GotoIfNot(
     294           0 :         IsValidFastJSArrayCapacity(len, CodeStubAssembler::SMI_PARAMETERS),
     295           0 :         &runtime);
     296             : 
     297             :     // We need to be conservative and start with holey because the builtins
     298             :     // that create output arrays aren't guaranteed to be called for every
     299             :     // element in the input array (maybe the callback deletes an element).
     300             :     const ElementsKind elements_kind =
     301             :         GetHoleyElementsKind(GetInitialFastElementsKind());
     302           0 :     TNode<Context> native_context = LoadNativeContext(context());
     303             :     TNode<Map> array_map =
     304           0 :         LoadJSArrayElementsMap(elements_kind, native_context);
     305           0 :     a_.Bind(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, len, CAST(len),
     306             :                             nullptr, CodeStubAssembler::SMI_PARAMETERS,
     307           0 :                             kAllowLargeObjectAllocation));
     308             : 
     309           0 :     Goto(&done);
     310             : 
     311           0 :     BIND(&runtime);
     312             :     {
     313             :       // 5. Let A be ? ArraySpeciesCreate(O, len).
     314             :       TNode<JSReceiver> constructor =
     315             :           CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()));
     316           0 :       a_.Bind(Construct(context(), constructor, len));
     317           0 :       Goto(&fully_spec_compliant_);
     318             :     }
     319             : 
     320           0 :     BIND(&done);
     321           0 :   }
     322             : 
     323         168 : TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) {
     324             :   TNode<Int32T> argc =
     325             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
     326             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     327             :   CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
     328             : 
     329         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     330          56 :   TNode<Object> receiver = args.GetReceiver();
     331             : 
     332          56 :   Label runtime(this, Label::kDeferred);
     333          56 :   Label fast(this);
     334             : 
     335             :   // Only pop in this stub if
     336             :   // 1) the array has fast elements
     337             :   // 2) the length is writable,
     338             :   // 3) the elements backing store isn't copy-on-write,
     339             :   // 4) we aren't supposed to shrink the backing store.
     340             : 
     341             :   // 1) Check that the array has fast elements.
     342          56 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
     343             : 
     344          56 :   BIND(&fast);
     345             :   {
     346             :     TNode<JSArray> array_receiver = CAST(receiver);
     347             :     CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
     348             :     TNode<IntPtrT> length =
     349          56 :         LoadAndUntagObjectField(array_receiver, JSArray::kLengthOffset);
     350          56 :     Label return_undefined(this), fast_elements(this);
     351         168 :     GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
     352             : 
     353             :     // 2) Ensure that the length is writable.
     354          56 :     EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime);
     355             : 
     356             :     // 3) Check that the elements backing store isn't copy-on-write.
     357             :     TNode<FixedArrayBase> elements = LoadElements(array_receiver);
     358         168 :     GotoIf(WordEqual(LoadMap(elements), LoadRoot(RootIndex::kFixedCOWArrayMap)),
     359          56 :            &runtime);
     360             : 
     361          56 :     TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1));
     362             : 
     363             :     // 4) Check that we're not supposed to shrink the backing store, as
     364             :     //    implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
     365         112 :     TNode<IntPtrT> capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
     366         112 :     GotoIf(IntPtrLessThan(
     367             :                IntPtrAdd(IntPtrAdd(new_length, new_length),
     368          56 :                          IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
     369          56 :                capacity),
     370          56 :            &runtime);
     371             : 
     372         112 :     StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
     373             :                                    SmiTag(new_length));
     374             : 
     375          56 :     TNode<Int32T> elements_kind = LoadElementsKind(array_receiver);
     376         112 :     GotoIf(Int32LessThanOrEqual(elements_kind,
     377         112 :                                 Int32Constant(TERMINAL_FAST_ELEMENTS_KIND)),
     378          56 :            &fast_elements);
     379             : 
     380             :     Node* value = LoadFixedDoubleArrayElement(CAST(elements), new_length,
     381          56 :                                               &return_undefined);
     382             : 
     383          56 :     StoreFixedDoubleArrayHole(CAST(elements), new_length);
     384         112 :     args.PopAndReturn(AllocateHeapNumberWithValue(value));
     385             : 
     386          56 :     BIND(&fast_elements);
     387             :     {
     388             :       Node* value = LoadFixedArrayElement(CAST(elements), new_length);
     389         112 :       StoreFixedArrayElement(CAST(elements), new_length, TheHoleConstant());
     390         112 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
     391          56 :       args.PopAndReturn(value);
     392             :     }
     393             : 
     394          56 :     BIND(&return_undefined);
     395         112 :     { args.PopAndReturn(UndefinedConstant()); }
     396             :   }
     397             : 
     398          56 :   BIND(&runtime);
     399             :   {
     400             :     // We are not using Parameter(Descriptor::kJSTarget) and loading the value
     401             :     // from the current frame here in order to reduce register pressure on the
     402             :     // fast path.
     403          56 :     TNode<JSFunction> target = LoadTargetFromFrame();
     404         112 :     TailCallBuiltin(Builtins::kArrayPop, context, target, UndefinedConstant(),
     405          56 :                     argc);
     406             :   }
     407          56 : }
     408             : 
     409         224 : TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) {
     410          56 :   TVARIABLE(IntPtrT, arg_index);
     411          56 :   Label default_label(this, &arg_index);
     412          56 :   Label smi_transition(this);
     413          56 :   Label object_push_pre(this);
     414          56 :   Label object_push(this, &arg_index);
     415          56 :   Label double_push(this, &arg_index);
     416          56 :   Label double_transition(this);
     417          56 :   Label runtime(this, Label::kDeferred);
     418             : 
     419             :   // TODO(ishell): use constants from Descriptor once the JSFunction linkage
     420             :   // arguments are reordered.
     421             :   TNode<Int32T> argc =
     422             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
     423             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     424             :   CSA_ASSERT(this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
     425             : 
     426         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     427          56 :   TNode<Object> receiver = args.GetReceiver();
     428             :   TNode<JSArray> array_receiver;
     429             :   Node* kind = nullptr;
     430             : 
     431          56 :   Label fast(this);
     432          56 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
     433             : 
     434          56 :   BIND(&fast);
     435             :   {
     436             :     array_receiver = CAST(receiver);
     437          56 :     arg_index = IntPtrConstant(0);
     438         112 :     kind = EnsureArrayPushable(LoadMap(array_receiver), &runtime);
     439         112 :     GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
     440          56 :            &object_push_pre);
     441             : 
     442         112 :     Node* new_length = BuildAppendJSArray(PACKED_SMI_ELEMENTS, array_receiver,
     443          56 :                                           &args, &arg_index, &smi_transition);
     444          56 :     args.PopAndReturn(new_length);
     445             :   }
     446             : 
     447             :   // If the argument is not a smi, then use a heavyweight SetProperty to
     448             :   // transition the array for only the single next element. If the argument is
     449             :   // a smi, the failure is due to some other reason and we should fall back on
     450             :   // the most generic implementation for the rest of the array.
     451          56 :   BIND(&smi_transition);
     452             :   {
     453         112 :     Node* arg = args.AtIndex(arg_index.value());
     454         112 :     GotoIf(TaggedIsSmi(arg), &default_label);
     455         112 :     Node* length = LoadJSArrayLength(array_receiver);
     456             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
     457             :     // calling into the runtime to do the elements transition is overkill.
     458             :     SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
     459          56 :     Increment(&arg_index);
     460             :     // The runtime SetProperty call could have converted the array to dictionary
     461             :     // mode, which must be detected to abort the fast-path.
     462         112 :     Node* kind = LoadElementsKind(array_receiver);
     463         168 :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
     464          56 :            &default_label);
     465             : 
     466          56 :     GotoIfNotNumber(arg, &object_push);
     467          56 :     Goto(&double_push);
     468             :   }
     469             : 
     470          56 :   BIND(&object_push_pre);
     471             :   {
     472         112 :     Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &double_push,
     473          56 :            &object_push);
     474             :   }
     475             : 
     476          56 :   BIND(&object_push);
     477             :   {
     478         112 :     Node* new_length = BuildAppendJSArray(PACKED_ELEMENTS, array_receiver,
     479          56 :                                           &args, &arg_index, &default_label);
     480          56 :     args.PopAndReturn(new_length);
     481             :   }
     482             : 
     483          56 :   BIND(&double_push);
     484             :   {
     485             :     Node* new_length =
     486          56 :         BuildAppendJSArray(PACKED_DOUBLE_ELEMENTS, array_receiver, &args,
     487          56 :                            &arg_index, &double_transition);
     488          56 :     args.PopAndReturn(new_length);
     489             :   }
     490             : 
     491             :   // If the argument is not a double, then use a heavyweight SetProperty to
     492             :   // transition the array for only the single next element. If the argument is
     493             :   // a double, the failure is due to some other reason and we should fall back
     494             :   // on the most generic implementation for the rest of the array.
     495          56 :   BIND(&double_transition);
     496             :   {
     497         112 :     Node* arg = args.AtIndex(arg_index.value());
     498          56 :     GotoIfNumber(arg, &default_label);
     499         112 :     Node* length = LoadJSArrayLength(array_receiver);
     500             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
     501             :     // calling into the runtime to do the elements transition is overkill.
     502             :     SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
     503          56 :     Increment(&arg_index);
     504             :     // The runtime SetProperty call could have converted the array to dictionary
     505             :     // mode, which must be detected to abort the fast-path.
     506         112 :     Node* kind = LoadElementsKind(array_receiver);
     507         168 :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
     508          56 :            &default_label);
     509          56 :     Goto(&object_push);
     510             :   }
     511             : 
     512             :   // Fallback that stores un-processed arguments using the full, heavyweight
     513             :   // SetProperty machinery.
     514          56 :   BIND(&default_label);
     515             :   {
     516          56 :     args.ForEach(
     517         168 :         [this, array_receiver, context](Node* arg) {
     518         112 :           Node* length = LoadJSArrayLength(array_receiver);
     519          56 :           SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
     520          56 :         },
     521          56 :         arg_index.value());
     522         112 :     args.PopAndReturn(LoadJSArrayLength(array_receiver));
     523             :   }
     524             : 
     525          56 :   BIND(&runtime);
     526             :   {
     527             :     // We are not using Parameter(Descriptor::kJSTarget) and loading the value
     528             :     // from the current frame here in order to reduce register pressure on the
     529             :     // fast path.
     530          56 :     TNode<JSFunction> target = LoadTargetFromFrame();
     531         112 :     TailCallBuiltin(Builtins::kArrayPush, context, target, UndefinedConstant(),
     532          56 :                     argc);
     533             :   }
     534          56 : }
     535             : 
     536         224 : TF_BUILTIN(ExtractFastJSArray, ArrayBuiltinsAssembler) {
     537             :   ParameterMode mode = OptimalParameterMode();
     538             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     539             :   Node* array = Parameter(Descriptor::kSource);
     540          56 :   Node* begin = TaggedToParameter(Parameter(Descriptor::kBegin), mode);
     541             :   Node* count = TaggedToParameter(Parameter(Descriptor::kCount), mode);
     542             : 
     543             :   CSA_ASSERT(this, IsJSArray(array));
     544             :   CSA_ASSERT(this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
     545             : 
     546         112 :   Return(ExtractFastJSArray(context, array, begin, count, mode));
     547          56 : }
     548             : 
     549         112 : TF_BUILTIN(CloneFastJSArray, ArrayBuiltinsAssembler) {
     550             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     551             :   TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
     552             : 
     553             :   CSA_ASSERT(this,
     554             :              Word32Or(Word32BinaryNot(
     555             :                           IsHoleyFastElementsKind(LoadElementsKind(array))),
     556             :                       Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
     557             : 
     558             :   ParameterMode mode = OptimalParameterMode();
     559         112 :   Return(CloneFastJSArray(context, array, mode));
     560          56 : }
     561             : 
     562             : // This builtin copies the backing store of fast arrays, while converting any
     563             : // holes to undefined.
     564             : // - If there are no holes in the source, its ElementsKind will be preserved. In
     565             : // that case, this builtin should perform as fast as CloneFastJSArray. (In fact,
     566             : // for fast packed arrays, the behavior is equivalent to CloneFastJSArray.)
     567             : // - If there are holes in the source, the ElementsKind of the "copy" will be
     568             : // PACKED_ELEMENTS (such that undefined can be stored).
     569         112 : TF_BUILTIN(CloneFastJSArrayFillingHoles, ArrayBuiltinsAssembler) {
     570             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     571             :   TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
     572             : 
     573             :   CSA_ASSERT(this,
     574             :              Word32Or(Word32BinaryNot(
     575             :                           IsHoleyFastElementsKind(LoadElementsKind(array))),
     576             :                       Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
     577             : 
     578             :   ParameterMode mode = OptimalParameterMode();
     579         112 :   Return(CloneFastJSArray(context, array, mode, nullptr,
     580          56 :                           HoleConversionMode::kConvertToUndefined));
     581          56 : }
     582             : 
     583          56 : class ArrayPopulatorAssembler : public CodeStubAssembler {
     584             :  public:
     585             :   explicit ArrayPopulatorAssembler(compiler::CodeAssemblerState* state)
     586          56 :       : CodeStubAssembler(state) {}
     587             : 
     588          56 :   TNode<Object> ConstructArrayLike(TNode<Context> context,
     589             :                                    TNode<Object> receiver) {
     590          56 :     TVARIABLE(Object, array);
     591          56 :     Label is_constructor(this), is_not_constructor(this), done(this);
     592         112 :     GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
     593         112 :     Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
     594             : 
     595          56 :     BIND(&is_constructor);
     596             :     {
     597             :       array = Construct(context, CAST(receiver));
     598          56 :       Goto(&done);
     599             :     }
     600             : 
     601          56 :     BIND(&is_not_constructor);
     602             :     {
     603          56 :       Label allocate_js_array(this);
     604             : 
     605          56 :       TNode<Map> array_map = CAST(LoadContextElement(
     606             :           context, Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX));
     607             : 
     608         168 :       array = AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, SmiConstant(0),
     609             :                               SmiConstant(0), nullptr,
     610         112 :                               ParameterMode::SMI_PARAMETERS);
     611          56 :       Goto(&done);
     612             :     }
     613             : 
     614          56 :     BIND(&done);
     615          56 :     return array.value();
     616             :   }
     617             : 
     618          56 :   TNode<Object> ConstructArrayLike(TNode<Context> context,
     619             :                                    TNode<Object> receiver,
     620             :                                    TNode<Number> length) {
     621          56 :     TVARIABLE(Object, array);
     622          56 :     Label is_constructor(this), is_not_constructor(this), done(this);
     623             :     CSA_ASSERT(this, IsNumberNormalized(length));
     624         112 :     GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
     625         112 :     Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
     626             : 
     627          56 :     BIND(&is_constructor);
     628             :     {
     629             :       array = Construct(context, CAST(receiver), length);
     630          56 :       Goto(&done);
     631             :     }
     632             : 
     633          56 :     BIND(&is_not_constructor);
     634             :     {
     635         112 :       array = ArrayCreate(context, length);
     636          56 :       Goto(&done);
     637             :     }
     638             : 
     639          56 :     BIND(&done);
     640          56 :     return array.value();
     641             :   }
     642             : };
     643             : 
     644             : // ES #sec-array.from
     645         224 : TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) {
     646             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     647             :   TNode<Int32T> argc =
     648             :       UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
     649             : 
     650         168 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     651          56 :   TNode<Object> items = args.GetOptionalArgumentValue(0);
     652          56 :   TNode<Object> receiver = args.GetReceiver();
     653             : 
     654          56 :   Label fast_iterate(this), normal_iterate(this);
     655             : 
     656             :   // Use fast path if:
     657             :   // * |items| is the only argument, and
     658             :   // * the receiver is the Array function.
     659         168 :   GotoIfNot(Word32Equal(argc, Int32Constant(1)), &normal_iterate);
     660             :   TNode<Object> array_function = LoadContextElement(
     661         112 :       LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
     662          56 :   Branch(WordEqual(array_function, receiver), &fast_iterate, &normal_iterate);
     663             : 
     664          56 :   BIND(&fast_iterate);
     665             :   {
     666          56 :     IteratorBuiltinsAssembler iterator_assembler(state());
     667             :     TVARIABLE(Object, var_fast_result);
     668             :     iterator_assembler.FastIterableToList(context, items, &var_fast_result,
     669          56 :                                           &normal_iterate);
     670          56 :     args.PopAndReturn(var_fast_result.value());
     671             :   }
     672             : 
     673          56 :   BIND(&normal_iterate);
     674          56 :   TNode<Object> map_function = args.GetOptionalArgumentValue(1);
     675             : 
     676             :   // If map_function is not undefined, then ensure it's callable else throw.
     677             :   {
     678          56 :     Label no_error(this), error(this);
     679         112 :     GotoIf(IsUndefined(map_function), &no_error);
     680         112 :     GotoIf(TaggedIsSmi(map_function), &error);
     681         112 :     Branch(IsCallable(CAST(map_function)), &no_error, &error);
     682             : 
     683          56 :     BIND(&error);
     684          56 :     ThrowTypeError(context, MessageTemplate::kCalledNonCallable, map_function);
     685             : 
     686          56 :     BIND(&no_error);
     687             :   }
     688             : 
     689          56 :   Label iterable(this), not_iterable(this), finished(this), if_exception(this);
     690             : 
     691          56 :   TNode<Object> this_arg = args.GetOptionalArgumentValue(2);
     692             :   // The spec doesn't require ToObject to be called directly on the iterable
     693             :   // branch, but it's part of GetMethod that is in the spec.
     694          56 :   TNode<JSReceiver> array_like = ToObject_Inline(context, items);
     695             : 
     696             :   TVARIABLE(Object, array);
     697             :   TVARIABLE(Number, length);
     698             : 
     699             :   // Determine whether items[Symbol.iterator] is defined:
     700          56 :   IteratorBuiltinsAssembler iterator_assembler(state());
     701             :   Node* iterator_method =
     702         112 :       iterator_assembler.GetIteratorMethod(context, array_like);
     703         112 :   Branch(IsNullOrUndefined(iterator_method), &not_iterable, &iterable);
     704             : 
     705          56 :   BIND(&iterable);
     706             :   {
     707         112 :     TVARIABLE(Number, index, SmiConstant(0));
     708             :     TVARIABLE(Object, var_exception);
     709          56 :     Label loop(this, &index), loop_done(this),
     710          56 :         on_exception(this, Label::kDeferred),
     711          56 :         index_overflow(this, Label::kDeferred);
     712             : 
     713             :     // Check that the method is callable.
     714             :     {
     715          56 :       Label get_method_not_callable(this, Label::kDeferred), next(this);
     716         112 :       GotoIf(TaggedIsSmi(iterator_method), &get_method_not_callable);
     717         112 :       GotoIfNot(IsCallable(CAST(iterator_method)), &get_method_not_callable);
     718          56 :       Goto(&next);
     719             : 
     720          56 :       BIND(&get_method_not_callable);
     721             :       ThrowTypeError(context, MessageTemplate::kCalledNonCallable,
     722          56 :                      iterator_method);
     723             : 
     724          56 :       BIND(&next);
     725             :     }
     726             : 
     727             :     // Construct the output array with empty length.
     728          56 :     array = ConstructArrayLike(context, receiver);
     729             : 
     730             :     // Actually get the iterator and throw if the iterator method does not yield
     731             :     // one.
     732             :     IteratorRecord iterator_record =
     733          56 :         iterator_assembler.GetIterator(context, items, iterator_method);
     734             : 
     735          56 :     TNode<Context> native_context = LoadNativeContext(context);
     736             :     TNode<Object> fast_iterator_result_map =
     737          56 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
     738             : 
     739          56 :     Goto(&loop);
     740             : 
     741          56 :     BIND(&loop);
     742             :     {
     743             :       // Loop while iterator is not done.
     744             :       TNode<Object> next = iterator_assembler.IteratorStep(
     745          56 :           context, iterator_record, &loop_done, fast_iterator_result_map);
     746          56 :       TVARIABLE(Object, value,
     747             :                 CAST(iterator_assembler.IteratorValue(
     748             :                     context, next, fast_iterator_result_map)));
     749             : 
     750             :       // If a map_function is supplied then call it (using this_arg as
     751             :       // receiver), on the value returned from the iterator. Exceptions are
     752             :       // caught so the iterator can be closed.
     753             :       {
     754          56 :         Label next(this);
     755         112 :         GotoIf(IsUndefined(map_function), &next);
     756             : 
     757             :         CSA_ASSERT(this, IsCallable(CAST(map_function)));
     758         112 :         Node* v = CallJS(CodeFactory::Call(isolate()), context, map_function,
     759          56 :                          this_arg, value.value(), index.value());
     760          56 :         GotoIfException(v, &on_exception, &var_exception);
     761             :         value = CAST(v);
     762          56 :         Goto(&next);
     763          56 :         BIND(&next);
     764             :       }
     765             : 
     766             :       // Store the result in the output object (catching any exceptions so the
     767             :       // iterator can be closed).
     768             :       Node* define_status =
     769             :           CallRuntime(Runtime::kCreateDataProperty, context, array.value(),
     770             :                       index.value(), value.value());
     771          56 :       GotoIfException(define_status, &on_exception, &var_exception);
     772             : 
     773         112 :       index = NumberInc(index.value());
     774             : 
     775             :       // The spec requires that we throw an exception if index reaches 2^53-1,
     776             :       // but an empty loop would take >100 days to do this many iterations. To
     777             :       // actually run for that long would require an iterator that never set
     778             :       // done to true and a target array which somehow never ran out of memory,
     779             :       // e.g. a proxy that discarded the values. Ignoring this case just means
     780             :       // we would repeatedly call CreateDataProperty with index = 2^53.
     781             :       CSA_ASSERT_BRANCH(this, [&](Label* ok, Label* not_ok) {
     782             :         BranchIfNumberRelationalComparison(Operation::kLessThan, index.value(),
     783             :                                            NumberConstant(kMaxSafeInteger), ok,
     784             :                                            not_ok);
     785             :       });
     786          56 :       Goto(&loop);
     787             :     }
     788             : 
     789          56 :     BIND(&loop_done);
     790             :     {
     791             :       length = index;
     792          56 :       Goto(&finished);
     793             :     }
     794             : 
     795          56 :     BIND(&on_exception);
     796             :     {
     797             :       // Close the iterator, rethrowing either the passed exception or
     798             :       // exceptions thrown during the close.
     799             :       iterator_assembler.IteratorCloseOnException(context, iterator_record,
     800          56 :                                                   var_exception.value());
     801             :     }
     802             :   }
     803             : 
     804          56 :   BIND(&not_iterable);
     805             :   {
     806             :     // Treat array_like as an array and try to get its length.
     807         112 :     length = ToLength_Inline(
     808         168 :         context, GetProperty(context, array_like, factory()->length_string()));
     809             : 
     810             :     // Construct an array using the receiver as constructor with the same length
     811             :     // as the input array.
     812          56 :     array = ConstructArrayLike(context, receiver, length.value());
     813             : 
     814         112 :     TVARIABLE(Number, index, SmiConstant(0));
     815             : 
     816             :     // TODO(ishell): remove <Object, Object>
     817         112 :     GotoIf(WordEqual<Object, Object>(length.value(), SmiConstant(0)),
     818          56 :            &finished);
     819             : 
     820             :     // Loop from 0 to length-1.
     821             :     {
     822          56 :       Label loop(this, &index);
     823          56 :       Goto(&loop);
     824          56 :       BIND(&loop);
     825             :       TVARIABLE(Object, value);
     826             : 
     827             :       value = GetProperty(context, array_like, index.value());
     828             : 
     829             :       // If a map_function is supplied then call it (using this_arg as
     830             :       // receiver), on the value retrieved from the array.
     831             :       {
     832          56 :         Label next(this);
     833         112 :         GotoIf(IsUndefined(map_function), &next);
     834             : 
     835             :         CSA_ASSERT(this, IsCallable(CAST(map_function)));
     836         112 :         value = CAST(CallJS(CodeFactory::Call(isolate()), context, map_function,
     837             :                             this_arg, value.value(), index.value()));
     838          56 :         Goto(&next);
     839          56 :         BIND(&next);
     840             :       }
     841             : 
     842             :       // Store the result in the output object.
     843             :       CallRuntime(Runtime::kCreateDataProperty, context, array.value(),
     844             :                   index.value(), value.value());
     845         112 :       index = NumberInc(index.value());
     846             :       BranchIfNumberRelationalComparison(Operation::kLessThan, index.value(),
     847          56 :                                          length.value(), &loop, &finished);
     848             :     }
     849             :   }
     850             : 
     851          56 :   BIND(&finished);
     852             : 
     853             :   // Finally set the length on the output and return it.
     854          56 :   SetPropertyLength(context, array.value(), length.value());
     855          56 :   args.PopAndReturn(array.value());
     856          56 : }
     857             : 
     858         168 : TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinsAssembler) {
     859             :   TNode<IntPtrT> argc =
     860          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
     861          56 :   CodeStubArguments args(this, argc);
     862             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     863          56 :   TNode<Object> receiver = args.GetReceiver();
     864         112 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
     865         112 :   Node* this_arg = args.GetOptionalArgumentValue(1);
     866             : 
     867             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
     868             : 
     869         224 :   GenerateIteratingTypedArrayBuiltinBody(
     870             :       "%TypedArray%.prototype.map",
     871             :       &ArrayBuiltinsAssembler::TypedArrayMapResultGenerator,
     872             :       &ArrayBuiltinsAssembler::TypedArrayMapProcessor,
     873          56 :       &ArrayBuiltinsAssembler::NullPostLoopAction);
     874          56 : }
     875             : 
     876         168 : TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
     877             :   TNode<Object> object = CAST(Parameter(Descriptor::kArg));
     878             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
     879             : 
     880          56 :   Label call_runtime(this), return_true(this), return_false(this);
     881             : 
     882         112 :   GotoIf(TaggedIsSmi(object), &return_false);
     883          56 :   TNode<Int32T> instance_type = LoadInstanceType(CAST(object));
     884             : 
     885         112 :   GotoIf(InstanceTypeEqual(instance_type, JS_ARRAY_TYPE), &return_true);
     886             : 
     887             :   // TODO(verwaest): Handle proxies in-place.
     888         112 :   Branch(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), &call_runtime,
     889          56 :          &return_false);
     890             : 
     891          56 :   BIND(&return_true);
     892         112 :   Return(TrueConstant());
     893             : 
     894          56 :   BIND(&return_false);
     895         112 :   Return(FalseConstant());
     896             : 
     897          56 :   BIND(&call_runtime);
     898          56 :   Return(CallRuntime(Runtime::kArrayIsArray, context, object));
     899          56 : }
     900             : 
     901         448 : class ArrayIncludesIndexofAssembler : public CodeStubAssembler {
     902             :  public:
     903             :   explicit ArrayIncludesIndexofAssembler(compiler::CodeAssemblerState* state)
     904         448 :       : CodeStubAssembler(state) {}
     905             : 
     906             :   enum SearchVariant { kIncludes, kIndexOf };
     907             : 
     908             :   void Generate(SearchVariant variant, TNode<IntPtrT> argc,
     909             :                 TNode<Context> context);
     910             :   void GenerateSmiOrObject(SearchVariant variant, Node* context, Node* elements,
     911             :                            Node* search_element, Node* array_length,
     912             :                            Node* from_index);
     913             :   void GeneratePackedDoubles(SearchVariant variant, Node* elements,
     914             :                              Node* search_element, Node* array_length,
     915             :                              Node* from_index);
     916             :   void GenerateHoleyDoubles(SearchVariant variant, Node* elements,
     917             :                             Node* search_element, Node* array_length,
     918             :                             Node* from_index);
     919             : };
     920             : 
     921         112 : void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant,
     922             :                                              TNode<IntPtrT> argc,
     923             :                                              TNode<Context> context) {
     924             :   const int kSearchElementArg = 0;
     925             :   const int kFromIndexArg = 1;
     926             : 
     927         112 :   CodeStubArguments args(this, argc);
     928             : 
     929         112 :   TNode<Object> receiver = args.GetReceiver();
     930             :   TNode<Object> search_element =
     931         112 :       args.GetOptionalArgumentValue(kSearchElementArg);
     932             : 
     933         224 :   Node* intptr_zero = IntPtrConstant(0);
     934             : 
     935         112 :   Label init_index(this), return_not_found(this), call_runtime(this);
     936             : 
     937             :   // Take slow path if not a JSArray, if retrieving elements requires
     938             :   // traversing prototype, or if access checks are required.
     939         112 :   BranchIfFastJSArray(receiver, context, &init_index, &call_runtime);
     940             : 
     941         112 :   BIND(&init_index);
     942         224 :   VARIABLE(index_var, MachineType::PointerRepresentation(), intptr_zero);
     943             :   TNode<JSArray> array = CAST(receiver);
     944             : 
     945             :   // JSArray length is always a positive Smi for fast arrays.
     946             :   CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array)));
     947         224 :   Node* array_length = LoadFastJSArrayLength(array);
     948         224 :   Node* array_length_untagged = SmiUntag(array_length);
     949             : 
     950             :   {
     951             :     // Initialize fromIndex.
     952         112 :     Label is_smi(this), is_nonsmi(this), done(this);
     953             : 
     954             :     // If no fromIndex was passed, default to 0.
     955         336 :     GotoIf(IntPtrLessThanOrEqual(argc, IntPtrConstant(kFromIndexArg)), &done);
     956             : 
     957         224 :     Node* start_from = args.AtIndex(kFromIndexArg);
     958             :     // Handle Smis and undefined here and everything else in runtime.
     959             :     // We must be very careful with side effects from the ToInteger conversion,
     960             :     // as the side effects might render previously checked assumptions about
     961             :     // the receiver being a fast JSArray and its length invalid.
     962         224 :     Branch(TaggedIsSmi(start_from), &is_smi, &is_nonsmi);
     963             : 
     964         112 :     BIND(&is_nonsmi);
     965             :     {
     966         224 :       GotoIfNot(IsUndefined(start_from), &call_runtime);
     967         112 :       Goto(&done);
     968             :     }
     969         112 :     BIND(&is_smi);
     970             :     {
     971         224 :       Node* intptr_start_from = SmiUntag(start_from);
     972         112 :       index_var.Bind(intptr_start_from);
     973             : 
     974         336 :       GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
     975             :       // The fromIndex is negative: add it to the array's length.
     976         336 :       index_var.Bind(IntPtrAdd(array_length_untagged, index_var.value()));
     977             :       // Clamp negative results at zero.
     978         336 :       GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
     979         112 :       index_var.Bind(intptr_zero);
     980         112 :       Goto(&done);
     981             :     }
     982         112 :     BIND(&done);
     983             :   }
     984             : 
     985             :   // Fail early if startIndex >= array.length.
     986         336 :   GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), array_length_untagged),
     987         112 :          &return_not_found);
     988             : 
     989         112 :   Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this);
     990             : 
     991         112 :   TNode<Int32T> elements_kind = LoadElementsKind(array);
     992             :   Node* elements = LoadElements(array);
     993             :   STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
     994             :   STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
     995             :   STATIC_ASSERT(PACKED_ELEMENTS == 2);
     996             :   STATIC_ASSERT(HOLEY_ELEMENTS == 3);
     997         336 :   GotoIf(Uint32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
     998         112 :          &if_smiorobjects);
     999         336 :   GotoIf(Word32Equal(elements_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
    1000         112 :          &if_packed_doubles);
    1001         336 :   GotoIf(Word32Equal(elements_kind, Int32Constant(HOLEY_DOUBLE_ELEMENTS)),
    1002         112 :          &if_holey_doubles);
    1003         112 :   Goto(&return_not_found);
    1004             : 
    1005         112 :   BIND(&if_smiorobjects);
    1006             :   {
    1007             :     Callable callable =
    1008             :         (variant == kIncludes)
    1009             :             ? Builtins::CallableFor(isolate(),
    1010             :                                     Builtins::kArrayIncludesSmiOrObject)
    1011             :             : Builtins::CallableFor(isolate(),
    1012         112 :                                     Builtins::kArrayIndexOfSmiOrObject);
    1013         224 :     Node* result = CallStub(callable, context, elements, search_element,
    1014         336 :                             array_length, SmiTag(index_var.value()));
    1015         112 :     args.PopAndReturn(result);
    1016             :   }
    1017             : 
    1018         112 :   BIND(&if_packed_doubles);
    1019             :   {
    1020             :     Callable callable =
    1021             :         (variant == kIncludes)
    1022             :             ? Builtins::CallableFor(isolate(),
    1023             :                                     Builtins::kArrayIncludesPackedDoubles)
    1024             :             : Builtins::CallableFor(isolate(),
    1025         112 :                                     Builtins::kArrayIndexOfPackedDoubles);
    1026         224 :     Node* result = CallStub(callable, context, elements, search_element,
    1027         336 :                             array_length, SmiTag(index_var.value()));
    1028         112 :     args.PopAndReturn(result);
    1029             :   }
    1030             : 
    1031         112 :   BIND(&if_holey_doubles);
    1032             :   {
    1033             :     Callable callable =
    1034             :         (variant == kIncludes)
    1035             :             ? Builtins::CallableFor(isolate(),
    1036             :                                     Builtins::kArrayIncludesHoleyDoubles)
    1037             :             : Builtins::CallableFor(isolate(),
    1038         112 :                                     Builtins::kArrayIndexOfHoleyDoubles);
    1039         224 :     Node* result = CallStub(callable, context, elements, search_element,
    1040         336 :                             array_length, SmiTag(index_var.value()));
    1041         112 :     args.PopAndReturn(result);
    1042             :   }
    1043             : 
    1044         112 :   BIND(&return_not_found);
    1045         112 :   if (variant == kIncludes) {
    1046         112 :     args.PopAndReturn(FalseConstant());
    1047             :   } else {
    1048         112 :     args.PopAndReturn(NumberConstant(-1));
    1049             :   }
    1050             : 
    1051         112 :   BIND(&call_runtime);
    1052             :   {
    1053             :     Node* start_from =
    1054         336 :         args.GetOptionalArgumentValue(kFromIndexArg, UndefinedConstant());
    1055             :     Runtime::FunctionId function = variant == kIncludes
    1056             :                                        ? Runtime::kArrayIncludes_Slow
    1057         112 :                                        : Runtime::kArrayIndexOf;
    1058             :     args.PopAndReturn(
    1059         112 :         CallRuntime(function, context, array, search_element, start_from));
    1060             :   }
    1061         112 : }
    1062             : 
    1063         112 : void ArrayIncludesIndexofAssembler::GenerateSmiOrObject(
    1064             :     SearchVariant variant, Node* context, Node* elements, Node* search_element,
    1065             :     Node* array_length, Node* from_index) {
    1066         336 :   VARIABLE(index_var, MachineType::PointerRepresentation(),
    1067             :            SmiUntag(from_index));
    1068         224 :   VARIABLE(search_num, MachineRepresentation::kFloat64);
    1069         224 :   Node* array_length_untagged = SmiUntag(array_length);
    1070             : 
    1071         112 :   Label ident_loop(this, &index_var), heap_num_loop(this, &search_num),
    1072         112 :       string_loop(this), bigint_loop(this, &index_var),
    1073         112 :       undef_loop(this, &index_var), not_smi(this), not_heap_num(this),
    1074         112 :       return_found(this), return_not_found(this);
    1075             : 
    1076         224 :   GotoIfNot(TaggedIsSmi(search_element), &not_smi);
    1077         224 :   search_num.Bind(SmiToFloat64(search_element));
    1078         112 :   Goto(&heap_num_loop);
    1079             : 
    1080         112 :   BIND(&not_smi);
    1081         112 :   if (variant == kIncludes) {
    1082         112 :     GotoIf(IsUndefined(search_element), &undef_loop);
    1083             :   }
    1084         224 :   Node* map = LoadMap(search_element);
    1085         224 :   GotoIfNot(IsHeapNumberMap(map), &not_heap_num);
    1086         224 :   search_num.Bind(LoadHeapNumberValue(search_element));
    1087         112 :   Goto(&heap_num_loop);
    1088             : 
    1089         112 :   BIND(&not_heap_num);
    1090         224 :   Node* search_type = LoadMapInstanceType(map);
    1091         224 :   GotoIf(IsStringInstanceType(search_type), &string_loop);
    1092         224 :   GotoIf(IsBigIntInstanceType(search_type), &bigint_loop);
    1093         112 :   Goto(&ident_loop);
    1094             : 
    1095         112 :   BIND(&ident_loop);
    1096             :   {
    1097         336 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1098         112 :               &return_not_found);
    1099             :     Node* element_k =
    1100         112 :         UnsafeLoadFixedArrayElement(CAST(elements), index_var.value());
    1101         224 :     GotoIf(WordEqual(element_k, search_element), &return_found);
    1102             : 
    1103         112 :     Increment(&index_var);
    1104         112 :     Goto(&ident_loop);
    1105             :   }
    1106             : 
    1107         112 :   if (variant == kIncludes) {
    1108          56 :     BIND(&undef_loop);
    1109             : 
    1110         168 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1111          56 :               &return_not_found);
    1112             :     Node* element_k =
    1113          56 :         UnsafeLoadFixedArrayElement(CAST(elements), index_var.value());
    1114         112 :     GotoIf(IsUndefined(element_k), &return_found);
    1115         112 :     GotoIf(IsTheHole(element_k), &return_found);
    1116             : 
    1117          56 :     Increment(&index_var);
    1118          56 :     Goto(&undef_loop);
    1119             :   }
    1120             : 
    1121         112 :   BIND(&heap_num_loop);
    1122             :   {
    1123         112 :     Label nan_loop(this, &index_var), not_nan_loop(this, &index_var);
    1124         112 :     Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    1125         112 :     BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    1126             : 
    1127         112 :     BIND(&not_nan_loop);
    1128             :     {
    1129         112 :       Label continue_loop(this), not_smi(this);
    1130         336 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1131         112 :                 &return_not_found);
    1132             :       Node* element_k =
    1133         112 :           UnsafeLoadFixedArrayElement(CAST(elements), index_var.value());
    1134         224 :       GotoIfNot(TaggedIsSmi(element_k), &not_smi);
    1135         448 :       Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)),
    1136         112 :              &return_found, &continue_loop);
    1137             : 
    1138         112 :       BIND(&not_smi);
    1139         224 :       GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    1140         448 :       Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)),
    1141         112 :              &return_found, &continue_loop);
    1142             : 
    1143         112 :       BIND(&continue_loop);
    1144         112 :       Increment(&index_var);
    1145         112 :       Goto(&not_nan_loop);
    1146             :     }
    1147             : 
    1148             :     // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    1149         112 :     if (variant == kIncludes) {
    1150          56 :       BIND(&nan_loop);
    1151          56 :       Label continue_loop(this);
    1152         168 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1153          56 :                 &return_not_found);
    1154             :       Node* element_k =
    1155          56 :           UnsafeLoadFixedArrayElement(CAST(elements), index_var.value());
    1156         112 :       GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1157         112 :       GotoIfNot(IsHeapNumber(CAST(element_k)), &continue_loop);
    1158         112 :       BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_found,
    1159          56 :                            &continue_loop);
    1160             : 
    1161          56 :       BIND(&continue_loop);
    1162          56 :       Increment(&index_var);
    1163          56 :       Goto(&nan_loop);
    1164             :     }
    1165             :   }
    1166             : 
    1167         112 :   BIND(&string_loop);
    1168             :   {
    1169             :     TNode<String> search_element_string = CAST(search_element);
    1170         112 :     Label continue_loop(this), next_iteration(this, &index_var),
    1171         112 :         slow_compare(this), runtime(this, Label::kDeferred);
    1172             :     TNode<IntPtrT> search_length =
    1173         112 :         LoadStringLengthAsWord(search_element_string);
    1174         112 :     Goto(&next_iteration);
    1175         112 :     BIND(&next_iteration);
    1176         336 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1177         112 :               &return_not_found);
    1178             :     Node* element_k =
    1179         112 :         UnsafeLoadFixedArrayElement(CAST(elements), index_var.value());
    1180         224 :     GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1181         112 :     GotoIf(WordEqual(search_element_string, element_k), &return_found);
    1182         224 :     Node* element_k_type = LoadInstanceType(element_k);
    1183         224 :     GotoIfNot(IsStringInstanceType(element_k_type), &continue_loop);
    1184         336 :     Branch(WordEqual(search_length, LoadStringLengthAsWord(element_k)),
    1185         112 :            &slow_compare, &continue_loop);
    1186             : 
    1187         112 :     BIND(&slow_compare);
    1188             :     StringBuiltinsAssembler string_asm(state());
    1189             :     string_asm.StringEqual_Core(context, search_element_string, search_type,
    1190             :                                 element_k, element_k_type, search_length,
    1191         112 :                                 &return_found, &continue_loop, &runtime);
    1192         112 :     BIND(&runtime);
    1193             :     TNode<Object> result = CallRuntime(Runtime::kStringEqual, context,
    1194             :                                        search_element_string, element_k);
    1195         224 :     Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop);
    1196             : 
    1197         112 :     BIND(&continue_loop);
    1198         112 :     Increment(&index_var);
    1199         112 :     Goto(&next_iteration);
    1200             :   }
    1201             : 
    1202         112 :   BIND(&bigint_loop);
    1203             :   {
    1204         336 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1205         112 :               &return_not_found);
    1206             : 
    1207             :     Node* element_k =
    1208         112 :         UnsafeLoadFixedArrayElement(CAST(elements), index_var.value());
    1209         112 :     Label continue_loop(this);
    1210         224 :     GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1211         224 :     GotoIfNot(IsBigInt(CAST(element_k)), &continue_loop);
    1212             :     TNode<Object> result = CallRuntime(Runtime::kBigIntEqualToBigInt, context,
    1213             :                                        search_element, element_k);
    1214         224 :     Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop);
    1215             : 
    1216         112 :     BIND(&continue_loop);
    1217         112 :     Increment(&index_var);
    1218         112 :     Goto(&bigint_loop);
    1219             :   }
    1220         112 :   BIND(&return_found);
    1221         112 :   if (variant == kIncludes) {
    1222         112 :     Return(TrueConstant());
    1223             :   } else {
    1224         168 :     Return(SmiTag(index_var.value()));
    1225             :   }
    1226             : 
    1227         112 :   BIND(&return_not_found);
    1228         112 :   if (variant == kIncludes) {
    1229         112 :     Return(FalseConstant());
    1230             :   } else {
    1231         112 :     Return(NumberConstant(-1));
    1232             :   }
    1233         112 : }
    1234             : 
    1235         112 : void ArrayIncludesIndexofAssembler::GeneratePackedDoubles(SearchVariant variant,
    1236             :                                                           Node* elements,
    1237             :                                                           Node* search_element,
    1238             :                                                           Node* array_length,
    1239             :                                                           Node* from_index) {
    1240         336 :   VARIABLE(index_var, MachineType::PointerRepresentation(),
    1241             :            SmiUntag(from_index));
    1242         224 :   Node* array_length_untagged = SmiUntag(array_length);
    1243             : 
    1244         112 :   Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    1245         112 :       hole_loop(this, &index_var), search_notnan(this), return_found(this),
    1246         112 :       return_not_found(this);
    1247         224 :   VARIABLE(search_num, MachineRepresentation::kFloat64);
    1248         224 :   search_num.Bind(Float64Constant(0));
    1249             : 
    1250         224 :   GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1251         224 :   search_num.Bind(SmiToFloat64(search_element));
    1252         112 :   Goto(&not_nan_loop);
    1253             : 
    1254         112 :   BIND(&search_notnan);
    1255         224 :   GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    1256             : 
    1257         224 :   search_num.Bind(LoadHeapNumberValue(search_element));
    1258             : 
    1259         112 :   Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    1260         112 :   BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    1261             : 
    1262         112 :   BIND(&not_nan_loop);
    1263             :   {
    1264         112 :     Label continue_loop(this);
    1265         336 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1266         112 :               &return_not_found);
    1267         224 :     Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    1268         224 :                                                   MachineType::Float64());
    1269         336 :     Branch(Float64Equal(element_k, search_num.value()), &return_found,
    1270         112 :            &continue_loop);
    1271         112 :     BIND(&continue_loop);
    1272         112 :     Increment(&index_var);
    1273         112 :     Goto(&not_nan_loop);
    1274             :   }
    1275             : 
    1276             :   // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    1277         112 :   if (variant == kIncludes) {
    1278          56 :     BIND(&nan_loop);
    1279          56 :     Label continue_loop(this);
    1280         168 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1281          56 :               &return_not_found);
    1282         112 :     Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    1283         112 :                                                   MachineType::Float64());
    1284          56 :     BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
    1285          56 :     BIND(&continue_loop);
    1286          56 :     Increment(&index_var);
    1287          56 :     Goto(&nan_loop);
    1288             :   }
    1289             : 
    1290         112 :   BIND(&return_found);
    1291         112 :   if (variant == kIncludes) {
    1292         112 :     Return(TrueConstant());
    1293             :   } else {
    1294         168 :     Return(SmiTag(index_var.value()));
    1295             :   }
    1296             : 
    1297         112 :   BIND(&return_not_found);
    1298         112 :   if (variant == kIncludes) {
    1299         112 :     Return(FalseConstant());
    1300             :   } else {
    1301         112 :     Return(NumberConstant(-1));
    1302             :   }
    1303         112 : }
    1304             : 
    1305         112 : void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant,
    1306             :                                                          Node* elements,
    1307             :                                                          Node* search_element,
    1308             :                                                          Node* array_length,
    1309             :                                                          Node* from_index) {
    1310         336 :   VARIABLE(index_var, MachineType::PointerRepresentation(),
    1311             :            SmiUntag(from_index));
    1312         224 :   Node* array_length_untagged = SmiUntag(array_length);
    1313             : 
    1314         112 :   Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    1315         112 :       hole_loop(this, &index_var), search_notnan(this), return_found(this),
    1316         112 :       return_not_found(this);
    1317         224 :   VARIABLE(search_num, MachineRepresentation::kFloat64);
    1318         224 :   search_num.Bind(Float64Constant(0));
    1319             : 
    1320         224 :   GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1321         224 :   search_num.Bind(SmiToFloat64(search_element));
    1322         112 :   Goto(&not_nan_loop);
    1323             : 
    1324         112 :   BIND(&search_notnan);
    1325         112 :   if (variant == kIncludes) {
    1326         112 :     GotoIf(IsUndefined(search_element), &hole_loop);
    1327             :   }
    1328         224 :   GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    1329             : 
    1330         224 :   search_num.Bind(LoadHeapNumberValue(search_element));
    1331             : 
    1332         112 :   Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    1333         112 :   BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    1334             : 
    1335         112 :   BIND(&not_nan_loop);
    1336             :   {
    1337         112 :     Label continue_loop(this);
    1338         336 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1339         112 :               &return_not_found);
    1340             : 
    1341             :     // No need for hole checking here; the following Float64Equal will
    1342             :     // return 'not equal' for holes anyway.
    1343         224 :     Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    1344         224 :                                                   MachineType::Float64());
    1345             : 
    1346         336 :     Branch(Float64Equal(element_k, search_num.value()), &return_found,
    1347         112 :            &continue_loop);
    1348         112 :     BIND(&continue_loop);
    1349         112 :     Increment(&index_var);
    1350         112 :     Goto(&not_nan_loop);
    1351             :   }
    1352             : 
    1353             :   // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    1354         112 :   if (variant == kIncludes) {
    1355          56 :     BIND(&nan_loop);
    1356          56 :     Label continue_loop(this);
    1357         168 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1358          56 :               &return_not_found);
    1359             : 
    1360             :     // Load double value or continue if it's the hole NaN.
    1361         112 :     Node* element_k = LoadFixedDoubleArrayElement(
    1362             :         elements, index_var.value(), MachineType::Float64(), 0,
    1363         112 :         INTPTR_PARAMETERS, &continue_loop);
    1364             : 
    1365          56 :     BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
    1366          56 :     BIND(&continue_loop);
    1367          56 :     Increment(&index_var);
    1368          56 :     Goto(&nan_loop);
    1369             :   }
    1370             : 
    1371             :   // Array.p.includes treats the hole as undefined.
    1372         112 :   if (variant == kIncludes) {
    1373          56 :     BIND(&hole_loop);
    1374         168 :     GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
    1375          56 :               &return_not_found);
    1376             : 
    1377             :     // Check if the element is a double hole, but don't load it.
    1378             :     LoadFixedDoubleArrayElement(elements, index_var.value(),
    1379             :                                 MachineType::None(), 0, INTPTR_PARAMETERS,
    1380         112 :                                 &return_found);
    1381             : 
    1382          56 :     Increment(&index_var);
    1383          56 :     Goto(&hole_loop);
    1384             :   }
    1385             : 
    1386         112 :   BIND(&return_found);
    1387         112 :   if (variant == kIncludes) {
    1388         112 :     Return(TrueConstant());
    1389             :   } else {
    1390         168 :     Return(SmiTag(index_var.value()));
    1391             :   }
    1392             : 
    1393         112 :   BIND(&return_not_found);
    1394         112 :   if (variant == kIncludes) {
    1395         112 :     Return(FalseConstant());
    1396             :   } else {
    1397         112 :     Return(NumberConstant(-1));
    1398             :   }
    1399         112 : }
    1400             : 
    1401         280 : TF_BUILTIN(ArrayIncludes, ArrayIncludesIndexofAssembler) {
    1402             :   TNode<IntPtrT> argc =
    1403          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1404          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1405             : 
    1406          56 :   Generate(kIncludes, argc, context);
    1407          56 : }
    1408             : 
    1409         224 : TF_BUILTIN(ArrayIncludesSmiOrObject, ArrayIncludesIndexofAssembler) {
    1410             :   Node* context = Parameter(Descriptor::kContext);
    1411             :   Node* elements = Parameter(Descriptor::kElements);
    1412             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1413             :   Node* array_length = Parameter(Descriptor::kLength);
    1414             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    1415             : 
    1416          56 :   GenerateSmiOrObject(kIncludes, context, elements, search_element,
    1417          56 :                       array_length, from_index);
    1418          56 : }
    1419             : 
    1420         224 : TF_BUILTIN(ArrayIncludesPackedDoubles, ArrayIncludesIndexofAssembler) {
    1421             :   Node* elements = Parameter(Descriptor::kElements);
    1422             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1423             :   Node* array_length = Parameter(Descriptor::kLength);
    1424             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    1425             : 
    1426          56 :   GeneratePackedDoubles(kIncludes, elements, search_element, array_length,
    1427          56 :                         from_index);
    1428          56 : }
    1429             : 
    1430         224 : TF_BUILTIN(ArrayIncludesHoleyDoubles, ArrayIncludesIndexofAssembler) {
    1431             :   Node* elements = Parameter(Descriptor::kElements);
    1432             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1433             :   Node* array_length = Parameter(Descriptor::kLength);
    1434             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    1435             : 
    1436          56 :   GenerateHoleyDoubles(kIncludes, elements, search_element, array_length,
    1437          56 :                        from_index);
    1438          56 : }
    1439             : 
    1440         280 : TF_BUILTIN(ArrayIndexOf, ArrayIncludesIndexofAssembler) {
    1441             :   TNode<IntPtrT> argc =
    1442          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1443          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1444             : 
    1445          56 :   Generate(kIndexOf, argc, context);
    1446          56 : }
    1447             : 
    1448         224 : TF_BUILTIN(ArrayIndexOfSmiOrObject, ArrayIncludesIndexofAssembler) {
    1449             :   Node* context = Parameter(Descriptor::kContext);
    1450             :   Node* elements = Parameter(Descriptor::kElements);
    1451             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1452             :   Node* array_length = Parameter(Descriptor::kLength);
    1453             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    1454             : 
    1455          56 :   GenerateSmiOrObject(kIndexOf, context, elements, search_element, array_length,
    1456          56 :                       from_index);
    1457          56 : }
    1458             : 
    1459         224 : TF_BUILTIN(ArrayIndexOfPackedDoubles, ArrayIncludesIndexofAssembler) {
    1460             :   Node* elements = Parameter(Descriptor::kElements);
    1461             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1462             :   Node* array_length = Parameter(Descriptor::kLength);
    1463             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    1464             : 
    1465          56 :   GeneratePackedDoubles(kIndexOf, elements, search_element, array_length,
    1466          56 :                         from_index);
    1467          56 : }
    1468             : 
    1469         224 : TF_BUILTIN(ArrayIndexOfHoleyDoubles, ArrayIncludesIndexofAssembler) {
    1470             :   Node* elements = Parameter(Descriptor::kElements);
    1471             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1472             :   Node* array_length = Parameter(Descriptor::kLength);
    1473             :   Node* from_index = Parameter(Descriptor::kFromIndex);
    1474             : 
    1475          56 :   GenerateHoleyDoubles(kIndexOf, elements, search_element, array_length,
    1476          56 :                        from_index);
    1477          56 : }
    1478             : 
    1479             : // ES #sec-array.prototype.values
    1480         224 : TF_BUILTIN(ArrayPrototypeValues, CodeStubAssembler) {
    1481          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1482          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1483         224 :   Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
    1484         112 :                              IterationKind::kValues));
    1485          56 : }
    1486             : 
    1487             : // ES #sec-array.prototype.entries
    1488         224 : TF_BUILTIN(ArrayPrototypeEntries, CodeStubAssembler) {
    1489          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1490          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1491         224 :   Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
    1492         112 :                              IterationKind::kEntries));
    1493          56 : }
    1494             : 
    1495             : // ES #sec-array.prototype.keys
    1496         224 : TF_BUILTIN(ArrayPrototypeKeys, CodeStubAssembler) {
    1497          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1498          56 :   TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
    1499         224 :   Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
    1500         112 :                              IterationKind::kKeys));
    1501          56 : }
    1502             : 
    1503             : // ES #sec-%arrayiteratorprototype%.next
    1504         168 : TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
    1505             :   const char* method_name = "Array Iterator.prototype.next";
    1506             : 
    1507             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1508             :   Node* iterator = Parameter(Descriptor::kReceiver);
    1509             : 
    1510         168 :   VARIABLE(var_done, MachineRepresentation::kTagged, TrueConstant());
    1511         168 :   VARIABLE(var_value, MachineRepresentation::kTagged, UndefinedConstant());
    1512             : 
    1513          56 :   Label allocate_entry_if_needed(this);
    1514          56 :   Label allocate_iterator_result(this);
    1515          56 :   Label if_typedarray(this), if_other(this, Label::kDeferred), if_array(this),
    1516          56 :       if_generic(this, Label::kDeferred);
    1517          56 :   Label set_done(this, Label::kDeferred);
    1518             : 
    1519             :   // If O does not have all of the internal slots of an Array Iterator Instance
    1520             :   // (22.1.5.3), throw a TypeError exception
    1521             :   ThrowIfNotInstanceType(context, iterator, JS_ARRAY_ITERATOR_TYPE,
    1522          56 :                          method_name);
    1523             : 
    1524             :   // Let a be O.[[IteratedObject]].
    1525             :   TNode<JSReceiver> array =
    1526             :       CAST(LoadObjectField(iterator, JSArrayIterator::kIteratedObjectOffset));
    1527             : 
    1528             :   // Let index be O.[[ArrayIteratorNextIndex]].
    1529             :   TNode<Number> index =
    1530             :       CAST(LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset));
    1531             :   CSA_ASSERT(this, IsNumberNonNegativeSafeInteger(index));
    1532             : 
    1533             :   // Dispatch based on the type of the {array}.
    1534          56 :   TNode<Map> array_map = LoadMap(array);
    1535          56 :   TNode<Int32T> array_type = LoadMapInstanceType(array_map);
    1536         112 :   GotoIf(InstanceTypeEqual(array_type, JS_ARRAY_TYPE), &if_array);
    1537         112 :   Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_typedarray,
    1538          56 :          &if_other);
    1539             : 
    1540          56 :   BIND(&if_array);
    1541             :   {
    1542             :     // If {array} is a JSArray, then the {index} must be in Unsigned32 range.
    1543             :     CSA_ASSERT(this, IsNumberArrayIndex(index));
    1544             : 
    1545             :     // Check that the {index} is within range for the {array}. We handle all
    1546             :     // kinds of JSArray's here, so we do the computation on Uint32.
    1547          56 :     TNode<Uint32T> index32 = ChangeNumberToUint32(index);
    1548             :     TNode<Uint32T> length32 =
    1549          56 :         ChangeNumberToUint32(LoadJSArrayLength(CAST(array)));
    1550         112 :     GotoIfNot(Uint32LessThan(index32, length32), &set_done);
    1551             :     StoreObjectField(
    1552             :         iterator, JSArrayIterator::kNextIndexOffset,
    1553         224 :         ChangeUint32ToTagged(Unsigned(Int32Add(index32, Int32Constant(1)))));
    1554             : 
    1555         112 :     var_done.Bind(FalseConstant());
    1556          56 :     var_value.Bind(index);
    1557             : 
    1558         224 :     GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
    1559             :                            iterator, JSArrayIterator::kKindOffset),
    1560         168 :                        Int32Constant(static_cast<int>(IterationKind::kKeys))),
    1561          56 :            &allocate_iterator_result);
    1562             : 
    1563          56 :     Label if_hole(this, Label::kDeferred);
    1564          56 :     TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
    1565          56 :     TNode<FixedArrayBase> elements = LoadElements(CAST(array));
    1566          56 :     GotoIfForceSlowPath(&if_generic);
    1567         112 :     var_value.Bind(LoadFixedArrayBaseElementAsTagged(
    1568         112 :         elements, Signed(ChangeUint32ToWord(index32)), elements_kind,
    1569          56 :         &if_generic, &if_hole));
    1570          56 :     Goto(&allocate_entry_if_needed);
    1571             : 
    1572          56 :     BIND(&if_hole);
    1573             :     {
    1574         112 :       GotoIf(IsNoElementsProtectorCellInvalid(), &if_generic);
    1575         112 :       GotoIfNot(IsPrototypeInitialArrayPrototype(context, array_map),
    1576          56 :                 &if_generic);
    1577         112 :       var_value.Bind(UndefinedConstant());
    1578          56 :       Goto(&allocate_entry_if_needed);
    1579             :     }
    1580             :   }
    1581             : 
    1582          56 :   BIND(&if_other);
    1583             :   {
    1584             :     // We cannot enter here with either JSArray's or JSTypedArray's.
    1585             :     CSA_ASSERT(this, Word32BinaryNot(IsJSArray(array)));
    1586             :     CSA_ASSERT(this, Word32BinaryNot(IsJSTypedArray(array)));
    1587             : 
    1588             :     // Check that the {index} is within the bounds of the {array}s "length".
    1589         168 :     TNode<Number> length = CAST(
    1590             :         CallBuiltin(Builtins::kToLength, context,
    1591             :                     GetProperty(context, array, factory()->length_string())));
    1592          56 :     GotoIfNumberGreaterThanOrEqual(index, length, &set_done);
    1593             :     StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset,
    1594         112 :                      NumberInc(index));
    1595             : 
    1596         112 :     var_done.Bind(FalseConstant());
    1597          56 :     var_value.Bind(index);
    1598             : 
    1599         224 :     Branch(Word32Equal(LoadAndUntagToWord32ObjectField(
    1600             :                            iterator, JSArrayIterator::kKindOffset),
    1601         168 :                        Int32Constant(static_cast<int>(IterationKind::kKeys))),
    1602          56 :            &allocate_iterator_result, &if_generic);
    1603             :   }
    1604             : 
    1605          56 :   BIND(&set_done);
    1606             :   {
    1607             :     // Change the [[ArrayIteratorNextIndex]] such that the {iterator} will
    1608             :     // never produce values anymore, because it will always fail the bounds
    1609             :     // check. Note that this is different from what the specification does,
    1610             :     // which is changing the [[IteratedObject]] to undefined, because leaving
    1611             :     // [[IteratedObject]] alone helps TurboFan to generate better code with
    1612             :     // the inlining in JSCallReducer::ReduceArrayIteratorPrototypeNext().
    1613             :     //
    1614             :     // The terminal value we chose here depends on the type of the {array},
    1615             :     // for JSArray's we use kMaxUInt32 so that TurboFan can always use
    1616             :     // Word32 representation for fast-path indices (and this is safe since
    1617             :     // the "length" of JSArray's is limited to Unsigned32 range). For other
    1618             :     // JSReceiver's we have to use kMaxSafeInteger, since the "length" can
    1619             :     // be any arbitrary value in the safe integer range.
    1620             :     //
    1621             :     // Note specifically that JSTypedArray's will never take this path, so
    1622             :     // we don't need to worry about their maximum value.
    1623             :     CSA_ASSERT(this, Word32BinaryNot(IsJSTypedArray(array)));
    1624             :     TNode<Number> max_length =
    1625             :         SelectConstant(IsJSArray(array), NumberConstant(kMaxUInt32),
    1626         168 :                        NumberConstant(kMaxSafeInteger));
    1627          56 :     StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset, max_length);
    1628          56 :     Goto(&allocate_iterator_result);
    1629             :   }
    1630             : 
    1631          56 :   BIND(&if_generic);
    1632             :   {
    1633          56 :     var_value.Bind(GetProperty(context, array, index));
    1634          56 :     Goto(&allocate_entry_if_needed);
    1635             :   }
    1636             : 
    1637          56 :   BIND(&if_typedarray);
    1638             :   {
    1639             :     // If {array} is a JSTypedArray, the {index} must always be a Smi.
    1640             :     CSA_ASSERT(this, TaggedIsSmi(index));
    1641             : 
    1642             :     // Check that the {array}s buffer wasn't detached.
    1643          56 :     ThrowIfArrayBufferViewBufferIsDetached(context, CAST(array), method_name);
    1644             : 
    1645             :     // If we go outside of the {length}, we don't need to update the
    1646             :     // [[ArrayIteratorNextIndex]] anymore, since a JSTypedArray's
    1647             :     // length cannot change anymore, so this {iterator} will never
    1648             :     // produce values again anyways.
    1649          56 :     TNode<Smi> length = LoadJSTypedArrayLength(CAST(array));
    1650         112 :     GotoIfNot(SmiBelow(CAST(index), length), &allocate_iterator_result);
    1651             :     StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
    1652         112 :                                    SmiInc(CAST(index)));
    1653             : 
    1654         112 :     var_done.Bind(FalseConstant());
    1655          56 :     var_value.Bind(index);
    1656             : 
    1657         224 :     GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
    1658             :                            iterator, JSArrayIterator::kKindOffset),
    1659         168 :                        Int32Constant(static_cast<int>(IterationKind::kKeys))),
    1660          56 :            &allocate_iterator_result);
    1661             : 
    1662          56 :     TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
    1663             :     Node* elements = LoadElements(CAST(array));
    1664             :     Node* base_ptr =
    1665             :         LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
    1666             :     Node* external_ptr =
    1667          56 :         LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
    1668          56 :                         MachineType::Pointer());
    1669             :     TNode<WordT> data_ptr =
    1670         112 :         IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
    1671         112 :     var_value.Bind(LoadFixedTypedArrayElementAsTagged(data_ptr, CAST(index),
    1672          56 :                                                       elements_kind));
    1673          56 :     Goto(&allocate_entry_if_needed);
    1674             :   }
    1675             : 
    1676          56 :   BIND(&allocate_entry_if_needed);
    1677             :   {
    1678         224 :     GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
    1679             :                            iterator, JSArrayIterator::kKindOffset),
    1680         168 :                        Int32Constant(static_cast<int>(IterationKind::kValues))),
    1681          56 :            &allocate_iterator_result);
    1682             : 
    1683             :     Node* result =
    1684          56 :         AllocateJSIteratorResultForEntry(context, index, var_value.value());
    1685          56 :     Return(result);
    1686             :   }
    1687             : 
    1688          56 :   BIND(&allocate_iterator_result);
    1689             :   {
    1690             :     Node* result =
    1691          56 :         AllocateJSIteratorResult(context, var_value.value(), var_done.value());
    1692          56 :     Return(result);
    1693             :   }
    1694          56 : }
    1695             : 
    1696         112 : class ArrayFlattenAssembler : public CodeStubAssembler {
    1697             :  public:
    1698             :   explicit ArrayFlattenAssembler(compiler::CodeAssemblerState* state)
    1699         112 :       : CodeStubAssembler(state) {}
    1700             : 
    1701             :   // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
    1702         112 :   Node* FlattenIntoArray(Node* context, Node* target, Node* source,
    1703             :                          Node* source_length, Node* start, Node* depth,
    1704             :                          Node* mapper_function = nullptr,
    1705             :                          Node* this_arg = nullptr) {
    1706             :     CSA_ASSERT(this, IsJSReceiver(target));
    1707             :     CSA_ASSERT(this, IsJSReceiver(source));
    1708             :     CSA_ASSERT(this, IsNumberPositive(source_length));
    1709             :     CSA_ASSERT(this, IsNumberPositive(start));
    1710             :     CSA_ASSERT(this, IsNumber(depth));
    1711             : 
    1712             :     // 1. Let targetIndex be start.
    1713         224 :     VARIABLE(var_target_index, MachineRepresentation::kTagged, start);
    1714             : 
    1715             :     // 2. Let sourceIndex be 0.
    1716         336 :     VARIABLE(var_source_index, MachineRepresentation::kTagged, SmiConstant(0));
    1717             : 
    1718             :     // 3. Repeat...
    1719         336 :     Label loop(this, {&var_target_index, &var_source_index}), done_loop(this);
    1720         112 :     Goto(&loop);
    1721         112 :     BIND(&loop);
    1722             :     {
    1723         112 :       Node* const source_index = var_source_index.value();
    1724         112 :       Node* const target_index = var_target_index.value();
    1725             : 
    1726             :       // ...while sourceIndex < sourceLen
    1727         112 :       GotoIfNumberGreaterThanOrEqual(source_index, source_length, &done_loop);
    1728             : 
    1729             :       // a. Let P be ! ToString(sourceIndex).
    1730             :       // b. Let exists be ? HasProperty(source, P).
    1731             :       CSA_ASSERT(this,
    1732             :                  SmiGreaterThanOrEqual(CAST(source_index), SmiConstant(0)));
    1733             :       Node* const exists =
    1734         224 :           HasProperty(context, source, source_index, kHasProperty);
    1735             : 
    1736             :       // c. If exists is true, then
    1737         112 :       Label next(this);
    1738         224 :       GotoIfNot(IsTrue(exists), &next);
    1739             :       {
    1740             :         // i. Let element be ? Get(source, P).
    1741             :         Node* element = GetProperty(context, source, source_index);
    1742             : 
    1743             :         // ii. If mapperFunction is present, then
    1744         112 :         if (mapper_function != nullptr) {
    1745             :           CSA_ASSERT(this, Word32Or(IsUndefined(mapper_function),
    1746             :                                     IsCallable(mapper_function)));
    1747             :           DCHECK_NOT_NULL(this_arg);
    1748             : 
    1749             :           // 1. Set element to ? Call(mapperFunction, thisArg , « element,
    1750             :           //                          sourceIndex, source »).
    1751             :           element =
    1752         112 :               CallJS(CodeFactory::Call(isolate()), context, mapper_function,
    1753          56 :                      this_arg, element, source_index, source);
    1754             :         }
    1755             : 
    1756             :         // iii. Let shouldFlatten be false.
    1757         112 :         Label if_flatten_array(this), if_flatten_proxy(this, Label::kDeferred),
    1758         112 :             if_noflatten(this);
    1759             :         // iv. If depth > 0, then
    1760         224 :         GotoIfNumberGreaterThanOrEqual(SmiConstant(0), depth, &if_noflatten);
    1761             :         // 1. Set shouldFlatten to ? IsArray(element).
    1762         224 :         GotoIf(TaggedIsSmi(element), &if_noflatten);
    1763         224 :         GotoIf(IsJSArray(element), &if_flatten_array);
    1764         224 :         GotoIfNot(IsJSProxy(element), &if_noflatten);
    1765         224 :         Branch(IsTrue(CallRuntime(Runtime::kArrayIsArray, context, element)),
    1766         112 :                &if_flatten_proxy, &if_noflatten);
    1767             : 
    1768         112 :         BIND(&if_flatten_array);
    1769             :         {
    1770             :           CSA_ASSERT(this, IsJSArray(element));
    1771             : 
    1772             :           // 1. Let elementLen be ? ToLength(? Get(element, "length")).
    1773             :           Node* const element_length =
    1774             :               LoadObjectField(element, JSArray::kLengthOffset);
    1775             : 
    1776             :           // 2. Set targetIndex to ? FlattenIntoArray(target, element,
    1777             :           //                                          elementLen, targetIndex,
    1778             :           //                                          depth - 1).
    1779             :           var_target_index.Bind(
    1780         224 :               CallBuiltin(Builtins::kFlattenIntoArray, context, target, element,
    1781         336 :                           element_length, target_index, NumberDec(depth)));
    1782         112 :           Goto(&next);
    1783             :         }
    1784             : 
    1785         112 :         BIND(&if_flatten_proxy);
    1786             :         {
    1787             :           CSA_ASSERT(this, IsJSProxy(element));
    1788             : 
    1789             :           // 1. Let elementLen be ? ToLength(? Get(element, "length")).
    1790         224 :           Node* const element_length = ToLength_Inline(
    1791         224 :               context, GetProperty(context, element, LengthStringConstant()));
    1792             : 
    1793             :           // 2. Set targetIndex to ? FlattenIntoArray(target, element,
    1794             :           //                                          elementLen, targetIndex,
    1795             :           //                                          depth - 1).
    1796             :           var_target_index.Bind(
    1797         224 :               CallBuiltin(Builtins::kFlattenIntoArray, context, target, element,
    1798         336 :                           element_length, target_index, NumberDec(depth)));
    1799         112 :           Goto(&next);
    1800             :         }
    1801             : 
    1802         112 :         BIND(&if_noflatten);
    1803             :         {
    1804             :           // 1. If targetIndex >= 2^53-1, throw a TypeError exception.
    1805         112 :           Label throw_error(this, Label::kDeferred);
    1806             :           GotoIfNumberGreaterThanOrEqual(
    1807         224 :               target_index, NumberConstant(kMaxSafeInteger), &throw_error);
    1808             : 
    1809             :           // 2. Perform ? CreateDataPropertyOrThrow(target,
    1810             :           //                                        ! ToString(targetIndex),
    1811             :           //                                        element).
    1812             :           CallRuntime(Runtime::kCreateDataProperty, context, target,
    1813             :                       target_index, element);
    1814             : 
    1815             :           // 3. Increase targetIndex by 1.
    1816         224 :           var_target_index.Bind(NumberInc(target_index));
    1817         112 :           Goto(&next);
    1818             : 
    1819         112 :           BIND(&throw_error);
    1820             :           ThrowTypeError(context, MessageTemplate::kFlattenPastSafeLength,
    1821         112 :                          source_length, target_index);
    1822             :         }
    1823             :       }
    1824         112 :       BIND(&next);
    1825             : 
    1826             :       // d. Increase sourceIndex by 1.
    1827         224 :       var_source_index.Bind(NumberInc(source_index));
    1828         112 :       Goto(&loop);
    1829             :     }
    1830             : 
    1831         112 :     BIND(&done_loop);
    1832         224 :     return var_target_index.value();
    1833             :   }
    1834             : };
    1835             : 
    1836             : // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
    1837         224 : TF_BUILTIN(FlattenIntoArray, ArrayFlattenAssembler) {
    1838             :   Node* const context = Parameter(Descriptor::kContext);
    1839             :   Node* const target = Parameter(Descriptor::kTarget);
    1840             :   Node* const source = Parameter(Descriptor::kSource);
    1841             :   Node* const source_length = Parameter(Descriptor::kSourceLength);
    1842             :   Node* const start = Parameter(Descriptor::kStart);
    1843             :   Node* const depth = Parameter(Descriptor::kDepth);
    1844             : 
    1845             :   // FlattenIntoArray might get called recursively, check stack for overflow
    1846             :   // manually as it has stub linkage.
    1847          56 :   PerformStackCheck(CAST(context));
    1848             : 
    1849         112 :   Return(
    1850          56 :       FlattenIntoArray(context, target, source, source_length, start, depth));
    1851          56 : }
    1852             : 
    1853             : // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
    1854         224 : TF_BUILTIN(FlatMapIntoArray, ArrayFlattenAssembler) {
    1855             :   Node* const context = Parameter(Descriptor::kContext);
    1856             :   Node* const target = Parameter(Descriptor::kTarget);
    1857             :   Node* const source = Parameter(Descriptor::kSource);
    1858             :   Node* const source_length = Parameter(Descriptor::kSourceLength);
    1859             :   Node* const start = Parameter(Descriptor::kStart);
    1860             :   Node* const depth = Parameter(Descriptor::kDepth);
    1861             :   Node* const mapper_function = Parameter(Descriptor::kMapperFunction);
    1862             :   Node* const this_arg = Parameter(Descriptor::kThisArg);
    1863             : 
    1864         112 :   Return(FlattenIntoArray(context, target, source, source_length, start, depth,
    1865          56 :                           mapper_function, this_arg));
    1866          56 : }
    1867             : 
    1868             : // https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flat
    1869         224 : TF_BUILTIN(ArrayPrototypeFlat, CodeStubAssembler) {
    1870             :   TNode<IntPtrT> const argc =
    1871          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1872          56 :   CodeStubArguments args(this, argc);
    1873             :   TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
    1874          56 :   TNode<Object> const receiver = args.GetReceiver();
    1875          56 :   TNode<Object> const depth = args.GetOptionalArgumentValue(0);
    1876             : 
    1877             :   // 1. Let O be ? ToObject(this value).
    1878          56 :   TNode<JSReceiver> const o = ToObject_Inline(context, receiver);
    1879             : 
    1880             :   // 2. Let sourceLen be ? ToLength(? Get(O, "length")).
    1881             :   TNode<Number> const source_length =
    1882         112 :       ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
    1883             : 
    1884             :   // 3. Let depthNum be 1.
    1885         112 :   TVARIABLE(Number, var_depth_num, SmiConstant(1));
    1886             : 
    1887             :   // 4. If depth is not undefined, then
    1888          56 :   Label done(this);
    1889         112 :   GotoIf(IsUndefined(depth), &done);
    1890             :   {
    1891             :     // a. Set depthNum to ? ToInteger(depth).
    1892         112 :     var_depth_num = ToInteger_Inline(context, depth);
    1893          56 :     Goto(&done);
    1894             :   }
    1895          56 :   BIND(&done);
    1896             : 
    1897             :   // 5. Let A be ? ArraySpeciesCreate(O, 0).
    1898             :   TNode<JSReceiver> const constructor =
    1899             :       CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
    1900          56 :   Node* const a = Construct(context, constructor, SmiConstant(0));
    1901             : 
    1902             :   // 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, depthNum).
    1903             :   CallBuiltin(Builtins::kFlattenIntoArray, context, a, o, source_length,
    1904         112 :               SmiConstant(0), var_depth_num.value());
    1905             : 
    1906             :   // 7. Return A.
    1907          56 :   args.PopAndReturn(a);
    1908          56 : }
    1909             : 
    1910             : // https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap
    1911         224 : TF_BUILTIN(ArrayPrototypeFlatMap, CodeStubAssembler) {
    1912             :   TNode<IntPtrT> const argc =
    1913          56 :       ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
    1914          56 :   CodeStubArguments args(this, argc);
    1915             :   TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
    1916          56 :   TNode<Object> const receiver = args.GetReceiver();
    1917          56 :   TNode<Object> const mapper_function = args.GetOptionalArgumentValue(0);
    1918             : 
    1919             :   // 1. Let O be ? ToObject(this value).
    1920          56 :   TNode<JSReceiver> const o = ToObject_Inline(context, receiver);
    1921             : 
    1922             :   // 2. Let sourceLen be ? ToLength(? Get(O, "length")).
    1923             :   TNode<Number> const source_length =
    1924         112 :       ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
    1925             : 
    1926             :   // 3. If IsCallable(mapperFunction) is false, throw a TypeError exception.
    1927          56 :   Label if_not_callable(this, Label::kDeferred);
    1928         112 :   GotoIf(TaggedIsSmi(mapper_function), &if_not_callable);
    1929         112 :   GotoIfNot(IsCallable(CAST(mapper_function)), &if_not_callable);
    1930             : 
    1931             :   // 4. If thisArg is present, let T be thisArg; else let T be undefined.
    1932          56 :   TNode<Object> const t = args.GetOptionalArgumentValue(1);
    1933             : 
    1934             :   // 5. Let A be ? ArraySpeciesCreate(O, 0).
    1935             :   TNode<JSReceiver> const constructor =
    1936             :       CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
    1937          56 :   TNode<JSReceiver> const a = Construct(context, constructor, SmiConstant(0));
    1938             : 
    1939             :   // 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T).
    1940             :   CallBuiltin(Builtins::kFlatMapIntoArray, context, a, o, source_length,
    1941         112 :               SmiConstant(0), SmiConstant(1), mapper_function, t);
    1942             : 
    1943             :   // 7. Return A.
    1944          56 :   args.PopAndReturn(a);
    1945             : 
    1946          56 :   BIND(&if_not_callable);
    1947          56 :   { ThrowTypeError(context, MessageTemplate::kMapperFunctionNonCallable); }
    1948          56 : }
    1949             : 
    1950         112 : TF_BUILTIN(ArrayConstructor, ArrayBuiltinsAssembler) {
    1951             :   // This is a trampoline to ArrayConstructorImpl which just adds
    1952             :   // allocation_site parameter value and sets new_target if necessary.
    1953             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1954             :   TNode<JSFunction> function = CAST(Parameter(Descriptor::kTarget));
    1955             :   TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
    1956             :   TNode<Int32T> argc =
    1957          56 :       UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
    1958             : 
    1959             :   // If new_target is undefined, then this is the 'Call' case, so set new_target
    1960             :   // to function.
    1961         112 :   new_target =
    1962             :       SelectConstant<Object>(IsUndefined(new_target), function, new_target);
    1963             : 
    1964             :   // Run the native code for the Array function called as a normal function.
    1965         112 :   TNode<Object> no_allocation_site = UndefinedConstant();
    1966          56 :   TailCallBuiltin(Builtins::kArrayConstructorImpl, context, function,
    1967          56 :                   new_target, argc, no_allocation_site);
    1968          56 : }
    1969             : 
    1970         784 : void ArrayBuiltinsAssembler::TailCallArrayConstructorStub(
    1971             :     const Callable& callable, TNode<Context> context, TNode<JSFunction> target,
    1972             :     TNode<HeapObject> allocation_site_or_undefined, TNode<Int32T> argc) {
    1973         784 :   TNode<Code> code = HeapConstant(callable.code());
    1974             : 
    1975             :   // We are going to call here ArrayNoArgumentsConstructor or
    1976             :   // ArraySingleArgumentsConstructor which in addition to the register arguments
    1977             :   // also expect some number of arguments on the expression stack.
    1978             :   // Since
    1979             :   // 1) incoming JS arguments are still on the stack,
    1980             :   // 2) the ArrayNoArgumentsConstructor, ArraySingleArgumentsConstructor and
    1981             :   //    ArrayNArgumentsConstructor are defined so that the register arguments
    1982             :   //    are passed on the same registers,
    1983             :   // in order to be able to generate a tail call to those builtins we do the
    1984             :   // following trick here: we tail call to the constructor builtin using
    1985             :   // ArrayNArgumentsConstructorDescriptor, so the tail call instruction
    1986             :   // pops the current frame but leaves all the incoming JS arguments on the
    1987             :   // expression stack so that the target builtin can still find them where it
    1988             :   // expects.
    1989         784 :   TailCallStub(ArrayNArgumentsConstructorDescriptor{}, code, context, target,
    1990             :                allocation_site_or_undefined, argc);
    1991         784 : }
    1992             : 
    1993         112 : void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
    1994             :     TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
    1995             :     AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
    1996         112 :   if (mode == DISABLE_ALLOCATION_SITES) {
    1997             :     Callable callable = CodeFactory::ArrayNoArgumentConstructor(
    1998          56 :         isolate(), GetInitialFastElementsKind(), mode);
    1999             : 
    2000         112 :     TailCallArrayConstructorStub(callable, context, target, UndefinedConstant(),
    2001          56 :                                  argc);
    2002             :   } else {
    2003             :     DCHECK_EQ(mode, DONT_OVERRIDE);
    2004          56 :     TNode<Int32T> elements_kind = LoadElementsKind(allocation_site);
    2005             : 
    2006             :     // TODO(ishell): Compute the builtin index dynamically instead of
    2007             :     // iterating over all expected elements kinds.
    2008             :     int last_index =
    2009          56 :         GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
    2010         728 :     for (int i = 0; i <= last_index; ++i) {
    2011         672 :       Label next(this);
    2012         336 :       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
    2013        1008 :       GotoIfNot(Word32Equal(elements_kind, Int32Constant(kind)), &next);
    2014             : 
    2015             :       Callable callable =
    2016         336 :           CodeFactory::ArrayNoArgumentConstructor(isolate(), kind, mode);
    2017             : 
    2018         336 :       TailCallArrayConstructorStub(callable, context, target, allocation_site,
    2019         336 :                                    argc);
    2020             : 
    2021         336 :       BIND(&next);
    2022             :     }
    2023             : 
    2024             :     // If we reached this point there is a problem.
    2025          56 :     Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
    2026             :   }
    2027         112 : }
    2028             : 
    2029         112 : void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
    2030             :     TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
    2031             :     AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
    2032         112 :   if (mode == DISABLE_ALLOCATION_SITES) {
    2033             :     ElementsKind initial = GetInitialFastElementsKind();
    2034             :     ElementsKind holey_initial = GetHoleyElementsKind(initial);
    2035             :     Callable callable = CodeFactory::ArraySingleArgumentConstructor(
    2036          56 :         isolate(), holey_initial, mode);
    2037             : 
    2038         112 :     TailCallArrayConstructorStub(callable, context, target, UndefinedConstant(),
    2039          56 :                                  argc);
    2040             :   } else {
    2041             :     DCHECK_EQ(mode, DONT_OVERRIDE);
    2042          56 :     TNode<Smi> transition_info = LoadTransitionInfo(allocation_site);
    2043             : 
    2044             :     // Least significant bit in fast array elements kind means holeyness.
    2045             :     STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
    2046             :     STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
    2047             :     STATIC_ASSERT(PACKED_ELEMENTS == 2);
    2048             :     STATIC_ASSERT(HOLEY_ELEMENTS == 3);
    2049             :     STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
    2050             :     STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
    2051             : 
    2052         112 :     Label normal_sequence(this);
    2053         112 :     TVARIABLE(Int32T, var_elements_kind,
    2054             :               Signed(DecodeWord32<AllocationSite::ElementsKindBits>(
    2055             :                   SmiToInt32(transition_info))));
    2056             :     // Is the low bit set? If so, we are holey and that is good.
    2057             :     int fast_elements_kind_holey_mask =
    2058             :         AllocationSite::ElementsKindBits::encode(static_cast<ElementsKind>(1));
    2059         112 :     GotoIf(IsSetSmi(transition_info, fast_elements_kind_holey_mask),
    2060          56 :            &normal_sequence);
    2061             :     {
    2062             :       // Make elements kind holey and update elements kind in the type info.
    2063         112 :       var_elements_kind =
    2064         112 :           Signed(Word32Or(var_elements_kind.value(), Int32Constant(1)));
    2065          56 :       StoreObjectFieldNoWriteBarrier(
    2066             :           allocation_site, AllocationSite::kTransitionInfoOrBoilerplateOffset,
    2067             :           SmiOr(transition_info, SmiConstant(fast_elements_kind_holey_mask)));
    2068          56 :       Goto(&normal_sequence);
    2069             :     }
    2070          56 :     BIND(&normal_sequence);
    2071             : 
    2072             :     // TODO(ishell): Compute the builtin index dynamically instead of
    2073             :     // iterating over all expected elements kinds.
    2074             :     // TODO(ishell): Given that the code above ensures that the elements kind
    2075             :     // is holey we can skip checking with non-holey elements kinds.
    2076             :     int last_index =
    2077          56 :         GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
    2078         728 :     for (int i = 0; i <= last_index; ++i) {
    2079         336 :       Label next(this);
    2080         336 :       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
    2081        1008 :       GotoIfNot(Word32Equal(var_elements_kind.value(), Int32Constant(kind)),
    2082         336 :                 &next);
    2083             : 
    2084             :       Callable callable =
    2085         336 :           CodeFactory::ArraySingleArgumentConstructor(isolate(), kind, mode);
    2086             : 
    2087         336 :       TailCallArrayConstructorStub(callable, context, target, allocation_site,
    2088         336 :                                    argc);
    2089             : 
    2090         336 :       BIND(&next);
    2091             :     }
    2092             : 
    2093             :     // If we reached this point there is a problem.
    2094          56 :     Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
    2095             :   }
    2096         112 : }
    2097             : 
    2098         112 : void ArrayBuiltinsAssembler::GenerateDispatchToArrayStub(
    2099             :     TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
    2100             :     AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
    2101         224 :   Label check_one_case(this), fallthrough(this);
    2102         336 :   GotoIfNot(Word32Equal(argc, Int32Constant(0)), &check_one_case);
    2103         112 :   CreateArrayDispatchNoArgument(context, target, argc, mode, allocation_site);
    2104             : 
    2105         112 :   BIND(&check_one_case);
    2106         336 :   GotoIfNot(Word32Equal(argc, Int32Constant(1)), &fallthrough);
    2107             :   CreateArrayDispatchSingleArgument(context, target, argc, mode,
    2108         112 :                                     allocation_site);
    2109             : 
    2110         112 :   BIND(&fallthrough);
    2111         112 : }
    2112             : 
    2113         168 : TF_BUILTIN(ArrayConstructorImpl, ArrayBuiltinsAssembler) {
    2114             :   TNode<JSFunction> target = CAST(Parameter(Descriptor::kTarget));
    2115             :   TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
    2116             :   TNode<Int32T> argc =
    2117          56 :       UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
    2118             :   TNode<HeapObject> maybe_allocation_site =
    2119             :       CAST(Parameter(Descriptor::kAllocationSite));
    2120             : 
    2121             :   // Initial map for the builtin Array functions should be Map.
    2122             :   CSA_ASSERT(this, IsMap(CAST(LoadObjectField(
    2123             :                        target, JSFunction::kPrototypeOrInitialMapOffset))));
    2124             : 
    2125             :   // We should either have undefined or a valid AllocationSite
    2126             :   CSA_ASSERT(this, Word32Or(IsUndefined(maybe_allocation_site),
    2127             :                             IsAllocationSite(maybe_allocation_site)));
    2128             : 
    2129             :   // "Enter" the context of the Array function.
    2130             :   TNode<Context> context =
    2131         112 :       CAST(LoadObjectField(target, JSFunction::kContextOffset));
    2132             : 
    2133          56 :   Label runtime(this, Label::kDeferred);
    2134          56 :   GotoIf(WordNotEqual(target, new_target), &runtime);
    2135             : 
    2136          56 :   Label no_info(this);
    2137             :   // If the feedback vector is the undefined value call an array constructor
    2138             :   // that doesn't use AllocationSites.
    2139         112 :   GotoIf(IsUndefined(maybe_allocation_site), &no_info);
    2140             : 
    2141          56 :   GenerateDispatchToArrayStub(context, target, argc, DONT_OVERRIDE,
    2142          56 :                               CAST(maybe_allocation_site));
    2143          56 :   Goto(&runtime);
    2144             : 
    2145          56 :   BIND(&no_info);
    2146          56 :   GenerateDispatchToArrayStub(context, target, argc, DISABLE_ALLOCATION_SITES);
    2147          56 :   Goto(&runtime);
    2148             : 
    2149          56 :   BIND(&runtime);
    2150             :   GenerateArrayNArgumentsConstructor(context, target, new_target, argc,
    2151          56 :                                      maybe_allocation_site);
    2152          56 : }
    2153             : 
    2154         448 : void ArrayBuiltinsAssembler::GenerateConstructor(
    2155             :     Node* context, Node* array_function, Node* array_map, Node* array_size,
    2156             :     Node* allocation_site, ElementsKind elements_kind,
    2157             :     AllocationSiteMode mode) {
    2158         896 :   Label ok(this);
    2159         448 :   Label smi_size(this);
    2160         448 :   Label small_smi_size(this);
    2161         448 :   Label call_runtime(this, Label::kDeferred);
    2162             : 
    2163         896 :   Branch(TaggedIsSmi(array_size), &smi_size, &call_runtime);
    2164             : 
    2165         448 :   BIND(&smi_size);
    2166             : 
    2167         448 :   if (IsFastPackedElementsKind(elements_kind)) {
    2168         224 :     Label abort(this, Label::kDeferred);
    2169         448 :     Branch(SmiEqual(CAST(array_size), SmiConstant(0)), &small_smi_size, &abort);
    2170             : 
    2171         224 :     BIND(&abort);
    2172             :     Node* reason = SmiConstant(AbortReason::kAllocatingNonEmptyPackedArray);
    2173         224 :     TailCallRuntime(Runtime::kAbort, context, reason);
    2174             :   } else {
    2175             :     int element_size =
    2176             :         IsDoubleElementsKind(elements_kind) ? kDoubleSize : kTaggedSize;
    2177             :     int max_fast_elements =
    2178             :         (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - JSArray::kSize -
    2179             :          AllocationMemento::kSize) /
    2180             :         element_size;
    2181         448 :     Branch(SmiAboveOrEqual(CAST(array_size), SmiConstant(max_fast_elements)),
    2182         224 :            &call_runtime, &small_smi_size);
    2183             :   }
    2184             : 
    2185         448 :   BIND(&small_smi_size);
    2186             :   {
    2187             :     TNode<JSArray> array = AllocateJSArray(
    2188             :         elements_kind, CAST(array_map), array_size, CAST(array_size),
    2189             :         mode == DONT_TRACK_ALLOCATION_SITE ? nullptr : allocation_site,
    2190         448 :         CodeStubAssembler::SMI_PARAMETERS);
    2191         448 :     Return(array);
    2192             :   }
    2193             : 
    2194         448 :   BIND(&call_runtime);
    2195             :   {
    2196         448 :     TailCallRuntime(Runtime::kNewArray, context, array_function, array_size,
    2197         448 :                     array_function, allocation_site);
    2198             :   }
    2199         448 : }
    2200             : 
    2201         448 : void ArrayBuiltinsAssembler::GenerateArrayNoArgumentConstructor(
    2202             :     ElementsKind kind, AllocationSiteOverrideMode mode) {
    2203             :   typedef ArrayNoArgumentConstructorDescriptor Descriptor;
    2204             :   Node* native_context = LoadObjectField(Parameter(Descriptor::kFunction),
    2205         448 :                                          JSFunction::kContextOffset);
    2206             :   bool track_allocation_site =
    2207         448 :       AllocationSite::ShouldTrack(kind) && mode != DISABLE_ALLOCATION_SITES;
    2208             :   Node* allocation_site =
    2209         448 :       track_allocation_site ? Parameter(Descriptor::kAllocationSite) : nullptr;
    2210         448 :   TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context);
    2211             :   TNode<JSArray> array = AllocateJSArray(
    2212         896 :       kind, array_map, IntPtrConstant(JSArray::kPreallocatedArrayElements),
    2213        1344 :       SmiConstant(0), allocation_site);
    2214         448 :   Return(array);
    2215         448 : }
    2216             : 
    2217         448 : void ArrayBuiltinsAssembler::GenerateArraySingleArgumentConstructor(
    2218             :     ElementsKind kind, AllocationSiteOverrideMode mode) {
    2219             :   typedef ArraySingleArgumentConstructorDescriptor Descriptor;
    2220         448 :   Node* context = Parameter(Descriptor::kContext);
    2221         448 :   Node* function = Parameter(Descriptor::kFunction);
    2222         448 :   Node* native_context = LoadObjectField(function, JSFunction::kContextOffset);
    2223         896 :   Node* array_map = LoadJSArrayElementsMap(kind, native_context);
    2224             : 
    2225             :   AllocationSiteMode allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
    2226         448 :   if (mode == DONT_OVERRIDE) {
    2227             :     allocation_site_mode = AllocationSite::ShouldTrack(kind)
    2228             :                                ? TRACK_ALLOCATION_SITE
    2229         112 :                                : DONT_TRACK_ALLOCATION_SITE;
    2230             :   }
    2231             : 
    2232         448 :   Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
    2233         448 :   Node* allocation_site = Parameter(Descriptor::kAllocationSite);
    2234             : 
    2235             :   GenerateConstructor(context, function, array_map, array_size, allocation_site,
    2236         448 :                       kind, allocation_site_mode);
    2237         448 : }
    2238             : 
    2239         112 : void ArrayBuiltinsAssembler::GenerateArrayNArgumentsConstructor(
    2240             :     TNode<Context> context, TNode<JSFunction> target, TNode<Object> new_target,
    2241             :     TNode<Int32T> argc, TNode<HeapObject> maybe_allocation_site) {
    2242             :   // Replace incoming JS receiver argument with the target.
    2243             :   // TODO(ishell): Avoid replacing the target on the stack and just add it
    2244             :   // as another additional parameter for Runtime::kNewArray.
    2245         336 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
    2246         112 :   args.SetReceiver(target);
    2247             : 
    2248             :   // Adjust arguments count for the runtime call: +1 for implicit receiver
    2249             :   // and +2 for new_target and maybe_allocation_site.
    2250         112 :   argc = Int32Add(argc, Int32Constant(3));
    2251             :   TailCallRuntime(Runtime::kNewArray, argc, context, new_target,
    2252             :                   maybe_allocation_site);
    2253         112 : }
    2254             : 
    2255         224 : TF_BUILTIN(ArrayNArgumentsConstructor, ArrayBuiltinsAssembler) {
    2256          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2257             :   TNode<JSFunction> target = CAST(Parameter(Descriptor::kFunction));
    2258             :   TNode<Int32T> argc =
    2259          56 :       UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
    2260             :   TNode<HeapObject> maybe_allocation_site =
    2261          56 :       CAST(Parameter(Descriptor::kAllocationSite));
    2262             : 
    2263         112 :   GenerateArrayNArgumentsConstructor(context, target, target, argc,
    2264          56 :                                      maybe_allocation_site);
    2265          56 : }
    2266             : 
    2267             : #define GENERATE_ARRAY_CTOR(name, kind_camel, kind_caps, mode_camel, \
    2268             :                             mode_caps)                               \
    2269             :   TF_BUILTIN(Array##name##Constructor_##kind_camel##_##mode_camel,   \
    2270             :              ArrayBuiltinsAssembler) {                               \
    2271             :     GenerateArray##name##Constructor(kind_caps, mode_caps);          \
    2272             :   }
    2273             : 
    2274             : // The ArrayNoArgumentConstructor builtin family.
    2275          56 : GENERATE_ARRAY_CTOR(NoArgument, PackedSmi, PACKED_SMI_ELEMENTS, DontOverride,
    2276             :                     DONT_OVERRIDE)
    2277          56 : GENERATE_ARRAY_CTOR(NoArgument, HoleySmi, HOLEY_SMI_ELEMENTS, DontOverride,
    2278             :                     DONT_OVERRIDE)
    2279          56 : GENERATE_ARRAY_CTOR(NoArgument, PackedSmi, PACKED_SMI_ELEMENTS,
    2280             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2281          56 : GENERATE_ARRAY_CTOR(NoArgument, HoleySmi, HOLEY_SMI_ELEMENTS,
    2282             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2283          56 : GENERATE_ARRAY_CTOR(NoArgument, Packed, PACKED_ELEMENTS, DisableAllocationSites,
    2284             :                     DISABLE_ALLOCATION_SITES)
    2285          56 : GENERATE_ARRAY_CTOR(NoArgument, Holey, HOLEY_ELEMENTS, DisableAllocationSites,
    2286             :                     DISABLE_ALLOCATION_SITES)
    2287          56 : GENERATE_ARRAY_CTOR(NoArgument, PackedDouble, PACKED_DOUBLE_ELEMENTS,
    2288             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2289          56 : GENERATE_ARRAY_CTOR(NoArgument, HoleyDouble, HOLEY_DOUBLE_ELEMENTS,
    2290             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2291             : 
    2292             : // The ArraySingleArgumentConstructor builtin family.
    2293          56 : GENERATE_ARRAY_CTOR(SingleArgument, PackedSmi, PACKED_SMI_ELEMENTS,
    2294             :                     DontOverride, DONT_OVERRIDE)
    2295          56 : GENERATE_ARRAY_CTOR(SingleArgument, HoleySmi, HOLEY_SMI_ELEMENTS, DontOverride,
    2296             :                     DONT_OVERRIDE)
    2297          56 : GENERATE_ARRAY_CTOR(SingleArgument, PackedSmi, PACKED_SMI_ELEMENTS,
    2298             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2299          56 : GENERATE_ARRAY_CTOR(SingleArgument, HoleySmi, HOLEY_SMI_ELEMENTS,
    2300             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2301          56 : GENERATE_ARRAY_CTOR(SingleArgument, Packed, PACKED_ELEMENTS,
    2302             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2303          56 : GENERATE_ARRAY_CTOR(SingleArgument, Holey, HOLEY_ELEMENTS,
    2304             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2305          56 : GENERATE_ARRAY_CTOR(SingleArgument, PackedDouble, PACKED_DOUBLE_ELEMENTS,
    2306             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2307          56 : GENERATE_ARRAY_CTOR(SingleArgument, HoleyDouble, HOLEY_DOUBLE_ELEMENTS,
    2308             :                     DisableAllocationSites, DISABLE_ALLOCATION_SITES)
    2309             : 
    2310             : #undef GENERATE_ARRAY_CTOR
    2311             : 
    2312         112 : TF_BUILTIN(InternalArrayNoArgumentConstructor_Packed, ArrayBuiltinsAssembler) {
    2313             :   typedef ArrayNoArgumentConstructorDescriptor Descriptor;
    2314             :   TNode<Map> array_map =
    2315          56 :       CAST(LoadObjectField(Parameter(Descriptor::kFunction),
    2316             :                            JSFunction::kPrototypeOrInitialMapOffset));
    2317             :   TNode<JSArray> array = AllocateJSArray(
    2318             :       PACKED_ELEMENTS, array_map,
    2319          56 :       IntPtrConstant(JSArray::kPreallocatedArrayElements), SmiConstant(0));
    2320          56 :   Return(array);
    2321          56 : }
    2322             : 
    2323             : }  // namespace internal
    2324       59456 : }  // namespace v8

Generated by: LCOV version 1.10