LCOV - code coverage report
Current view: top level - src/builtins - builtins-array-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1147 1157 99.1 %
Date: 2017-10-20 Functions: 103 106 97.2 %

          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-string-gen.h"
       6             : #include "src/builtins/builtins-utils-gen.h"
       7             : #include "src/builtins/builtins.h"
       8             : #include "src/code-stub-assembler.h"
       9             : #include "src/factory-inl.h"
      10             : #include "src/frame-constants.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15        1488 : class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
      16             :  public:
      17         744 :   explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state)
      18             :       : CodeStubAssembler(state),
      19             :         k_(this, MachineRepresentation::kTagged),
      20             :         a_(this, MachineRepresentation::kTagged),
      21             :         to_(this, MachineRepresentation::kTagged, SmiConstant(0)),
      22        2232 :         fully_spec_compliant_(this, {&k_, &a_, &to_}) {}
      23             : 
      24             :   typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
      25             :       BuiltinResultGenerator;
      26             : 
      27             :   typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm,
      28             :                               Node* k_value, Node* k)>
      29             :       CallResultProcessor;
      30             : 
      31             :   typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
      32             :       PostLoopAction;
      33             : 
      34         620 :   void ForEachResultGenerator() { a_.Bind(UndefinedConstant()); }
      35             : 
      36         372 :   Node* ForEachProcessor(Node* k_value, Node* k) {
      37             :     CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(),
      38         744 :            k_value, k, o());
      39         372 :     return a();
      40             :   }
      41             : 
      42         620 :   void SomeResultGenerator() { a_.Bind(FalseConstant()); }
      43             : 
      44         372 :   Node* SomeProcessor(Node* k_value, Node* k) {
      45             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      46         744 :                          this_arg(), k_value, k, o());
      47         372 :     Label false_continue(this), return_true(this);
      48         372 :     BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
      49         372 :     BIND(&return_true);
      50         744 :     ReturnFromBuiltin(TrueConstant());
      51         372 :     BIND(&false_continue);
      52         372 :     return a();
      53             :   }
      54             : 
      55         620 :   void EveryResultGenerator() { a_.Bind(TrueConstant()); }
      56             : 
      57         372 :   Node* EveryProcessor(Node* k_value, Node* k) {
      58             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      59         744 :                          this_arg(), k_value, k, o());
      60         372 :     Label true_continue(this), return_false(this);
      61         372 :     BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
      62         372 :     BIND(&return_false);
      63         744 :     ReturnFromBuiltin(FalseConstant());
      64         372 :     BIND(&true_continue);
      65         372 :     return a();
      66             :   }
      67             : 
      68         620 :   void ReduceResultGenerator() { return a_.Bind(this_arg()); }
      69             : 
      70        2232 :   Node* ReduceProcessor(Node* k_value, Node* k) {
      71         744 :     VARIABLE(result, MachineRepresentation::kTagged);
      72        2232 :     Label done(this, {&result}), initial(this);
      73        1488 :     GotoIf(WordEqual(a(), TheHoleConstant()), &initial);
      74             :     result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      75        2232 :                        UndefinedConstant(), a(), k_value, k, o()));
      76         744 :     Goto(&done);
      77             : 
      78         744 :     BIND(&initial);
      79         744 :     result.Bind(k_value);
      80         744 :     Goto(&done);
      81             : 
      82         744 :     BIND(&done);
      83        1488 :     return result.value();
      84             :   }
      85             : 
      86        1488 :   void ReducePostLoopAction() {
      87         744 :     Label ok(this);
      88        1488 :     GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok);
      89         744 :     ThrowTypeError(context(), MessageTemplate::kReduceNoInitial);
      90         744 :     BIND(&ok);
      91         744 :   }
      92             : 
      93          31 :   void FilterResultGenerator() {
      94             :     // 7. Let A be ArraySpeciesCreate(O, 0).
      95             :     // This version of ArraySpeciesCreate will create with the correct
      96             :     // ElementsKind in the fast case.
      97          31 :     ArraySpeciesCreate();
      98          31 :   }
      99             : 
     100         279 :   Node* FilterProcessor(Node* k_value, Node* k) {
     101             :     // ii. Let selected be ToBoolean(? Call(callbackfn, T, kValue, k, O)).
     102             :     Node* selected = CallJS(CodeFactory::Call(isolate()), context(),
     103         186 :                             callbackfn(), this_arg(), k_value, k, o());
     104         186 :     Label true_continue(this, &to_), false_continue(this);
     105          93 :     BranchIfToBooleanIsTrue(selected, &true_continue, &false_continue);
     106          93 :     BIND(&true_continue);
     107             :     // iii. If selected is true, then...
     108             :     {
     109             :       Label after_work(this, &to_);
     110             :       Node* kind = nullptr;
     111             : 
     112             :       // If a() is a JSArray, we can have a fast path.
     113          93 :       Label fast(this);
     114          93 :       Label runtime(this);
     115          93 :       Label object_push_pre(this), object_push(this), double_push(this);
     116          93 :       BranchIfFastJSArray(a(), context(), &fast, &runtime);
     117             : 
     118          93 :       BIND(&fast);
     119             :       {
     120         372 :         GotoIf(SmiNotEqual(LoadJSArrayLength(a()), to_.value()), &runtime);
     121          93 :         kind = EnsureArrayPushable(a(), &runtime);
     122             :         GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
     123         186 :                &object_push_pre);
     124             : 
     125          93 :         BuildAppendJSArray(HOLEY_SMI_ELEMENTS, a(), k_value, &runtime);
     126          93 :         Goto(&after_work);
     127             :       }
     128             : 
     129          93 :       BIND(&object_push_pre);
     130             :       {
     131             :         Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &double_push,
     132         186 :                &object_push);
     133             :       }
     134             : 
     135          93 :       BIND(&object_push);
     136             :       {
     137          93 :         BuildAppendJSArray(HOLEY_ELEMENTS, a(), k_value, &runtime);
     138          93 :         Goto(&after_work);
     139             :       }
     140             : 
     141          93 :       BIND(&double_push);
     142             :       {
     143          93 :         BuildAppendJSArray(HOLEY_DOUBLE_ELEMENTS, a(), k_value, &runtime);
     144          93 :         Goto(&after_work);
     145             :       }
     146             : 
     147          93 :       BIND(&runtime);
     148             :       {
     149             :         // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
     150             :         CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
     151          93 :                     k_value);
     152          93 :         Goto(&after_work);
     153             :       }
     154             : 
     155          93 :       BIND(&after_work);
     156             :       {
     157             :         // 2. Increase to by 1.
     158          93 :         to_.Bind(NumberInc(to_.value()));
     159          93 :         Goto(&false_continue);
     160          93 :       }
     161             :     }
     162          93 :     BIND(&false_continue);
     163          93 :     return a();
     164             :   }
     165             : 
     166          62 :   void MapResultGenerator() { ArraySpeciesCreate(len_); }
     167             : 
     168         558 :   void TypedArrayMapResultGenerator() {
     169             :     // 6. Let A be ? TypedArraySpeciesCreate(O, len).
     170         558 :     Node* a = TypedArraySpeciesCreateByLength(context(), o(), len_);
     171             :     // In the Spec and our current implementation, the length check is already
     172             :     // performed in TypedArraySpeciesCreate.
     173             :     CSA_ASSERT(this,
     174             :                SmiLessThanOrEqual(
     175             :                    len_, LoadObjectField(a, JSTypedArray::kLengthOffset)));
     176        1395 :     fast_typed_array_target_ = Word32Equal(LoadInstanceType(LoadElements(o_)),
     177        1953 :                                            LoadInstanceType(LoadElements(a)));
     178         279 :     a_.Bind(a);
     179         279 :   }
     180             : 
     181          62 :   Node* SpecCompliantMapProcessor(Node* k_value, Node* k) {
     182             :     //  i. Let kValue be ? Get(O, Pk). Performed by the caller of
     183             :     //  SpecCompliantMapProcessor.
     184             :     // ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O).
     185             :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
     186          62 :                                 callbackfn(), this_arg(), k_value, k, o());
     187             : 
     188             :     // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     189             :     CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mapped_value);
     190          31 :     return a();
     191             :   }
     192             : 
     193         310 :   Node* FastMapProcessor(Node* k_value, Node* k) {
     194             :     //  i. Let kValue be ? Get(O, Pk). Performed by the caller of
     195             :     //  FastMapProcessor.
     196             :     // ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O).
     197             :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
     198         124 :                                 callbackfn(), this_arg(), k_value, k, o());
     199             : 
     200             :     // mode is SMI_PARAMETERS because k has tagged representation.
     201             :     ParameterMode mode = SMI_PARAMETERS;
     202          62 :     Label runtime(this), finished(this);
     203          62 :     Label transition_pre(this), transition_smi_fast(this),
     204          62 :         transition_smi_double(this);
     205          62 :     Label array_not_smi(this), array_fast(this), array_double(this);
     206             : 
     207         186 :     Node* kind = LoadMapElementsKind(LoadMap(a()));
     208         124 :     Node* elements = LoadElements(a());
     209         124 :     GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), &array_not_smi);
     210             :     TryStoreArrayElement(HOLEY_SMI_ELEMENTS, mode, &transition_pre, elements, k,
     211          62 :                          mapped_value);
     212          62 :     Goto(&finished);
     213             : 
     214          62 :     BIND(&transition_pre);
     215             :     {
     216             :       // array is smi. Value is either tagged or a heap number.
     217             :       CSA_ASSERT(this, TaggedIsNotSmi(mapped_value));
     218         186 :       GotoIf(IsHeapNumberMap(LoadMap(mapped_value)), &transition_smi_double);
     219          62 :       Goto(&transition_smi_fast);
     220             :     }
     221             : 
     222          62 :     BIND(&array_not_smi);
     223             :     {
     224             :       Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &array_double,
     225         124 :              &array_fast);
     226             :     }
     227             : 
     228          62 :     BIND(&transition_smi_fast);
     229             :     {
     230             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     231         124 :       Node* const native_context = LoadNativeContext(context());
     232             :       Node* const fast_map = LoadContextElement(
     233         124 :           native_context, Context::JS_ARRAY_HOLEY_ELEMENTS_MAP_INDEX);
     234             : 
     235             :       // Since this transition is only a map change, just do it right here.
     236             :       // Since a() doesn't have an allocation site, it's safe to do the
     237             :       // map store directly, otherwise I'd call TransitionElementsKind().
     238          62 :       StoreMap(a(), fast_map);
     239          62 :       Goto(&array_fast);
     240             :     }
     241             : 
     242          62 :     BIND(&array_fast);
     243             :     {
     244             :       TryStoreArrayElement(HOLEY_ELEMENTS, mode, &runtime, elements, k,
     245          62 :                            mapped_value);
     246          62 :       Goto(&finished);
     247             :     }
     248             : 
     249          62 :     BIND(&transition_smi_double);
     250             :     {
     251             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     252         124 :       Node* const native_context = LoadNativeContext(context());
     253             :       Node* const double_map = LoadContextElement(
     254         124 :           native_context, Context::JS_ARRAY_HOLEY_DOUBLE_ELEMENTS_MAP_INDEX);
     255             :       CallStub(CodeFactory::TransitionElementsKind(
     256             :                    isolate(), HOLEY_SMI_ELEMENTS, HOLEY_DOUBLE_ELEMENTS, true),
     257         124 :                context(), a(), double_map);
     258          62 :       Goto(&array_double);
     259             :     }
     260             : 
     261          62 :     BIND(&array_double);
     262             :     {
     263             :       // TODO(mvstanton): If we use a variable for elements and bind it
     264             :       // appropriately, we can avoid an extra load of elements by binding the
     265             :       // value only after a transition from smi to double.
     266         124 :       elements = LoadElements(a());
     267             :       // If the mapped_value isn't a number, this will bail out to the runtime
     268             :       // to make the transition.
     269             :       TryStoreArrayElement(HOLEY_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
     270          62 :                            mapped_value);
     271          62 :       Goto(&finished);
     272             :     }
     273             : 
     274          62 :     BIND(&runtime);
     275             :     {
     276             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
     277             :       CallRuntime(Runtime::kCreateDataProperty, context(), a(), k,
     278             :                   mapped_value);
     279          62 :       Goto(&finished);
     280             :     }
     281             : 
     282          62 :     BIND(&finished);
     283          62 :     return a();
     284             :   }
     285             : 
     286             :   // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map.
     287         837 :   Node* TypedArrayMapProcessor(Node* k_value, Node* k) {
     288             :     // 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »).
     289             :     Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
     290         558 :                                 callbackfn(), this_arg(), k_value, k, o());
     291         279 :     Label fast(this), slow(this), done(this), detached(this, Label::kDeferred);
     292             : 
     293             :     // 8. d. Perform ? Set(A, Pk, mapped_value, true).
     294             :     // Since we know that A is a TypedArray, this always ends up in
     295             :     // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then
     296             :     // tc39.github.io/ecma262/#sec-integerindexedelementset .
     297         558 :     Branch(fast_typed_array_target_, &fast, &slow);
     298             : 
     299         279 :     BIND(&fast);
     300             :     // #sec-integerindexedelementset 3. Let numValue be ? ToNumber(value).
     301         558 :     Node* num_value = ToNumber(context(), mapped_value);
     302             :     // The only way how this can bailout is because of a detached buffer.
     303             :     EmitElementStore(a(), k, num_value, false, source_elements_kind_,
     304         558 :                      KeyedAccessStoreMode::STANDARD_STORE, &detached);
     305         279 :     Goto(&done);
     306             : 
     307         279 :     BIND(&slow);
     308             :     CallRuntime(Runtime::kSetProperty, context(), a(), k, mapped_value,
     309         279 :                 SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     310         279 :     Goto(&done);
     311             : 
     312         279 :     BIND(&detached);
     313             :     // tc39.github.io/ecma262/#sec-integerindexedelementset
     314             :     // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
     315         279 :     ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_);
     316             : 
     317         279 :     BIND(&done);
     318         279 :     return a();
     319             :   }
     320             : 
     321        1581 :   void NullPostLoopAction() {}
     322             : 
     323             :  protected:
     324             :   Node* context() { return context_; }
     325             :   Node* receiver() { return receiver_; }
     326             :   Node* new_target() { return new_target_; }
     327             :   Node* argc() { return argc_; }
     328             :   Node* o() { return o_; }
     329             :   Node* len() { return len_; }
     330             :   Node* callbackfn() { return callbackfn_; }
     331             :   Node* this_arg() { return this_arg_; }
     332        1519 :   Node* k() { return k_.value(); }
     333        5425 :   Node* a() { return a_.value(); }
     334             : 
     335        3069 :   void ReturnFromBuiltin(Node* value) {
     336        3069 :     if (argc_ == nullptr) {
     337          62 :       Return(value);
     338             :     } else {
     339             :       // argc_ doesn't include the receiver, so it has to be added back in
     340             :       // manually.
     341        9021 :       PopAndReturn(IntPtrAdd(argc_, IntPtrConstant(1)), value);
     342             :     }
     343        3069 :   }
     344             : 
     345             :   void InitIteratingArrayBuiltinBody(Node* context, Node* receiver,
     346             :                                      Node* callbackfn, Node* this_arg,
     347             :                                      Node* new_target, Node* argc) {
     348         403 :     context_ = context;
     349         403 :     receiver_ = receiver;
     350         403 :     new_target_ = new_target;
     351         403 :     callbackfn_ = callbackfn;
     352         403 :     this_arg_ = this_arg;
     353         403 :     argc_ = argc;
     354             :   }
     355             : 
     356         217 :   void GenerateIteratingArrayBuiltinBody(
     357             :       const char* name, const BuiltinResultGenerator& generator,
     358             :       const CallResultProcessor& processor, const PostLoopAction& action,
     359             :       const Callable& slow_case_continuation,
     360        3069 :       ForEachDirection direction = ForEachDirection::kForward) {
     361         868 :     Label non_array(this), array_changes(this, {&k_, &a_, &to_});
     362             : 
     363             :     // TODO(danno): Seriously? Do we really need to throw the exact error
     364             :     // message on null and undefined so that the webkit tests pass?
     365         217 :     Label throw_null_undefined_exception(this, Label::kDeferred);
     366         434 :     GotoIf(WordEqual(receiver(), NullConstant()),
     367         217 :            &throw_null_undefined_exception);
     368         434 :     GotoIf(WordEqual(receiver(), UndefinedConstant()),
     369         217 :            &throw_null_undefined_exception);
     370             : 
     371             :     // By the book: taken directly from the ECMAScript 2015 specification
     372             : 
     373             :     // 1. Let O be ToObject(this value).
     374             :     // 2. ReturnIfAbrupt(O)
     375         217 :     o_ = CallBuiltin(Builtins::kToObject, context(), receiver());
     376             : 
     377             :     // 3. Let len be ToLength(Get(O, "length")).
     378             :     // 4. ReturnIfAbrupt(len).
     379         434 :     VARIABLE(merged_length, MachineRepresentation::kTagged);
     380         217 :     Label has_length(this, &merged_length), not_js_array(this);
     381         434 :     GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), &not_js_array);
     382         434 :     merged_length.Bind(LoadJSArrayLength(o()));
     383         217 :     Goto(&has_length);
     384         217 :     BIND(&not_js_array);
     385             :     Node* len_property =
     386         434 :         GetProperty(context(), o(), isolate()->factory()->length_string());
     387         217 :     merged_length.Bind(ToLength_Inline(context(), len_property));
     388         217 :     Goto(&has_length);
     389         217 :     BIND(&has_length);
     390         217 :     len_ = merged_length.value();
     391             : 
     392             :     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
     393         217 :     Label type_exception(this, Label::kDeferred);
     394         217 :     Label done(this);
     395         434 :     GotoIf(TaggedIsSmi(callbackfn()), &type_exception);
     396         651 :     Branch(IsCallableMap(LoadMap(callbackfn())), &done, &type_exception);
     397             : 
     398         217 :     BIND(&throw_null_undefined_exception);
     399         217 :     ThrowTypeError(context(), MessageTemplate::kCalledOnNullOrUndefined, name);
     400             : 
     401         217 :     BIND(&type_exception);
     402             :     ThrowTypeError(context(), MessageTemplate::kCalledNonCallable,
     403         217 :                    callbackfn());
     404             : 
     405         217 :     BIND(&done);
     406             : 
     407             :     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
     408             :     // [Already done by the arguments adapter]
     409             : 
     410         217 :     if (direction == ForEachDirection::kForward) {
     411             :       // 7. Let k be 0.
     412         372 :       k_.Bind(SmiConstant(0));
     413             :     } else {
     414          31 :       k_.Bind(NumberDec(len()));
     415             :     }
     416             : 
     417         217 :     generator(this);
     418             : 
     419         217 :     HandleFastElements(processor, action, &fully_spec_compliant_, direction);
     420             : 
     421         217 :     BIND(&fully_spec_compliant_);
     422             : 
     423             :     Node* result =
     424             :         CallStub(slow_case_continuation, context(), receiver(), callbackfn(),
     425         868 :                  this_arg(), a_.value(), o(), k_.value(), len(), to_.value());
     426         434 :     ReturnFromBuiltin(result);
     427         217 :   }
     428             : 
     429             :   void InitIteratingArrayBuiltinLoopContinuation(Node* context, Node* receiver,
     430             :                                                  Node* callbackfn,
     431             :                                                  Node* this_arg, Node* a,
     432             :                                                  Node* o, Node* initial_k,
     433             :                                                  Node* len, Node* to) {
     434         217 :     context_ = context;
     435         217 :     this_arg_ = this_arg;
     436         217 :     callbackfn_ = callbackfn;
     437         217 :     argc_ = nullptr;
     438         217 :     a_.Bind(a);
     439         217 :     k_.Bind(initial_k);
     440         217 :     o_ = o;
     441         217 :     len_ = len;
     442         217 :     to_.Bind(to);
     443             :   }
     444             : 
     445         186 :   void GenerateIteratingTypedArrayBuiltinBody(
     446             :       const char* name, const BuiltinResultGenerator& generator,
     447             :       const CallResultProcessor& processor, const PostLoopAction& action,
     448          31 :       ForEachDirection direction = ForEachDirection::kForward) {
     449         186 :     name_ = name;
     450             : 
     451             :     // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
     452             : 
     453         186 :     Label throw_not_typed_array(this, Label::kDeferred),
     454         186 :         throw_detached(this, Label::kDeferred);
     455             : 
     456         558 :     GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
     457             :     GotoIfNot(HasInstanceType(receiver_, JS_TYPED_ARRAY_TYPE),
     458         372 :               &throw_not_typed_array);
     459             : 
     460         186 :     o_ = receiver_;
     461             :     Node* array_buffer = LoadObjectField(o_, JSTypedArray::kBufferOffset);
     462         372 :     GotoIf(IsDetachedBuffer(array_buffer), &throw_detached);
     463             : 
     464         372 :     len_ = LoadObjectField(o_, JSTypedArray::kLengthOffset);
     465             : 
     466         186 :     Label throw_not_callable(this, Label::kDeferred);
     467         186 :     Label distinguish_types(this);
     468         558 :     GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable);
     469         372 :     Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types,
     470         558 :            &throw_not_callable);
     471             : 
     472         186 :     BIND(&throw_not_typed_array);
     473         186 :     ThrowTypeError(context_, MessageTemplate::kNotTypedArray);
     474             : 
     475         186 :     BIND(&throw_detached);
     476         186 :     ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_);
     477             : 
     478         186 :     BIND(&throw_not_callable);
     479         186 :     ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_);
     480             : 
     481         186 :     Label unexpected_instance_type(this);
     482         186 :     BIND(&unexpected_instance_type);
     483         186 :     Unreachable();
     484             : 
     485             :     std::vector<int32_t> instance_types = {
     486             : #define INSTANCE_TYPE(Type, type, TYPE, ctype, size) FIXED_##TYPE##_ARRAY_TYPE,
     487             :         TYPED_ARRAYS(INSTANCE_TYPE)
     488             : #undef INSTANCE_TYPE
     489             :     };
     490         186 :     std::vector<Label> labels;
     491        3720 :     for (size_t i = 0; i < instance_types.size(); ++i) {
     492        1674 :       labels.push_back(Label(this));
     493             :     }
     494             :     std::vector<Label*> label_ptrs;
     495        2046 :     for (Label& label : labels) {
     496        3348 :       label_ptrs.push_back(&label);
     497             :     }
     498             : 
     499         186 :     BIND(&distinguish_types);
     500             : 
     501         186 :     if (direction == ForEachDirection::kForward) {
     502         310 :       k_.Bind(SmiConstant(0));
     503             :     } else {
     504          31 :       k_.Bind(NumberDec(len()));
     505             :     }
     506         744 :     Node* instance_type = LoadInstanceType(LoadElements(o_));
     507             :     Switch(instance_type, &unexpected_instance_type, instance_types.data(),
     508         372 :            label_ptrs.data(), labels.size());
     509             : 
     510        3720 :     for (size_t i = 0; i < labels.size(); ++i) {
     511        1674 :       BIND(&labels[i]);
     512             :       Label done(this);
     513             :       source_elements_kind_ = ElementsKindForInstanceType(
     514        3348 :           static_cast<InstanceType>(instance_types[i]));
     515        1674 :       generator(this);
     516             :       // TODO(tebbi): Silently cancelling the loop on buffer detachment is a
     517             :       // spec violation. Should go to &throw_detached and throw a TypeError
     518             :       // instead.
     519        1674 :       VisitAllTypedArrayElements(array_buffer, processor, &done, direction);
     520        1674 :       Goto(&done);
     521             :       // No exception, return success
     522        1674 :       BIND(&done);
     523        1674 :       action(this);
     524        1674 :       ReturnFromBuiltin(a_.value());
     525        1860 :     }
     526         186 :   }
     527             : 
     528         217 :   void GenerateIteratingArrayBuiltinLoopContinuation(
     529             :       const CallResultProcessor& processor, const PostLoopAction& action,
     530         651 :       ForEachDirection direction = ForEachDirection::kForward) {
     531         434 :     Label loop(this, {&k_, &a_, &to_});
     532         217 :     Label after_loop(this);
     533         217 :     Goto(&loop);
     534         217 :     BIND(&loop);
     535             :     {
     536         217 :       if (direction == ForEachDirection::kForward) {
     537             :         // 8. Repeat, while k < len
     538         372 :         GotoIfNumberGreaterThanOrEqual(k(), len_, &after_loop);
     539             :       } else {
     540             :         // OR
     541             :         // 10. Repeat, while k >= 0
     542          62 :         GotoIfNumberGreaterThanOrEqual(SmiConstant(-1), k(), &after_loop);
     543             :       }
     544             : 
     545             :       Label done_element(this, &to_);
     546             :       // a. Let Pk be ToString(k).
     547             :       // We never have to perform a ToString conversion as the above guards
     548             :       // guarantee that we have a positive {k} which also is a valid array
     549             :       // index in the range [0, 2^32-1).
     550             :       CSA_ASSERT(this, IsNumberArrayIndex(k()));
     551             : 
     552             :       // b. Let kPresent be HasProperty(O, Pk).
     553             :       // c. ReturnIfAbrupt(kPresent).
     554         217 :       Node* k_present = HasProperty(o(), k(), context(), kHasProperty);
     555             : 
     556             :       // d. If kPresent is true, then
     557         434 :       GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element);
     558             : 
     559             :       // i. Let kValue be Get(O, Pk).
     560             :       // ii. ReturnIfAbrupt(kValue).
     561         217 :       Node* k_value = GetProperty(context(), o(), k());
     562             : 
     563             :       // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
     564             :       // iv. ReturnIfAbrupt(funcResult).
     565         217 :       a_.Bind(processor(this, k_value, k()));
     566         217 :       Goto(&done_element);
     567             : 
     568         217 :       BIND(&done_element);
     569             : 
     570         217 :       if (direction == ForEachDirection::kForward) {
     571             :         // e. Increase k by 1.
     572         186 :         k_.Bind(NumberInc(k()));
     573             :       } else {
     574             :         // e. Decrease k by 1.
     575          31 :         k_.Bind(NumberDec(k()));
     576             :       }
     577         217 :       Goto(&loop);
     578             :     }
     579         217 :     BIND(&after_loop);
     580             : 
     581         217 :     action(this);
     582         651 :     Return(a_.value());
     583         217 :   }
     584             : 
     585             :  private:
     586        1674 :   static ElementsKind ElementsKindForInstanceType(InstanceType type) {
     587        1674 :     switch (type) {
     588             : #define INSTANCE_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size) \
     589             :   case FIXED_##TYPE##_ARRAY_TYPE:                                     \
     590             :     return TYPE##_ELEMENTS;
     591             : 
     592         186 :       TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
     593             : #undef INSTANCE_TYPE_TO_ELEMENTS_KIND
     594             : 
     595             :       default:
     596           0 :         UNREACHABLE();
     597             :     }
     598             :   }
     599             : 
     600        1674 :   void VisitAllTypedArrayElements(Node* array_buffer,
     601             :                                   const CallResultProcessor& processor,
     602             :                                   Label* detached, ForEachDirection direction) {
     603        1674 :     VariableList list({&a_, &k_, &to_}, zone());
     604             : 
     605        1674 :     FastLoopBody body = [&](Node* index) {
     606        3348 :       GotoIf(IsDetachedBuffer(array_buffer), detached);
     607        5022 :       Node* elements = LoadElements(o_);
     608             :       Node* base_ptr =
     609        1674 :           LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
     610             :       Node* external_ptr =
     611             :           LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
     612        1674 :                           MachineType::Pointer());
     613        5022 :       Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
     614             :       Node* value = LoadFixedTypedArrayElementAsTagged(
     615        1674 :           data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
     616        1674 :       k_.Bind(index);
     617        1674 :       a_.Bind(processor(this, value, index));
     618        1674 :     };
     619        3348 :     Node* start = SmiConstant(0);
     620        1674 :     Node* end = len_;
     621             :     IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
     622             :     int incr = 1;
     623        1674 :     if (direction == ForEachDirection::kReverse) {
     624             :       std::swap(start, end);
     625             :       advance_mode = IndexAdvanceMode::kPre;
     626             :       incr = -1;
     627             :     }
     628             :     BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS,
     629        1674 :                   advance_mode);
     630        1674 :   }
     631             : 
     632         434 :   void VisitAllFastElementsOneKind(ElementsKind kind,
     633             :                                    const CallResultProcessor& processor,
     634             :                                    Label* array_changed, ParameterMode mode,
     635         868 :                                    ForEachDirection direction) {
     636         434 :     Comment("begin VisitAllFastElementsOneKind");
     637         434 :     VARIABLE(original_map, MachineRepresentation::kTagged);
     638         868 :     original_map.Bind(LoadMap(o()));
     639         434 :     VariableList list({&original_map, &a_, &k_, &to_}, zone());
     640         434 :     Node* start = IntPtrOrSmiConstant(0, mode);
     641             :     Node* end = TaggedToParameter(len(), mode);
     642             :     IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse
     643             :                                         ? IndexAdvanceMode::kPre
     644         434 :                                         : IndexAdvanceMode::kPost;
     645         434 :     if (direction == ForEachDirection::kReverse) std::swap(start, end);
     646             :     BuildFastLoop(
     647             :         list, start, end,
     648        1302 :         [=, &original_map](Node* index) {
     649        2170 :           k_.Bind(ParameterToTagged(index, mode));
     650        1302 :           Label one_element_done(this), hole_element(this);
     651             : 
     652             :           // Check if o's map has changed during the callback. If so, we have to
     653             :           // fall back to the slower spec implementation for the rest of the
     654             :           // iteration.
     655        1302 :           Node* o_map = LoadMap(o());
     656        1302 :           GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
     657             : 
     658             :           // Check if o's length has changed during the callback and if the
     659             :           // index is now out of range of the new length.
     660        1302 :           GotoIf(SmiGreaterThanOrEqual(k_.value(), LoadJSArrayLength(o())),
     661        1736 :                  array_changed);
     662             : 
     663             :           // Re-load the elements array. If may have been resized.
     664        1302 :           Node* elements = LoadElements(o());
     665             : 
     666             :           // Fast case: load the element directly from the elements FixedArray
     667             :           // and call the callback if the element is not the hole.
     668             :           DCHECK(kind == PACKED_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS);
     669         434 :           int base_size = kind == PACKED_ELEMENTS
     670             :                               ? FixedArray::kHeaderSize
     671         434 :                               : (FixedArray::kHeaderSize - kHeapObjectTag);
     672         434 :           Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
     673             :           Node* value = nullptr;
     674         434 :           if (kind == PACKED_ELEMENTS) {
     675         217 :             value = LoadObjectField(elements, offset);
     676         651 :             GotoIf(WordEqual(value, TheHoleConstant()), &hole_element);
     677             :           } else {
     678             :             Node* double_value =
     679         217 :                 LoadDoubleWithHoleCheck(elements, offset, &hole_element);
     680         434 :             value = AllocateHeapNumberWithValue(double_value);
     681             :           }
     682         868 :           a_.Bind(processor(this, value, k()));
     683         434 :           Goto(&one_element_done);
     684             : 
     685         434 :           BIND(&hole_element);
     686             :           // Check if o's prototype change unexpectedly has elements after the
     687             :           // callback in the case of a hole.
     688             :           BranchIfPrototypesHaveNoElements(o_map, &one_element_done,
     689         434 :                                            array_changed);
     690             : 
     691         434 :           BIND(&one_element_done);
     692         434 :         },
     693        1736 :         1, mode, advance_mode);
     694         434 :     Comment("end VisitAllFastElementsOneKind");
     695         434 :   }
     696             : 
     697         217 :   void HandleFastElements(const CallResultProcessor& processor,
     698             :                           const PostLoopAction& action, Label* slow,
     699         651 :                           ForEachDirection direction) {
     700         434 :     Label switch_on_elements_kind(this), fast_elements(this),
     701         217 :         maybe_double_elements(this), fast_double_elements(this);
     702             : 
     703         217 :     Comment("begin HandleFastElements");
     704             :     // Non-smi lengths must use the slow path.
     705         434 :     GotoIf(TaggedIsNotSmi(len()), slow);
     706             : 
     707             :     BranchIfFastJSArray(o(), context(),
     708         217 :                         &switch_on_elements_kind, slow);
     709             : 
     710         217 :     BIND(&switch_on_elements_kind);
     711             :     // Select by ElementsKind
     712         434 :     Node* o_map = LoadMap(o());
     713         434 :     Node* bit_field2 = LoadMapBitField2(o_map);
     714             :     Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
     715             :     Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
     716         434 :            &maybe_double_elements, &fast_elements);
     717             : 
     718             :     ParameterMode mode = OptimalParameterMode();
     719         217 :     BIND(&fast_elements);
     720             :     {
     721             :       VisitAllFastElementsOneKind(PACKED_ELEMENTS, processor, slow, mode,
     722         217 :                                   direction);
     723             : 
     724         217 :       action(this);
     725             : 
     726             :       // No exception, return success
     727         217 :       ReturnFromBuiltin(a_.value());
     728             :     }
     729             : 
     730         217 :     BIND(&maybe_double_elements);
     731             :     Branch(IsElementsKindGreaterThan(kind, HOLEY_DOUBLE_ELEMENTS), slow,
     732         434 :            &fast_double_elements);
     733             : 
     734         217 :     BIND(&fast_double_elements);
     735             :     {
     736             :       VisitAllFastElementsOneKind(PACKED_DOUBLE_ELEMENTS, processor, slow, mode,
     737         217 :                                   direction);
     738             : 
     739         217 :       action(this);
     740             : 
     741             :       // No exception, return success
     742         217 :       ReturnFromBuiltin(a_.value());
     743         217 :     }
     744         217 :   }
     745             : 
     746             :   // Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
     747             :   // This version is specialized to create a zero length array
     748             :   // of the elements kind of the input array.
     749         186 :   void ArraySpeciesCreate() {
     750          62 :     Label runtime(this, Label::kDeferred), done(this);
     751             : 
     752          31 :     TNode<Smi> len = SmiConstant(0);
     753          31 :     TNode<Map> original_map = LoadMap(o());
     754             :     GotoIfNot(
     755          31 :         InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE),
     756          93 :         &runtime);
     757             : 
     758             :     GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
     759          62 :               &runtime);
     760             : 
     761          62 :     Node* species_protector = SpeciesProtectorConstant();
     762             :     Node* value =
     763             :         LoadObjectField(species_protector, PropertyCell::kValueOffset);
     764             :     TNode<Smi> const protector_invalid =
     765          31 :         SmiConstant(Isolate::kProtectorInvalid);
     766          31 :     GotoIf(WordEqual(value, protector_invalid), &runtime);
     767             : 
     768             :     // Respect the ElementsKind of the input array.
     769          31 :     TNode<Int32T> elements_kind = LoadMapElementsKind(original_map);
     770          62 :     GotoIfNot(IsFastElementsKind(elements_kind), &runtime);
     771          31 :     TNode<Context> native_context = CAST(LoadNativeContext(context()));
     772             :     TNode<Map> array_map =
     773          31 :         CAST(LoadJSArrayElementsMap(elements_kind, native_context));
     774             :     TNode<JSArray> array =
     775          31 :         CAST(AllocateJSArray(GetInitialFastElementsKind(), array_map, len, len,
     776             :                              nullptr, CodeStubAssembler::SMI_PARAMETERS));
     777          31 :     a_.Bind(array);
     778             : 
     779          31 :     Goto(&done);
     780             : 
     781          31 :     BIND(&runtime);
     782             :     {
     783             :       // 5. Let A be ? ArraySpeciesCreate(O, len).
     784             :       Node* constructor =
     785             :           CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
     786             :       a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
     787          62 :                           constructor, len));
     788          31 :       Goto(&fully_spec_compliant_);
     789             :     }
     790             : 
     791          62 :     BIND(&done);
     792          31 :   }
     793             : 
     794             :   // Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
     795         186 :   void ArraySpeciesCreate(SloppyTNode<Smi> len) {
     796          62 :     Label runtime(this, Label::kDeferred), done(this);
     797             : 
     798          62 :     Node* const original_map = LoadMap(o());
     799             :     GotoIfNot(
     800          31 :         InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE),
     801          93 :         &runtime);
     802             : 
     803             :     GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
     804          62 :               &runtime);
     805             : 
     806          62 :     Node* species_protector = SpeciesProtectorConstant();
     807             :     Node* value =
     808             :         LoadObjectField(species_protector, PropertyCell::kValueOffset);
     809          62 :     Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
     810          62 :     GotoIf(WordEqual(value, protector_invalid), &runtime);
     811             : 
     812          62 :     GotoIfNot(TaggedIsPositiveSmi(len), &runtime);
     813             :     GotoIf(SmiAbove(len, SmiConstant(JSArray::kInitialMaxFastElementArray)),
     814          93 :            &runtime);
     815             : 
     816             :     // We need to be conservative and start with holey because the builtins
     817             :     // that create output arrays aren't guaranteed to be called for every
     818             :     // element in the input array (maybe the callback deletes an element).
     819             :     const ElementsKind elements_kind =
     820             :         GetHoleyElementsKind(GetInitialFastElementsKind());
     821          31 :     TNode<Context> native_context = CAST(LoadNativeContext(context()));
     822             :     TNode<Map> array_map =
     823          31 :         CAST(LoadJSArrayElementsMap(elements_kind, native_context));
     824             :     a_.Bind(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, len, len, nullptr,
     825          31 :                             CodeStubAssembler::SMI_PARAMETERS));
     826             : 
     827          31 :     Goto(&done);
     828             : 
     829          31 :     BIND(&runtime);
     830             :     {
     831             :       // 5. Let A be ? ArraySpeciesCreate(O, len).
     832             :       Node* constructor =
     833             :           CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
     834             :       a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
     835          62 :                           constructor, len));
     836          31 :       Goto(&fully_spec_compliant_);
     837             :     }
     838             : 
     839          62 :     BIND(&done);
     840          31 :   }
     841             : 
     842             :   Node* callbackfn_ = nullptr;
     843             :   Node* o_ = nullptr;
     844             :   Node* this_arg_ = nullptr;
     845             :   Node* len_ = nullptr;
     846             :   Node* context_ = nullptr;
     847             :   Node* receiver_ = nullptr;
     848             :   Node* new_target_ = nullptr;
     849             :   Node* argc_ = nullptr;
     850             :   Node* fast_typed_array_target_ = nullptr;
     851             :   const char* name_ = nullptr;
     852             :   Variable k_;
     853             :   Variable a_;
     854             :   Variable to_;
     855             :   Label fully_spec_compliant_;
     856             :   ElementsKind source_elements_kind_ = ElementsKind::NO_ELEMENTS;
     857             : };
     858             : 
     859          93 : TF_BUILTIN(FastArrayPop, CodeStubAssembler) {
     860             :   Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
     861             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     862             :   CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget),
     863             :                              UndefinedConstant()));
     864             : 
     865          93 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     866          62 :   Node* receiver = args.GetReceiver();
     867             : 
     868             :   Label runtime(this, Label::kDeferred);
     869          31 :   Label fast(this);
     870             : 
     871             :   // Only pop in this stub if
     872             :   // 1) the array has fast elements
     873             :   // 2) the length is writable,
     874             :   // 3) the elements backing store isn't copy-on-write,
     875             :   // 4) we aren't supposed to shrink the backing store.
     876             : 
     877             :   // 1) Check that the array has fast elements.
     878          31 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
     879             : 
     880          31 :   BIND(&fast);
     881             :   {
     882             :     CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(receiver)));
     883          62 :     Node* length = LoadAndUntagObjectField(receiver, JSArray::kLengthOffset);
     884          31 :     Label return_undefined(this), fast_elements(this);
     885          93 :     GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
     886             : 
     887             :     // 2) Ensure that the length is writable.
     888          62 :     EnsureArrayLengthWritable(LoadMap(receiver), &runtime);
     889             : 
     890             :     // 3) Check that the elements backing store isn't copy-on-write.
     891          62 :     Node* elements = LoadElements(receiver);
     892             :     GotoIf(WordEqual(LoadMap(elements),
     893          93 :                      LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
     894          31 :            &runtime);
     895             : 
     896          93 :     Node* new_length = IntPtrSub(length, IntPtrConstant(1));
     897             : 
     898             :     // 4) Check that we're not supposed to shrink the backing store, as
     899             :     //    implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
     900          93 :     Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
     901             :     GotoIf(IntPtrLessThan(
     902          31 :                IntPtrAdd(IntPtrAdd(new_length, new_length),
     903         124 :                          IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
     904          93 :                capacity),
     905          62 :            &runtime);
     906             : 
     907             :     StoreObjectFieldNoWriteBarrier(receiver, JSArray::kLengthOffset,
     908          62 :                                    SmiTag(new_length));
     909             : 
     910          93 :     Node* elements_kind = LoadMapElementsKind(LoadMap(receiver));
     911             :     GotoIf(Int32LessThanOrEqual(elements_kind,
     912          62 :                                 Int32Constant(TERMINAL_FAST_ELEMENTS_KIND)),
     913          62 :            &fast_elements);
     914             : 
     915             :     Node* value = LoadFixedDoubleArrayElement(
     916             :         elements, new_length, MachineType::Float64(), 0, INTPTR_PARAMETERS,
     917          31 :         &return_undefined);
     918             : 
     919             :     int32_t header_size = FixedDoubleArray::kHeaderSize - kHeapObjectTag;
     920             :     Node* offset = ElementOffsetFromIndex(new_length, HOLEY_DOUBLE_ELEMENTS,
     921          31 :                                           INTPTR_PARAMETERS, header_size);
     922          31 :     if (Is64()) {
     923          62 :       Node* double_hole = Int64Constant(kHoleNanInt64);
     924             :       StoreNoWriteBarrier(MachineRepresentation::kWord64, elements, offset,
     925          31 :                           double_hole);
     926             :     } else {
     927             :       STATIC_ASSERT(kHoleNanLower32 == kHoleNanUpper32);
     928           0 :       Node* double_hole = Int32Constant(kHoleNanLower32);
     929             :       StoreNoWriteBarrier(MachineRepresentation::kWord32, elements, offset,
     930           0 :                           double_hole);
     931             :       StoreNoWriteBarrier(MachineRepresentation::kWord32, elements,
     932           0 :                           IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
     933           0 :                           double_hole);
     934             :     }
     935          62 :     args.PopAndReturn(AllocateHeapNumberWithValue(value));
     936             : 
     937          31 :     BIND(&fast_elements);
     938             :     {
     939          31 :       Node* value = LoadFixedArrayElement(elements, new_length);
     940          62 :       StoreFixedArrayElement(elements, new_length, TheHoleConstant());
     941          62 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
     942          31 :       args.PopAndReturn(value);
     943             :     }
     944             : 
     945          31 :     BIND(&return_undefined);
     946          93 :     { args.PopAndReturn(UndefinedConstant()); }
     947             :   }
     948             : 
     949          31 :   BIND(&runtime);
     950             :   {
     951             :     Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
     952          31 :                                  MachineType::TaggedPointer());
     953             :     TailCallStub(CodeFactory::ArrayPop(isolate()), context, target,
     954          62 :                  UndefinedConstant(), argc);
     955          31 :   }
     956          31 : }
     957             : 
     958         124 : TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
     959          31 :   TVARIABLE(IntPtrT, arg_index);
     960          31 :   Label default_label(this, &arg_index);
     961          31 :   Label smi_transition(this);
     962          31 :   Label object_push_pre(this);
     963          31 :   Label object_push(this, &arg_index);
     964          31 :   Label double_push(this, &arg_index);
     965          31 :   Label double_transition(this);
     966          31 :   Label runtime(this, Label::kDeferred);
     967             : 
     968             :   // TODO(ishell): use constants from Descriptor once the JSFunction linkage
     969             :   // arguments are reordered.
     970             :   Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
     971             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     972             :   CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget),
     973             :                              UndefinedConstant()));
     974             : 
     975          93 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     976          62 :   Node* receiver = args.GetReceiver();
     977             :   Node* kind = nullptr;
     978             : 
     979          31 :   Label fast(this);
     980          31 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
     981             : 
     982          31 :   BIND(&fast);
     983             :   {
     984          31 :     arg_index = IntPtrConstant(0);
     985          31 :     kind = EnsureArrayPushable(receiver, &runtime);
     986             :     GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
     987          62 :            &object_push_pre);
     988             : 
     989             :     Node* new_length = BuildAppendJSArray(PACKED_SMI_ELEMENTS, receiver, &args,
     990          62 :                                           &arg_index, &smi_transition);
     991          31 :     args.PopAndReturn(new_length);
     992             :   }
     993             : 
     994             :   // If the argument is not a smi, then use a heavyweight SetProperty to
     995             :   // transition the array for only the single next element. If the argument is
     996             :   // a smi, the failure is due to some other reason and we should fall back on
     997             :   // the most generic implementation for the rest of the array.
     998          31 :   BIND(&smi_transition);
     999             :   {
    1000          62 :     Node* arg = args.AtIndex(arg_index);
    1001          62 :     GotoIf(TaggedIsSmi(arg), &default_label);
    1002          62 :     Node* length = LoadJSArrayLength(receiver);
    1003             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
    1004             :     // calling into the runtime to do the elements transition is overkill.
    1005             :     CallRuntime(Runtime::kSetProperty, context, receiver, length, arg,
    1006          31 :                 SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
    1007          31 :     Increment(&arg_index);
    1008             :     // The runtime SetProperty call could have converted the array to dictionary
    1009             :     // mode, which must be detected to abort the fast-path.
    1010          62 :     Node* map = LoadMap(receiver);
    1011          62 :     Node* bit_field2 = LoadMapBitField2(map);
    1012             :     Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
    1013          62 :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
    1014          62 :            &default_label);
    1015             : 
    1016          31 :     GotoIfNotNumber(arg, &object_push);
    1017          31 :     Goto(&double_push);
    1018             :   }
    1019             : 
    1020          31 :   BIND(&object_push_pre);
    1021             :   {
    1022             :     Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &double_push,
    1023          62 :            &object_push);
    1024             :   }
    1025             : 
    1026          31 :   BIND(&object_push);
    1027             :   {
    1028             :     Node* new_length = BuildAppendJSArray(PACKED_ELEMENTS, receiver, &args,
    1029          62 :                                           &arg_index, &default_label);
    1030          31 :     args.PopAndReturn(new_length);
    1031             :   }
    1032             : 
    1033          31 :   BIND(&double_push);
    1034             :   {
    1035             :     Node* new_length =
    1036             :         BuildAppendJSArray(PACKED_DOUBLE_ELEMENTS, receiver, &args, &arg_index,
    1037          62 :                            &double_transition);
    1038          31 :     args.PopAndReturn(new_length);
    1039             :   }
    1040             : 
    1041             :   // If the argument is not a double, then use a heavyweight SetProperty to
    1042             :   // transition the array for only the single next element. If the argument is
    1043             :   // a double, the failure is due to some other reason and we should fall back
    1044             :   // on the most generic implementation for the rest of the array.
    1045          31 :   BIND(&double_transition);
    1046             :   {
    1047          62 :     Node* arg = args.AtIndex(arg_index);
    1048          31 :     GotoIfNumber(arg, &default_label);
    1049          62 :     Node* length = LoadJSArrayLength(receiver);
    1050             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
    1051             :     // calling into the runtime to do the elements transition is overkill.
    1052             :     CallRuntime(Runtime::kSetProperty, context, receiver, length, arg,
    1053          31 :                 SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
    1054          31 :     Increment(&arg_index);
    1055             :     // The runtime SetProperty call could have converted the array to dictionary
    1056             :     // mode, which must be detected to abort the fast-path.
    1057          62 :     Node* map = LoadMap(receiver);
    1058          62 :     Node* bit_field2 = LoadMapBitField2(map);
    1059             :     Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
    1060          62 :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
    1061          62 :            &default_label);
    1062          31 :     Goto(&object_push);
    1063             :   }
    1064             : 
    1065             :   // Fallback that stores un-processed arguments using the full, heavyweight
    1066             :   // SetProperty machinery.
    1067          31 :   BIND(&default_label);
    1068             :   {
    1069             :     args.ForEach(
    1070          31 :         [this, receiver, context](Node* arg) {
    1071          93 :           Node* length = LoadJSArrayLength(receiver);
    1072             :           CallRuntime(Runtime::kSetProperty, context, receiver, length, arg,
    1073          31 :                       SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
    1074          31 :         },
    1075          62 :         arg_index);
    1076          62 :     args.PopAndReturn(LoadJSArrayLength(receiver));
    1077             :   }
    1078             : 
    1079          31 :   BIND(&runtime);
    1080             :   {
    1081             :     Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
    1082          31 :                                  MachineType::TaggedPointer());
    1083             :     TailCallStub(CodeFactory::ArrayPush(isolate()), context, target,
    1084          62 :                  UndefinedConstant(), argc);
    1085             :   }
    1086          31 : }
    1087             : 
    1088          93 : TF_BUILTIN(FastArrayShift, CodeStubAssembler) {
    1089             :   Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
    1090             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1091             :   CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget),
    1092             :                              UndefinedConstant()));
    1093             : 
    1094          93 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
    1095          62 :   Node* receiver = args.GetReceiver();
    1096             : 
    1097             :   Label runtime(this, Label::kDeferred);
    1098          31 :   Label fast(this);
    1099             : 
    1100             :   // Only shift in this stub if
    1101             :   // 1) the array has fast elements
    1102             :   // 2) the length is writable,
    1103             :   // 3) the elements backing store isn't copy-on-write,
    1104             :   // 4) we aren't supposed to shrink the backing store,
    1105             :   // 5) we aren't supposed to left-trim the backing store.
    1106             : 
    1107             :   // 1) Check that the array has fast elements.
    1108          31 :   BranchIfFastJSArray(receiver, context, &fast, &runtime);
    1109             : 
    1110          31 :   BIND(&fast);
    1111             :   {
    1112             :     CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(receiver)));
    1113          62 :     Node* length = LoadAndUntagObjectField(receiver, JSArray::kLengthOffset);
    1114          31 :     Label return_undefined(this), fast_elements_tagged(this),
    1115          31 :         fast_elements_smi(this);
    1116          93 :     GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
    1117             : 
    1118             :     // 2) Ensure that the length is writable.
    1119          62 :     EnsureArrayLengthWritable(LoadMap(receiver), &runtime);
    1120             : 
    1121             :     // 3) Check that the elements backing store isn't copy-on-write.
    1122          62 :     Node* elements = LoadElements(receiver);
    1123             :     GotoIf(WordEqual(LoadMap(elements),
    1124          93 :                      LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
    1125          31 :            &runtime);
    1126             : 
    1127          93 :     Node* new_length = IntPtrSub(length, IntPtrConstant(1));
    1128             : 
    1129             :     // 4) Check that we're not supposed to right-trim the backing store, as
    1130             :     //    implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
    1131         124 :     Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
    1132             :     GotoIf(IntPtrLessThan(
    1133          31 :                IntPtrAdd(IntPtrAdd(new_length, new_length),
    1134         124 :                          IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
    1135          93 :                capacity),
    1136          62 :            &runtime);
    1137             : 
    1138             :     // 5) Check that we're not supposed to left-trim the backing store, as
    1139             :     //    implemented in elements.cc:FastElementsAccessor::MoveElements.
    1140             :     GotoIf(IntPtrGreaterThan(new_length,
    1141          62 :                              IntPtrConstant(JSArray::kMaxCopyElements)),
    1142          62 :            &runtime);
    1143             : 
    1144             :     StoreObjectFieldNoWriteBarrier(receiver, JSArray::kLengthOffset,
    1145          62 :                                    SmiTag(new_length));
    1146             : 
    1147          93 :     Node* elements_kind = LoadMapElementsKind(LoadMap(receiver));
    1148             :     GotoIf(
    1149          62 :         Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_SMI_ELEMENTS)),
    1150          62 :         &fast_elements_smi);
    1151          62 :     GotoIf(Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
    1152          62 :            &fast_elements_tagged);
    1153             : 
    1154             :     // Fast double elements kind:
    1155             :     {
    1156             :       CSA_ASSERT(this,
    1157             :                  Int32LessThanOrEqual(elements_kind,
    1158             :                                       Int32Constant(HOLEY_DOUBLE_ELEMENTS)));
    1159             : 
    1160          62 :       VARIABLE(result, MachineRepresentation::kTagged, UndefinedConstant());
    1161             : 
    1162          31 :       Label move_elements(this);
    1163             :       result.Bind(AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement(
    1164             :           elements, IntPtrConstant(0), MachineType::Float64(), 0,
    1165         124 :           INTPTR_PARAMETERS, &move_elements)));
    1166          31 :       Goto(&move_elements);
    1167          31 :       BIND(&move_elements);
    1168             : 
    1169             :       int32_t header_size = FixedDoubleArray::kHeaderSize - kHeapObjectTag;
    1170             :       Node* memmove =
    1171          62 :           ExternalConstant(ExternalReference::libc_memmove_function(isolate()));
    1172             :       Node* start = IntPtrAdd(
    1173          62 :           BitcastTaggedToWord(elements),
    1174             :           ElementOffsetFromIndex(IntPtrConstant(0), HOLEY_DOUBLE_ELEMENTS,
    1175         186 :                                  INTPTR_PARAMETERS, header_size));
    1176             :       CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
    1177             :                      MachineType::Pointer(), MachineType::UintPtr(), memmove,
    1178          62 :                      start, IntPtrAdd(start, IntPtrConstant(kDoubleSize)),
    1179         155 :                      IntPtrMul(new_length, IntPtrConstant(kDoubleSize)));
    1180             :       Node* offset = ElementOffsetFromIndex(new_length, HOLEY_DOUBLE_ELEMENTS,
    1181          31 :                                             INTPTR_PARAMETERS, header_size);
    1182          31 :       if (Is64()) {
    1183          62 :         Node* double_hole = Int64Constant(kHoleNanInt64);
    1184             :         StoreNoWriteBarrier(MachineRepresentation::kWord64, elements, offset,
    1185          31 :                             double_hole);
    1186             :       } else {
    1187             :         STATIC_ASSERT(kHoleNanLower32 == kHoleNanUpper32);
    1188           0 :         Node* double_hole = Int32Constant(kHoleNanLower32);
    1189             :         StoreNoWriteBarrier(MachineRepresentation::kWord32, elements, offset,
    1190           0 :                             double_hole);
    1191             :         StoreNoWriteBarrier(MachineRepresentation::kWord32, elements,
    1192           0 :                             IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
    1193           0 :                             double_hole);
    1194             :       }
    1195          62 :       args.PopAndReturn(result.value());
    1196             :     }
    1197             : 
    1198          31 :     BIND(&fast_elements_tagged);
    1199             :     {
    1200          31 :       Node* value = LoadFixedArrayElement(elements, 0);
    1201             :       BuildFastLoop(IntPtrConstant(0), new_length,
    1202          31 :                     [&](Node* index) {
    1203             :                       StoreFixedArrayElement(
    1204             :                           elements, index,
    1205             :                           LoadFixedArrayElement(
    1206          93 :                               elements, IntPtrAdd(index, IntPtrConstant(1))));
    1207          31 :                     },
    1208             :                     1, ParameterMode::INTPTR_PARAMETERS,
    1209          93 :                     IndexAdvanceMode::kPost);
    1210          62 :       StoreFixedArrayElement(elements, new_length, TheHoleConstant());
    1211          62 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
    1212          31 :       args.PopAndReturn(value);
    1213             :     }
    1214             : 
    1215          31 :     BIND(&fast_elements_smi);
    1216             :     {
    1217          31 :       Node* value = LoadFixedArrayElement(elements, 0);
    1218             :       BuildFastLoop(IntPtrConstant(0), new_length,
    1219          31 :                     [&](Node* index) {
    1220             :                       StoreFixedArrayElement(
    1221             :                           elements, index,
    1222             :                           LoadFixedArrayElement(
    1223          93 :                               elements, IntPtrAdd(index, IntPtrConstant(1))),
    1224          62 :                           SKIP_WRITE_BARRIER);
    1225          31 :                     },
    1226             :                     1, ParameterMode::INTPTR_PARAMETERS,
    1227          93 :                     IndexAdvanceMode::kPost);
    1228          62 :       StoreFixedArrayElement(elements, new_length, TheHoleConstant());
    1229          62 :       GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
    1230          31 :       args.PopAndReturn(value);
    1231             :     }
    1232             : 
    1233          31 :     BIND(&return_undefined);
    1234          93 :     { args.PopAndReturn(UndefinedConstant()); }
    1235             :   }
    1236             : 
    1237          31 :   BIND(&runtime);
    1238             :   {
    1239             :     Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
    1240          31 :                                  MachineType::TaggedPointer());
    1241             :     TailCallStub(CodeFactory::ArrayShift(isolate()), context, target,
    1242          62 :                  UndefinedConstant(), argc);
    1243          31 :   }
    1244          31 : }
    1245             : 
    1246          62 : TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1247             :   Node* context = Parameter(Descriptor::kContext);
    1248             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1249             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1250             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1251             :   Node* array = Parameter(Descriptor::kArray);
    1252             :   Node* object = Parameter(Descriptor::kObject);
    1253             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1254             :   Node* len = Parameter(Descriptor::kLength);
    1255             :   Node* to = Parameter(Descriptor::kTo);
    1256             : 
    1257             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1258             :                                             this_arg, array, object, initial_k,
    1259             :                                             len, to);
    1260             : 
    1261             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1262             :       &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
    1263          93 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1264          31 : }
    1265             : 
    1266          62 : TF_BUILTIN(ArrayForEachLoopEagerDeoptContinuation,
    1267             :            ArrayBuiltinCodeStubAssembler) {
    1268             :   Node* context = Parameter(Descriptor::kContext);
    1269             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1270             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1271             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1272             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1273             :   Node* len = Parameter(Descriptor::kLength);
    1274             : 
    1275             :   Callable stub(Builtins::CallableFor(isolate(),
    1276          31 :                                       Builtins::kArrayForEachLoopContinuation));
    1277             :   Return(CallStub(stub, context, receiver, callbackfn, this_arg,
    1278             :                   UndefinedConstant(), receiver, initial_k, len,
    1279          62 :                   UndefinedConstant()));
    1280          31 : }
    1281             : 
    1282          62 : TF_BUILTIN(ArrayForEachLoopLazyDeoptContinuation,
    1283             :            ArrayBuiltinCodeStubAssembler) {
    1284             :   Node* context = Parameter(Descriptor::kContext);
    1285             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1286             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1287             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1288             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1289             :   Node* len = Parameter(Descriptor::kLength);
    1290             : 
    1291             :   Callable stub(Builtins::CallableFor(isolate(),
    1292          31 :                                       Builtins::kArrayForEachLoopContinuation));
    1293             :   Return(CallStub(stub, context, receiver, callbackfn, this_arg,
    1294             :                   UndefinedConstant(), receiver, initial_k, len,
    1295          62 :                   UndefinedConstant()));
    1296          31 : }
    1297             : 
    1298          93 : TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) {
    1299             :   Node* argc =
    1300          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1301          31 :   CodeStubArguments args(this, argc);
    1302             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1303             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1304          62 :   Node* receiver = args.GetReceiver();
    1305          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1306          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1307             : 
    1308             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1309             :                                 new_target, argc);
    1310             : 
    1311             :   GenerateIteratingArrayBuiltinBody(
    1312             :       "Array.prototype.forEach",
    1313             :       &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator,
    1314             :       &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
    1315             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1316             :       Builtins::CallableFor(isolate(),
    1317         155 :                             Builtins::kArrayForEachLoopContinuation));
    1318          31 : }
    1319             : 
    1320          93 : TF_BUILTIN(TypedArrayPrototypeForEach, ArrayBuiltinCodeStubAssembler) {
    1321             :   Node* argc =
    1322          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1323          31 :   CodeStubArguments args(this, argc);
    1324             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1325             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1326          62 :   Node* receiver = args.GetReceiver();
    1327          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1328          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1329             : 
    1330             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1331             :                                 new_target, argc);
    1332             : 
    1333             :   GenerateIteratingTypedArrayBuiltinBody(
    1334             :       "%TypedArray%.prototype.forEach",
    1335             :       &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator,
    1336             :       &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
    1337         124 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1338          31 : }
    1339             : 
    1340          62 : TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1341             :   Node* context = Parameter(Descriptor::kContext);
    1342             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1343             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1344             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1345             :   Node* array = Parameter(Descriptor::kArray);
    1346             :   Node* object = Parameter(Descriptor::kObject);
    1347             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1348             :   Node* len = Parameter(Descriptor::kLength);
    1349             :   Node* to = Parameter(Descriptor::kTo);
    1350             : 
    1351             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1352             :                                             this_arg, array, object, initial_k,
    1353             :                                             len, to);
    1354             : 
    1355             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1356             :       &ArrayBuiltinCodeStubAssembler::SomeProcessor,
    1357          93 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1358          31 : }
    1359             : 
    1360          93 : TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) {
    1361             :   Node* argc =
    1362          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1363          31 :   CodeStubArguments args(this, argc);
    1364             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1365             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1366          62 :   Node* receiver = args.GetReceiver();
    1367          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1368          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1369             : 
    1370             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1371             :                                 new_target, argc);
    1372             : 
    1373             :   GenerateIteratingArrayBuiltinBody(
    1374             :       "Array.prototype.some",
    1375             :       &ArrayBuiltinCodeStubAssembler::SomeResultGenerator,
    1376             :       &ArrayBuiltinCodeStubAssembler::SomeProcessor,
    1377             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1378         155 :       Builtins::CallableFor(isolate(), Builtins::kArraySomeLoopContinuation));
    1379          31 : }
    1380             : 
    1381          93 : TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinCodeStubAssembler) {
    1382             :   Node* argc =
    1383          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1384          31 :   CodeStubArguments args(this, argc);
    1385             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1386             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1387          62 :   Node* receiver = args.GetReceiver();
    1388          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1389          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1390             : 
    1391             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1392             :                                 new_target, argc);
    1393             : 
    1394             :   GenerateIteratingTypedArrayBuiltinBody(
    1395             :       "%TypedArray%.prototype.some",
    1396             :       &ArrayBuiltinCodeStubAssembler::SomeResultGenerator,
    1397             :       &ArrayBuiltinCodeStubAssembler::SomeProcessor,
    1398         124 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1399          31 : }
    1400             : 
    1401          62 : TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1402             :   Node* context = Parameter(Descriptor::kContext);
    1403             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1404             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1405             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1406             :   Node* array = Parameter(Descriptor::kArray);
    1407             :   Node* object = Parameter(Descriptor::kObject);
    1408             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1409             :   Node* len = Parameter(Descriptor::kLength);
    1410             :   Node* to = Parameter(Descriptor::kTo);
    1411             : 
    1412             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1413             :                                             this_arg, array, object, initial_k,
    1414             :                                             len, to);
    1415             : 
    1416             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1417             :       &ArrayBuiltinCodeStubAssembler::EveryProcessor,
    1418          93 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1419          31 : }
    1420             : 
    1421          93 : TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) {
    1422             :   Node* argc =
    1423          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1424          31 :   CodeStubArguments args(this, argc);
    1425             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1426             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1427          62 :   Node* receiver = args.GetReceiver();
    1428          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1429          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1430             : 
    1431             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1432             :                                 new_target, argc);
    1433             : 
    1434             :   GenerateIteratingArrayBuiltinBody(
    1435             :       "Array.prototype.every",
    1436             :       &ArrayBuiltinCodeStubAssembler::EveryResultGenerator,
    1437             :       &ArrayBuiltinCodeStubAssembler::EveryProcessor,
    1438             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1439         155 :       Builtins::CallableFor(isolate(), Builtins::kArrayEveryLoopContinuation));
    1440          31 : }
    1441             : 
    1442          93 : TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinCodeStubAssembler) {
    1443             :   Node* argc =
    1444          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1445          31 :   CodeStubArguments args(this, argc);
    1446             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1447             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1448          62 :   Node* receiver = args.GetReceiver();
    1449          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1450          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1451             : 
    1452             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1453             :                                 new_target, argc);
    1454             : 
    1455             :   GenerateIteratingTypedArrayBuiltinBody(
    1456             :       "%TypedArray%.prototype.every",
    1457             :       &ArrayBuiltinCodeStubAssembler::EveryResultGenerator,
    1458             :       &ArrayBuiltinCodeStubAssembler::EveryProcessor,
    1459         124 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1460          31 : }
    1461             : 
    1462          62 : TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1463             :   Node* context = Parameter(Descriptor::kContext);
    1464             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1465             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1466             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1467             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    1468             :   Node* object = Parameter(Descriptor::kObject);
    1469             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1470             :   Node* len = Parameter(Descriptor::kLength);
    1471             :   Node* to = Parameter(Descriptor::kTo);
    1472             : 
    1473             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1474             :                                             this_arg, accumulator, object,
    1475             :                                             initial_k, len, to);
    1476             : 
    1477             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1478             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1479          93 :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
    1480          31 : }
    1481             : 
    1482          93 : TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) {
    1483             :   Node* argc =
    1484          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1485          31 :   CodeStubArguments args(this, argc);
    1486             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1487             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1488          62 :   Node* receiver = args.GetReceiver();
    1489          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1490          93 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    1491             : 
    1492             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1493             :                                 new_target, argc);
    1494             : 
    1495             :   GenerateIteratingArrayBuiltinBody(
    1496             :       "Array.prototype.reduce",
    1497             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1498             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1499             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1500         155 :       Builtins::CallableFor(isolate(), Builtins::kArrayReduceLoopContinuation));
    1501          31 : }
    1502             : 
    1503          93 : TF_BUILTIN(TypedArrayPrototypeReduce, ArrayBuiltinCodeStubAssembler) {
    1504             :   Node* argc =
    1505          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1506          31 :   CodeStubArguments args(this, argc);
    1507             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1508             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1509          62 :   Node* receiver = args.GetReceiver();
    1510          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1511          93 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    1512             : 
    1513             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1514             :                                 new_target, argc);
    1515             : 
    1516             :   GenerateIteratingTypedArrayBuiltinBody(
    1517             :       "%TypedArray%.prototype.reduce",
    1518             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1519             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1520         124 :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
    1521          31 : }
    1522             : 
    1523          62 : TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1524             :   Node* context = Parameter(Descriptor::kContext);
    1525             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1526             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1527             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1528             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    1529             :   Node* object = Parameter(Descriptor::kObject);
    1530             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1531             :   Node* len = Parameter(Descriptor::kLength);
    1532             :   Node* to = Parameter(Descriptor::kTo);
    1533             : 
    1534             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1535             :                                             this_arg, accumulator, object,
    1536             :                                             initial_k, len, to);
    1537             : 
    1538             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1539             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1540             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1541          93 :       ForEachDirection::kReverse);
    1542          31 : }
    1543             : 
    1544          93 : TF_BUILTIN(ArrayReduceRight, ArrayBuiltinCodeStubAssembler) {
    1545             :   Node* argc =
    1546          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1547          31 :   CodeStubArguments args(this, argc);
    1548             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1549             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1550          62 :   Node* receiver = args.GetReceiver();
    1551          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1552          93 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    1553             : 
    1554             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1555             :                                 new_target, argc);
    1556             : 
    1557             :   GenerateIteratingArrayBuiltinBody(
    1558             :       "Array.prototype.reduceRight",
    1559             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1560             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1561             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1562             :       Builtins::CallableFor(isolate(),
    1563             :                             Builtins::kArrayReduceRightLoopContinuation),
    1564         155 :       ForEachDirection::kReverse);
    1565          31 : }
    1566             : 
    1567          93 : TF_BUILTIN(TypedArrayPrototypeReduceRight, ArrayBuiltinCodeStubAssembler) {
    1568             :   Node* argc =
    1569          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1570          31 :   CodeStubArguments args(this, argc);
    1571             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1572             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1573          62 :   Node* receiver = args.GetReceiver();
    1574          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1575          93 :   Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
    1576             : 
    1577             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1578             :                                 new_target, argc);
    1579             : 
    1580             :   GenerateIteratingTypedArrayBuiltinBody(
    1581             :       "%TypedArray%.prototype.reduceRight",
    1582             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1583             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1584             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1585         124 :       ForEachDirection::kReverse);
    1586          31 : }
    1587             : 
    1588          62 : TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1589             :   Node* context = Parameter(Descriptor::kContext);
    1590             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1591             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1592             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1593             :   Node* array = Parameter(Descriptor::kArray);
    1594             :   Node* object = Parameter(Descriptor::kObject);
    1595             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1596             :   Node* len = Parameter(Descriptor::kLength);
    1597             :   Node* to = Parameter(Descriptor::kTo);
    1598             : 
    1599             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1600             :                                             this_arg, array, object, initial_k,
    1601             :                                             len, to);
    1602             : 
    1603             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1604             :       &ArrayBuiltinCodeStubAssembler::FilterProcessor,
    1605          93 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1606          31 : }
    1607             : 
    1608          93 : TF_BUILTIN(ArrayFilter, ArrayBuiltinCodeStubAssembler) {
    1609             :   Node* argc =
    1610          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1611          31 :   CodeStubArguments args(this, argc);
    1612             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1613             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1614          62 :   Node* receiver = args.GetReceiver();
    1615          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1616          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1617             : 
    1618             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1619             :                                 new_target, argc);
    1620             : 
    1621             :   GenerateIteratingArrayBuiltinBody(
    1622             :       "Array.prototype.filter",
    1623             :       &ArrayBuiltinCodeStubAssembler::FilterResultGenerator,
    1624             :       &ArrayBuiltinCodeStubAssembler::FilterProcessor,
    1625             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1626         155 :       Builtins::CallableFor(isolate(), Builtins::kArrayFilterLoopContinuation));
    1627          31 : }
    1628             : 
    1629          62 : TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1630             :   Node* context = Parameter(Descriptor::kContext);
    1631             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1632             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1633             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1634             :   Node* array = Parameter(Descriptor::kArray);
    1635             :   Node* object = Parameter(Descriptor::kObject);
    1636             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1637             :   Node* len = Parameter(Descriptor::kLength);
    1638             :   Node* to = Parameter(Descriptor::kTo);
    1639             : 
    1640             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1641             :                                             this_arg, array, object, initial_k,
    1642             :                                             len, to);
    1643             : 
    1644             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1645             :       &ArrayBuiltinCodeStubAssembler::SpecCompliantMapProcessor,
    1646          93 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1647          31 : }
    1648             : 
    1649          62 : TF_BUILTIN(ArrayMapLoopEagerDeoptContinuation, ArrayBuiltinCodeStubAssembler) {
    1650             :   Node* context = Parameter(Descriptor::kContext);
    1651             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1652             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1653             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1654             :   Node* array = Parameter(Descriptor::kArray);
    1655             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1656             :   Node* len = Parameter(Descriptor::kLength);
    1657             : 
    1658             :   Callable stub(
    1659          31 :       Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation));
    1660             :   Return(CallStub(stub, context, receiver, callbackfn, this_arg, array,
    1661          62 :                   receiver, initial_k, len, UndefinedConstant()));
    1662          31 : }
    1663             : 
    1664          62 : TF_BUILTIN(ArrayMapLoopLazyDeoptContinuation, ArrayBuiltinCodeStubAssembler) {
    1665             :   Node* context = Parameter(Descriptor::kContext);
    1666             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1667             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1668             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1669             :   Node* array = Parameter(Descriptor::kArray);
    1670             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1671             :   Node* len = Parameter(Descriptor::kLength);
    1672             :   Node* result = Parameter(Descriptor::kResult);
    1673             : 
    1674             :   // This custom lazy deopt point is right after the callback. map() needs
    1675             :   // to pick up at the next step, which is setting the callback result in
    1676             :   // the output array. After incrementing k, we can glide into the loop
    1677             :   // continuation builtin.
    1678             : 
    1679             :   // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
    1680             :   CallRuntime(Runtime::kCreateDataProperty, context, array, initial_k, result);
    1681             :   // Then we have to increment k before going on.
    1682          31 :   initial_k = NumberInc(initial_k);
    1683             : 
    1684             :   Callable stub(
    1685          31 :       Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation));
    1686             :   Return(CallStub(stub, context, receiver, callbackfn, this_arg, array,
    1687          62 :                   receiver, initial_k, len, UndefinedConstant()));
    1688          31 : }
    1689             : 
    1690          93 : TF_BUILTIN(ArrayMap, ArrayBuiltinCodeStubAssembler) {
    1691             :   Node* argc =
    1692          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1693          31 :   CodeStubArguments args(this, argc);
    1694             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1695             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1696          62 :   Node* receiver = args.GetReceiver();
    1697          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1698          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1699             : 
    1700             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1701             :                                 new_target, argc);
    1702             : 
    1703             :   GenerateIteratingArrayBuiltinBody(
    1704             :       "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator,
    1705             :       &ArrayBuiltinCodeStubAssembler::FastMapProcessor,
    1706             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1707         155 :       Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation));
    1708          31 : }
    1709             : 
    1710          93 : TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinCodeStubAssembler) {
    1711             :   Node* argc =
    1712          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1713          31 :   CodeStubArguments args(this, argc);
    1714             :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1715             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
    1716          62 :   Node* receiver = args.GetReceiver();
    1717          62 :   Node* callbackfn = args.GetOptionalArgumentValue(0);
    1718          62 :   Node* this_arg = args.GetOptionalArgumentValue(1);
    1719             : 
    1720             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1721             :                                 new_target, argc);
    1722             : 
    1723             :   GenerateIteratingTypedArrayBuiltinBody(
    1724             :       "%TypedArray%.prototype.map",
    1725             :       &ArrayBuiltinCodeStubAssembler::TypedArrayMapResultGenerator,
    1726             :       &ArrayBuiltinCodeStubAssembler::TypedArrayMapProcessor,
    1727         124 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1728          31 : }
    1729             : 
    1730          93 : TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
    1731             :   TNode<Object> object = CAST(Parameter(Descriptor::kArg));
    1732             :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    1733             : 
    1734          31 :   Label call_runtime(this), return_true(this), return_false(this);
    1735             : 
    1736          62 :   GotoIf(TaggedIsSmi(object), &return_false);
    1737          62 :   TNode<Word32T> instance_type = LoadInstanceType(CAST(object));
    1738             : 
    1739          62 :   GotoIf(InstanceTypeEqual(instance_type, JS_ARRAY_TYPE), &return_true);
    1740             : 
    1741             :   // TODO(verwaest): Handle proxies in-place.
    1742             :   Branch(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), &call_runtime,
    1743          62 :          &return_false);
    1744             : 
    1745          31 :   BIND(&return_true);
    1746          62 :   Return(BooleanConstant(true));
    1747             : 
    1748          31 :   BIND(&return_false);
    1749          62 :   Return(BooleanConstant(false));
    1750             : 
    1751          31 :   BIND(&call_runtime);
    1752          62 :   Return(CallRuntime(Runtime::kArrayIsArray, context, object));
    1753          31 : }
    1754             : 
    1755             : class ArrayIncludesIndexofAssembler : public CodeStubAssembler {
    1756             :  public:
    1757             :   explicit ArrayIncludesIndexofAssembler(compiler::CodeAssemblerState* state)
    1758          62 :       : CodeStubAssembler(state) {}
    1759             : 
    1760             :   enum SearchVariant { kIncludes, kIndexOf };
    1761             : 
    1762             :   void Generate(SearchVariant variant);
    1763             : };
    1764             : 
    1765          62 : void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant) {
    1766             :   const int kSearchElementArg = 0;
    1767             :   const int kFromIndexArg = 1;
    1768             : 
    1769             :   TNode<IntPtrT> argc =
    1770         124 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
    1771          62 :   CodeStubArguments args(this, argc);
    1772             : 
    1773          62 :   TNode<Object> receiver = args.GetReceiver();
    1774             :   TNode<Object> search_element =
    1775          62 :       args.GetOptionalArgumentValue(kSearchElementArg);
    1776          62 :   Node* context = Parameter(BuiltinDescriptor::kContext);
    1777             : 
    1778         124 :   Node* intptr_zero = IntPtrConstant(0);
    1779             : 
    1780          62 :   Label init_index(this), return_found(this), return_not_found(this),
    1781          62 :       call_runtime(this);
    1782             : 
    1783             :   // Take slow path if not a JSArray, if retrieving elements requires
    1784             :   // traversing prototype, or if access checks are required.
    1785          62 :   BranchIfFastJSArray(receiver, context, &init_index, &call_runtime);
    1786             : 
    1787          62 :   BIND(&init_index);
    1788         124 :   VARIABLE(index_var, MachineType::PointerRepresentation(), intptr_zero);
    1789             :   TNode<JSArray> array = CAST(receiver);
    1790             : 
    1791             :   // JSArray length is always a positive Smi for fast arrays.
    1792             :   CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array)));
    1793         186 :   Node* array_length = SmiUntag(LoadFastJSArrayLength(array));
    1794             : 
    1795             :   {
    1796             :     // Initialize fromIndex.
    1797          62 :     Label is_smi(this), is_nonsmi(this), done(this);
    1798             : 
    1799             :     // If no fromIndex was passed, default to 0.
    1800         186 :     GotoIf(IntPtrLessThanOrEqual(argc, IntPtrConstant(kFromIndexArg)), &done);
    1801             : 
    1802         124 :     Node* start_from = args.AtIndex(kFromIndexArg);
    1803             :     // Handle Smis and undefined here and everything else in runtime.
    1804             :     // We must be very careful with side effects from the ToInteger conversion,
    1805             :     // as the side effects might render previously checked assumptions about
    1806             :     // the receiver being a fast JSArray and its length invalid.
    1807         124 :     Branch(TaggedIsSmi(start_from), &is_smi, &is_nonsmi);
    1808             : 
    1809          62 :     BIND(&is_nonsmi);
    1810             :     {
    1811         124 :       GotoIfNot(IsUndefined(start_from), &call_runtime);
    1812          62 :       Goto(&done);
    1813             :     }
    1814          62 :     BIND(&is_smi);
    1815             :     {
    1816         124 :       Node* intptr_start_from = SmiUntag(start_from);
    1817          62 :       index_var.Bind(intptr_start_from);
    1818             : 
    1819         186 :       GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
    1820             :       // The fromIndex is negative: add it to the array's length.
    1821         186 :       index_var.Bind(IntPtrAdd(array_length, index_var.value()));
    1822             :       // Clamp negative results at zero.
    1823         186 :       GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
    1824          62 :       index_var.Bind(intptr_zero);
    1825          62 :       Goto(&done);
    1826             :     }
    1827         124 :     BIND(&done);
    1828             :   }
    1829             : 
    1830             :   // Fail early if startIndex >= array.length.
    1831         124 :   GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), array_length),
    1832         124 :          &return_not_found);
    1833             : 
    1834          62 :   Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this);
    1835             : 
    1836         186 :   Node* elements_kind = LoadMapElementsKind(LoadMap(array));
    1837         124 :   Node* elements = LoadElements(array);
    1838             :   STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
    1839             :   STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
    1840             :   STATIC_ASSERT(PACKED_ELEMENTS == 2);
    1841             :   STATIC_ASSERT(HOLEY_ELEMENTS == 3);
    1842         124 :   GotoIf(Uint32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
    1843         124 :          &if_smiorobjects);
    1844         124 :   GotoIf(Word32Equal(elements_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
    1845         124 :          &if_packed_doubles);
    1846         124 :   GotoIf(Word32Equal(elements_kind, Int32Constant(HOLEY_DOUBLE_ELEMENTS)),
    1847         124 :          &if_holey_doubles);
    1848          62 :   Goto(&return_not_found);
    1849             : 
    1850          62 :   BIND(&if_smiorobjects);
    1851             :   {
    1852          62 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1853          62 :     Label ident_loop(this, &index_var), heap_num_loop(this, &search_num),
    1854          62 :         string_loop(this), bigint_loop(this, &index_var),
    1855          62 :         undef_loop(this, &index_var), not_smi(this), not_heap_num(this);
    1856             : 
    1857         124 :     GotoIfNot(TaggedIsSmi(search_element), &not_smi);
    1858         124 :     search_num.Bind(SmiToFloat64(CAST(search_element)));
    1859          62 :     Goto(&heap_num_loop);
    1860             : 
    1861          62 :     BIND(&not_smi);
    1862          62 :     if (variant == kIncludes) {
    1863          62 :       GotoIf(IsUndefined(search_element), &undef_loop);
    1864             :     }
    1865         124 :     Node* map = LoadMap(CAST(search_element));
    1866         124 :     GotoIfNot(IsHeapNumberMap(map), &not_heap_num);
    1867         124 :     search_num.Bind(LoadHeapNumberValue(CAST(search_element)));
    1868          62 :     Goto(&heap_num_loop);
    1869             : 
    1870          62 :     BIND(&not_heap_num);
    1871         124 :     Node* search_type = LoadMapInstanceType(map);
    1872         124 :     GotoIf(IsStringInstanceType(search_type), &string_loop);
    1873         124 :     GotoIf(IsBigIntInstanceType(search_type), &bigint_loop);
    1874          62 :     Goto(&ident_loop);
    1875             : 
    1876          62 :     BIND(&ident_loop);
    1877             :     {
    1878         124 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    1879         124 :                 &return_not_found);
    1880          62 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1881          62 :       GotoIf(WordEqual(element_k, search_element), &return_found);
    1882             : 
    1883          62 :       Increment(&index_var);
    1884          62 :       Goto(&ident_loop);
    1885             :     }
    1886             : 
    1887          62 :     if (variant == kIncludes) {
    1888          31 :       BIND(&undef_loop);
    1889             : 
    1890          62 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    1891          62 :                 &return_not_found);
    1892          31 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1893          62 :       GotoIf(IsUndefined(element_k), &return_found);
    1894          62 :       GotoIf(IsTheHole(element_k), &return_found);
    1895             : 
    1896          31 :       Increment(&index_var);
    1897          31 :       Goto(&undef_loop);
    1898             :     }
    1899             : 
    1900          62 :     BIND(&heap_num_loop);
    1901             :     {
    1902          62 :       Label nan_loop(this, &index_var), not_nan_loop(this, &index_var);
    1903             :       Label* nan_handling =
    1904          62 :           variant == kIncludes ? &nan_loop : &return_not_found;
    1905          62 :       BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    1906             : 
    1907          62 :       BIND(&not_nan_loop);
    1908             :       {
    1909          62 :         Label continue_loop(this), not_smi(this);
    1910         124 :         GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    1911         124 :                   &return_not_found);
    1912          62 :         Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1913         124 :         GotoIfNot(TaggedIsSmi(element_k), &not_smi);
    1914         186 :         Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)),
    1915         124 :                &return_found, &continue_loop);
    1916             : 
    1917          62 :         BIND(&not_smi);
    1918         124 :         GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    1919         186 :         Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)),
    1920         124 :                &return_found, &continue_loop);
    1921             : 
    1922          62 :         BIND(&continue_loop);
    1923          62 :         Increment(&index_var);
    1924         124 :         Goto(&not_nan_loop);
    1925             :       }
    1926             : 
    1927             :       // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    1928          62 :       if (variant == kIncludes) {
    1929          31 :         BIND(&nan_loop);
    1930             :         Label continue_loop(this);
    1931          62 :         GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    1932          62 :                   &return_not_found);
    1933          31 :         Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1934          62 :         GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1935          62 :         GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    1936          31 :         BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_found,
    1937          62 :                              &continue_loop);
    1938             : 
    1939          31 :         BIND(&continue_loop);
    1940          31 :         Increment(&index_var);
    1941          31 :         Goto(&nan_loop);
    1942          62 :       }
    1943             :     }
    1944             : 
    1945          62 :     BIND(&string_loop);
    1946             :     {
    1947             :       TNode<String> search_element_string = CAST(search_element);
    1948          62 :       Label continue_loop(this), next_iteration(this, &index_var),
    1949          62 :           slow_compare(this), runtime(this, Label::kDeferred);
    1950         124 :       Node* search_length = LoadStringLength(search_element_string);
    1951          62 :       Goto(&next_iteration);
    1952          62 :       BIND(&next_iteration);
    1953         124 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    1954         124 :                 &return_not_found);
    1955          62 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1956         124 :       GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1957          62 :       GotoIf(WordEqual(search_element_string, element_k), &return_found);
    1958         124 :       Node* element_k_type = LoadInstanceType(element_k);
    1959         124 :       GotoIfNot(IsStringInstanceType(element_k_type), &continue_loop);
    1960         124 :       Branch(WordEqual(search_length, LoadStringLength(element_k)),
    1961          62 :              &slow_compare, &continue_loop);
    1962             : 
    1963          62 :       BIND(&slow_compare);
    1964             :       StringBuiltinsAssembler string_asm(state());
    1965             :       string_asm.StringEqual_Core(context, search_element_string, search_type,
    1966             :                                   search_length, element_k, element_k_type,
    1967          62 :                                   &return_found, &continue_loop, &runtime);
    1968          62 :       BIND(&runtime);
    1969             :       TNode<Object> result = CallRuntime(Runtime::kStringEqual, context,
    1970             :                                          search_element_string, element_k);
    1971          62 :       Branch(WordEqual(BooleanConstant(true), result), &return_found,
    1972          62 :              &continue_loop);
    1973             : 
    1974          62 :       BIND(&continue_loop);
    1975          62 :       Increment(&index_var);
    1976         124 :       Goto(&next_iteration);
    1977             :     }
    1978             : 
    1979          62 :     BIND(&bigint_loop);
    1980             :     {
    1981         124 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    1982         124 :                 &return_not_found);
    1983          62 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1984             :       TNode<Object> result = CallRuntime(Runtime::kBigIntEqual, context,
    1985             :                                          search_element, element_k);
    1986         124 :       GotoIf(WordEqual(result, TrueConstant()), &return_found);
    1987          62 :       Increment(&index_var);
    1988          62 :       Goto(&bigint_loop);
    1989          62 :     }
    1990             :   }
    1991             : 
    1992          62 :   BIND(&if_packed_doubles);
    1993             :   {
    1994          62 :     Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    1995          62 :         hole_loop(this, &index_var), search_notnan(this);
    1996         124 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1997             : 
    1998         124 :     GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1999         124 :     search_num.Bind(SmiToFloat64(CAST(search_element)));
    2000          62 :     Goto(&not_nan_loop);
    2001             : 
    2002          62 :     BIND(&search_notnan);
    2003         124 :     GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    2004             : 
    2005         124 :     search_num.Bind(LoadHeapNumberValue(CAST(search_element)));
    2006             : 
    2007          62 :     Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    2008          62 :     BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    2009             : 
    2010          62 :     BIND(&not_nan_loop);
    2011             :     {
    2012             :       Label continue_loop(this);
    2013         124 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    2014         124 :                 &return_not_found);
    2015             :       Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    2016          62 :                                                     MachineType::Float64());
    2017         124 :       Branch(Float64Equal(element_k, search_num.value()), &return_found,
    2018         124 :              &continue_loop);
    2019          62 :       BIND(&continue_loop);
    2020          62 :       Increment(&index_var);
    2021          62 :       Goto(&not_nan_loop);
    2022             :     }
    2023             : 
    2024             :     // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    2025          62 :     if (variant == kIncludes) {
    2026          31 :       BIND(&nan_loop);
    2027             :       Label continue_loop(this);
    2028          62 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    2029          62 :                 &return_not_found);
    2030             :       Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    2031          31 :                                                     MachineType::Float64());
    2032          31 :       BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
    2033          31 :       BIND(&continue_loop);
    2034          31 :       Increment(&index_var);
    2035          31 :       Goto(&nan_loop);
    2036          62 :     }
    2037             :   }
    2038             : 
    2039          62 :   BIND(&if_holey_doubles);
    2040             :   {
    2041          62 :     Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    2042          62 :         hole_loop(this, &index_var), search_notnan(this);
    2043         124 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    2044             : 
    2045         124 :     GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    2046         124 :     search_num.Bind(SmiToFloat64(CAST(search_element)));
    2047          62 :     Goto(&not_nan_loop);
    2048             : 
    2049          62 :     BIND(&search_notnan);
    2050          62 :     if (variant == kIncludes) {
    2051          62 :       GotoIf(IsUndefined(search_element), &hole_loop);
    2052             :     }
    2053         124 :     GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    2054             : 
    2055         124 :     search_num.Bind(LoadHeapNumberValue(CAST(search_element)));
    2056             : 
    2057          62 :     Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
    2058          62 :     BranchIfFloat64IsNaN(search_num.value(), nan_handling, &not_nan_loop);
    2059             : 
    2060          62 :     BIND(&not_nan_loop);
    2061             :     {
    2062             :       Label continue_loop(this);
    2063         124 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    2064         124 :                 &return_not_found);
    2065             : 
    2066             :       // No need for hole checking here; the following Float64Equal will
    2067             :       // return 'not equal' for holes anyway.
    2068             :       Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    2069          62 :                                                     MachineType::Float64());
    2070             : 
    2071         124 :       Branch(Float64Equal(element_k, search_num.value()), &return_found,
    2072         124 :              &continue_loop);
    2073          62 :       BIND(&continue_loop);
    2074          62 :       Increment(&index_var);
    2075          62 :       Goto(&not_nan_loop);
    2076             :     }
    2077             : 
    2078             :     // Array.p.includes uses SameValueZero comparisons, where NaN == NaN.
    2079          62 :     if (variant == kIncludes) {
    2080          31 :       BIND(&nan_loop);
    2081             :       Label continue_loop(this);
    2082          62 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    2083          62 :                 &return_not_found);
    2084             : 
    2085             :       // Load double value or continue if it's the hole NaN.
    2086             :       Node* element_k = LoadFixedDoubleArrayElement(
    2087             :           elements, index_var.value(), MachineType::Float64(), 0,
    2088          31 :           INTPTR_PARAMETERS, &continue_loop);
    2089             : 
    2090          31 :       BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
    2091          31 :       BIND(&continue_loop);
    2092          31 :       Increment(&index_var);
    2093          31 :       Goto(&nan_loop);
    2094             :     }
    2095             : 
    2096             :     // Array.p.includes treats the hole as undefined.
    2097          62 :     if (variant == kIncludes) {
    2098          31 :       BIND(&hole_loop);
    2099          62 :       GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
    2100          62 :                 &return_not_found);
    2101             : 
    2102             :       // Check if the element is a double hole, but don't load it.
    2103             :       LoadFixedDoubleArrayElement(elements, index_var.value(),
    2104             :                                   MachineType::None(), 0, INTPTR_PARAMETERS,
    2105          31 :                                   &return_found);
    2106             : 
    2107          31 :       Increment(&index_var);
    2108          31 :       Goto(&hole_loop);
    2109          62 :     }
    2110             :   }
    2111             : 
    2112          62 :   BIND(&return_found);
    2113          62 :   if (variant == kIncludes) {
    2114          62 :     args.PopAndReturn(TrueConstant());
    2115             :   } else {
    2116          93 :     args.PopAndReturn(SmiTag(index_var.value()));
    2117             :   }
    2118             : 
    2119          62 :   BIND(&return_not_found);
    2120          62 :   if (variant == kIncludes) {
    2121          62 :     args.PopAndReturn(FalseConstant());
    2122             :   } else {
    2123          62 :     args.PopAndReturn(NumberConstant(-1));
    2124             :   }
    2125             : 
    2126          62 :   BIND(&call_runtime);
    2127             :   {
    2128         124 :     Node* start_from = args.GetOptionalArgumentValue(kFromIndexArg);
    2129             :     Runtime::FunctionId function = variant == kIncludes
    2130             :                                        ? Runtime::kArrayIncludes_Slow
    2131          62 :                                        : Runtime::kArrayIndexOf;
    2132             :     args.PopAndReturn(
    2133          62 :         CallRuntime(function, context, array, search_element, start_from));
    2134          62 :   }
    2135          62 : }
    2136             : 
    2137          93 : TF_BUILTIN(ArrayIncludes, ArrayIncludesIndexofAssembler) {
    2138          31 :   Generate(kIncludes);
    2139           0 : }
    2140             : 
    2141          93 : TF_BUILTIN(ArrayIndexOf, ArrayIncludesIndexofAssembler) { Generate(kIndexOf); }
    2142             : 
    2143             : class ArrayPrototypeIterationAssembler : public CodeStubAssembler {
    2144             :  public:
    2145             :   explicit ArrayPrototypeIterationAssembler(compiler::CodeAssemblerState* state)
    2146          93 :       : CodeStubAssembler(state) {}
    2147             : 
    2148             :  protected:
    2149          93 :   void Generate_ArrayPrototypeIterationMethod(Node* context, Node* receiver,
    2150             :                                               IterationKind iteration_kind) {
    2151          93 :     VARIABLE(var_array, MachineRepresentation::kTagged);
    2152         186 :     VARIABLE(var_map, MachineRepresentation::kTagged);
    2153         186 :     VARIABLE(var_type, MachineRepresentation::kWord32);
    2154             : 
    2155          93 :     Label if_isnotobject(this, Label::kDeferred);
    2156          93 :     Label create_array_iterator(this);
    2157             : 
    2158         186 :     GotoIf(TaggedIsSmi(receiver), &if_isnotobject);
    2159          93 :     var_array.Bind(receiver);
    2160         186 :     var_map.Bind(LoadMap(receiver));
    2161         279 :     var_type.Bind(LoadMapInstanceType(var_map.value()));
    2162             :     Branch(IsJSReceiverInstanceType(var_type.value()), &create_array_iterator,
    2163         186 :            &if_isnotobject);
    2164             : 
    2165          93 :     BIND(&if_isnotobject);
    2166             :     {
    2167          93 :       Node* result = CallBuiltin(Builtins::kToObject, context, receiver);
    2168          93 :       var_array.Bind(result);
    2169         186 :       var_map.Bind(LoadMap(result));
    2170         279 :       var_type.Bind(LoadMapInstanceType(var_map.value()));
    2171          93 :       Goto(&create_array_iterator);
    2172             :     }
    2173             : 
    2174          93 :     BIND(&create_array_iterator);
    2175             :     Return(CreateArrayIterator(var_array.value(), var_map.value(),
    2176         279 :                                var_type.value(), context, iteration_kind));
    2177          93 :   }
    2178             : };
    2179             : 
    2180         124 : TF_BUILTIN(ArrayPrototypeValues, ArrayPrototypeIterationAssembler) {
    2181             :   Node* context = Parameter(Descriptor::kContext);
    2182             :   Node* receiver = Parameter(Descriptor::kReceiver);
    2183             :   Generate_ArrayPrototypeIterationMethod(context, receiver,
    2184          31 :                                          IterationKind::kValues);
    2185          31 : }
    2186             : 
    2187         124 : TF_BUILTIN(ArrayPrototypeEntries, ArrayPrototypeIterationAssembler) {
    2188             :   Node* context = Parameter(Descriptor::kContext);
    2189             :   Node* receiver = Parameter(Descriptor::kReceiver);
    2190             :   Generate_ArrayPrototypeIterationMethod(context, receiver,
    2191          31 :                                          IterationKind::kEntries);
    2192          31 : }
    2193             : 
    2194         124 : TF_BUILTIN(ArrayPrototypeKeys, ArrayPrototypeIterationAssembler) {
    2195             :   Node* context = Parameter(Descriptor::kContext);
    2196             :   Node* receiver = Parameter(Descriptor::kReceiver);
    2197             :   Generate_ArrayPrototypeIterationMethod(context, receiver,
    2198          31 :                                          IterationKind::kKeys);
    2199          31 : }
    2200             : 
    2201         124 : TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
    2202             :   Handle<String> operation = factory()->NewStringFromAsciiChecked(
    2203          31 :       "Array Iterator.prototype.next", TENURED);
    2204             : 
    2205             :   Node* context = Parameter(Descriptor::kContext);
    2206             :   Node* iterator = Parameter(Descriptor::kReceiver);
    2207             : 
    2208          31 :   VARIABLE(var_value, MachineRepresentation::kTagged);
    2209          62 :   VARIABLE(var_done, MachineRepresentation::kTagged);
    2210             : 
    2211             :   // Required, or else `throw_bad_receiver` fails a DCHECK due to these
    2212             :   // variables not being bound along all paths, despite not being used.
    2213          62 :   var_done.Bind(TrueConstant());
    2214          62 :   var_value.Bind(UndefinedConstant());
    2215             : 
    2216          31 :   Label throw_bad_receiver(this, Label::kDeferred);
    2217          31 :   Label set_done(this);
    2218          31 :   Label allocate_key_result(this);
    2219          31 :   Label allocate_entry_if_needed(this);
    2220          31 :   Label allocate_iterator_result(this);
    2221          31 :   Label generic_values(this);
    2222             : 
    2223             :   // If O does not have all of the internal slots of an Array Iterator Instance
    2224             :   // (22.1.5.3), throw a TypeError exception
    2225          62 :   GotoIf(TaggedIsSmi(iterator), &throw_bad_receiver);
    2226          31 :   TNode<Int32T> instance_type = LoadInstanceType(iterator);
    2227          62 :   GotoIf(IsArrayIteratorInstanceType(instance_type), &throw_bad_receiver);
    2228             : 
    2229             :   // Let a be O.[[IteratedObject]].
    2230             :   Node* array =
    2231             :       LoadObjectField(iterator, JSArrayIterator::kIteratedObjectOffset);
    2232             : 
    2233             :   // Let index be O.[[ArrayIteratorNextIndex]].
    2234             :   Node* index = LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset);
    2235             :   Node* orig_map =
    2236             :       LoadObjectField(iterator, JSArrayIterator::kIteratedObjectMapOffset);
    2237          62 :   Node* array_map = LoadMap(array);
    2238             : 
    2239          31 :   Label if_isfastarray(this), if_isnotfastarray(this),
    2240          31 :       if_isdetached(this, Label::kDeferred);
    2241             : 
    2242          62 :   Branch(WordEqual(orig_map, array_map), &if_isfastarray, &if_isnotfastarray);
    2243             : 
    2244          31 :   BIND(&if_isfastarray);
    2245             :   {
    2246             :     CSA_ASSERT(
    2247             :         this, InstanceTypeEqual(LoadMapInstanceType(array_map), JS_ARRAY_TYPE));
    2248             : 
    2249          62 :     Node* length = LoadJSArrayLength(array);
    2250             : 
    2251             :     CSA_ASSERT(this, TaggedIsSmi(length));
    2252             :     CSA_ASSERT(this, TaggedIsSmi(index));
    2253             : 
    2254          62 :     GotoIfNot(SmiBelow(index, length), &set_done);
    2255             : 
    2256          62 :     Node* one = SmiConstant(1);
    2257             :     StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
    2258          62 :                                    SmiAdd(index, one));
    2259             : 
    2260          62 :     var_done.Bind(FalseConstant());
    2261          62 :     Node* elements = LoadElements(array);
    2262             : 
    2263             :     static int32_t kInstanceType[] = {
    2264             :         JS_FAST_ARRAY_KEY_ITERATOR_TYPE,
    2265             :         JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2266             :         JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2267             :         JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2268             :         JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2269             :         JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2270             :         JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2271             :         JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE,
    2272             :         JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE,
    2273             :         JS_FAST_ARRAY_VALUE_ITERATOR_TYPE,
    2274             :         JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE,
    2275             :         JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
    2276             :         JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
    2277             :     };
    2278             : 
    2279          31 :     Label packed_object_values(this), holey_object_values(this),
    2280          31 :         packed_double_values(this), holey_double_values(this);
    2281             :     Label* kInstanceTypeHandlers[] = {
    2282             :         &allocate_key_result,  &packed_object_values, &holey_object_values,
    2283             :         &packed_object_values, &holey_object_values,  &packed_double_values,
    2284             :         &holey_double_values,  &packed_object_values, &holey_object_values,
    2285             :         &packed_object_values, &holey_object_values,  &packed_double_values,
    2286          31 :         &holey_double_values};
    2287             : 
    2288             :     Switch(instance_type, &throw_bad_receiver, kInstanceType,
    2289          31 :            kInstanceTypeHandlers, arraysize(kInstanceType));
    2290             : 
    2291          31 :     BIND(&packed_object_values);
    2292             :     {
    2293          31 :       var_value.Bind(LoadFixedArrayElement(elements, index, 0, SMI_PARAMETERS));
    2294          31 :       Goto(&allocate_entry_if_needed);
    2295             :     }
    2296             : 
    2297          31 :     BIND(&packed_double_values);
    2298             :     {
    2299             :       Node* value = LoadFixedDoubleArrayElement(
    2300          31 :           elements, index, MachineType::Float64(), 0, SMI_PARAMETERS);
    2301          62 :       var_value.Bind(AllocateHeapNumberWithValue(value));
    2302          31 :       Goto(&allocate_entry_if_needed);
    2303             :     }
    2304             : 
    2305          31 :     BIND(&holey_object_values);
    2306             :     {
    2307             :       // Check the array_protector cell, and take the slow path if it's invalid.
    2308          62 :       GotoIf(IsArrayProtectorCellInvalid(), &generic_values);
    2309             : 
    2310          62 :       var_value.Bind(UndefinedConstant());
    2311          31 :       Node* value = LoadFixedArrayElement(elements, index, 0, SMI_PARAMETERS);
    2312          62 :       GotoIf(WordEqual(value, TheHoleConstant()), &allocate_entry_if_needed);
    2313          31 :       var_value.Bind(value);
    2314          31 :       Goto(&allocate_entry_if_needed);
    2315             :     }
    2316             : 
    2317          31 :     BIND(&holey_double_values);
    2318             :     {
    2319             :       // Check the array_protector cell, and take the slow path if it's invalid.
    2320          62 :       GotoIf(IsArrayProtectorCellInvalid(), &generic_values);
    2321             : 
    2322          62 :       var_value.Bind(UndefinedConstant());
    2323             :       Node* value = LoadFixedDoubleArrayElement(
    2324             :           elements, index, MachineType::Float64(), 0, SMI_PARAMETERS,
    2325          31 :           &allocate_entry_if_needed);
    2326          62 :       var_value.Bind(AllocateHeapNumberWithValue(value));
    2327          31 :       Goto(&allocate_entry_if_needed);
    2328          31 :     }
    2329             :   }
    2330             : 
    2331          31 :   BIND(&if_isnotfastarray);
    2332             :   {
    2333          31 :     Label if_istypedarray(this), if_isgeneric(this);
    2334             : 
    2335             :     // If a is undefined, return CreateIterResultObject(undefined, true)
    2336          62 :     GotoIf(WordEqual(array, UndefinedConstant()), &allocate_iterator_result);
    2337             : 
    2338          62 :     Node* array_type = LoadInstanceType(array);
    2339             :     Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_istypedarray,
    2340          62 :            &if_isgeneric);
    2341             : 
    2342          31 :     BIND(&if_isgeneric);
    2343             :     {
    2344             :       Label if_wasfastarray(this);
    2345             : 
    2346             :       Node* length = nullptr;
    2347             :       {
    2348          31 :         VARIABLE(var_length, MachineRepresentation::kTagged);
    2349          31 :         Label if_isarray(this), if_isnotarray(this), done(this);
    2350             :         Branch(InstanceTypeEqual(array_type, JS_ARRAY_TYPE), &if_isarray,
    2351          62 :                &if_isnotarray);
    2352             : 
    2353          31 :         BIND(&if_isarray);
    2354             :         {
    2355          62 :           var_length.Bind(LoadJSArrayLength(array));
    2356             : 
    2357             :           // Invalidate protector cell if needed
    2358          62 :           Branch(WordNotEqual(orig_map, UndefinedConstant()), &if_wasfastarray,
    2359          31 :                  &done);
    2360             : 
    2361          31 :           BIND(&if_wasfastarray);
    2362             :           {
    2363             :             Label if_invalid(this, Label::kDeferred);
    2364             :             // A fast array iterator transitioned to a slow iterator during
    2365             :             // iteration. Invalidate fast_array_iteration_prtoector cell to
    2366             :             // prevent potential deopt loops.
    2367             :             StoreObjectFieldNoWriteBarrier(
    2368             :                 iterator, JSArrayIterator::kIteratedObjectMapOffset,
    2369          62 :                 UndefinedConstant());
    2370             :             GotoIf(Uint32LessThanOrEqual(
    2371             :                        instance_type,
    2372          62 :                        Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
    2373          62 :                    &done);
    2374             : 
    2375          62 :             Node* invalid = SmiConstant(Isolate::kProtectorInvalid);
    2376          62 :             Node* cell = LoadRoot(Heap::kFastArrayIterationProtectorRootIndex);
    2377          31 :             StoreObjectFieldNoWriteBarrier(cell, Cell::kValueOffset, invalid);
    2378          31 :             Goto(&done);
    2379             :           }
    2380             :         }
    2381             : 
    2382          31 :         BIND(&if_isnotarray);
    2383             :         {
    2384             :           Node* length =
    2385          62 :               GetProperty(context, array, factory()->length_string());
    2386          31 :           var_length.Bind(ToLength_Inline(context, length));
    2387          31 :           Goto(&done);
    2388             :         }
    2389             : 
    2390          31 :         BIND(&done);
    2391          62 :         length = var_length.value();
    2392             :       }
    2393             : 
    2394          31 :       GotoIfNumberGreaterThanOrEqual(index, length, &set_done);
    2395             : 
    2396             :       StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset,
    2397          31 :                        NumberInc(index));
    2398          62 :       var_done.Bind(FalseConstant());
    2399             : 
    2400             :       Branch(
    2401             :           Uint32LessThanOrEqual(
    2402          62 :               instance_type, Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
    2403          62 :           &allocate_key_result, &generic_values);
    2404             : 
    2405          31 :       BIND(&generic_values);
    2406             :       {
    2407          31 :         var_value.Bind(GetProperty(context, array, index));
    2408          31 :         Goto(&allocate_entry_if_needed);
    2409          31 :       }
    2410             :     }
    2411             : 
    2412          31 :     BIND(&if_istypedarray);
    2413             :     {
    2414             :       Node* buffer = LoadObjectField(array, JSTypedArray::kBufferOffset);
    2415          62 :       GotoIf(IsDetachedBuffer(buffer), &if_isdetached);
    2416             : 
    2417             :       Node* length = LoadObjectField(array, JSTypedArray::kLengthOffset);
    2418             : 
    2419             :       CSA_ASSERT(this, TaggedIsSmi(length));
    2420             :       CSA_ASSERT(this, TaggedIsSmi(index));
    2421             : 
    2422          62 :       GotoIfNot(SmiBelow(index, length), &set_done);
    2423             : 
    2424          62 :       Node* one = SmiConstant(1);
    2425             :       StoreObjectFieldNoWriteBarrier(
    2426          62 :           iterator, JSArrayIterator::kNextIndexOffset, SmiAdd(index, one));
    2427          62 :       var_done.Bind(FalseConstant());
    2428             : 
    2429          62 :       Node* elements = LoadElements(array);
    2430             :       Node* base_ptr =
    2431             :           LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
    2432             :       Node* external_ptr =
    2433             :           LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
    2434          31 :                           MachineType::Pointer());
    2435          93 :       Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
    2436             : 
    2437             :       static int32_t kInstanceType[] = {
    2438             :           JS_TYPED_ARRAY_KEY_ITERATOR_TYPE,
    2439             :           JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2440             :           JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2441             :           JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2442             :           JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2443             :           JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2444             :           JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2445             :           JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2446             :           JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2447             :           JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2448             :           JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE,
    2449             :           JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE,
    2450             :           JS_INT8_ARRAY_VALUE_ITERATOR_TYPE,
    2451             :           JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE,
    2452             :           JS_INT16_ARRAY_VALUE_ITERATOR_TYPE,
    2453             :           JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE,
    2454             :           JS_INT32_ARRAY_VALUE_ITERATOR_TYPE,
    2455             :           JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE,
    2456             :           JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE,
    2457             :       };
    2458             : 
    2459          31 :       Label uint8_values(this), int8_values(this), uint16_values(this),
    2460          31 :           int16_values(this), uint32_values(this), int32_values(this),
    2461          31 :           float32_values(this), float64_values(this);
    2462             :       Label* kInstanceTypeHandlers[] = {
    2463             :           &allocate_key_result, &uint8_values,  &uint8_values,
    2464             :           &int8_values,         &uint16_values, &int16_values,
    2465             :           &uint32_values,       &int32_values,  &float32_values,
    2466             :           &float64_values,      &uint8_values,  &uint8_values,
    2467             :           &int8_values,         &uint16_values, &int16_values,
    2468             :           &uint32_values,       &int32_values,  &float32_values,
    2469             :           &float64_values,
    2470          31 :       };
    2471             : 
    2472          62 :       var_done.Bind(FalseConstant());
    2473             :       Switch(instance_type, &throw_bad_receiver, kInstanceType,
    2474          31 :              kInstanceTypeHandlers, arraysize(kInstanceType));
    2475             : 
    2476          31 :       BIND(&uint8_values);
    2477             :       {
    2478             :         Node* value_uint8 = LoadFixedTypedArrayElement(
    2479          31 :             data_ptr, index, UINT8_ELEMENTS, SMI_PARAMETERS);
    2480          62 :         var_value.Bind(SmiFromWord32(value_uint8));
    2481          31 :         Goto(&allocate_entry_if_needed);
    2482             :       }
    2483          31 :       BIND(&int8_values);
    2484             :       {
    2485             :         Node* value_int8 = LoadFixedTypedArrayElement(
    2486          31 :             data_ptr, index, INT8_ELEMENTS, SMI_PARAMETERS);
    2487          62 :         var_value.Bind(SmiFromWord32(value_int8));
    2488          31 :         Goto(&allocate_entry_if_needed);
    2489             :       }
    2490          31 :       BIND(&uint16_values);
    2491             :       {
    2492             :         Node* value_uint16 = LoadFixedTypedArrayElement(
    2493          31 :             data_ptr, index, UINT16_ELEMENTS, SMI_PARAMETERS);
    2494          62 :         var_value.Bind(SmiFromWord32(value_uint16));
    2495          31 :         Goto(&allocate_entry_if_needed);
    2496             :       }
    2497          31 :       BIND(&int16_values);
    2498             :       {
    2499             :         Node* value_int16 = LoadFixedTypedArrayElement(
    2500          31 :             data_ptr, index, INT16_ELEMENTS, SMI_PARAMETERS);
    2501          62 :         var_value.Bind(SmiFromWord32(value_int16));
    2502          31 :         Goto(&allocate_entry_if_needed);
    2503             :       }
    2504          31 :       BIND(&uint32_values);
    2505             :       {
    2506             :         Node* value_uint32 = LoadFixedTypedArrayElement(
    2507          31 :             data_ptr, index, UINT32_ELEMENTS, SMI_PARAMETERS);
    2508          62 :         var_value.Bind(ChangeUint32ToTagged(value_uint32));
    2509          31 :         Goto(&allocate_entry_if_needed);
    2510             :       }
    2511          31 :       BIND(&int32_values);
    2512             :       {
    2513             :         Node* value_int32 = LoadFixedTypedArrayElement(
    2514          31 :             data_ptr, index, INT32_ELEMENTS, SMI_PARAMETERS);
    2515          62 :         var_value.Bind(ChangeInt32ToTagged(value_int32));
    2516          31 :         Goto(&allocate_entry_if_needed);
    2517             :       }
    2518          31 :       BIND(&float32_values);
    2519             :       {
    2520             :         Node* value_float32 = LoadFixedTypedArrayElement(
    2521          31 :             data_ptr, index, FLOAT32_ELEMENTS, SMI_PARAMETERS);
    2522             :         var_value.Bind(
    2523          93 :             AllocateHeapNumberWithValue(ChangeFloat32ToFloat64(value_float32)));
    2524          31 :         Goto(&allocate_entry_if_needed);
    2525             :       }
    2526          31 :       BIND(&float64_values);
    2527             :       {
    2528             :         Node* value_float64 = LoadFixedTypedArrayElement(
    2529          31 :             data_ptr, index, FLOAT64_ELEMENTS, SMI_PARAMETERS);
    2530          62 :         var_value.Bind(AllocateHeapNumberWithValue(value_float64));
    2531          31 :         Goto(&allocate_entry_if_needed);
    2532          31 :       }
    2533          31 :     }
    2534             :   }
    2535             : 
    2536          31 :   BIND(&set_done);
    2537             :   {
    2538             :     StoreObjectFieldNoWriteBarrier(
    2539          62 :         iterator, JSArrayIterator::kIteratedObjectOffset, UndefinedConstant());
    2540          31 :     Goto(&allocate_iterator_result);
    2541             :   }
    2542             : 
    2543          31 :   BIND(&allocate_key_result);
    2544             :   {
    2545          31 :     var_value.Bind(index);
    2546          62 :     var_done.Bind(FalseConstant());
    2547          31 :     Goto(&allocate_iterator_result);
    2548             :   }
    2549             : 
    2550          31 :   BIND(&allocate_entry_if_needed);
    2551             :   {
    2552             :     GotoIf(Uint32LessThan(Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE),
    2553          62 :                           instance_type),
    2554          62 :            &allocate_iterator_result);
    2555             : 
    2556          62 :     Node* elements = AllocateFixedArray(PACKED_ELEMENTS, IntPtrConstant(2));
    2557          31 :     StoreFixedArrayElement(elements, 0, index, SKIP_WRITE_BARRIER);
    2558          31 :     StoreFixedArrayElement(elements, 1, var_value.value(), SKIP_WRITE_BARRIER);
    2559             : 
    2560          31 :     Node* entry = Allocate(JSArray::kSize);
    2561          31 :     Node* map = LoadContextElement(LoadNativeContext(context),
    2562          93 :                                    Context::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
    2563             : 
    2564          31 :     StoreMapNoWriteBarrier(entry, map);
    2565             :     StoreObjectFieldRoot(entry, JSArray::kPropertiesOrHashOffset,
    2566          31 :                          Heap::kEmptyFixedArrayRootIndex);
    2567          31 :     StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset, elements);
    2568             :     StoreObjectFieldNoWriteBarrier(entry, JSArray::kLengthOffset,
    2569          62 :                                    SmiConstant(2));
    2570             : 
    2571          31 :     var_value.Bind(entry);
    2572          31 :     Goto(&allocate_iterator_result);
    2573             :   }
    2574             : 
    2575          31 :   BIND(&allocate_iterator_result);
    2576             :   {
    2577          31 :     Node* result = Allocate(JSIteratorResult::kSize);
    2578          31 :     Node* map = LoadContextElement(LoadNativeContext(context),
    2579          93 :                                    Context::ITERATOR_RESULT_MAP_INDEX);
    2580          31 :     StoreMapNoWriteBarrier(result, map);
    2581             :     StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOrHashOffset,
    2582          31 :                          Heap::kEmptyFixedArrayRootIndex);
    2583             :     StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
    2584          31 :                          Heap::kEmptyFixedArrayRootIndex);
    2585             :     StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset,
    2586          31 :                                    var_value.value());
    2587             :     StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset,
    2588          31 :                                    var_done.value());
    2589          31 :     Return(result);
    2590             :   }
    2591             : 
    2592          31 :   BIND(&throw_bad_receiver);
    2593             :   {
    2594             :     // The {receiver} is not a valid JSArrayIterator.
    2595             :     CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
    2596             :                 HeapConstant(operation), iterator);
    2597          31 :     Unreachable();
    2598             :   }
    2599             : 
    2600          31 :   BIND(&if_isdetached);
    2601             :   ThrowTypeError(context, MessageTemplate::kDetachedOperation,
    2602          62 :                  HeapConstant(operation));
    2603          31 : }
    2604             : 
    2605             : }  // namespace internal
    2606             : }  // namespace v8

Generated by: LCOV version 1.10