LCOV - code coverage report
Current view: top level - src/builtins - builtins-array-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 958 959 99.9 %
Date: 2017-04-26 Functions: 81 82 98.8 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-utils-gen.h"
       6             : #include "src/builtins/builtins.h"
       7             : #include "src/code-stub-assembler.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : 
      12        1548 : class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
      13             :  public:
      14         774 :   explicit ArrayBuiltinCodeStubAssembler(compiler::CodeAssemblerState* state)
      15             :       : CodeStubAssembler(state),
      16             :         k_(this, MachineRepresentation::kTagged),
      17             :         a_(this, MachineRepresentation::kTagged),
      18         774 :         to_(this, MachineRepresentation::kTagged, SmiConstant(0)) {}
      19             : 
      20             :   typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm)>
      21             :       BuiltinResultGenerator;
      22             : 
      23             :   typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
      24             :       BuiltinResultIndexInitializer;
      25             : 
      26             :   typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm,
      27             :                               Node* k_value, Node* k)>
      28             :       CallResultProcessor;
      29             : 
      30             :   typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
      31             :       PostLoopAction;
      32             : 
      33          43 :   Node* ForEachResultGenerator() { return UndefinedConstant(); }
      34             : 
      35         129 :   Node* ForEachProcessor(Node* k_value, Node* k) {
      36             :     CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(),
      37         258 :            k_value, k, o());
      38         129 :     return a();
      39             :   }
      40             : 
      41          86 :   Node* SomeResultGenerator() { return FalseConstant(); }
      42             : 
      43         516 :   Node* SomeProcessor(Node* k_value, Node* k) {
      44             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      45        1032 :                          this_arg(), k_value, k, o());
      46         516 :     Label false_continue(this), return_true(this);
      47         516 :     BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
      48         516 :     BIND(&return_true);
      49         516 :     Return(TrueConstant());
      50         516 :     BIND(&false_continue);
      51         516 :     return a();
      52             :   }
      53             : 
      54          86 :   Node* EveryResultGenerator() { return TrueConstant(); }
      55             : 
      56         516 :   Node* EveryProcessor(Node* k_value, Node* k) {
      57             :     Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
      58        1032 :                          this_arg(), k_value, k, o());
      59         516 :     Label true_continue(this), return_false(this);
      60         516 :     BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
      61         516 :     BIND(&return_false);
      62         516 :     Return(FalseConstant());
      63         516 :     BIND(&true_continue);
      64         516 :     return a();
      65             :   }
      66             : 
      67         344 :   Node* ReduceResultGenerator() {
      68         172 :     VARIABLE(a, MachineRepresentation::kTagged, UndefinedConstant());
      69         516 :     Label no_initial_value(this), has_initial_value(this), done(this, {&a});
      70             : 
      71             :     // 8. If initialValue is present, then
      72         172 :     Node* parent_frame_ptr = LoadParentFramePointer();
      73             :     Node* marker_or_function = LoadBufferObject(
      74         172 :         parent_frame_ptr, CommonFrameConstants::kContextOrFrameTypeOffset);
      75             :     GotoIf(
      76             :         MarkerIsNotFrameType(marker_or_function, StackFrame::ARGUMENTS_ADAPTOR),
      77         172 :         &has_initial_value);
      78             : 
      79             :     // Has arguments adapter, check count.
      80             :     Node* adapted_parameter_count = LoadBufferObject(
      81         172 :         parent_frame_ptr, ArgumentsAdaptorFrameConstants::kLengthOffset);
      82             :     Branch(SmiLessThan(adapted_parameter_count,
      83             :                        SmiConstant(IteratingArrayBuiltinDescriptor::kThisArg)),
      84         172 :            &no_initial_value, &has_initial_value);
      85             : 
      86             :     // a. Set accumulator to initialValue.
      87         172 :     BIND(&has_initial_value);
      88         172 :     a.Bind(this_arg());
      89         172 :     Goto(&done);
      90             : 
      91             :     // 9. Else initialValue is not present,
      92         172 :     BIND(&no_initial_value);
      93             : 
      94             :     // a. Let kPresent be false.
      95         172 :     a.Bind(TheHoleConstant());
      96         172 :     Goto(&done);
      97         172 :     BIND(&done);
      98         344 :     return a.value();
      99             :   }
     100             : 
     101        3096 :   Node* ReduceProcessor(Node* k_value, Node* k) {
     102        1032 :     VARIABLE(result, MachineRepresentation::kTagged);
     103        3096 :     Label done(this, {&result}), initial(this);
     104        2064 :     GotoIf(WordEqual(a(), TheHoleConstant()), &initial);
     105             :     result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
     106        3096 :                        UndefinedConstant(), a(), k_value, k, o()));
     107        1032 :     Goto(&done);
     108             : 
     109        1032 :     BIND(&initial);
     110        1032 :     result.Bind(k_value);
     111        1032 :     Goto(&done);
     112             : 
     113        1032 :     BIND(&done);
     114        2064 :     return result.value();
     115             :   }
     116             : 
     117        2064 :   void ReducePostLoopAction() {
     118        1032 :     Label ok(this);
     119        2064 :     GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok);
     120             :     CallRuntime(Runtime::kThrowTypeError, context(),
     121        2064 :                 SmiConstant(MessageTemplate::kReduceNoInitial));
     122        1032 :     Unreachable();
     123        1032 :     BIND(&ok);
     124        1032 :   }
     125             : 
     126          86 :   Node* FilterResultGenerator() {
     127             :     // 7. Let A be ArraySpeciesCreate(O, 0).
     128          86 :     return ArraySpeciesCreate(context(), o(), SmiConstant(0));
     129             :   }
     130             : 
     131         387 :   Node* FilterProcessor(Node* k_value, Node* k) {
     132             :     // ii. Let selected be ToBoolean(? Call(callbackfn, T, kValue, k, O)).
     133             :     Node* selected = CallJS(CodeFactory::Call(isolate()), context(),
     134         258 :                             callbackfn(), this_arg(), k_value, k, o());
     135         258 :     Label true_continue(this, &to_), false_continue(this);
     136         129 :     BranchIfToBooleanIsTrue(selected, &true_continue, &false_continue);
     137         129 :     BIND(&true_continue);
     138             :     // iii. If selected is true, then...
     139             :     {
     140             :       Label after_work(this, &to_);
     141             :       Node* kind = nullptr;
     142             : 
     143             :       // If a() is a JSArray, we can have a fast path.
     144         129 :       Label fast(this);
     145         129 :       Label runtime(this);
     146         129 :       Label object_push_pre(this), object_push(this), double_push(this);
     147             :       BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS,
     148         129 :                           &fast, &runtime);
     149             : 
     150         129 :       BIND(&fast);
     151             :       {
     152         129 :         kind = EnsureArrayPushable(a(), &runtime);
     153             :         GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS),
     154         129 :                &object_push_pre);
     155             : 
     156         129 :         BuildAppendJSArray(FAST_SMI_ELEMENTS, a(), k_value, &runtime);
     157         129 :         Goto(&after_work);
     158             :       }
     159             : 
     160         129 :       BIND(&object_push_pre);
     161             :       {
     162             :         Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS),
     163         129 :                &double_push, &object_push);
     164             :       }
     165             : 
     166         129 :       BIND(&object_push);
     167             :       {
     168         129 :         BuildAppendJSArray(FAST_ELEMENTS, a(), k_value, &runtime);
     169         129 :         Goto(&after_work);
     170             :       }
     171             : 
     172         129 :       BIND(&double_push);
     173             :       {
     174         129 :         BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, a(), k_value, &runtime);
     175         129 :         Goto(&after_work);
     176             :       }
     177             : 
     178         129 :       BIND(&runtime);
     179             :       {
     180             :         // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
     181             :         CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
     182         258 :                     k_value);
     183         129 :         Goto(&after_work);
     184             :       }
     185             : 
     186         129 :       BIND(&after_work);
     187             :       {
     188             :         // 2. Increase to by 1.
     189         129 :         to_.Bind(NumberInc(to_.value()));
     190         129 :         Goto(&false_continue);
     191         129 :       }
     192             :     }
     193         129 :     BIND(&false_continue);
     194         129 :     return a();
     195             :   }
     196             : 
     197          86 :   Node* MapResultGenerator() {
     198             :     // 5. Let A be ? ArraySpeciesCreate(O, len).
     199          86 :     return ArraySpeciesCreate(context(), o(), len_);
     200             :   }
     201             : 
     202         387 :   Node* MapProcessor(Node* k_value, Node* k) {
     203             :     //  i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor.
     204             :     // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O).
     205             :     Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
     206         258 :                                callbackfn(), this_arg(), k_value, k, o());
     207             : 
     208             :     Label finished(this);
     209             :     Node* kind = nullptr;
     210             :     Node* elements = nullptr;
     211             : 
     212             :     // If a() is a JSArray, we can have a fast path.
     213             :     // mode is SMI_PARAMETERS because k has tagged representation.
     214             :     ParameterMode mode = SMI_PARAMETERS;
     215         129 :     Label fast(this);
     216         129 :     Label runtime(this);
     217         129 :     Label object_push_pre(this), object_push(this), double_push(this);
     218             :     BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS,
     219         129 :                         &fast, &runtime);
     220             : 
     221         129 :     BIND(&fast);
     222             :     {
     223         129 :       kind = EnsureArrayPushable(a(), &runtime);
     224         129 :       elements = LoadElements(a());
     225             :       GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS),
     226         129 :              &object_push_pre);
     227             :       TryStoreArrayElement(FAST_SMI_ELEMENTS, mode, &runtime, elements, k,
     228         129 :                            mappedValue);
     229         129 :       Goto(&finished);
     230             :     }
     231             : 
     232         129 :     BIND(&object_push_pre);
     233             :     {
     234             :       Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push,
     235         129 :              &object_push);
     236             :     }
     237             : 
     238         129 :     BIND(&object_push);
     239             :     {
     240             :       TryStoreArrayElement(FAST_ELEMENTS, mode, &runtime, elements, k,
     241         129 :                            mappedValue);
     242         129 :       Goto(&finished);
     243             :     }
     244             : 
     245         129 :     BIND(&double_push);
     246             :     {
     247             :       TryStoreArrayElement(FAST_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
     248         129 :                            mappedValue);
     249         129 :       Goto(&finished);
     250             :     }
     251             : 
     252         129 :     BIND(&runtime);
     253             :     {
     254             :       // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
     255         129 :       CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
     256         129 :       Goto(&finished);
     257             :     }
     258             : 
     259         129 :     BIND(&finished);
     260         129 :     return a();
     261             :   }
     262             : 
     263        1419 :   void NullPostLoopAction() {}
     264             : 
     265             :  protected:
     266             :   Node* context() { return context_; }
     267             :   Node* receiver() { return receiver_; }
     268             :   Node* new_target() { return new_target_; }
     269             :   Node* o() { return o_; }
     270             :   Node* len() { return len_; }
     271             :   Node* callbackfn() { return callbackfn_; }
     272             :   Node* this_arg() { return this_arg_; }
     273        2107 :   Node* k() { return k_.value(); }
     274        5805 :   Node* a() { return a_.value(); }
     275             : 
     276             :   void InitIteratingArrayBuiltinBody(Node* context, Node* receiver,
     277             :                                      Node* callbackfn, Node* this_arg,
     278             :                                      Node* new_target) {
     279         473 :     context_ = context;
     280         473 :     receiver_ = receiver;
     281         473 :     new_target_ = new_target;
     282         473 :     callbackfn_ = callbackfn;
     283         473 :     this_arg_ = this_arg;
     284             :   }
     285             : 
     286         301 :   void GenerateIteratingArrayBuiltinBody(
     287             :       const char* name, const BuiltinResultGenerator& generator,
     288             :       const CallResultProcessor& processor, const PostLoopAction& action,
     289             :       const Callable& slow_case_continuation,
     290        4859 :       ForEachDirection direction = ForEachDirection::kForward) {
     291        1204 :     Label non_array(this), slow(this, {&k_, &a_, &to_}),
     292         903 :         array_changes(this, {&k_, &a_, &to_});
     293             : 
     294             :     // TODO(danno): Seriously? Do we really need to throw the exact error
     295             :     // message on null and undefined so that the webkit tests pass?
     296         301 :     Label throw_null_undefined_exception(this, Label::kDeferred);
     297             :     GotoIf(WordEqual(receiver(), NullConstant()),
     298         602 :            &throw_null_undefined_exception);
     299             :     GotoIf(WordEqual(receiver(), UndefinedConstant()),
     300         602 :            &throw_null_undefined_exception);
     301             : 
     302             :     // By the book: taken directly from the ECMAScript 2015 specification
     303             : 
     304             :     // 1. Let O be ToObject(this value).
     305             :     // 2. ReturnIfAbrupt(O)
     306         602 :     o_ = CallStub(CodeFactory::ToObject(isolate()), context(), receiver());
     307             : 
     308             :     // 3. Let len be ToLength(Get(O, "length")).
     309             :     // 4. ReturnIfAbrupt(len).
     310         602 :     VARIABLE(merged_length, MachineRepresentation::kTagged);
     311         301 :     Label has_length(this, &merged_length), not_js_array(this);
     312         301 :     GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), &not_js_array);
     313         301 :     merged_length.Bind(LoadJSArrayLength(o()));
     314         301 :     Goto(&has_length);
     315         301 :     BIND(&not_js_array);
     316             :     Node* len_property =
     317         602 :         GetProperty(context(), o(), isolate()->factory()->length_string());
     318             :     merged_length.Bind(
     319         602 :         CallStub(CodeFactory::ToLength(isolate()), context(), len_property));
     320         301 :     Goto(&has_length);
     321         301 :     BIND(&has_length);
     322         301 :     len_ = merged_length.value();
     323             : 
     324             :     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
     325         301 :     Label type_exception(this, Label::kDeferred);
     326         301 :     Label done(this);
     327         301 :     GotoIf(TaggedIsSmi(callbackfn()), &type_exception);
     328         301 :     Branch(IsCallableMap(LoadMap(callbackfn())), &done, &type_exception);
     329             : 
     330         301 :     BIND(&throw_null_undefined_exception);
     331             :     {
     332             :       CallRuntime(
     333             :           Runtime::kThrowTypeError, context(),
     334             :           SmiConstant(MessageTemplate::kCalledOnNullOrUndefined),
     335         903 :           HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name)));
     336         301 :       Unreachable();
     337             :     }
     338             : 
     339         301 :     BIND(&type_exception);
     340             :     {
     341             :       CallRuntime(Runtime::kThrowTypeError, context(),
     342             :                   SmiConstant(MessageTemplate::kCalledNonCallable),
     343         602 :                   callbackfn());
     344         301 :       Unreachable();
     345             :     }
     346             : 
     347         301 :     BIND(&done);
     348             : 
     349             :     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
     350             :     // [Already done by the arguments adapter]
     351             : 
     352         301 :     if (direction == ForEachDirection::kForward) {
     353             :       // 7. Let k be 0.
     354         258 :       k_.Bind(SmiConstant(0));
     355             :     } else {
     356          43 :       k_.Bind(NumberDec(len()));
     357             :     }
     358             : 
     359         301 :     a_.Bind(generator(this));
     360             : 
     361         301 :     HandleFastElements(processor, action, &slow, direction);
     362             : 
     363         301 :     BIND(&slow);
     364             : 
     365             :     Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
     366         301 :                                  MachineType::TaggedPointer());
     367             :     TailCallStub(
     368             :         slow_case_continuation, context(), target, new_target(),
     369             :         Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity),
     370             :         receiver(), callbackfn(), this_arg(), a_.value(), o(), k_.value(),
     371        1806 :         len(), to_.value());
     372         301 :   }
     373             : 
     374             :   void InitIteratingArrayBuiltinLoopContinuation(Node* context, Node* receiver,
     375             :                                                  Node* callbackfn,
     376             :                                                  Node* this_arg, Node* a,
     377             :                                                  Node* o, Node* initial_k,
     378             :                                                  Node* len, Node* to) {
     379         301 :     context_ = context;
     380         301 :     this_arg_ = this_arg;
     381         301 :     callbackfn_ = callbackfn;
     382         301 :     a_.Bind(a);
     383         301 :     k_.Bind(initial_k);
     384         301 :     o_ = o;
     385         301 :     len_ = len;
     386         301 :     to_.Bind(to);
     387             :   }
     388             : 
     389         172 :   void GenerateIteratingTypedArrayBuiltinBody(
     390             :       const char* name, const BuiltinResultGenerator& generator,
     391             :       const CallResultProcessor& processor, const PostLoopAction& action,
     392          43 :       ForEachDirection direction = ForEachDirection::kForward) {
     393             :     Node* name_string =
     394         344 :         HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name));
     395             : 
     396             :     // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
     397             : 
     398             :     Label throw_not_typed_array(this, Label::kDeferred),
     399         172 :         throw_detached(this, Label::kDeferred);
     400             : 
     401         172 :     GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
     402             :     GotoIfNot(HasInstanceType(receiver_, JS_TYPED_ARRAY_TYPE),
     403         172 :               &throw_not_typed_array);
     404             : 
     405         172 :     o_ = receiver_;
     406         172 :     Node* array_buffer = LoadObjectField(o_, JSTypedArray::kBufferOffset);
     407         172 :     GotoIf(IsDetachedBuffer(array_buffer), &throw_detached);
     408             : 
     409         172 :     len_ = LoadObjectField(o_, JSTypedArray::kLengthOffset);
     410             : 
     411         172 :     Label throw_not_callable(this, Label::kDeferred);
     412         172 :     Label distinguish_types(this);
     413         172 :     GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable);
     414             :     Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types,
     415         172 :            &throw_not_callable);
     416             : 
     417         172 :     BIND(&throw_not_typed_array);
     418             :     {
     419             :       CallRuntime(Runtime::kThrowTypeError, context_,
     420         172 :                   SmiConstant(MessageTemplate::kNotTypedArray));
     421         172 :       Unreachable();
     422             :     }
     423             : 
     424         172 :     BIND(&throw_detached);
     425             :     {
     426             :       CallRuntime(Runtime::kThrowTypeError, context_,
     427             :                   SmiConstant(MessageTemplate::kDetachedOperation),
     428         172 :                   name_string);
     429         172 :       Unreachable();
     430             :     }
     431             : 
     432         172 :     BIND(&throw_not_callable);
     433             :     {
     434             :       CallRuntime(Runtime::kThrowTypeError, context_,
     435             :                   SmiConstant(MessageTemplate::kCalledNonCallable),
     436         172 :                   callbackfn_);
     437         172 :       Unreachable();
     438             :     }
     439             : 
     440         172 :     Label unexpected_instance_type(this);
     441         172 :     BIND(&unexpected_instance_type);
     442         172 :     Unreachable();
     443             : 
     444             :     std::vector<int32_t> instance_types = {
     445             : #define INSTANCE_TYPE(Type, type, TYPE, ctype, size) FIXED_##TYPE##_ARRAY_TYPE,
     446             :         TYPED_ARRAYS(INSTANCE_TYPE)
     447             : #undef INSTANCE_TYPE
     448             :     };
     449         172 :     std::vector<Label> labels;
     450        3440 :     for (size_t i = 0; i < instance_types.size(); ++i) {
     451        1548 :       labels.push_back(Label(this));
     452             :     }
     453             :     std::vector<Label*> label_ptrs;
     454        1892 :     for (Label& label : labels) {
     455        3096 :       label_ptrs.push_back(&label);
     456             :     }
     457             : 
     458         172 :     BIND(&distinguish_types);
     459             : 
     460         172 :     if (direction == ForEachDirection::kForward) {
     461         129 :       k_.Bind(SmiConstant(0));
     462             :     } else {
     463          43 :       k_.Bind(NumberDec(len()));
     464             :     }
     465         172 :     a_.Bind(generator(this));
     466         172 :     Node* elements_type = LoadInstanceType(LoadElements(o_));
     467             :     Switch(elements_type, &unexpected_instance_type, instance_types.data(),
     468         344 :            label_ptrs.data(), labels.size());
     469             : 
     470        3440 :     for (size_t i = 0; i < labels.size(); ++i) {
     471        1548 :       BIND(&labels[i]);
     472             :       Label done(this);
     473             :       // TODO(tebbi): Silently cancelling the loop on buffer detachment is a
     474             :       // spec violation. Should go to &detached and throw a TypeError instead.
     475             :       VisitAllTypedArrayElements(
     476             :           ElementsKindForInstanceType(
     477        1548 :               static_cast<InstanceType>(instance_types[i])),
     478        1548 :           array_buffer, processor, &done, direction);
     479        1548 :       Goto(&done);
     480             :       // No exception, return success
     481        1548 :       BIND(&done);
     482        1548 :       action(this);
     483        1548 :       Return(a_.value());
     484        1720 :     }
     485         172 :   }
     486             : 
     487         301 :   void GenerateIteratingArrayBuiltinLoopContinuation(
     488             :       const CallResultProcessor& processor, const PostLoopAction& action,
     489         903 :       ForEachDirection direction = ForEachDirection::kForward) {
     490         602 :     Label loop(this, {&k_, &a_, &to_});
     491         301 :     Label after_loop(this);
     492         301 :     Goto(&loop);
     493         301 :     BIND(&loop);
     494             :     {
     495         301 :       if (direction == ForEachDirection::kForward) {
     496             :         // 8. Repeat, while k < len
     497         516 :         GotoUnlessNumberLessThan(k(), len_, &after_loop);
     498             :       } else {
     499             :         // OR
     500             :         // 10. Repeat, while k >= 0
     501          43 :         GotoUnlessNumberLessThan(SmiConstant(-1), k(), &after_loop);
     502             :       }
     503             : 
     504             :       Label done_element(this, &to_);
     505             :       // a. Let Pk be ToString(k).
     506         301 :       Node* p_k = ToString(context(), k());
     507             : 
     508             :       // b. Let kPresent be HasProperty(O, Pk).
     509             :       // c. ReturnIfAbrupt(kPresent).
     510         301 :       Node* k_present = HasProperty(o(), p_k, context());
     511             : 
     512             :       // d. If kPresent is true, then
     513         301 :       GotoIf(WordNotEqual(k_present, TrueConstant()), &done_element);
     514             : 
     515             :       // i. Let kValue be Get(O, Pk).
     516             :       // ii. ReturnIfAbrupt(kValue).
     517         301 :       Node* k_value = GetProperty(context(), o(), k());
     518             : 
     519             :       // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
     520             :       // iv. ReturnIfAbrupt(funcResult).
     521         301 :       a_.Bind(processor(this, k_value, k()));
     522         301 :       Goto(&done_element);
     523             : 
     524         301 :       BIND(&done_element);
     525             : 
     526         301 :       if (direction == ForEachDirection::kForward) {
     527             :         // e. Increase k by 1.
     528         258 :         k_.Bind(NumberInc(k()));
     529             :       } else {
     530             :         // e. Decrease k by 1.
     531          43 :         k_.Bind(NumberDec(k()));
     532             :       }
     533         301 :       Goto(&loop);
     534             :     }
     535         301 :     BIND(&after_loop);
     536             : 
     537         301 :     action(this);
     538         602 :     Return(a_.value());
     539         301 :   }
     540             : 
     541             :  private:
     542        1548 :   static ElementsKind ElementsKindForInstanceType(InstanceType type) {
     543        1548 :     switch (type) {
     544             : #define INSTANCE_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size) \
     545             :   case FIXED_##TYPE##_ARRAY_TYPE:                                     \
     546             :     return TYPE##_ELEMENTS;
     547             : 
     548         172 :       TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
     549             : #undef INSTANCE_TYPE_TO_ELEMENTS_KIND
     550             : 
     551             :       default:
     552           0 :         UNREACHABLE();
     553             :         return static_cast<ElementsKind>(-1);
     554             :     }
     555             :   }
     556             : 
     557        1548 :   void VisitAllTypedArrayElements(ElementsKind kind, Node* array_buffer,
     558             :                                   const CallResultProcessor& processor,
     559             :                                   Label* detached, ForEachDirection direction) {
     560        1548 :     VariableList list({&a_, &k_, &to_}, zone());
     561             : 
     562        1548 :     FastLoopBody body = [&](Node* index) {
     563        1548 :       GotoIf(IsDetachedBuffer(array_buffer), detached);
     564        1548 :       Node* elements = LoadElements(o_);
     565             :       Node* base_ptr =
     566        1548 :           LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
     567             :       Node* external_ptr =
     568             :           LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
     569        1548 :                           MachineType::Pointer());
     570        1548 :       Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
     571             :       Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind,
     572        1548 :                                                        SMI_PARAMETERS);
     573        1548 :       k_.Bind(index);
     574        1548 :       a_.Bind(processor(this, value, index));
     575        1548 :     };
     576        1548 :     Node* start = SmiConstant(0);
     577        1548 :     Node* end = len_;
     578             :     IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
     579             :     int incr = 1;
     580        1548 :     if (direction == ForEachDirection::kReverse) {
     581             :       std::swap(start, end);
     582             :       advance_mode = IndexAdvanceMode::kPre;
     583             :       incr = -1;
     584             :     }
     585             :     BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS,
     586        1548 :                   advance_mode);
     587        1548 :   }
     588             : 
     589         602 :   void VisitAllFastElementsOneKind(ElementsKind kind,
     590             :                                    const CallResultProcessor& processor,
     591             :                                    Label* array_changed, ParameterMode mode,
     592        1204 :                                    ForEachDirection direction) {
     593         602 :     Comment("begin VisitAllFastElementsOneKind");
     594         602 :     VARIABLE(original_map, MachineRepresentation::kTagged);
     595         602 :     original_map.Bind(LoadMap(o()));
     596         602 :     VariableList list({&original_map, &a_, &k_, &to_}, zone());
     597         602 :     Node* start = IntPtrOrSmiConstant(0, mode);
     598             :     Node* end = TaggedToParameter(len(), mode);
     599             :     IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse
     600             :                                         ? IndexAdvanceMode::kPre
     601         602 :                                         : IndexAdvanceMode::kPost;
     602         602 :     if (direction == ForEachDirection::kReverse) std::swap(start, end);
     603             :     BuildFastLoop(
     604             :         list, start, end,
     605        1806 :         [=, &original_map](Node* index) {
     606        3010 :           k_.Bind(ParameterToTagged(index, mode));
     607        1806 :           Label one_element_done(this), hole_element(this);
     608             : 
     609             :           // Check if o's map has changed during the callback. If so, we have to
     610             :           // fall back to the slower spec implementation for the rest of the
     611             :           // iteration.
     612        1204 :           Node* o_map = LoadMap(o());
     613         602 :           GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
     614             : 
     615             :           // Check if o's length has changed during the callback and if the
     616             :           // index is now out of range of the new length.
     617             :           GotoIf(SmiGreaterThanOrEqual(k_.value(), LoadJSArrayLength(o())),
     618        1204 :                  array_changed);
     619             : 
     620             :           // Re-load the elements array. If may have been resized.
     621        1204 :           Node* elements = LoadElements(o());
     622             : 
     623             :           // Fast case: load the element directly from the elements FixedArray
     624             :           // and call the callback if the element is not the hole.
     625             :           DCHECK(kind == FAST_ELEMENTS || kind == FAST_DOUBLE_ELEMENTS);
     626         602 :           int base_size = kind == FAST_ELEMENTS
     627             :                               ? FixedArray::kHeaderSize
     628         602 :                               : (FixedArray::kHeaderSize - kHeapObjectTag);
     629         602 :           Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
     630             :           Node* value = nullptr;
     631         602 :           if (kind == FAST_ELEMENTS) {
     632         301 :             value = LoadObjectField(elements, offset);
     633         301 :             GotoIf(WordEqual(value, TheHoleConstant()), &hole_element);
     634             :           } else {
     635             :             Node* double_value =
     636         301 :                 LoadDoubleWithHoleCheck(elements, offset, &hole_element);
     637         301 :             value = AllocateHeapNumberWithValue(double_value);
     638             :           }
     639        1204 :           a_.Bind(processor(this, value, k()));
     640         602 :           Goto(&one_element_done);
     641             : 
     642         602 :           BIND(&hole_element);
     643             :           // Check if o's prototype change unexpectedly has elements after the
     644             :           // callback in the case of a hole.
     645             :           BranchIfPrototypesHaveNoElements(o_map, &one_element_done,
     646         602 :                                            array_changed);
     647             : 
     648         602 :           BIND(&one_element_done);
     649         602 :         },
     650        2408 :         1, mode, advance_mode);
     651         602 :     Comment("end VisitAllFastElementsOneKind");
     652         602 :   }
     653             : 
     654         301 :   void HandleFastElements(const CallResultProcessor& processor,
     655             :                           const PostLoopAction& action, Label* slow,
     656         903 :                           ForEachDirection direction) {
     657         602 :     Label switch_on_elements_kind(this), fast_elements(this),
     658         301 :         maybe_double_elements(this), fast_double_elements(this);
     659             : 
     660         301 :     Comment("begin HandleFastElements");
     661             :     // Non-smi lengths must use the slow path.
     662         301 :     GotoIf(TaggedIsNotSmi(len()), slow);
     663             : 
     664             :     BranchIfFastJSArray(o(), context(),
     665             :                         CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ,
     666         301 :                         &switch_on_elements_kind, slow);
     667             : 
     668         301 :     BIND(&switch_on_elements_kind);
     669             :     // Select by ElementsKind
     670         301 :     Node* o_map = LoadMap(o());
     671         301 :     Node* bit_field2 = LoadMapBitField2(o_map);
     672             :     Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
     673             :     Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS),
     674         301 :            &maybe_double_elements, &fast_elements);
     675             : 
     676             :     ParameterMode mode = OptimalParameterMode();
     677         301 :     BIND(&fast_elements);
     678             :     {
     679             :       VisitAllFastElementsOneKind(FAST_ELEMENTS, processor, slow, mode,
     680         301 :                                   direction);
     681             : 
     682         301 :       action(this);
     683             : 
     684             :       // No exception, return success
     685         301 :       Return(a_.value());
     686             :     }
     687             : 
     688         301 :     BIND(&maybe_double_elements);
     689             :     Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_DOUBLE_ELEMENTS), slow,
     690         301 :            &fast_double_elements);
     691             : 
     692         301 :     BIND(&fast_double_elements);
     693             :     {
     694             :       VisitAllFastElementsOneKind(FAST_DOUBLE_ELEMENTS, processor, slow, mode,
     695         301 :                                   direction);
     696             : 
     697         301 :       action(this);
     698             : 
     699             :       // No exception, return success
     700         301 :       Return(a_.value());
     701         301 :     }
     702         301 :   }
     703             : 
     704             :   Node* callbackfn_ = nullptr;
     705             :   Node* o_ = nullptr;
     706             :   Node* this_arg_ = nullptr;
     707             :   Node* len_ = nullptr;
     708             :   Node* context_ = nullptr;
     709             :   Node* receiver_ = nullptr;
     710             :   Node* new_target_ = nullptr;
     711             :   Variable k_;
     712             :   Variable a_;
     713             :   Variable to_;
     714             : };
     715             : 
     716         172 : TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
     717          43 :   VARIABLE(arg_index, MachineType::PointerRepresentation());
     718          43 :   Label default_label(this, &arg_index);
     719          43 :   Label smi_transition(this);
     720          43 :   Label object_push_pre(this);
     721          43 :   Label object_push(this, &arg_index);
     722          43 :   Label double_push(this, &arg_index);
     723          43 :   Label double_transition(this);
     724          43 :   Label runtime(this, Label::kDeferred);
     725             : 
     726             :   // TODO(ishell): use constants from Descriptor once the JSFunction linkage
     727             :   // arguments are reordered.
     728             :   Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
     729             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     730             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
     731             : 
     732          43 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     733          43 :   Node* receiver = args.GetReceiver();
     734             :   Node* kind = nullptr;
     735             : 
     736          43 :   Label fast(this);
     737             :   BranchIfFastJSArray(receiver, context, FastJSArrayAccessMode::ANY_ACCESS,
     738          43 :                       &fast, &runtime);
     739             : 
     740          43 :   BIND(&fast);
     741             :   {
     742          43 :     arg_index.Bind(IntPtrConstant(0));
     743          43 :     kind = EnsureArrayPushable(receiver, &runtime);
     744             :     GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS),
     745          43 :            &object_push_pre);
     746             : 
     747             :     Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, receiver, args,
     748          43 :                                           arg_index, &smi_transition);
     749          43 :     args.PopAndReturn(new_length);
     750             :   }
     751             : 
     752             :   // If the argument is not a smi, then use a heavyweight SetProperty to
     753             :   // transition the array for only the single next element. If the argument is
     754             :   // a smi, the failure is due to some other reason and we should fall back on
     755             :   // the most generic implementation for the rest of the array.
     756          43 :   BIND(&smi_transition);
     757             :   {
     758          43 :     Node* arg = args.AtIndex(arg_index.value());
     759          43 :     GotoIf(TaggedIsSmi(arg), &default_label);
     760          43 :     Node* length = LoadJSArrayLength(receiver);
     761             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
     762             :     // calling into the runtime to do the elements transition is overkill.
     763             :     CallRuntime(Runtime::kSetProperty, context, receiver, length, arg,
     764          43 :                 SmiConstant(STRICT));
     765          43 :     Increment(arg_index);
     766             :     // The runtime SetProperty call could have converted the array to dictionary
     767             :     // mode, which must be detected to abort the fast-path.
     768          43 :     Node* map = LoadMap(receiver);
     769          43 :     Node* bit_field2 = LoadMapBitField2(map);
     770             :     Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
     771             :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
     772          43 :            &default_label);
     773             : 
     774          43 :     GotoIfNotNumber(arg, &object_push);
     775          43 :     Goto(&double_push);
     776             :   }
     777             : 
     778          43 :   BIND(&object_push_pre);
     779             :   {
     780             :     Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push,
     781          43 :            &object_push);
     782             :   }
     783             : 
     784          43 :   BIND(&object_push);
     785             :   {
     786             :     Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, receiver, args,
     787          43 :                                           arg_index, &default_label);
     788          43 :     args.PopAndReturn(new_length);
     789             :   }
     790             : 
     791          43 :   BIND(&double_push);
     792             :   {
     793             :     Node* new_length = BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, receiver, args,
     794          43 :                                           arg_index, &double_transition);
     795          43 :     args.PopAndReturn(new_length);
     796             :   }
     797             : 
     798             :   // If the argument is not a double, then use a heavyweight SetProperty to
     799             :   // transition the array for only the single next element. If the argument is
     800             :   // a double, the failure is due to some other reason and we should fall back
     801             :   // on the most generic implementation for the rest of the array.
     802          43 :   BIND(&double_transition);
     803             :   {
     804          43 :     Node* arg = args.AtIndex(arg_index.value());
     805          43 :     GotoIfNumber(arg, &default_label);
     806          43 :     Node* length = LoadJSArrayLength(receiver);
     807             :     // TODO(danno): Use the KeyedStoreGeneric stub here when possible,
     808             :     // calling into the runtime to do the elements transition is overkill.
     809             :     CallRuntime(Runtime::kSetProperty, context, receiver, length, arg,
     810          43 :                 SmiConstant(STRICT));
     811          43 :     Increment(arg_index);
     812             :     // The runtime SetProperty call could have converted the array to dictionary
     813             :     // mode, which must be detected to abort the fast-path.
     814          43 :     Node* map = LoadMap(receiver);
     815          43 :     Node* bit_field2 = LoadMapBitField2(map);
     816             :     Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
     817             :     GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
     818          43 :            &default_label);
     819          43 :     Goto(&object_push);
     820             :   }
     821             : 
     822             :   // Fallback that stores un-processed arguments using the full, heavyweight
     823             :   // SetProperty machinery.
     824          43 :   BIND(&default_label);
     825             :   {
     826             :     args.ForEach(
     827          43 :         [this, receiver, context](Node* arg) {
     828          43 :           Node* length = LoadJSArrayLength(receiver);
     829             :           CallRuntime(Runtime::kSetProperty, context, receiver, length, arg,
     830          43 :                       SmiConstant(STRICT));
     831          43 :         },
     832         129 :         arg_index.value());
     833          43 :     args.PopAndReturn(LoadJSArrayLength(receiver));
     834             :   }
     835             : 
     836          43 :   BIND(&runtime);
     837             :   {
     838             :     Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
     839          43 :                                  MachineType::TaggedPointer());
     840             :     TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target,
     841          86 :                  argc);
     842          43 :   }
     843          43 : }
     844             : 
     845          86 : TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) {
     846             :   Node* context = Parameter(Descriptor::kContext);
     847             :   Node* receiver = Parameter(Descriptor::kReceiver);
     848             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     849             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     850             :   Node* array = Parameter(Descriptor::kArray);
     851             :   Node* object = Parameter(Descriptor::kObject);
     852             :   Node* initial_k = Parameter(Descriptor::kInitialK);
     853             :   Node* len = Parameter(Descriptor::kLength);
     854             :   Node* to = Parameter(Descriptor::kTo);
     855             : 
     856             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
     857             :                                             this_arg, array, object, initial_k,
     858             :                                             len, to);
     859             : 
     860             :   GenerateIteratingArrayBuiltinLoopContinuation(
     861             :       &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
     862         129 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
     863          43 : }
     864             : 
     865          86 : TF_BUILTIN(ArrayForEach, ArrayBuiltinCodeStubAssembler) {
     866             :   Node* context = Parameter(Descriptor::kContext);
     867             :   Node* receiver = Parameter(Descriptor::kReceiver);
     868             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     869             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     870             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     871             : 
     872             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
     873             :                                 new_target);
     874             : 
     875             :   GenerateIteratingArrayBuiltinBody(
     876             :       "Array.prototype.forEach",
     877             :       &ArrayBuiltinCodeStubAssembler::ForEachResultGenerator,
     878             :       &ArrayBuiltinCodeStubAssembler::ForEachProcessor,
     879             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
     880         215 :       CodeFactory::ArrayForEachLoopContinuation(isolate()));
     881          43 : }
     882             : 
     883          86 : TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) {
     884             :   Node* context = Parameter(Descriptor::kContext);
     885             :   Node* receiver = Parameter(Descriptor::kReceiver);
     886             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     887             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     888             :   Node* array = Parameter(Descriptor::kArray);
     889             :   Node* object = Parameter(Descriptor::kObject);
     890             :   Node* initial_k = Parameter(Descriptor::kInitialK);
     891             :   Node* len = Parameter(Descriptor::kLength);
     892             :   Node* to = Parameter(Descriptor::kTo);
     893             : 
     894             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
     895             :                                             this_arg, array, object, initial_k,
     896             :                                             len, to);
     897             : 
     898             :   GenerateIteratingArrayBuiltinLoopContinuation(
     899             :       &ArrayBuiltinCodeStubAssembler::SomeProcessor,
     900         129 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
     901          43 : }
     902             : 
     903          86 : TF_BUILTIN(ArraySome, ArrayBuiltinCodeStubAssembler) {
     904             :   Node* context = Parameter(Descriptor::kContext);
     905             :   Node* receiver = Parameter(Descriptor::kReceiver);
     906             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     907             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     908             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     909             : 
     910             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
     911             :                                 new_target);
     912             : 
     913             :   GenerateIteratingArrayBuiltinBody(
     914             :       "Array.prototype.some",
     915             :       &ArrayBuiltinCodeStubAssembler::SomeResultGenerator,
     916             :       &ArrayBuiltinCodeStubAssembler::SomeProcessor,
     917             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
     918         215 :       CodeFactory::ArraySomeLoopContinuation(isolate()));
     919          43 : }
     920             : 
     921          86 : TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinCodeStubAssembler) {
     922             :   Node* context = Parameter(Descriptor::kContext);
     923             :   Node* receiver = Parameter(Descriptor::kReceiver);
     924             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     925             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     926             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     927             : 
     928             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
     929             :                                 new_target);
     930             : 
     931             :   GenerateIteratingTypedArrayBuiltinBody(
     932             :       "%TypedArray%.prototype.some",
     933             :       &ArrayBuiltinCodeStubAssembler::SomeResultGenerator,
     934             :       &ArrayBuiltinCodeStubAssembler::SomeProcessor,
     935         172 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
     936          43 : }
     937             : 
     938          86 : TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) {
     939             :   Node* context = Parameter(Descriptor::kContext);
     940             :   Node* receiver = Parameter(Descriptor::kReceiver);
     941             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     942             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     943             :   Node* array = Parameter(Descriptor::kArray);
     944             :   Node* object = Parameter(Descriptor::kObject);
     945             :   Node* initial_k = Parameter(Descriptor::kInitialK);
     946             :   Node* len = Parameter(Descriptor::kLength);
     947             :   Node* to = Parameter(Descriptor::kTo);
     948             : 
     949             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
     950             :                                             this_arg, array, object, initial_k,
     951             :                                             len, to);
     952             : 
     953             :   GenerateIteratingArrayBuiltinLoopContinuation(
     954             :       &ArrayBuiltinCodeStubAssembler::EveryProcessor,
     955         129 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
     956          43 : }
     957             : 
     958          86 : TF_BUILTIN(ArrayEvery, ArrayBuiltinCodeStubAssembler) {
     959             :   Node* context = Parameter(Descriptor::kContext);
     960             :   Node* receiver = Parameter(Descriptor::kReceiver);
     961             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     962             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     963             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     964             : 
     965             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
     966             :                                 new_target);
     967             : 
     968             :   GenerateIteratingArrayBuiltinBody(
     969             :       "Array.prototype.every",
     970             :       &ArrayBuiltinCodeStubAssembler::EveryResultGenerator,
     971             :       &ArrayBuiltinCodeStubAssembler::EveryProcessor,
     972             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
     973         215 :       CodeFactory::ArrayEveryLoopContinuation(isolate()));
     974          43 : }
     975             : 
     976          86 : TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinCodeStubAssembler) {
     977             :   Node* context = Parameter(Descriptor::kContext);
     978             :   Node* receiver = Parameter(Descriptor::kReceiver);
     979             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     980             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     981             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     982             : 
     983             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
     984             :                                 new_target);
     985             : 
     986             :   GenerateIteratingTypedArrayBuiltinBody(
     987             :       "%TypedArray%.prototype.every",
     988             :       &ArrayBuiltinCodeStubAssembler::EveryResultGenerator,
     989             :       &ArrayBuiltinCodeStubAssembler::EveryProcessor,
     990         172 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
     991          43 : }
     992             : 
     993          86 : TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) {
     994             :   Node* context = Parameter(Descriptor::kContext);
     995             :   Node* receiver = Parameter(Descriptor::kReceiver);
     996             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
     997             :   Node* this_arg = Parameter(Descriptor::kThisArg);
     998             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
     999             :   Node* object = Parameter(Descriptor::kObject);
    1000             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1001             :   Node* len = Parameter(Descriptor::kLength);
    1002             :   Node* to = Parameter(Descriptor::kTo);
    1003             : 
    1004             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1005             :                                             this_arg, accumulator, object,
    1006             :                                             initial_k, len, to);
    1007             : 
    1008             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1009             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1010         129 :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
    1011          43 : }
    1012             : 
    1013          86 : TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) {
    1014             :   Node* context = Parameter(Descriptor::kContext);
    1015             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1016             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1017             :   Node* initial_value = Parameter(Descriptor::kInitialValue);
    1018             :   Node* new_target = Parameter(Descriptor::kNewTarget);
    1019             : 
    1020             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1021             :                                 new_target);
    1022             : 
    1023             :   GenerateIteratingArrayBuiltinBody(
    1024             :       "Array.prototype.reduce",
    1025             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1026             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1027             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1028         215 :       CodeFactory::ArrayReduceLoopContinuation(isolate()));
    1029          43 : }
    1030             : 
    1031          86 : TF_BUILTIN(TypedArrayPrototypeReduce, ArrayBuiltinCodeStubAssembler) {
    1032             :   Node* context = Parameter(Descriptor::kContext);
    1033             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1034             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1035             :   Node* initial_value = Parameter(Descriptor::kInitialValue);
    1036             :   Node* new_target = Parameter(Descriptor::kNewTarget);
    1037             : 
    1038             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1039             :                                 new_target);
    1040             : 
    1041             :   GenerateIteratingTypedArrayBuiltinBody(
    1042             :       "%TypedArray%.prototype.reduce",
    1043             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1044             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1045         172 :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
    1046          43 : }
    1047             : 
    1048          86 : TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1049             :   Node* context = Parameter(Descriptor::kContext);
    1050             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1051             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1052             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1053             :   Node* accumulator = Parameter(Descriptor::kAccumulator);
    1054             :   Node* object = Parameter(Descriptor::kObject);
    1055             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1056             :   Node* len = Parameter(Descriptor::kLength);
    1057             :   Node* to = Parameter(Descriptor::kTo);
    1058             : 
    1059             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1060             :                                             this_arg, accumulator, object,
    1061             :                                             initial_k, len, to);
    1062             : 
    1063             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1064             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1065             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1066         129 :       ForEachDirection::kReverse);
    1067          43 : }
    1068             : 
    1069          86 : TF_BUILTIN(ArrayReduceRight, ArrayBuiltinCodeStubAssembler) {
    1070             :   Node* context = Parameter(Descriptor::kContext);
    1071             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1072             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1073             :   Node* initial_value = Parameter(Descriptor::kInitialValue);
    1074             :   Node* new_target = Parameter(Descriptor::kNewTarget);
    1075             : 
    1076             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1077             :                                 new_target);
    1078             : 
    1079             :   GenerateIteratingArrayBuiltinBody(
    1080             :       "Array.prototype.reduceRight",
    1081             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1082             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1083             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1084             :       CodeFactory::ArrayReduceRightLoopContinuation(isolate()),
    1085         215 :       ForEachDirection::kReverse);
    1086          43 : }
    1087             : 
    1088          86 : TF_BUILTIN(TypedArrayPrototypeReduceRight, ArrayBuiltinCodeStubAssembler) {
    1089             :   Node* context = Parameter(Descriptor::kContext);
    1090             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1091             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1092             :   Node* initial_value = Parameter(Descriptor::kInitialValue);
    1093             :   Node* new_target = Parameter(Descriptor::kNewTarget);
    1094             : 
    1095             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
    1096             :                                 new_target);
    1097             : 
    1098             :   GenerateIteratingTypedArrayBuiltinBody(
    1099             :       "%TypedArray%.prototype.reduceRight",
    1100             :       &ArrayBuiltinCodeStubAssembler::ReduceResultGenerator,
    1101             :       &ArrayBuiltinCodeStubAssembler::ReduceProcessor,
    1102             :       &ArrayBuiltinCodeStubAssembler::ReducePostLoopAction,
    1103         172 :       ForEachDirection::kReverse);
    1104          43 : }
    1105             : 
    1106          86 : TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1107             :   Node* context = Parameter(Descriptor::kContext);
    1108             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1109             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1110             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1111             :   Node* array = Parameter(Descriptor::kArray);
    1112             :   Node* object = Parameter(Descriptor::kObject);
    1113             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1114             :   Node* len = Parameter(Descriptor::kLength);
    1115             :   Node* to = Parameter(Descriptor::kTo);
    1116             : 
    1117             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1118             :                                             this_arg, array, object, initial_k,
    1119             :                                             len, to);
    1120             : 
    1121             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1122             :       &ArrayBuiltinCodeStubAssembler::FilterProcessor,
    1123         129 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1124          43 : }
    1125             : 
    1126          86 : TF_BUILTIN(ArrayFilter, ArrayBuiltinCodeStubAssembler) {
    1127             :   Node* context = Parameter(Descriptor::kContext);
    1128             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1129             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1130             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1131             :   Node* new_target = Parameter(Descriptor::kNewTarget);
    1132             : 
    1133             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1134             :                                 new_target);
    1135             : 
    1136             :   GenerateIteratingArrayBuiltinBody(
    1137             :       "Array.prototype.filter",
    1138             :       &ArrayBuiltinCodeStubAssembler::FilterResultGenerator,
    1139             :       &ArrayBuiltinCodeStubAssembler::FilterProcessor,
    1140             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1141         215 :       CodeFactory::ArrayFilterLoopContinuation(isolate()));
    1142          43 : }
    1143             : 
    1144          86 : TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinCodeStubAssembler) {
    1145             :   Node* context = Parameter(Descriptor::kContext);
    1146             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1147             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1148             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1149             :   Node* array = Parameter(Descriptor::kArray);
    1150             :   Node* object = Parameter(Descriptor::kObject);
    1151             :   Node* initial_k = Parameter(Descriptor::kInitialK);
    1152             :   Node* len = Parameter(Descriptor::kLength);
    1153             :   Node* to = Parameter(Descriptor::kTo);
    1154             : 
    1155             :   InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
    1156             :                                             this_arg, array, object, initial_k,
    1157             :                                             len, to);
    1158             : 
    1159             :   GenerateIteratingArrayBuiltinLoopContinuation(
    1160             :       &ArrayBuiltinCodeStubAssembler::MapProcessor,
    1161         129 :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
    1162          43 : }
    1163             : 
    1164          86 : TF_BUILTIN(ArrayMap, ArrayBuiltinCodeStubAssembler) {
    1165             :   Node* context = Parameter(Descriptor::kContext);
    1166             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1167             :   Node* callbackfn = Parameter(Descriptor::kCallbackFn);
    1168             :   Node* this_arg = Parameter(Descriptor::kThisArg);
    1169             :   Node* new_target = Parameter(Descriptor::kNewTarget);
    1170             : 
    1171             :   InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
    1172             :                                 new_target);
    1173             : 
    1174             :   GenerateIteratingArrayBuiltinBody(
    1175             :       "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator,
    1176             :       &ArrayBuiltinCodeStubAssembler::MapProcessor,
    1177             :       &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
    1178         215 :       CodeFactory::ArrayMapLoopContinuation(isolate()));
    1179          43 : }
    1180             : 
    1181         129 : TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
    1182             :   Node* object = Parameter(Descriptor::kArg);
    1183             :   Node* context = Parameter(Descriptor::kContext);
    1184             : 
    1185          43 :   Label call_runtime(this), return_true(this), return_false(this);
    1186             : 
    1187          43 :   GotoIf(TaggedIsSmi(object), &return_false);
    1188          43 :   Node* instance_type = LoadInstanceType(object);
    1189             : 
    1190             :   GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)),
    1191          43 :          &return_true);
    1192             : 
    1193             :   // TODO(verwaest): Handle proxies in-place.
    1194             :   Branch(Word32Equal(instance_type, Int32Constant(JS_PROXY_TYPE)),
    1195          43 :          &call_runtime, &return_false);
    1196             : 
    1197          43 :   BIND(&return_true);
    1198          43 :   Return(BooleanConstant(true));
    1199             : 
    1200          43 :   BIND(&return_false);
    1201          43 :   Return(BooleanConstant(false));
    1202             : 
    1203          43 :   BIND(&call_runtime);
    1204          86 :   Return(CallRuntime(Runtime::kArrayIsArray, context, object));
    1205          43 : }
    1206             : 
    1207         129 : TF_BUILTIN(ArrayIncludes, CodeStubAssembler) {
    1208             :   Node* const array = Parameter(Descriptor::kReceiver);
    1209             :   Node* const search_element = Parameter(Descriptor::kSearchElement);
    1210             :   Node* const start_from = Parameter(Descriptor::kFromIndex);
    1211             :   Node* const context = Parameter(Descriptor::kContext);
    1212             : 
    1213          43 :   VARIABLE(index_var, MachineType::PointerRepresentation());
    1214             : 
    1215          43 :   Label init_k(this), return_true(this), return_false(this), call_runtime(this);
    1216          43 :   Label init_len(this), select_loop(this);
    1217             : 
    1218          43 :   index_var.Bind(IntPtrConstant(0));
    1219             : 
    1220             :   // Take slow path if not a JSArray, if retrieving elements requires
    1221             :   // traversing prototype, or if access checks are required.
    1222             :   BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ,
    1223          43 :                       &init_len, &call_runtime);
    1224             : 
    1225          43 :   BIND(&init_len);
    1226             :   // JSArray length is always an Smi for fast arrays.
    1227             :   CSA_ASSERT(this, TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset)));
    1228          43 :   Node* const len = LoadAndUntagObjectField(array, JSArray::kLengthOffset);
    1229             : 
    1230          43 :   GotoIf(IsUndefined(start_from), &select_loop);
    1231             : 
    1232             :   // Bailout to slow path if startIndex is not an Smi.
    1233          43 :   Branch(TaggedIsSmi(start_from), &init_k, &call_runtime);
    1234             : 
    1235          43 :   BIND(&init_k);
    1236             :   CSA_ASSERT(this, TaggedIsSmi(start_from));
    1237             :   Node* const untagged_start_from = SmiToWord(start_from);
    1238             :   index_var.Bind(
    1239             :       Select(IntPtrGreaterThanOrEqual(untagged_start_from, IntPtrConstant(0)),
    1240          43 :              [=]() { return untagged_start_from; },
    1241          43 :              [=]() {
    1242          43 :                Node* const index = IntPtrAdd(len, untagged_start_from);
    1243             :                return SelectConstant(IntPtrLessThan(index, IntPtrConstant(0)),
    1244             :                                      IntPtrConstant(0), index,
    1245          43 :                                      MachineType::PointerRepresentation());
    1246             :              },
    1247         129 :              MachineType::PointerRepresentation()));
    1248             : 
    1249          43 :   Goto(&select_loop);
    1250          43 :   BIND(&select_loop);
    1251             :   static int32_t kElementsKind[] = {
    1252             :       FAST_SMI_ELEMENTS,   FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
    1253             :       FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS,    FAST_HOLEY_DOUBLE_ELEMENTS,
    1254             :   };
    1255             : 
    1256          43 :   Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this);
    1257             :   Label* element_kind_handlers[] = {&if_smiorobjects,   &if_smiorobjects,
    1258             :                                     &if_smiorobjects,   &if_smiorobjects,
    1259          43 :                                     &if_packed_doubles, &if_holey_doubles};
    1260             : 
    1261          43 :   Node* map = LoadMap(array);
    1262          43 :   Node* elements_kind = LoadMapElementsKind(map);
    1263          43 :   Node* elements = LoadElements(array);
    1264             :   Switch(elements_kind, &return_false, kElementsKind, element_kind_handlers,
    1265          43 :          arraysize(kElementsKind));
    1266             : 
    1267          43 :   BIND(&if_smiorobjects);
    1268             :   {
    1269          43 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1270          43 :     Label ident_loop(this, &index_var), heap_num_loop(this, &search_num),
    1271          43 :         string_loop(this, &index_var), undef_loop(this, &index_var),
    1272          43 :         not_smi(this), not_heap_num(this);
    1273             : 
    1274          43 :     GotoIfNot(TaggedIsSmi(search_element), &not_smi);
    1275          43 :     search_num.Bind(SmiToFloat64(search_element));
    1276          43 :     Goto(&heap_num_loop);
    1277             : 
    1278          43 :     BIND(&not_smi);
    1279          43 :     GotoIf(WordEqual(search_element, UndefinedConstant()), &undef_loop);
    1280          43 :     Node* map = LoadMap(search_element);
    1281          43 :     GotoIfNot(IsHeapNumberMap(map), &not_heap_num);
    1282          43 :     search_num.Bind(LoadHeapNumberValue(search_element));
    1283          43 :     Goto(&heap_num_loop);
    1284             : 
    1285          43 :     BIND(&not_heap_num);
    1286          43 :     Node* search_type = LoadMapInstanceType(map);
    1287          43 :     GotoIf(IsStringInstanceType(search_type), &string_loop);
    1288          43 :     Goto(&ident_loop);
    1289             : 
    1290          43 :     BIND(&ident_loop);
    1291             :     {
    1292          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1293          43 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1294          43 :       GotoIf(WordEqual(element_k, search_element), &return_true);
    1295             : 
    1296          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1297          43 :       Goto(&ident_loop);
    1298             :     }
    1299             : 
    1300          43 :     BIND(&undef_loop);
    1301             :     {
    1302          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1303          43 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1304          43 :       GotoIf(WordEqual(element_k, UndefinedConstant()), &return_true);
    1305          43 :       GotoIf(WordEqual(element_k, TheHoleConstant()), &return_true);
    1306             : 
    1307          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1308          43 :       Goto(&undef_loop);
    1309             :     }
    1310             : 
    1311          43 :     BIND(&heap_num_loop);
    1312             :     {
    1313          43 :       Label nan_loop(this, &index_var), not_nan_loop(this, &index_var);
    1314          43 :       BranchIfFloat64IsNaN(search_num.value(), &nan_loop, &not_nan_loop);
    1315             : 
    1316          43 :       BIND(&not_nan_loop);
    1317             :       {
    1318          43 :         Label continue_loop(this), not_smi(this);
    1319          43 :         GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1320          43 :         Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1321          43 :         GotoIfNot(TaggedIsSmi(element_k), &not_smi);
    1322             :         Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)),
    1323          43 :                &return_true, &continue_loop);
    1324             : 
    1325          43 :         BIND(&not_smi);
    1326          43 :         GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    1327             :         Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)),
    1328          43 :                &return_true, &continue_loop);
    1329             : 
    1330          43 :         BIND(&continue_loop);
    1331          43 :         index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1332          86 :         Goto(&not_nan_loop);
    1333             :       }
    1334             : 
    1335          43 :       BIND(&nan_loop);
    1336             :       {
    1337             :         Label continue_loop(this);
    1338          43 :         GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1339          43 :         Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1340          43 :         GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1341          43 :         GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    1342             :         BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_true,
    1343          43 :                              &continue_loop);
    1344             : 
    1345          43 :         BIND(&continue_loop);
    1346          43 :         index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1347          43 :         Goto(&nan_loop);
    1348          43 :       }
    1349             :     }
    1350             : 
    1351          43 :     BIND(&string_loop);
    1352             :     {
    1353             :       Label continue_loop(this);
    1354          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1355          43 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1356          43 :       GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1357             :       GotoIfNot(IsStringInstanceType(LoadInstanceType(element_k)),
    1358          43 :                 &continue_loop);
    1359             : 
    1360             :       // TODO(bmeurer): Consider inlining the StringEqual logic here.
    1361             :       Node* result = CallStub(CodeFactory::StringEqual(isolate()), context,
    1362          86 :                               search_element, element_k);
    1363             :       Branch(WordEqual(BooleanConstant(true), result), &return_true,
    1364          43 :              &continue_loop);
    1365             : 
    1366          43 :       BIND(&continue_loop);
    1367          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1368          43 :       Goto(&string_loop);
    1369          43 :     }
    1370             :   }
    1371             : 
    1372          43 :   BIND(&if_packed_doubles);
    1373             :   {
    1374          43 :     Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    1375          43 :         hole_loop(this, &index_var), search_notnan(this);
    1376          86 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1377             : 
    1378          43 :     GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1379          43 :     search_num.Bind(SmiToFloat64(search_element));
    1380          43 :     Goto(&not_nan_loop);
    1381             : 
    1382          43 :     BIND(&search_notnan);
    1383          43 :     GotoIfNot(IsHeapNumber(search_element), &return_false);
    1384             : 
    1385          43 :     search_num.Bind(LoadHeapNumberValue(search_element));
    1386             : 
    1387          43 :     BranchIfFloat64IsNaN(search_num.value(), &nan_loop, &not_nan_loop);
    1388             : 
    1389             :     // Search for HeapNumber
    1390          43 :     BIND(&not_nan_loop);
    1391             :     {
    1392             :       Label continue_loop(this);
    1393          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1394             :       Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    1395          43 :                                                     MachineType::Float64());
    1396             :       Branch(Float64Equal(element_k, search_num.value()), &return_true,
    1397          43 :              &continue_loop);
    1398          43 :       BIND(&continue_loop);
    1399          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1400          43 :       Goto(&not_nan_loop);
    1401             :     }
    1402             : 
    1403             :     // Search for NaN
    1404          43 :     BIND(&nan_loop);
    1405             :     {
    1406             :       Label continue_loop(this);
    1407          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1408             :       Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    1409          43 :                                                     MachineType::Float64());
    1410          43 :       BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop);
    1411          43 :       BIND(&continue_loop);
    1412          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1413          43 :       Goto(&nan_loop);
    1414          43 :     }
    1415             :   }
    1416             : 
    1417          43 :   BIND(&if_holey_doubles);
    1418             :   {
    1419          43 :     Label nan_loop(this, &index_var), not_nan_loop(this, &index_var),
    1420          43 :         hole_loop(this, &index_var), search_notnan(this);
    1421          86 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1422             : 
    1423          43 :     GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1424          43 :     search_num.Bind(SmiToFloat64(search_element));
    1425          43 :     Goto(&not_nan_loop);
    1426             : 
    1427          43 :     BIND(&search_notnan);
    1428          43 :     GotoIf(WordEqual(search_element, UndefinedConstant()), &hole_loop);
    1429          43 :     GotoIfNot(IsHeapNumber(search_element), &return_false);
    1430             : 
    1431          43 :     search_num.Bind(LoadHeapNumberValue(search_element));
    1432             : 
    1433          43 :     BranchIfFloat64IsNaN(search_num.value(), &nan_loop, &not_nan_loop);
    1434             : 
    1435             :     // Search for HeapNumber
    1436          43 :     BIND(&not_nan_loop);
    1437             :     {
    1438             :       Label continue_loop(this);
    1439          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1440             : 
    1441             :       // Load double value or continue if it contains a double hole.
    1442             :       Node* element_k = LoadFixedDoubleArrayElement(
    1443             :           elements, index_var.value(), MachineType::Float64(), 0,
    1444          43 :           INTPTR_PARAMETERS, &continue_loop);
    1445             : 
    1446             :       Branch(Float64Equal(element_k, search_num.value()), &return_true,
    1447          43 :              &continue_loop);
    1448          43 :       BIND(&continue_loop);
    1449          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1450          43 :       Goto(&not_nan_loop);
    1451             :     }
    1452             : 
    1453             :     // Search for NaN
    1454          43 :     BIND(&nan_loop);
    1455             :     {
    1456             :       Label continue_loop(this);
    1457          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1458             : 
    1459             :       // Load double value or continue if it contains a double hole.
    1460             :       Node* element_k = LoadFixedDoubleArrayElement(
    1461             :           elements, index_var.value(), MachineType::Float64(), 0,
    1462          43 :           INTPTR_PARAMETERS, &continue_loop);
    1463             : 
    1464          43 :       BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop);
    1465          43 :       BIND(&continue_loop);
    1466          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1467          43 :       Goto(&nan_loop);
    1468             :     }
    1469             : 
    1470             :     // Search for the Hole
    1471          43 :     BIND(&hole_loop);
    1472             :     {
    1473          43 :       GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false);
    1474             : 
    1475             :       // Check if the element is a double hole, but don't load it.
    1476             :       LoadFixedDoubleArrayElement(elements, index_var.value(),
    1477             :                                   MachineType::None(), 0, INTPTR_PARAMETERS,
    1478          43 :                                   &return_true);
    1479             : 
    1480          43 :       index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1)));
    1481          43 :       Goto(&hole_loop);
    1482          43 :     }
    1483             :   }
    1484             : 
    1485          43 :   BIND(&return_true);
    1486          43 :   Return(TrueConstant());
    1487             : 
    1488          43 :   BIND(&return_false);
    1489          43 :   Return(FalseConstant());
    1490             : 
    1491          43 :   BIND(&call_runtime);
    1492             :   Return(CallRuntime(Runtime::kArrayIncludes_Slow, context, array,
    1493          86 :                      search_element, start_from));
    1494          43 : }
    1495             : 
    1496         129 : TF_BUILTIN(ArrayIndexOf, CodeStubAssembler) {
    1497             :   Node* array = Parameter(Descriptor::kReceiver);
    1498             :   Node* search_element = Parameter(Descriptor::kSearchElement);
    1499             :   Node* start_from = Parameter(Descriptor::kFromIndex);
    1500             :   Node* context = Parameter(Descriptor::kContext);
    1501             : 
    1502          43 :   Node* intptr_zero = IntPtrConstant(0);
    1503          43 :   Node* intptr_one = IntPtrConstant(1);
    1504             : 
    1505          43 :   VARIABLE(len_var, MachineType::PointerRepresentation());
    1506          86 :   VARIABLE(index_var, MachineType::PointerRepresentation());
    1507          86 :   VARIABLE(start_from_var, MachineType::PointerRepresentation());
    1508             : 
    1509          43 :   Label init_k(this), return_found(this), return_not_found(this),
    1510          43 :       call_runtime(this);
    1511             : 
    1512          43 :   Label init_len(this);
    1513             : 
    1514          43 :   index_var.Bind(intptr_zero);
    1515          43 :   len_var.Bind(intptr_zero);
    1516             : 
    1517             :   // Take slow path if not a JSArray, if retrieving elements requires
    1518             :   // traversing prototype, or if access checks are required.
    1519             :   BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ,
    1520          43 :                       &init_len, &call_runtime);
    1521             : 
    1522          43 :   BIND(&init_len);
    1523             :   {
    1524             :     // JSArray length is always an Smi for fast arrays.
    1525             :     CSA_ASSERT(this,
    1526             :                TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset)));
    1527          43 :     Node* len = LoadAndUntagObjectField(array, JSArray::kLengthOffset);
    1528             : 
    1529          43 :     len_var.Bind(len);
    1530          43 :     Branch(WordEqual(len_var.value(), intptr_zero), &return_not_found, &init_k);
    1531             :   }
    1532             : 
    1533          43 :   BIND(&init_k);
    1534             :   {
    1535             :     // For now only deal with undefined and Smis here; we must be really careful
    1536             :     // with side-effects from the ToInteger conversion as the side-effects might
    1537             :     // render our assumptions about the receiver being a fast JSArray and the
    1538             :     // length invalid.
    1539          43 :     Label done(this), init_k_smi(this), init_k_other(this), init_k_zero(this),
    1540          43 :         init_k_n(this);
    1541          43 :     Branch(TaggedIsSmi(start_from), &init_k_smi, &init_k_other);
    1542             : 
    1543          43 :     BIND(&init_k_smi);
    1544             :     {
    1545             :       // The fromIndex is a Smi.
    1546          43 :       start_from_var.Bind(SmiUntag(start_from));
    1547          43 :       Goto(&init_k_n);
    1548             :     }
    1549             : 
    1550          43 :     BIND(&init_k_other);
    1551             :     {
    1552             :       // The fromIndex must be undefined then, otherwise bailout and let the
    1553             :       // runtime deal with the full ToInteger conversion.
    1554          43 :       GotoIfNot(IsUndefined(start_from), &call_runtime);
    1555          43 :       start_from_var.Bind(intptr_zero);
    1556          43 :       Goto(&init_k_n);
    1557             :     }
    1558             : 
    1559          43 :     BIND(&init_k_n);
    1560             :     {
    1561          43 :       Label if_positive(this), if_negative(this), done(this);
    1562             :       Branch(IntPtrLessThan(start_from_var.value(), intptr_zero), &if_negative,
    1563          43 :              &if_positive);
    1564             : 
    1565          43 :       BIND(&if_positive);
    1566             :       {
    1567          43 :         index_var.Bind(start_from_var.value());
    1568          43 :         Goto(&done);
    1569             :       }
    1570             : 
    1571          43 :       BIND(&if_negative);
    1572             :       {
    1573          43 :         index_var.Bind(IntPtrAdd(len_var.value(), start_from_var.value()));
    1574             :         Branch(IntPtrLessThan(index_var.value(), intptr_zero), &init_k_zero,
    1575          43 :                &done);
    1576             :       }
    1577             : 
    1578          43 :       BIND(&init_k_zero);
    1579             :       {
    1580          43 :         index_var.Bind(intptr_zero);
    1581          43 :         Goto(&done);
    1582             :       }
    1583             : 
    1584          86 :       BIND(&done);
    1585          43 :     }
    1586             :   }
    1587             : 
    1588             :   static int32_t kElementsKind[] = {
    1589             :       FAST_SMI_ELEMENTS,   FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
    1590             :       FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS,    FAST_HOLEY_DOUBLE_ELEMENTS,
    1591             :   };
    1592             : 
    1593          43 :   Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this);
    1594             :   Label* element_kind_handlers[] = {&if_smiorobjects,   &if_smiorobjects,
    1595             :                                     &if_smiorobjects,   &if_smiorobjects,
    1596          43 :                                     &if_packed_doubles, &if_holey_doubles};
    1597             : 
    1598          43 :   Node* map = LoadMap(array);
    1599          43 :   Node* elements_kind = LoadMapElementsKind(map);
    1600          43 :   Node* elements = LoadElements(array);
    1601             :   Switch(elements_kind, &return_not_found, kElementsKind, element_kind_handlers,
    1602          43 :          arraysize(kElementsKind));
    1603             : 
    1604          43 :   BIND(&if_smiorobjects);
    1605             :   {
    1606          43 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1607          43 :     Label ident_loop(this, &index_var), heap_num_loop(this, &search_num),
    1608          43 :         string_loop(this, &index_var), not_smi(this), not_heap_num(this);
    1609             : 
    1610          43 :     GotoIfNot(TaggedIsSmi(search_element), &not_smi);
    1611          43 :     search_num.Bind(SmiToFloat64(search_element));
    1612          43 :     Goto(&heap_num_loop);
    1613             : 
    1614          43 :     BIND(&not_smi);
    1615          43 :     Node* map = LoadMap(search_element);
    1616          43 :     GotoIfNot(IsHeapNumberMap(map), &not_heap_num);
    1617          43 :     search_num.Bind(LoadHeapNumberValue(search_element));
    1618          43 :     Goto(&heap_num_loop);
    1619             : 
    1620          43 :     BIND(&not_heap_num);
    1621          43 :     Node* search_type = LoadMapInstanceType(map);
    1622          43 :     GotoIf(IsStringInstanceType(search_type), &string_loop);
    1623          43 :     Goto(&ident_loop);
    1624             : 
    1625          43 :     BIND(&ident_loop);
    1626             :     {
    1627             :       GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()),
    1628          43 :                 &return_not_found);
    1629          43 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1630          43 :       GotoIf(WordEqual(element_k, search_element), &return_found);
    1631             : 
    1632          43 :       index_var.Bind(IntPtrAdd(index_var.value(), intptr_one));
    1633          43 :       Goto(&ident_loop);
    1634             :     }
    1635             : 
    1636          43 :     BIND(&heap_num_loop);
    1637             :     {
    1638             :       Label not_nan_loop(this, &index_var);
    1639             :       BranchIfFloat64IsNaN(search_num.value(), &return_not_found,
    1640          43 :                            &not_nan_loop);
    1641             : 
    1642          43 :       BIND(&not_nan_loop);
    1643             :       {
    1644          43 :         Label continue_loop(this), not_smi(this);
    1645             :         GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()),
    1646          43 :                   &return_not_found);
    1647          43 :         Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1648          43 :         GotoIfNot(TaggedIsSmi(element_k), &not_smi);
    1649             :         Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)),
    1650          43 :                &return_found, &continue_loop);
    1651             : 
    1652          43 :         BIND(&not_smi);
    1653          43 :         GotoIfNot(IsHeapNumber(element_k), &continue_loop);
    1654             :         Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)),
    1655          43 :                &return_found, &continue_loop);
    1656             : 
    1657          43 :         BIND(&continue_loop);
    1658          43 :         index_var.Bind(IntPtrAdd(index_var.value(), intptr_one));
    1659          86 :         Goto(&not_nan_loop);
    1660          43 :       }
    1661             :     }
    1662             : 
    1663          43 :     BIND(&string_loop);
    1664             :     {
    1665             :       Label continue_loop(this);
    1666             :       GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()),
    1667          43 :                 &return_not_found);
    1668          43 :       Node* element_k = LoadFixedArrayElement(elements, index_var.value());
    1669          43 :       GotoIf(TaggedIsSmi(element_k), &continue_loop);
    1670          43 :       GotoIfNot(IsString(element_k), &continue_loop);
    1671             : 
    1672             :       // TODO(bmeurer): Consider inlining the StringEqual logic here.
    1673          43 :       Callable callable = CodeFactory::StringEqual(isolate());
    1674          43 :       Node* result = CallStub(callable, context, search_element, element_k);
    1675             :       Branch(WordEqual(BooleanConstant(true), result), &return_found,
    1676          43 :              &continue_loop);
    1677             : 
    1678          43 :       BIND(&continue_loop);
    1679          43 :       index_var.Bind(IntPtrAdd(index_var.value(), intptr_one));
    1680          86 :       Goto(&string_loop);
    1681          43 :     }
    1682             :   }
    1683             : 
    1684          43 :   BIND(&if_packed_doubles);
    1685             :   {
    1686          43 :     Label not_nan_loop(this, &index_var), search_notnan(this);
    1687          86 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1688             : 
    1689          43 :     GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1690          43 :     search_num.Bind(SmiToFloat64(search_element));
    1691          43 :     Goto(&not_nan_loop);
    1692             : 
    1693          43 :     BIND(&search_notnan);
    1694          43 :     GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    1695             : 
    1696          43 :     search_num.Bind(LoadHeapNumberValue(search_element));
    1697             : 
    1698          43 :     BranchIfFloat64IsNaN(search_num.value(), &return_not_found, &not_nan_loop);
    1699             : 
    1700             :     // Search for HeapNumber
    1701          43 :     BIND(&not_nan_loop);
    1702             :     {
    1703             :       GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()),
    1704          43 :                 &return_not_found);
    1705             :       Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
    1706          43 :                                                     MachineType::Float64());
    1707          43 :       GotoIf(Float64Equal(element_k, search_num.value()), &return_found);
    1708             : 
    1709          43 :       index_var.Bind(IntPtrAdd(index_var.value(), intptr_one));
    1710          43 :       Goto(&not_nan_loop);
    1711          43 :     }
    1712             :   }
    1713             : 
    1714          43 :   BIND(&if_holey_doubles);
    1715             :   {
    1716          43 :     Label not_nan_loop(this, &index_var), search_notnan(this);
    1717          86 :     VARIABLE(search_num, MachineRepresentation::kFloat64);
    1718             : 
    1719          43 :     GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
    1720          43 :     search_num.Bind(SmiToFloat64(search_element));
    1721          43 :     Goto(&not_nan_loop);
    1722             : 
    1723          43 :     BIND(&search_notnan);
    1724          43 :     GotoIfNot(IsHeapNumber(search_element), &return_not_found);
    1725             : 
    1726          43 :     search_num.Bind(LoadHeapNumberValue(search_element));
    1727             : 
    1728          43 :     BranchIfFloat64IsNaN(search_num.value(), &return_not_found, &not_nan_loop);
    1729             : 
    1730             :     // Search for HeapNumber
    1731          43 :     BIND(&not_nan_loop);
    1732             :     {
    1733             :       Label continue_loop(this);
    1734             :       GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()),
    1735          43 :                 &return_not_found);
    1736             : 
    1737             :       // Load double value or continue if it contains a double hole.
    1738             :       Node* element_k = LoadFixedDoubleArrayElement(
    1739             :           elements, index_var.value(), MachineType::Float64(), 0,
    1740          43 :           INTPTR_PARAMETERS, &continue_loop);
    1741             : 
    1742             :       Branch(Float64Equal(element_k, search_num.value()), &return_found,
    1743          43 :              &continue_loop);
    1744          43 :       BIND(&continue_loop);
    1745          43 :       index_var.Bind(IntPtrAdd(index_var.value(), intptr_one));
    1746          43 :       Goto(&not_nan_loop);
    1747          43 :     }
    1748             :   }
    1749             : 
    1750          43 :   BIND(&return_found);
    1751          43 :   Return(SmiTag(index_var.value()));
    1752             : 
    1753          43 :   BIND(&return_not_found);
    1754          43 :   Return(NumberConstant(-1));
    1755             : 
    1756          43 :   BIND(&call_runtime);
    1757             :   Return(CallRuntime(Runtime::kArrayIndexOf, context, array, search_element,
    1758          86 :                      start_from));
    1759          43 : }
    1760             : 
    1761             : class ArrayPrototypeIterationAssembler : public CodeStubAssembler {
    1762             :  public:
    1763             :   explicit ArrayPrototypeIterationAssembler(compiler::CodeAssemblerState* state)
    1764         129 :       : CodeStubAssembler(state) {}
    1765             : 
    1766             :  protected:
    1767         129 :   void Generate_ArrayPrototypeIterationMethod(Node* context, Node* receiver,
    1768             :                                               IterationKind iteration_kind) {
    1769         129 :     VARIABLE(var_array, MachineRepresentation::kTagged);
    1770         258 :     VARIABLE(var_map, MachineRepresentation::kTagged);
    1771         258 :     VARIABLE(var_type, MachineRepresentation::kWord32);
    1772             : 
    1773         129 :     Label if_isnotobject(this, Label::kDeferred);
    1774         129 :     Label create_array_iterator(this);
    1775             : 
    1776         129 :     GotoIf(TaggedIsSmi(receiver), &if_isnotobject);
    1777         129 :     var_array.Bind(receiver);
    1778         129 :     var_map.Bind(LoadMap(receiver));
    1779         129 :     var_type.Bind(LoadMapInstanceType(var_map.value()));
    1780             :     Branch(IsJSReceiverInstanceType(var_type.value()), &create_array_iterator,
    1781         129 :            &if_isnotobject);
    1782             : 
    1783         129 :     BIND(&if_isnotobject);
    1784             :     {
    1785         129 :       Callable callable = CodeFactory::ToObject(isolate());
    1786         129 :       Node* result = CallStub(callable, context, receiver);
    1787         129 :       var_array.Bind(result);
    1788         129 :       var_map.Bind(LoadMap(result));
    1789         129 :       var_type.Bind(LoadMapInstanceType(var_map.value()));
    1790         129 :       Goto(&create_array_iterator);
    1791             :     }
    1792             : 
    1793         129 :     BIND(&create_array_iterator);
    1794             :     Return(CreateArrayIterator(var_array.value(), var_map.value(),
    1795         258 :                                var_type.value(), context, iteration_kind));
    1796         129 :   }
    1797             : };
    1798             : 
    1799         172 : TF_BUILTIN(ArrayPrototypeValues, ArrayPrototypeIterationAssembler) {
    1800             :   Node* context = Parameter(Descriptor::kContext);
    1801             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1802             :   Generate_ArrayPrototypeIterationMethod(context, receiver,
    1803          43 :                                          IterationKind::kValues);
    1804          43 : }
    1805             : 
    1806         172 : TF_BUILTIN(ArrayPrototypeEntries, ArrayPrototypeIterationAssembler) {
    1807             :   Node* context = Parameter(Descriptor::kContext);
    1808             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1809             :   Generate_ArrayPrototypeIterationMethod(context, receiver,
    1810          43 :                                          IterationKind::kEntries);
    1811          43 : }
    1812             : 
    1813         172 : TF_BUILTIN(ArrayPrototypeKeys, ArrayPrototypeIterationAssembler) {
    1814             :   Node* context = Parameter(Descriptor::kContext);
    1815             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1816             :   Generate_ArrayPrototypeIterationMethod(context, receiver,
    1817          43 :                                          IterationKind::kKeys);
    1818          43 : }
    1819             : 
    1820         172 : TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
    1821             :   Handle<String> operation = factory()->NewStringFromAsciiChecked(
    1822          43 :       "Array Iterator.prototype.next", TENURED);
    1823             : 
    1824             :   Node* context = Parameter(Descriptor::kContext);
    1825             :   Node* iterator = Parameter(Descriptor::kReceiver);
    1826             : 
    1827          43 :   VARIABLE(var_value, MachineRepresentation::kTagged);
    1828          86 :   VARIABLE(var_done, MachineRepresentation::kTagged);
    1829             : 
    1830             :   // Required, or else `throw_bad_receiver` fails a DCHECK due to these
    1831             :   // variables not being bound along all paths, despite not being used.
    1832          43 :   var_done.Bind(TrueConstant());
    1833          43 :   var_value.Bind(UndefinedConstant());
    1834             : 
    1835          43 :   Label throw_bad_receiver(this, Label::kDeferred);
    1836          43 :   Label set_done(this);
    1837          43 :   Label allocate_key_result(this);
    1838          43 :   Label allocate_entry_if_needed(this);
    1839          43 :   Label allocate_iterator_result(this);
    1840          43 :   Label generic_values(this);
    1841             : 
    1842             :   // If O does not have all of the internal slots of an Array Iterator Instance
    1843             :   // (22.1.5.3), throw a TypeError exception
    1844          43 :   GotoIf(TaggedIsSmi(iterator), &throw_bad_receiver);
    1845          43 :   Node* instance_type = LoadInstanceType(iterator);
    1846             :   GotoIf(
    1847             :       Uint32LessThan(
    1848             :           Int32Constant(LAST_ARRAY_ITERATOR_TYPE - FIRST_ARRAY_ITERATOR_TYPE),
    1849             :           Int32Sub(instance_type, Int32Constant(FIRST_ARRAY_ITERATOR_TYPE))),
    1850          43 :       &throw_bad_receiver);
    1851             : 
    1852             :   // Let a be O.[[IteratedObject]].
    1853             :   Node* array =
    1854          43 :       LoadObjectField(iterator, JSArrayIterator::kIteratedObjectOffset);
    1855             : 
    1856             :   // Let index be O.[[ArrayIteratorNextIndex]].
    1857          43 :   Node* index = LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset);
    1858             :   Node* orig_map =
    1859          43 :       LoadObjectField(iterator, JSArrayIterator::kIteratedObjectMapOffset);
    1860          43 :   Node* array_map = LoadMap(array);
    1861             : 
    1862          43 :   Label if_isfastarray(this), if_isnotfastarray(this),
    1863          43 :       if_isdetached(this, Label::kDeferred);
    1864             : 
    1865          43 :   Branch(WordEqual(orig_map, array_map), &if_isfastarray, &if_isnotfastarray);
    1866             : 
    1867          43 :   BIND(&if_isfastarray);
    1868             :   {
    1869             :     CSA_ASSERT(this, Word32Equal(LoadMapInstanceType(array_map),
    1870             :                                  Int32Constant(JS_ARRAY_TYPE)));
    1871             : 
    1872          43 :     Node* length = LoadObjectField(array, JSArray::kLengthOffset);
    1873             : 
    1874             :     CSA_ASSERT(this, TaggedIsSmi(length));
    1875             :     CSA_ASSERT(this, TaggedIsSmi(index));
    1876             : 
    1877          43 :     GotoIfNot(SmiBelow(index, length), &set_done);
    1878             : 
    1879          43 :     Node* one = SmiConstant(Smi::FromInt(1));
    1880             :     StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
    1881          43 :                                    SmiAdd(index, one));
    1882             : 
    1883          43 :     var_done.Bind(FalseConstant());
    1884          43 :     Node* elements = LoadElements(array);
    1885             : 
    1886             :     static int32_t kInstanceType[] = {
    1887             :         JS_FAST_ARRAY_KEY_ITERATOR_TYPE,
    1888             :         JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    1889             :         JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    1890             :         JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    1891             :         JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    1892             :         JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    1893             :         JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    1894             :         JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE,
    1895             :         JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE,
    1896             :         JS_FAST_ARRAY_VALUE_ITERATOR_TYPE,
    1897             :         JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE,
    1898             :         JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
    1899             :         JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
    1900             :     };
    1901             : 
    1902          43 :     Label packed_object_values(this), holey_object_values(this),
    1903          43 :         packed_double_values(this), holey_double_values(this);
    1904             :     Label* kInstanceTypeHandlers[] = {
    1905             :         &allocate_key_result,  &packed_object_values, &holey_object_values,
    1906             :         &packed_object_values, &holey_object_values,  &packed_double_values,
    1907             :         &holey_double_values,  &packed_object_values, &holey_object_values,
    1908             :         &packed_object_values, &holey_object_values,  &packed_double_values,
    1909          43 :         &holey_double_values};
    1910             : 
    1911             :     Switch(instance_type, &throw_bad_receiver, kInstanceType,
    1912          43 :            kInstanceTypeHandlers, arraysize(kInstanceType));
    1913             : 
    1914          43 :     BIND(&packed_object_values);
    1915             :     {
    1916          43 :       var_value.Bind(LoadFixedArrayElement(elements, index, 0, SMI_PARAMETERS));
    1917          43 :       Goto(&allocate_entry_if_needed);
    1918             :     }
    1919             : 
    1920          43 :     BIND(&packed_double_values);
    1921             :     {
    1922             :       Node* value = LoadFixedDoubleArrayElement(
    1923          43 :           elements, index, MachineType::Float64(), 0, SMI_PARAMETERS);
    1924          43 :       var_value.Bind(AllocateHeapNumberWithValue(value));
    1925          43 :       Goto(&allocate_entry_if_needed);
    1926             :     }
    1927             : 
    1928          43 :     BIND(&holey_object_values);
    1929             :     {
    1930             :       // Check the array_protector cell, and take the slow path if it's invalid.
    1931          43 :       Node* invalid = SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid));
    1932          43 :       Node* cell = LoadRoot(Heap::kArrayProtectorRootIndex);
    1933          43 :       Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
    1934          43 :       GotoIf(WordEqual(cell_value, invalid), &generic_values);
    1935             : 
    1936          43 :       var_value.Bind(UndefinedConstant());
    1937          43 :       Node* value = LoadFixedArrayElement(elements, index, 0, SMI_PARAMETERS);
    1938          43 :       GotoIf(WordEqual(value, TheHoleConstant()), &allocate_entry_if_needed);
    1939          43 :       var_value.Bind(value);
    1940          43 :       Goto(&allocate_entry_if_needed);
    1941             :     }
    1942             : 
    1943          43 :     BIND(&holey_double_values);
    1944             :     {
    1945             :       // Check the array_protector cell, and take the slow path if it's invalid.
    1946          43 :       Node* invalid = SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid));
    1947          43 :       Node* cell = LoadRoot(Heap::kArrayProtectorRootIndex);
    1948          43 :       Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
    1949          43 :       GotoIf(WordEqual(cell_value, invalid), &generic_values);
    1950             : 
    1951          43 :       var_value.Bind(UndefinedConstant());
    1952             :       Node* value = LoadFixedDoubleArrayElement(
    1953             :           elements, index, MachineType::Float64(), 0, SMI_PARAMETERS,
    1954          43 :           &allocate_entry_if_needed);
    1955          43 :       var_value.Bind(AllocateHeapNumberWithValue(value));
    1956          43 :       Goto(&allocate_entry_if_needed);
    1957          43 :     }
    1958             :   }
    1959             : 
    1960          43 :   BIND(&if_isnotfastarray);
    1961             :   {
    1962          43 :     Label if_istypedarray(this), if_isgeneric(this);
    1963             : 
    1964             :     // If a is undefined, return CreateIterResultObject(undefined, true)
    1965          43 :     GotoIf(WordEqual(array, UndefinedConstant()), &allocate_iterator_result);
    1966             : 
    1967          43 :     Node* array_type = LoadInstanceType(array);
    1968             :     Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
    1969          43 :            &if_istypedarray, &if_isgeneric);
    1970             : 
    1971          43 :     BIND(&if_isgeneric);
    1972             :     {
    1973             :       Label if_wasfastarray(this);
    1974             : 
    1975             :       Node* length = nullptr;
    1976             :       {
    1977          43 :         VARIABLE(var_length, MachineRepresentation::kTagged);
    1978          43 :         Label if_isarray(this), if_isnotarray(this), done(this);
    1979             :         Branch(Word32Equal(array_type, Int32Constant(JS_ARRAY_TYPE)),
    1980          43 :                &if_isarray, &if_isnotarray);
    1981             : 
    1982          43 :         BIND(&if_isarray);
    1983             :         {
    1984          43 :           var_length.Bind(LoadObjectField(array, JSArray::kLengthOffset));
    1985             : 
    1986             :           // Invalidate protector cell if needed
    1987             :           Branch(WordNotEqual(orig_map, UndefinedConstant()), &if_wasfastarray,
    1988          43 :                  &done);
    1989             : 
    1990          43 :           BIND(&if_wasfastarray);
    1991             :           {
    1992             :             Label if_invalid(this, Label::kDeferred);
    1993             :             // A fast array iterator transitioned to a slow iterator during
    1994             :             // iteration. Invalidate fast_array_iteration_prtoector cell to
    1995             :             // prevent potential deopt loops.
    1996             :             StoreObjectFieldNoWriteBarrier(
    1997             :                 iterator, JSArrayIterator::kIteratedObjectMapOffset,
    1998          43 :                 UndefinedConstant());
    1999             :             GotoIf(Uint32LessThanOrEqual(
    2000             :                        instance_type,
    2001             :                        Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
    2002          43 :                    &done);
    2003             : 
    2004             :             Node* invalid =
    2005          43 :                 SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid));
    2006          43 :             Node* cell = LoadRoot(Heap::kFastArrayIterationProtectorRootIndex);
    2007          43 :             StoreObjectFieldNoWriteBarrier(cell, Cell::kValueOffset, invalid);
    2008          43 :             Goto(&done);
    2009             :           }
    2010             :         }
    2011             : 
    2012          43 :         BIND(&if_isnotarray);
    2013             :         {
    2014             :           Node* length =
    2015          86 :               GetProperty(context, array, factory()->length_string());
    2016          43 :           Callable to_length = CodeFactory::ToLength(isolate());
    2017          43 :           var_length.Bind(CallStub(to_length, context, length));
    2018          43 :           Goto(&done);
    2019             :         }
    2020             : 
    2021          43 :         BIND(&done);
    2022          86 :         length = var_length.value();
    2023             :       }
    2024             : 
    2025          43 :       GotoUnlessNumberLessThan(index, length, &set_done);
    2026             : 
    2027             :       StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset,
    2028          43 :                        NumberInc(index));
    2029          43 :       var_done.Bind(FalseConstant());
    2030             : 
    2031             :       Branch(
    2032             :           Uint32LessThanOrEqual(
    2033             :               instance_type, Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
    2034          43 :           &allocate_key_result, &generic_values);
    2035             : 
    2036          43 :       BIND(&generic_values);
    2037             :       {
    2038          43 :         var_value.Bind(GetProperty(context, array, index));
    2039          43 :         Goto(&allocate_entry_if_needed);
    2040          43 :       }
    2041             :     }
    2042             : 
    2043          43 :     BIND(&if_istypedarray);
    2044             :     {
    2045          43 :       Node* buffer = LoadObjectField(array, JSTypedArray::kBufferOffset);
    2046          43 :       GotoIf(IsDetachedBuffer(buffer), &if_isdetached);
    2047             : 
    2048          43 :       Node* length = LoadObjectField(array, JSTypedArray::kLengthOffset);
    2049             : 
    2050             :       CSA_ASSERT(this, TaggedIsSmi(length));
    2051             :       CSA_ASSERT(this, TaggedIsSmi(index));
    2052             : 
    2053          43 :       GotoIfNot(SmiBelow(index, length), &set_done);
    2054             : 
    2055          43 :       Node* one = SmiConstant(1);
    2056             :       StoreObjectFieldNoWriteBarrier(
    2057          43 :           iterator, JSArrayIterator::kNextIndexOffset, SmiAdd(index, one));
    2058          43 :       var_done.Bind(FalseConstant());
    2059             : 
    2060          43 :       Node* elements = LoadElements(array);
    2061             :       Node* base_ptr =
    2062          43 :           LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
    2063             :       Node* external_ptr =
    2064             :           LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
    2065          43 :                           MachineType::Pointer());
    2066          43 :       Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
    2067             : 
    2068             :       static int32_t kInstanceType[] = {
    2069             :           JS_TYPED_ARRAY_KEY_ITERATOR_TYPE,
    2070             :           JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2071             :           JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2072             :           JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2073             :           JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2074             :           JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2075             :           JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2076             :           JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2077             :           JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2078             :           JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE,
    2079             :           JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE,
    2080             :           JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE,
    2081             :           JS_INT8_ARRAY_VALUE_ITERATOR_TYPE,
    2082             :           JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE,
    2083             :           JS_INT16_ARRAY_VALUE_ITERATOR_TYPE,
    2084             :           JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE,
    2085             :           JS_INT32_ARRAY_VALUE_ITERATOR_TYPE,
    2086             :           JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE,
    2087             :           JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE,
    2088             :       };
    2089             : 
    2090          43 :       Label uint8_values(this), int8_values(this), uint16_values(this),
    2091          43 :           int16_values(this), uint32_values(this), int32_values(this),
    2092          43 :           float32_values(this), float64_values(this);
    2093             :       Label* kInstanceTypeHandlers[] = {
    2094             :           &allocate_key_result, &uint8_values,  &uint8_values,
    2095             :           &int8_values,         &uint16_values, &int16_values,
    2096             :           &uint32_values,       &int32_values,  &float32_values,
    2097             :           &float64_values,      &uint8_values,  &uint8_values,
    2098             :           &int8_values,         &uint16_values, &int16_values,
    2099             :           &uint32_values,       &int32_values,  &float32_values,
    2100             :           &float64_values,
    2101          43 :       };
    2102             : 
    2103          43 :       var_done.Bind(FalseConstant());
    2104             :       Switch(instance_type, &throw_bad_receiver, kInstanceType,
    2105          43 :              kInstanceTypeHandlers, arraysize(kInstanceType));
    2106             : 
    2107          43 :       BIND(&uint8_values);
    2108             :       {
    2109             :         Node* value_uint8 = LoadFixedTypedArrayElement(
    2110          43 :             data_ptr, index, UINT8_ELEMENTS, SMI_PARAMETERS);
    2111          43 :         var_value.Bind(SmiFromWord32(value_uint8));
    2112          43 :         Goto(&allocate_entry_if_needed);
    2113             :       }
    2114          43 :       BIND(&int8_values);
    2115             :       {
    2116             :         Node* value_int8 = LoadFixedTypedArrayElement(
    2117          43 :             data_ptr, index, INT8_ELEMENTS, SMI_PARAMETERS);
    2118          43 :         var_value.Bind(SmiFromWord32(value_int8));
    2119          43 :         Goto(&allocate_entry_if_needed);
    2120             :       }
    2121          43 :       BIND(&uint16_values);
    2122             :       {
    2123             :         Node* value_uint16 = LoadFixedTypedArrayElement(
    2124          43 :             data_ptr, index, UINT16_ELEMENTS, SMI_PARAMETERS);
    2125          43 :         var_value.Bind(SmiFromWord32(value_uint16));
    2126          43 :         Goto(&allocate_entry_if_needed);
    2127             :       }
    2128          43 :       BIND(&int16_values);
    2129             :       {
    2130             :         Node* value_int16 = LoadFixedTypedArrayElement(
    2131          43 :             data_ptr, index, INT16_ELEMENTS, SMI_PARAMETERS);
    2132          43 :         var_value.Bind(SmiFromWord32(value_int16));
    2133          43 :         Goto(&allocate_entry_if_needed);
    2134             :       }
    2135          43 :       BIND(&uint32_values);
    2136             :       {
    2137             :         Node* value_uint32 = LoadFixedTypedArrayElement(
    2138          43 :             data_ptr, index, UINT32_ELEMENTS, SMI_PARAMETERS);
    2139          43 :         var_value.Bind(ChangeUint32ToTagged(value_uint32));
    2140          43 :         Goto(&allocate_entry_if_needed);
    2141             :       }
    2142          43 :       BIND(&int32_values);
    2143             :       {
    2144             :         Node* value_int32 = LoadFixedTypedArrayElement(
    2145          43 :             data_ptr, index, INT32_ELEMENTS, SMI_PARAMETERS);
    2146          43 :         var_value.Bind(ChangeInt32ToTagged(value_int32));
    2147          43 :         Goto(&allocate_entry_if_needed);
    2148             :       }
    2149          43 :       BIND(&float32_values);
    2150             :       {
    2151             :         Node* value_float32 = LoadFixedTypedArrayElement(
    2152          43 :             data_ptr, index, FLOAT32_ELEMENTS, SMI_PARAMETERS);
    2153             :         var_value.Bind(
    2154          43 :             AllocateHeapNumberWithValue(ChangeFloat32ToFloat64(value_float32)));
    2155          43 :         Goto(&allocate_entry_if_needed);
    2156             :       }
    2157          43 :       BIND(&float64_values);
    2158             :       {
    2159             :         Node* value_float64 = LoadFixedTypedArrayElement(
    2160          43 :             data_ptr, index, FLOAT64_ELEMENTS, SMI_PARAMETERS);
    2161          43 :         var_value.Bind(AllocateHeapNumberWithValue(value_float64));
    2162          43 :         Goto(&allocate_entry_if_needed);
    2163          43 :       }
    2164          43 :     }
    2165             :   }
    2166             : 
    2167          43 :   BIND(&set_done);
    2168             :   {
    2169             :     StoreObjectFieldNoWriteBarrier(
    2170          43 :         iterator, JSArrayIterator::kIteratedObjectOffset, UndefinedConstant());
    2171          43 :     Goto(&allocate_iterator_result);
    2172             :   }
    2173             : 
    2174          43 :   BIND(&allocate_key_result);
    2175             :   {
    2176          43 :     var_value.Bind(index);
    2177          43 :     var_done.Bind(FalseConstant());
    2178          43 :     Goto(&allocate_iterator_result);
    2179             :   }
    2180             : 
    2181          43 :   BIND(&allocate_entry_if_needed);
    2182             :   {
    2183             :     GotoIf(Int32GreaterThan(instance_type,
    2184             :                             Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE)),
    2185          43 :            &allocate_iterator_result);
    2186             : 
    2187          43 :     Node* elements = AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
    2188          43 :     StoreFixedArrayElement(elements, 0, index, SKIP_WRITE_BARRIER);
    2189          43 :     StoreFixedArrayElement(elements, 1, var_value.value(), SKIP_WRITE_BARRIER);
    2190             : 
    2191          43 :     Node* entry = Allocate(JSArray::kSize);
    2192             :     Node* map = LoadContextElement(LoadNativeContext(context),
    2193          43 :                                    Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX);
    2194             : 
    2195          43 :     StoreMapNoWriteBarrier(entry, map);
    2196             :     StoreObjectFieldRoot(entry, JSArray::kPropertiesOffset,
    2197          43 :                          Heap::kEmptyFixedArrayRootIndex);
    2198          43 :     StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset, elements);
    2199             :     StoreObjectFieldNoWriteBarrier(entry, JSArray::kLengthOffset,
    2200          43 :                                    SmiConstant(Smi::FromInt(2)));
    2201             : 
    2202          43 :     var_value.Bind(entry);
    2203          43 :     Goto(&allocate_iterator_result);
    2204             :   }
    2205             : 
    2206          43 :   BIND(&allocate_iterator_result);
    2207             :   {
    2208          43 :     Node* result = Allocate(JSIteratorResult::kSize);
    2209             :     Node* map = LoadContextElement(LoadNativeContext(context),
    2210          43 :                                    Context::ITERATOR_RESULT_MAP_INDEX);
    2211          43 :     StoreMapNoWriteBarrier(result, map);
    2212             :     StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
    2213          43 :                          Heap::kEmptyFixedArrayRootIndex);
    2214             :     StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
    2215          43 :                          Heap::kEmptyFixedArrayRootIndex);
    2216             :     StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset,
    2217          43 :                                    var_value.value());
    2218             :     StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset,
    2219          43 :                                    var_done.value());
    2220          43 :     Return(result);
    2221             :   }
    2222             : 
    2223          43 :   BIND(&throw_bad_receiver);
    2224             :   {
    2225             :     // The {receiver} is not a valid JSArrayIterator.
    2226             :     CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
    2227          43 :                 HeapConstant(operation), iterator);
    2228          43 :     Unreachable();
    2229             :   }
    2230             : 
    2231          43 :   BIND(&if_isdetached);
    2232             :   {
    2233          43 :     Node* message = SmiConstant(MessageTemplate::kDetachedOperation);
    2234             :     CallRuntime(Runtime::kThrowTypeError, context, message,
    2235          43 :                 HeapConstant(operation));
    2236          43 :     Unreachable();
    2237          43 :   }
    2238          43 : }
    2239             : 
    2240             : }  // namespace internal
    2241             : }  // namespace v8

Generated by: LCOV version 1.10