11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/compiler/js-call-reducer.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <functional>
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "src/api/api-inl.h"
101cb0ef41Sopenharmony_ci#include "src/base/small-vector.h"
111cb0ef41Sopenharmony_ci#include "src/builtins/builtins-promise.h"
121cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils.h"
131cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h"
141cb0ef41Sopenharmony_ci#include "src/codegen/tnode.h"
151cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h"
161cb0ef41Sopenharmony_ci#include "src/compiler/access-info.h"
171cb0ef41Sopenharmony_ci#include "src/compiler/allocation-builder-inl.h"
181cb0ef41Sopenharmony_ci#include "src/compiler/allocation-builder.h"
191cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h"
201cb0ef41Sopenharmony_ci#include "src/compiler/compilation-dependencies.h"
211cb0ef41Sopenharmony_ci#include "src/compiler/fast-api-calls.h"
221cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h"
231cb0ef41Sopenharmony_ci#include "src/compiler/graph-assembler.h"
241cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h"
251cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h"
261cb0ef41Sopenharmony_ci#include "src/compiler/map-inference.h"
271cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h"
281cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h"
291cb0ef41Sopenharmony_ci#include "src/compiler/property-access-builder.h"
301cb0ef41Sopenharmony_ci#include "src/compiler/simplified-operator.h"
311cb0ef41Sopenharmony_ci#include "src/compiler/state-values-utils.h"
321cb0ef41Sopenharmony_ci#include "src/compiler/type-cache.h"
331cb0ef41Sopenharmony_ci#include "src/ic/call-optimization.h"
341cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
351cb0ef41Sopenharmony_ci#include "src/objects/arguments-inl.h"
361cb0ef41Sopenharmony_ci#include "src/objects/feedback-vector-inl.h"
371cb0ef41Sopenharmony_ci#include "src/objects/js-array-buffer-inl.h"
381cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h"
391cb0ef41Sopenharmony_ci#include "src/objects/js-function.h"
401cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
411cb0ef41Sopenharmony_ci#include "src/objects/ordered-hash-table.h"
421cb0ef41Sopenharmony_ci#include "src/objects/string-inl.h"
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT
451cb0ef41Sopenharmony_ci#include "src/objects/intl-objects.h"
461cb0ef41Sopenharmony_ci#endif
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_cinamespace v8 {
491cb0ef41Sopenharmony_cinamespace internal {
501cb0ef41Sopenharmony_cinamespace compiler {
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci// Shorter lambda declarations with less visual clutter.
531cb0ef41Sopenharmony_ci#define _ [&]()
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ciclass JSCallReducerAssembler : public JSGraphAssembler {
561cb0ef41Sopenharmony_ci protected:
571cb0ef41Sopenharmony_ci  class CatchScope;
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci private:
601cb0ef41Sopenharmony_ci  static constexpr bool kMarkLoopExits = true;
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci public:
631cb0ef41Sopenharmony_ci  JSCallReducerAssembler(JSCallReducer* reducer, Node* node)
641cb0ef41Sopenharmony_ci      : JSGraphAssembler(
651cb0ef41Sopenharmony_ci            reducer->JSGraphForGraphAssembler(),
661cb0ef41Sopenharmony_ci            reducer->ZoneForGraphAssembler(),
671cb0ef41Sopenharmony_ci            [reducer](Node* n) { reducer->RevisitForGraphAssembler(n); },
681cb0ef41Sopenharmony_ci            kMarkLoopExits),
691cb0ef41Sopenharmony_ci        dependencies_(reducer->dependencies()),
701cb0ef41Sopenharmony_ci        node_(node),
711cb0ef41Sopenharmony_ci        outermost_catch_scope_(
721cb0ef41Sopenharmony_ci            CatchScope::Outermost(reducer->ZoneForGraphAssembler())),
731cb0ef41Sopenharmony_ci        catch_scope_(&outermost_catch_scope_) {
741cb0ef41Sopenharmony_ci    InitializeEffectControl(NodeProperties::GetEffectInput(node),
751cb0ef41Sopenharmony_ci                            NodeProperties::GetControlInput(node));
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci    // Finish initializing the outermost catch scope.
781cb0ef41Sopenharmony_ci    bool has_handler =
791cb0ef41Sopenharmony_ci        NodeProperties::IsExceptionalCall(node, &outermost_handler_);
801cb0ef41Sopenharmony_ci    outermost_catch_scope_.set_has_handler(has_handler);
811cb0ef41Sopenharmony_ci    outermost_catch_scope_.set_gasm(this);
821cb0ef41Sopenharmony_ci  }
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  TNode<Object> ReduceJSCallWithArrayLikeOrSpreadOfEmpty(
851cb0ef41Sopenharmony_ci      std::unordered_set<Node*>* generated_calls_with_array_like_or_spread);
861cb0ef41Sopenharmony_ci  TNode<Object> ReduceMathUnary(const Operator* op);
871cb0ef41Sopenharmony_ci  TNode<Object> ReduceMathBinary(const Operator* op);
881cb0ef41Sopenharmony_ci  TNode<String> ReduceStringPrototypeSubstring();
891cb0ef41Sopenharmony_ci  TNode<Boolean> ReduceStringPrototypeStartsWith();
901cb0ef41Sopenharmony_ci  TNode<Boolean> ReduceStringPrototypeStartsWith(
911cb0ef41Sopenharmony_ci      const StringRef& search_element_string);
921cb0ef41Sopenharmony_ci  TNode<String> ReduceStringPrototypeSlice();
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  TNode<Object> TargetInput() const { return JSCallNode{node_ptr()}.target(); }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  template <typename T>
971cb0ef41Sopenharmony_ci  TNode<T> ReceiverInputAs() const {
981cb0ef41Sopenharmony_ci    return TNode<T>::UncheckedCast(JSCallNode{node_ptr()}.receiver());
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  TNode<Object> ReceiverInput() const { return ReceiverInputAs<Object>(); }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  CatchScope* catch_scope() const { return catch_scope_; }
1041cb0ef41Sopenharmony_ci  Node* outermost_handler() const { return outermost_handler_; }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  Node* node_ptr() const { return node_; }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci protected:
1091cb0ef41Sopenharmony_ci  using NodeGenerator0 = std::function<TNode<Object>()>;
1101cb0ef41Sopenharmony_ci  using VoidGenerator0 = std::function<void()>;
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  // TODO(jgruber): Currently IfBuilder0 and IfBuilder1 are implemented as
1131cb0ef41Sopenharmony_ci  // separate classes. If, in the future, we encounter additional use cases that
1141cb0ef41Sopenharmony_ci  // return more than 1 value, we should merge these back into a single variadic
1151cb0ef41Sopenharmony_ci  // implementation.
1161cb0ef41Sopenharmony_ci  class IfBuilder0 final {
1171cb0ef41Sopenharmony_ci   public:
1181cb0ef41Sopenharmony_ci    IfBuilder0(JSGraphAssembler* gasm, TNode<Boolean> cond, bool negate_cond)
1191cb0ef41Sopenharmony_ci        : gasm_(gasm),
1201cb0ef41Sopenharmony_ci          cond_(cond),
1211cb0ef41Sopenharmony_ci          negate_cond_(negate_cond),
1221cb0ef41Sopenharmony_ci          initial_effect_(gasm->effect()),
1231cb0ef41Sopenharmony_ci          initial_control_(gasm->control()) {}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci    IfBuilder0& ExpectTrue() {
1261cb0ef41Sopenharmony_ci      DCHECK_EQ(hint_, BranchHint::kNone);
1271cb0ef41Sopenharmony_ci      hint_ = BranchHint::kTrue;
1281cb0ef41Sopenharmony_ci      return *this;
1291cb0ef41Sopenharmony_ci    }
1301cb0ef41Sopenharmony_ci    IfBuilder0& ExpectFalse() {
1311cb0ef41Sopenharmony_ci      DCHECK_EQ(hint_, BranchHint::kNone);
1321cb0ef41Sopenharmony_ci      hint_ = BranchHint::kFalse;
1331cb0ef41Sopenharmony_ci      return *this;
1341cb0ef41Sopenharmony_ci    }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci    IfBuilder0& Then(const VoidGenerator0& body) {
1371cb0ef41Sopenharmony_ci      then_body_ = body;
1381cb0ef41Sopenharmony_ci      return *this;
1391cb0ef41Sopenharmony_ci    }
1401cb0ef41Sopenharmony_ci    IfBuilder0& Else(const VoidGenerator0& body) {
1411cb0ef41Sopenharmony_ci      else_body_ = body;
1421cb0ef41Sopenharmony_ci      return *this;
1431cb0ef41Sopenharmony_ci    }
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci    ~IfBuilder0() {
1461cb0ef41Sopenharmony_ci      // Ensure correct usage: effect/control must not have been modified while
1471cb0ef41Sopenharmony_ci      // the IfBuilder0 instance is alive.
1481cb0ef41Sopenharmony_ci      DCHECK_EQ(gasm_->effect(), initial_effect_);
1491cb0ef41Sopenharmony_ci      DCHECK_EQ(gasm_->control(), initial_control_);
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci      // Unlike IfBuilder1, this supports an empty then or else body. This is
1521cb0ef41Sopenharmony_ci      // possible since the merge does not take any value inputs.
1531cb0ef41Sopenharmony_ci      DCHECK(then_body_ || else_body_);
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci      if (negate_cond_) std::swap(then_body_, else_body_);
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci      auto if_true = (hint_ == BranchHint::kFalse) ? gasm_->MakeDeferredLabel()
1581cb0ef41Sopenharmony_ci                                                   : gasm_->MakeLabel();
1591cb0ef41Sopenharmony_ci      auto if_false = (hint_ == BranchHint::kTrue) ? gasm_->MakeDeferredLabel()
1601cb0ef41Sopenharmony_ci                                                   : gasm_->MakeLabel();
1611cb0ef41Sopenharmony_ci      auto merge = gasm_->MakeLabel();
1621cb0ef41Sopenharmony_ci      gasm_->Branch(cond_, &if_true, &if_false);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci      gasm_->Bind(&if_true);
1651cb0ef41Sopenharmony_ci      if (then_body_) then_body_();
1661cb0ef41Sopenharmony_ci      if (gasm_->HasActiveBlock()) gasm_->Goto(&merge);
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci      gasm_->Bind(&if_false);
1691cb0ef41Sopenharmony_ci      if (else_body_) else_body_();
1701cb0ef41Sopenharmony_ci      if (gasm_->HasActiveBlock()) gasm_->Goto(&merge);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci      gasm_->Bind(&merge);
1731cb0ef41Sopenharmony_ci    }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci    IfBuilder0(const IfBuilder0&) = delete;
1761cb0ef41Sopenharmony_ci    IfBuilder0& operator=(const IfBuilder0&) = delete;
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci   private:
1791cb0ef41Sopenharmony_ci    JSGraphAssembler* const gasm_;
1801cb0ef41Sopenharmony_ci    const TNode<Boolean> cond_;
1811cb0ef41Sopenharmony_ci    const bool negate_cond_;
1821cb0ef41Sopenharmony_ci    const Effect initial_effect_;
1831cb0ef41Sopenharmony_ci    const Control initial_control_;
1841cb0ef41Sopenharmony_ci    BranchHint hint_ = BranchHint::kNone;
1851cb0ef41Sopenharmony_ci    VoidGenerator0 then_body_;
1861cb0ef41Sopenharmony_ci    VoidGenerator0 else_body_;
1871cb0ef41Sopenharmony_ci  };
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci  IfBuilder0 If(TNode<Boolean> cond) { return {this, cond, false}; }
1901cb0ef41Sopenharmony_ci  IfBuilder0 IfNot(TNode<Boolean> cond) { return {this, cond, true}; }
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  template <typename T>
1931cb0ef41Sopenharmony_ci  class IfBuilder1 {
1941cb0ef41Sopenharmony_ci    using If1BodyFunction = std::function<TNode<T>()>;
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci   public:
1971cb0ef41Sopenharmony_ci    IfBuilder1(JSGraphAssembler* gasm, TNode<Boolean> cond)
1981cb0ef41Sopenharmony_ci        : gasm_(gasm), cond_(cond) {}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT IfBuilder1& ExpectTrue() {
2011cb0ef41Sopenharmony_ci      DCHECK_EQ(hint_, BranchHint::kNone);
2021cb0ef41Sopenharmony_ci      hint_ = BranchHint::kTrue;
2031cb0ef41Sopenharmony_ci      return *this;
2041cb0ef41Sopenharmony_ci    }
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT IfBuilder1& ExpectFalse() {
2071cb0ef41Sopenharmony_ci      DCHECK_EQ(hint_, BranchHint::kNone);
2081cb0ef41Sopenharmony_ci      hint_ = BranchHint::kFalse;
2091cb0ef41Sopenharmony_ci      return *this;
2101cb0ef41Sopenharmony_ci    }
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT IfBuilder1& Then(const If1BodyFunction& body) {
2131cb0ef41Sopenharmony_ci      then_body_ = body;
2141cb0ef41Sopenharmony_ci      return *this;
2151cb0ef41Sopenharmony_ci    }
2161cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT IfBuilder1& Else(const If1BodyFunction& body) {
2171cb0ef41Sopenharmony_ci      else_body_ = body;
2181cb0ef41Sopenharmony_ci      return *this;
2191cb0ef41Sopenharmony_ci    }
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT TNode<T> Value() {
2221cb0ef41Sopenharmony_ci      DCHECK(then_body_);
2231cb0ef41Sopenharmony_ci      DCHECK(else_body_);
2241cb0ef41Sopenharmony_ci      auto if_true = (hint_ == BranchHint::kFalse) ? gasm_->MakeDeferredLabel()
2251cb0ef41Sopenharmony_ci                                                   : gasm_->MakeLabel();
2261cb0ef41Sopenharmony_ci      auto if_false = (hint_ == BranchHint::kTrue) ? gasm_->MakeDeferredLabel()
2271cb0ef41Sopenharmony_ci                                                   : gasm_->MakeLabel();
2281cb0ef41Sopenharmony_ci      auto merge = gasm_->MakeLabel(kPhiRepresentation);
2291cb0ef41Sopenharmony_ci      gasm_->Branch(cond_, &if_true, &if_false);
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci      gasm_->Bind(&if_true);
2321cb0ef41Sopenharmony_ci      TNode<T> then_result = then_body_();
2331cb0ef41Sopenharmony_ci      if (gasm_->HasActiveBlock()) gasm_->Goto(&merge, then_result);
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci      gasm_->Bind(&if_false);
2361cb0ef41Sopenharmony_ci      TNode<T> else_result = else_body_();
2371cb0ef41Sopenharmony_ci      if (gasm_->HasActiveBlock()) {
2381cb0ef41Sopenharmony_ci        gasm_->Goto(&merge, else_result);
2391cb0ef41Sopenharmony_ci      }
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci      gasm_->Bind(&merge);
2421cb0ef41Sopenharmony_ci      return merge.PhiAt<T>(0);
2431cb0ef41Sopenharmony_ci    }
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci   private:
2461cb0ef41Sopenharmony_ci    static constexpr MachineRepresentation kPhiRepresentation =
2471cb0ef41Sopenharmony_ci        MachineRepresentation::kTagged;
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci    JSGraphAssembler* const gasm_;
2501cb0ef41Sopenharmony_ci    const TNode<Boolean> cond_;
2511cb0ef41Sopenharmony_ci    BranchHint hint_ = BranchHint::kNone;
2521cb0ef41Sopenharmony_ci    If1BodyFunction then_body_;
2531cb0ef41Sopenharmony_ci    If1BodyFunction else_body_;
2541cb0ef41Sopenharmony_ci  };
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  template <typename T>
2571cb0ef41Sopenharmony_ci  IfBuilder1<T> SelectIf(TNode<Boolean> cond) {
2581cb0ef41Sopenharmony_ci    return {this, cond};
2591cb0ef41Sopenharmony_ci  }
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  // Simplified operators.
2621cb0ef41Sopenharmony_ci  TNode<Number> SpeculativeToNumber(
2631cb0ef41Sopenharmony_ci      TNode<Object> value,
2641cb0ef41Sopenharmony_ci      NumberOperationHint hint = NumberOperationHint::kNumberOrOddball);
2651cb0ef41Sopenharmony_ci  TNode<Smi> CheckSmi(TNode<Object> value);
2661cb0ef41Sopenharmony_ci  TNode<String> CheckString(TNode<Object> value);
2671cb0ef41Sopenharmony_ci  TNode<Number> CheckBounds(TNode<Number> value, TNode<Number> limit);
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci  // Common operators.
2701cb0ef41Sopenharmony_ci  TNode<Smi> TypeGuardUnsignedSmall(TNode<Object> value);
2711cb0ef41Sopenharmony_ci  TNode<Object> TypeGuardNonInternal(TNode<Object> value);
2721cb0ef41Sopenharmony_ci  TNode<Number> TypeGuardFixedArrayLength(TNode<Object> value);
2731cb0ef41Sopenharmony_ci  TNode<Object> Call4(const Callable& callable, TNode<Context> context,
2741cb0ef41Sopenharmony_ci                      TNode<Object> arg0, TNode<Object> arg1,
2751cb0ef41Sopenharmony_ci                      TNode<Object> arg2, TNode<Object> arg3);
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  // Javascript operators.
2781cb0ef41Sopenharmony_ci  TNode<Object> JSCall3(TNode<Object> function, TNode<Object> this_arg,
2791cb0ef41Sopenharmony_ci                        TNode<Object> arg0, TNode<Object> arg1,
2801cb0ef41Sopenharmony_ci                        TNode<Object> arg2, FrameState frame_state);
2811cb0ef41Sopenharmony_ci  TNode<Object> JSCall4(TNode<Object> function, TNode<Object> this_arg,
2821cb0ef41Sopenharmony_ci                        TNode<Object> arg0, TNode<Object> arg1,
2831cb0ef41Sopenharmony_ci                        TNode<Object> arg2, TNode<Object> arg3,
2841cb0ef41Sopenharmony_ci                        FrameState frame_state);
2851cb0ef41Sopenharmony_ci  TNode<Object> JSCallRuntime2(Runtime::FunctionId function_id,
2861cb0ef41Sopenharmony_ci                               TNode<Object> arg0, TNode<Object> arg1,
2871cb0ef41Sopenharmony_ci                               FrameState frame_state);
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci  // Emplace a copy of the call node into the graph at current effect/control.
2901cb0ef41Sopenharmony_ci  TNode<Object> CopyNode();
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  // Used in special cases in which we are certain CreateArray does not throw.
2931cb0ef41Sopenharmony_ci  TNode<JSArray> CreateArrayNoThrow(TNode<Object> ctor, TNode<Number> size,
2941cb0ef41Sopenharmony_ci                                    FrameState frame_state);
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  TNode<JSArray> AllocateEmptyJSArray(ElementsKind kind,
2971cb0ef41Sopenharmony_ci                                      const NativeContextRef& native_context);
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  TNode<Number> NumberInc(TNode<Number> value) {
3001cb0ef41Sopenharmony_ci    return NumberAdd(value, OneConstant());
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  void MaybeInsertMapChecks(MapInference* inference,
3041cb0ef41Sopenharmony_ci                            bool has_stability_dependency) {
3051cb0ef41Sopenharmony_ci    // TODO(jgruber): Implement MapInference::InsertMapChecks in graph
3061cb0ef41Sopenharmony_ci    // assembler.
3071cb0ef41Sopenharmony_ci    if (!has_stability_dependency) {
3081cb0ef41Sopenharmony_ci      Effect e = effect();
3091cb0ef41Sopenharmony_ci      inference->InsertMapChecks(jsgraph(), &e, Control{control()}, feedback());
3101cb0ef41Sopenharmony_ci      InitializeEffectControl(e, control());
3111cb0ef41Sopenharmony_ci    }
3121cb0ef41Sopenharmony_ci  }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci  // TODO(jgruber): Currently, it's the responsibility of the developer to note
3151cb0ef41Sopenharmony_ci  // which operations may throw and appropriately wrap these in a call to
3161cb0ef41Sopenharmony_ci  // MayThrow (see e.g. JSCall3 and CallRuntime2). A more methodical approach
3171cb0ef41Sopenharmony_ci  // would be good.
3181cb0ef41Sopenharmony_ci  TNode<Object> MayThrow(const NodeGenerator0& body) {
3191cb0ef41Sopenharmony_ci    TNode<Object> result = body();
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci    if (catch_scope()->has_handler()) {
3221cb0ef41Sopenharmony_ci      // The IfException node is later merged into the outer graph.
3231cb0ef41Sopenharmony_ci      // Note: AddNode is intentionally not called since effect and control
3241cb0ef41Sopenharmony_ci      // should not be updated.
3251cb0ef41Sopenharmony_ci      Node* if_exception =
3261cb0ef41Sopenharmony_ci          graph()->NewNode(common()->IfException(), effect(), control());
3271cb0ef41Sopenharmony_ci      catch_scope()->RegisterIfExceptionNode(if_exception);
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci      // Control resumes here.
3301cb0ef41Sopenharmony_ci      AddNode(graph()->NewNode(common()->IfSuccess(), control()));
3311cb0ef41Sopenharmony_ci    }
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci    return result;
3341cb0ef41Sopenharmony_ci  }
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci  // A catch scope represents a single catch handler. The handler can be
3371cb0ef41Sopenharmony_ci  // custom catch logic within the reduction itself; or a catch handler in the
3381cb0ef41Sopenharmony_ci  // outside graph into which the reduction will be integrated (in this case
3391cb0ef41Sopenharmony_ci  // the scope is called 'outermost').
3401cb0ef41Sopenharmony_ci  class V8_NODISCARD CatchScope {
3411cb0ef41Sopenharmony_ci   private:
3421cb0ef41Sopenharmony_ci    // Only used to partially construct the outermost scope.
3431cb0ef41Sopenharmony_ci    explicit CatchScope(Zone* zone) : if_exception_nodes_(zone) {}
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci    // For all inner scopes.
3461cb0ef41Sopenharmony_ci    CatchScope(Zone* zone, JSCallReducerAssembler* gasm)
3471cb0ef41Sopenharmony_ci        : gasm_(gasm),
3481cb0ef41Sopenharmony_ci          parent_(gasm->catch_scope_),
3491cb0ef41Sopenharmony_ci          has_handler_(true),
3501cb0ef41Sopenharmony_ci          if_exception_nodes_(zone) {
3511cb0ef41Sopenharmony_ci      gasm_->catch_scope_ = this;
3521cb0ef41Sopenharmony_ci    }
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci   public:
3551cb0ef41Sopenharmony_ci    ~CatchScope() { gasm_->catch_scope_ = parent_; }
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci    static CatchScope Outermost(Zone* zone) { return CatchScope{zone}; }
3581cb0ef41Sopenharmony_ci    static CatchScope Inner(Zone* zone, JSCallReducerAssembler* gasm) {
3591cb0ef41Sopenharmony_ci      return {zone, gasm};
3601cb0ef41Sopenharmony_ci    }
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci    bool has_handler() const { return has_handler_; }
3631cb0ef41Sopenharmony_ci    bool is_outermost() const { return parent_ == nullptr; }
3641cb0ef41Sopenharmony_ci    CatchScope* parent() const { return parent_; }
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci    // Should only be used to initialize the outermost scope (inner scopes
3671cb0ef41Sopenharmony_ci    // always have a handler and are passed the gasm pointer at construction).
3681cb0ef41Sopenharmony_ci    void set_has_handler(bool v) {
3691cb0ef41Sopenharmony_ci      DCHECK(is_outermost());
3701cb0ef41Sopenharmony_ci      has_handler_ = v;
3711cb0ef41Sopenharmony_ci    }
3721cb0ef41Sopenharmony_ci    void set_gasm(JSCallReducerAssembler* v) {
3731cb0ef41Sopenharmony_ci      DCHECK(is_outermost());
3741cb0ef41Sopenharmony_ci      gasm_ = v;
3751cb0ef41Sopenharmony_ci    }
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci    bool has_exceptional_control_flow() const {
3781cb0ef41Sopenharmony_ci      return !if_exception_nodes_.empty();
3791cb0ef41Sopenharmony_ci    }
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci    void RegisterIfExceptionNode(Node* if_exception) {
3821cb0ef41Sopenharmony_ci      DCHECK(has_handler());
3831cb0ef41Sopenharmony_ci      if_exception_nodes_.push_back(if_exception);
3841cb0ef41Sopenharmony_ci    }
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci    void MergeExceptionalPaths(TNode<Object>* exception_out, Effect* effect_out,
3871cb0ef41Sopenharmony_ci                               Control* control_out) {
3881cb0ef41Sopenharmony_ci      DCHECK(has_handler());
3891cb0ef41Sopenharmony_ci      DCHECK(has_exceptional_control_flow());
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci      const int size = static_cast<int>(if_exception_nodes_.size());
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci      if (size == 1) {
3941cb0ef41Sopenharmony_ci        // No merge needed.
3951cb0ef41Sopenharmony_ci        Node* e = if_exception_nodes_.at(0);
3961cb0ef41Sopenharmony_ci        *exception_out = TNode<Object>::UncheckedCast(e);
3971cb0ef41Sopenharmony_ci        *effect_out = Effect(e);
3981cb0ef41Sopenharmony_ci        *control_out = Control(e);
3991cb0ef41Sopenharmony_ci      } else {
4001cb0ef41Sopenharmony_ci        DCHECK_GT(size, 1);
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci        Node* merge = gasm_->graph()->NewNode(gasm_->common()->Merge(size),
4031cb0ef41Sopenharmony_ci                                              size, if_exception_nodes_.data());
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci        // These phis additionally take {merge} as an input. Temporarily add
4061cb0ef41Sopenharmony_ci        // it to the list.
4071cb0ef41Sopenharmony_ci        if_exception_nodes_.push_back(merge);
4081cb0ef41Sopenharmony_ci        const int size_with_merge =
4091cb0ef41Sopenharmony_ci            static_cast<int>(if_exception_nodes_.size());
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci        Node* ephi = gasm_->graph()->NewNode(gasm_->common()->EffectPhi(size),
4121cb0ef41Sopenharmony_ci                                             size_with_merge,
4131cb0ef41Sopenharmony_ci                                             if_exception_nodes_.data());
4141cb0ef41Sopenharmony_ci        Node* phi = gasm_->graph()->NewNode(
4151cb0ef41Sopenharmony_ci            gasm_->common()->Phi(MachineRepresentation::kTagged, size),
4161cb0ef41Sopenharmony_ci            size_with_merge, if_exception_nodes_.data());
4171cb0ef41Sopenharmony_ci        if_exception_nodes_.pop_back();
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci        *exception_out = TNode<Object>::UncheckedCast(phi);
4201cb0ef41Sopenharmony_ci        *effect_out = Effect(ephi);
4211cb0ef41Sopenharmony_ci        *control_out = Control(merge);
4221cb0ef41Sopenharmony_ci      }
4231cb0ef41Sopenharmony_ci    }
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ci   private:
4261cb0ef41Sopenharmony_ci    JSCallReducerAssembler* gasm_ = nullptr;
4271cb0ef41Sopenharmony_ci    CatchScope* const parent_ = nullptr;
4281cb0ef41Sopenharmony_ci    bool has_handler_ = false;
4291cb0ef41Sopenharmony_ci    NodeVector if_exception_nodes_;
4301cb0ef41Sopenharmony_ci  };
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  class TryCatchBuilder0 {
4331cb0ef41Sopenharmony_ci   public:
4341cb0ef41Sopenharmony_ci    using TryFunction = VoidGenerator0;
4351cb0ef41Sopenharmony_ci    using CatchFunction = std::function<void(TNode<Object>)>;
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci    TryCatchBuilder0(JSCallReducerAssembler* gasm, const TryFunction& try_body)
4381cb0ef41Sopenharmony_ci        : gasm_(gasm), try_body_(try_body) {}
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci    void Catch(const CatchFunction& catch_body) {
4411cb0ef41Sopenharmony_ci      TNode<Object> handler_exception;
4421cb0ef41Sopenharmony_ci      Effect handler_effect{nullptr};
4431cb0ef41Sopenharmony_ci      Control handler_control{nullptr};
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci      auto continuation = gasm_->MakeLabel();
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci      // Try.
4481cb0ef41Sopenharmony_ci      {
4491cb0ef41Sopenharmony_ci        CatchScope catch_scope = CatchScope::Inner(gasm_->temp_zone(), gasm_);
4501cb0ef41Sopenharmony_ci        try_body_();
4511cb0ef41Sopenharmony_ci        gasm_->Goto(&continuation);
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci        catch_scope.MergeExceptionalPaths(&handler_exception, &handler_effect,
4541cb0ef41Sopenharmony_ci                                          &handler_control);
4551cb0ef41Sopenharmony_ci      }
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci      // Catch.
4581cb0ef41Sopenharmony_ci      {
4591cb0ef41Sopenharmony_ci        gasm_->InitializeEffectControl(handler_effect, handler_control);
4601cb0ef41Sopenharmony_ci        catch_body(handler_exception);
4611cb0ef41Sopenharmony_ci        gasm_->Goto(&continuation);
4621cb0ef41Sopenharmony_ci      }
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci      gasm_->Bind(&continuation);
4651cb0ef41Sopenharmony_ci    }
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci   private:
4681cb0ef41Sopenharmony_ci    JSCallReducerAssembler* const gasm_;
4691cb0ef41Sopenharmony_ci    const VoidGenerator0 try_body_;
4701cb0ef41Sopenharmony_ci  };
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  TryCatchBuilder0 Try(const VoidGenerator0& try_body) {
4731cb0ef41Sopenharmony_ci    return {this, try_body};
4741cb0ef41Sopenharmony_ci  }
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci  using ConditionFunction1 = std::function<TNode<Boolean>(TNode<Number>)>;
4771cb0ef41Sopenharmony_ci  using StepFunction1 = std::function<TNode<Number>(TNode<Number>)>;
4781cb0ef41Sopenharmony_ci  class ForBuilder0 {
4791cb0ef41Sopenharmony_ci    using For0BodyFunction = std::function<void(TNode<Number>)>;
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci   public:
4821cb0ef41Sopenharmony_ci    ForBuilder0(JSGraphAssembler* gasm, TNode<Number> initial_value,
4831cb0ef41Sopenharmony_ci                const ConditionFunction1& cond, const StepFunction1& step)
4841cb0ef41Sopenharmony_ci        : gasm_(gasm),
4851cb0ef41Sopenharmony_ci          initial_value_(initial_value),
4861cb0ef41Sopenharmony_ci          cond_(cond),
4871cb0ef41Sopenharmony_ci          step_(step) {}
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci    void Do(const For0BodyFunction& body) {
4901cb0ef41Sopenharmony_ci      auto loop_exit = gasm_->MakeLabel();
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci      {
4931cb0ef41Sopenharmony_ci        GraphAssembler::LoopScope<kPhiRepresentation> loop_scope(gasm_);
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci        auto loop_header = loop_scope.loop_header_label();
4961cb0ef41Sopenharmony_ci        auto loop_body = gasm_->MakeLabel();
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci        gasm_->Goto(loop_header, initial_value_);
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci        gasm_->Bind(loop_header);
5011cb0ef41Sopenharmony_ci        TNode<Number> i = loop_header->PhiAt<Number>(0);
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci        gasm_->BranchWithHint(cond_(i), &loop_body, &loop_exit,
5041cb0ef41Sopenharmony_ci                              BranchHint::kTrue);
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci        gasm_->Bind(&loop_body);
5071cb0ef41Sopenharmony_ci        body(i);
5081cb0ef41Sopenharmony_ci        gasm_->Goto(loop_header, step_(i));
5091cb0ef41Sopenharmony_ci      }
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci      gasm_->Bind(&loop_exit);
5121cb0ef41Sopenharmony_ci    }
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci   private:
5151cb0ef41Sopenharmony_ci    static constexpr MachineRepresentation kPhiRepresentation =
5161cb0ef41Sopenharmony_ci        MachineRepresentation::kTagged;
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ci    JSGraphAssembler* const gasm_;
5191cb0ef41Sopenharmony_ci    const TNode<Number> initial_value_;
5201cb0ef41Sopenharmony_ci    const ConditionFunction1 cond_;
5211cb0ef41Sopenharmony_ci    const StepFunction1 step_;
5221cb0ef41Sopenharmony_ci  };
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  ForBuilder0 ForZeroUntil(TNode<Number> excluded_limit) {
5251cb0ef41Sopenharmony_ci    TNode<Number> initial_value = ZeroConstant();
5261cb0ef41Sopenharmony_ci    auto cond = [=](TNode<Number> i) {
5271cb0ef41Sopenharmony_ci      return NumberLessThan(i, excluded_limit);
5281cb0ef41Sopenharmony_ci    };
5291cb0ef41Sopenharmony_ci    auto step = [=](TNode<Number> i) { return NumberAdd(i, OneConstant()); };
5301cb0ef41Sopenharmony_ci    return {this, initial_value, cond, step};
5311cb0ef41Sopenharmony_ci  }
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci  ForBuilder0 Forever(TNode<Number> initial_value, const StepFunction1& step) {
5341cb0ef41Sopenharmony_ci    return {this, initial_value, [=](TNode<Number>) { return TrueConstant(); },
5351cb0ef41Sopenharmony_ci            step};
5361cb0ef41Sopenharmony_ci  }
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  using For1BodyFunction = std::function<void(TNode<Number>, TNode<Object>*)>;
5391cb0ef41Sopenharmony_ci  class ForBuilder1 {
5401cb0ef41Sopenharmony_ci   public:
5411cb0ef41Sopenharmony_ci    ForBuilder1(JSGraphAssembler* gasm, TNode<Number> initial_value,
5421cb0ef41Sopenharmony_ci                const ConditionFunction1& cond, const StepFunction1& step,
5431cb0ef41Sopenharmony_ci                TNode<Object> initial_arg0)
5441cb0ef41Sopenharmony_ci        : gasm_(gasm),
5451cb0ef41Sopenharmony_ci          initial_value_(initial_value),
5461cb0ef41Sopenharmony_ci          cond_(cond),
5471cb0ef41Sopenharmony_ci          step_(step),
5481cb0ef41Sopenharmony_ci          initial_arg0_(initial_arg0) {}
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT ForBuilder1& Do(const For1BodyFunction& body) {
5511cb0ef41Sopenharmony_ci      body_ = body;
5521cb0ef41Sopenharmony_ci      return *this;
5531cb0ef41Sopenharmony_ci    }
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ci    V8_WARN_UNUSED_RESULT TNode<Object> Value() {
5561cb0ef41Sopenharmony_ci      DCHECK(body_);
5571cb0ef41Sopenharmony_ci      TNode<Object> arg0 = initial_arg0_;
5581cb0ef41Sopenharmony_ci
5591cb0ef41Sopenharmony_ci      auto loop_exit = gasm_->MakeDeferredLabel(kPhiRepresentation);
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci      {
5621cb0ef41Sopenharmony_ci        GraphAssembler::LoopScope<kPhiRepresentation, kPhiRepresentation>
5631cb0ef41Sopenharmony_ci            loop_scope(gasm_);
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci        auto loop_header = loop_scope.loop_header_label();
5661cb0ef41Sopenharmony_ci        auto loop_body = gasm_->MakeDeferredLabel(kPhiRepresentation);
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci        gasm_->Goto(loop_header, initial_value_, initial_arg0_);
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci        gasm_->Bind(loop_header);
5711cb0ef41Sopenharmony_ci        TNode<Number> i = loop_header->PhiAt<Number>(0);
5721cb0ef41Sopenharmony_ci        arg0 = loop_header->PhiAt<Object>(1);
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci        gasm_->BranchWithHint(cond_(i), &loop_body, &loop_exit,
5751cb0ef41Sopenharmony_ci                              BranchHint::kTrue, arg0);
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci        gasm_->Bind(&loop_body);
5781cb0ef41Sopenharmony_ci        body_(i, &arg0);
5791cb0ef41Sopenharmony_ci        gasm_->Goto(loop_header, step_(i), arg0);
5801cb0ef41Sopenharmony_ci      }
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci      gasm_->Bind(&loop_exit);
5831cb0ef41Sopenharmony_ci      return TNode<Object>::UncheckedCast(loop_exit.PhiAt<Object>(0));
5841cb0ef41Sopenharmony_ci    }
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_ci    void ValueIsUnused() { USE(Value()); }
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci   private:
5891cb0ef41Sopenharmony_ci    static constexpr MachineRepresentation kPhiRepresentation =
5901cb0ef41Sopenharmony_ci        MachineRepresentation::kTagged;
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci    JSGraphAssembler* const gasm_;
5931cb0ef41Sopenharmony_ci    const TNode<Number> initial_value_;
5941cb0ef41Sopenharmony_ci    const ConditionFunction1 cond_;
5951cb0ef41Sopenharmony_ci    const StepFunction1 step_;
5961cb0ef41Sopenharmony_ci    For1BodyFunction body_;
5971cb0ef41Sopenharmony_ci    const TNode<Object> initial_arg0_;
5981cb0ef41Sopenharmony_ci  };
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci  ForBuilder1 For1(TNode<Number> initial_value, const ConditionFunction1& cond,
6011cb0ef41Sopenharmony_ci                   const StepFunction1& step, TNode<Object> initial_arg0) {
6021cb0ef41Sopenharmony_ci    return {this, initial_value, cond, step, initial_arg0};
6031cb0ef41Sopenharmony_ci  }
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  ForBuilder1 For1ZeroUntil(TNode<Number> excluded_limit,
6061cb0ef41Sopenharmony_ci                            TNode<Object> initial_arg0) {
6071cb0ef41Sopenharmony_ci    TNode<Number> initial_value = ZeroConstant();
6081cb0ef41Sopenharmony_ci    auto cond = [=](TNode<Number> i) {
6091cb0ef41Sopenharmony_ci      return NumberLessThan(i, excluded_limit);
6101cb0ef41Sopenharmony_ci    };
6111cb0ef41Sopenharmony_ci    auto step = [=](TNode<Number> i) { return NumberAdd(i, OneConstant()); };
6121cb0ef41Sopenharmony_ci    return {this, initial_value, cond, step, initial_arg0};
6131cb0ef41Sopenharmony_ci  }
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci  void ThrowIfNotCallable(TNode<Object> maybe_callable,
6161cb0ef41Sopenharmony_ci                          FrameState frame_state) {
6171cb0ef41Sopenharmony_ci    IfNot(ObjectIsCallable(maybe_callable))
6181cb0ef41Sopenharmony_ci        .Then(_ {
6191cb0ef41Sopenharmony_ci          JSCallRuntime2(Runtime::kThrowTypeError,
6201cb0ef41Sopenharmony_ci                         NumberConstant(static_cast<double>(
6211cb0ef41Sopenharmony_ci                             MessageTemplate::kCalledNonCallable)),
6221cb0ef41Sopenharmony_ci                         maybe_callable, frame_state);
6231cb0ef41Sopenharmony_ci          Unreachable();  // The runtime call throws unconditionally.
6241cb0ef41Sopenharmony_ci        })
6251cb0ef41Sopenharmony_ci        .ExpectTrue();
6261cb0ef41Sopenharmony_ci  }
6271cb0ef41Sopenharmony_ci
6281cb0ef41Sopenharmony_ci  const FeedbackSource& feedback() const {
6291cb0ef41Sopenharmony_ci    CallParameters const& p = CallParametersOf(node_ptr()->op());
6301cb0ef41Sopenharmony_ci    return p.feedback();
6311cb0ef41Sopenharmony_ci  }
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci  int ArgumentCount() const { return JSCallNode{node_ptr()}.ArgumentCount(); }
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci  TNode<Object> Argument(int index) const {
6361cb0ef41Sopenharmony_ci    return TNode<Object>::UncheckedCast(JSCallNode{node_ptr()}.Argument(index));
6371cb0ef41Sopenharmony_ci  }
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci  template <typename T>
6401cb0ef41Sopenharmony_ci  TNode<T> ArgumentAs(int index) const {
6411cb0ef41Sopenharmony_ci    return TNode<T>::UncheckedCast(Argument(index));
6421cb0ef41Sopenharmony_ci  }
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci  TNode<Object> ArgumentOrNaN(int index) {
6451cb0ef41Sopenharmony_ci    return TNode<Object>::UncheckedCast(
6461cb0ef41Sopenharmony_ci        ArgumentCount() > index ? Argument(index) : NaNConstant());
6471cb0ef41Sopenharmony_ci  }
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci  TNode<Object> ArgumentOrUndefined(int index) {
6501cb0ef41Sopenharmony_ci    return TNode<Object>::UncheckedCast(
6511cb0ef41Sopenharmony_ci        ArgumentCount() > index ? Argument(index) : UndefinedConstant());
6521cb0ef41Sopenharmony_ci  }
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ci  TNode<Number> ArgumentOrZero(int index) {
6551cb0ef41Sopenharmony_ci    return TNode<Number>::UncheckedCast(
6561cb0ef41Sopenharmony_ci        ArgumentCount() > index ? Argument(index) : ZeroConstant());
6571cb0ef41Sopenharmony_ci  }
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  TNode<Context> ContextInput() const {
6601cb0ef41Sopenharmony_ci    return TNode<Context>::UncheckedCast(
6611cb0ef41Sopenharmony_ci        NodeProperties::GetContextInput(node_));
6621cb0ef41Sopenharmony_ci  }
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_ci  FrameState FrameStateInput() const {
6651cb0ef41Sopenharmony_ci    return FrameState(NodeProperties::GetFrameStateInput(node_));
6661cb0ef41Sopenharmony_ci  }
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_ci  JSOperatorBuilder* javascript() const { return jsgraph()->javascript(); }
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci  CompilationDependencies* dependencies() const { return dependencies_; }
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ci private:
6731cb0ef41Sopenharmony_ci  CompilationDependencies* const dependencies_;
6741cb0ef41Sopenharmony_ci  Node* const node_;
6751cb0ef41Sopenharmony_ci  CatchScope outermost_catch_scope_;
6761cb0ef41Sopenharmony_ci  Node* outermost_handler_;
6771cb0ef41Sopenharmony_ci  CatchScope* catch_scope_;
6781cb0ef41Sopenharmony_ci  friend class CatchScope;
6791cb0ef41Sopenharmony_ci};
6801cb0ef41Sopenharmony_ci
6811cb0ef41Sopenharmony_cienum class ArrayReduceDirection { kLeft, kRight };
6821cb0ef41Sopenharmony_cienum class ArrayFindVariant { kFind, kFindIndex };
6831cb0ef41Sopenharmony_cienum class ArrayEverySomeVariant { kEvery, kSome };
6841cb0ef41Sopenharmony_cienum class ArrayIndexOfIncludesVariant { kIncludes, kIndexOf };
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci// This subclass bundles functionality specific to reducing iterating array
6871cb0ef41Sopenharmony_ci// builtins.
6881cb0ef41Sopenharmony_ciclass IteratingArrayBuiltinReducerAssembler : public JSCallReducerAssembler {
6891cb0ef41Sopenharmony_ci public:
6901cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler(JSCallReducer* reducer, Node* node)
6911cb0ef41Sopenharmony_ci      : JSCallReducerAssembler(reducer, node) {
6921cb0ef41Sopenharmony_ci    DCHECK(FLAG_turbo_inline_array_builtins);
6931cb0ef41Sopenharmony_ci  }
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci  TNode<Object> ReduceArrayPrototypeForEach(
6961cb0ef41Sopenharmony_ci      MapInference* inference, const bool has_stability_dependency,
6971cb0ef41Sopenharmony_ci      ElementsKind kind, const SharedFunctionInfoRef& shared);
6981cb0ef41Sopenharmony_ci  TNode<Object> ReduceArrayPrototypeReduce(MapInference* inference,
6991cb0ef41Sopenharmony_ci                                           const bool has_stability_dependency,
7001cb0ef41Sopenharmony_ci                                           ElementsKind kind,
7011cb0ef41Sopenharmony_ci                                           ArrayReduceDirection direction,
7021cb0ef41Sopenharmony_ci                                           const SharedFunctionInfoRef& shared);
7031cb0ef41Sopenharmony_ci  TNode<JSArray> ReduceArrayPrototypeMap(
7041cb0ef41Sopenharmony_ci      MapInference* inference, const bool has_stability_dependency,
7051cb0ef41Sopenharmony_ci      ElementsKind kind, const SharedFunctionInfoRef& shared,
7061cb0ef41Sopenharmony_ci      const NativeContextRef& native_context);
7071cb0ef41Sopenharmony_ci  TNode<JSArray> ReduceArrayPrototypeFilter(
7081cb0ef41Sopenharmony_ci      MapInference* inference, const bool has_stability_dependency,
7091cb0ef41Sopenharmony_ci      ElementsKind kind, const SharedFunctionInfoRef& shared,
7101cb0ef41Sopenharmony_ci      const NativeContextRef& native_context);
7111cb0ef41Sopenharmony_ci  TNode<Object> ReduceArrayPrototypeFind(MapInference* inference,
7121cb0ef41Sopenharmony_ci                                         const bool has_stability_dependency,
7131cb0ef41Sopenharmony_ci                                         ElementsKind kind,
7141cb0ef41Sopenharmony_ci                                         const SharedFunctionInfoRef& shared,
7151cb0ef41Sopenharmony_ci                                         const NativeContextRef& native_context,
7161cb0ef41Sopenharmony_ci                                         ArrayFindVariant variant);
7171cb0ef41Sopenharmony_ci  TNode<Boolean> ReduceArrayPrototypeEverySome(
7181cb0ef41Sopenharmony_ci      MapInference* inference, const bool has_stability_dependency,
7191cb0ef41Sopenharmony_ci      ElementsKind kind, const SharedFunctionInfoRef& shared,
7201cb0ef41Sopenharmony_ci      const NativeContextRef& native_context, ArrayEverySomeVariant variant);
7211cb0ef41Sopenharmony_ci  TNode<Object> ReduceArrayPrototypeIndexOfIncludes(
7221cb0ef41Sopenharmony_ci      ElementsKind kind, ArrayIndexOfIncludesVariant variant);
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci private:
7251cb0ef41Sopenharmony_ci  // Returns {index,value}. Assumes that the map has not changed, but possibly
7261cb0ef41Sopenharmony_ci  // the length and backing store.
7271cb0ef41Sopenharmony_ci  std::pair<TNode<Number>, TNode<Object>> SafeLoadElement(ElementsKind kind,
7281cb0ef41Sopenharmony_ci                                                          TNode<JSArray> o,
7291cb0ef41Sopenharmony_ci                                                          TNode<Number> index) {
7301cb0ef41Sopenharmony_ci    // Make sure that the access is still in bounds, since the callback could
7311cb0ef41Sopenharmony_ci    // have changed the array's size.
7321cb0ef41Sopenharmony_ci    TNode<Number> length = LoadJSArrayLength(o, kind);
7331cb0ef41Sopenharmony_ci    index = CheckBounds(index, length);
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci    // Reload the elements pointer before calling the callback, since the
7361cb0ef41Sopenharmony_ci    // previous callback might have resized the array causing the elements
7371cb0ef41Sopenharmony_ci    // buffer to be re-allocated.
7381cb0ef41Sopenharmony_ci    TNode<HeapObject> elements =
7391cb0ef41Sopenharmony_ci        LoadField<HeapObject>(AccessBuilder::ForJSObjectElements(), o);
7401cb0ef41Sopenharmony_ci    TNode<Object> value = LoadElement<Object>(
7411cb0ef41Sopenharmony_ci        AccessBuilder::ForFixedArrayElement(kind), elements, index);
7421cb0ef41Sopenharmony_ci    return std::make_pair(index, value);
7431cb0ef41Sopenharmony_ci  }
7441cb0ef41Sopenharmony_ci
7451cb0ef41Sopenharmony_ci  template <typename... Vars>
7461cb0ef41Sopenharmony_ci  TNode<Object> MaybeSkipHole(
7471cb0ef41Sopenharmony_ci      TNode<Object> o, ElementsKind kind,
7481cb0ef41Sopenharmony_ci      GraphAssemblerLabel<sizeof...(Vars)>* continue_label,
7491cb0ef41Sopenharmony_ci      TNode<Vars>... vars) {
7501cb0ef41Sopenharmony_ci    if (!IsHoleyElementsKind(kind)) return o;
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ci    std::array<MachineRepresentation, sizeof...(Vars)> reps = {
7531cb0ef41Sopenharmony_ci        MachineRepresentationOf<Vars>::value...};
7541cb0ef41Sopenharmony_ci    auto if_not_hole =
7551cb0ef41Sopenharmony_ci        MakeLabel<sizeof...(Vars)>(reps, GraphAssemblerLabelType::kNonDeferred);
7561cb0ef41Sopenharmony_ci    BranchWithHint(HoleCheck(kind, o), continue_label, &if_not_hole,
7571cb0ef41Sopenharmony_ci                   BranchHint::kFalse, vars...);
7581cb0ef41Sopenharmony_ci
7591cb0ef41Sopenharmony_ci    // The contract is that we don't leak "the hole" into "user JavaScript",
7601cb0ef41Sopenharmony_ci    // so we must rename the {element} here to explicitly exclude "the hole"
7611cb0ef41Sopenharmony_ci    // from the type of {element}.
7621cb0ef41Sopenharmony_ci    Bind(&if_not_hole);
7631cb0ef41Sopenharmony_ci    return TypeGuardNonInternal(o);
7641cb0ef41Sopenharmony_ci  }
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci  TNode<Smi> LoadJSArrayLength(TNode<JSArray> array, ElementsKind kind) {
7671cb0ef41Sopenharmony_ci    return LoadField<Smi>(AccessBuilder::ForJSArrayLength(kind), array);
7681cb0ef41Sopenharmony_ci  }
7691cb0ef41Sopenharmony_ci  void StoreJSArrayLength(TNode<JSArray> array, TNode<Number> value,
7701cb0ef41Sopenharmony_ci                          ElementsKind kind) {
7711cb0ef41Sopenharmony_ci    StoreField(AccessBuilder::ForJSArrayLength(kind), array, value);
7721cb0ef41Sopenharmony_ci  }
7731cb0ef41Sopenharmony_ci  void StoreFixedArrayBaseElement(TNode<FixedArrayBase> o, TNode<Number> index,
7741cb0ef41Sopenharmony_ci                                  TNode<Object> v, ElementsKind kind) {
7751cb0ef41Sopenharmony_ci    StoreElement(AccessBuilder::ForFixedArrayElement(kind), o, index, v);
7761cb0ef41Sopenharmony_ci  }
7771cb0ef41Sopenharmony_ci
7781cb0ef41Sopenharmony_ci  TNode<FixedArrayBase> LoadElements(TNode<JSObject> o) {
7791cb0ef41Sopenharmony_ci    return LoadField<FixedArrayBase>(AccessBuilder::ForJSObjectElements(), o);
7801cb0ef41Sopenharmony_ci  }
7811cb0ef41Sopenharmony_ci  TNode<Smi> LoadFixedArrayBaseLength(TNode<FixedArrayBase> o) {
7821cb0ef41Sopenharmony_ci    return LoadField<Smi>(AccessBuilder::ForFixedArrayLength(), o);
7831cb0ef41Sopenharmony_ci  }
7841cb0ef41Sopenharmony_ci
7851cb0ef41Sopenharmony_ci  TNode<Boolean> HoleCheck(ElementsKind kind, TNode<Object> v) {
7861cb0ef41Sopenharmony_ci    return IsDoubleElementsKind(kind)
7871cb0ef41Sopenharmony_ci               ? NumberIsFloat64Hole(TNode<Number>::UncheckedCast(v))
7881cb0ef41Sopenharmony_ci               : IsTheHole(v);
7891cb0ef41Sopenharmony_ci  }
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_ci  TNode<Number> CheckFloat64Hole(TNode<Number> value,
7921cb0ef41Sopenharmony_ci                                 CheckFloat64HoleMode mode) {
7931cb0ef41Sopenharmony_ci    return AddNode<Number>(
7941cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->CheckFloat64Hole(mode, feedback()),
7951cb0ef41Sopenharmony_ci                         value, effect(), control()));
7961cb0ef41Sopenharmony_ci  }
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_ci  // May deopt for holey double elements.
7991cb0ef41Sopenharmony_ci  TNode<Object> TryConvertHoleToUndefined(TNode<Object> value,
8001cb0ef41Sopenharmony_ci                                          ElementsKind kind) {
8011cb0ef41Sopenharmony_ci    DCHECK(IsHoleyElementsKind(kind));
8021cb0ef41Sopenharmony_ci    if (kind == HOLEY_DOUBLE_ELEMENTS) {
8031cb0ef41Sopenharmony_ci      // TODO(7409): avoid deopt if not all uses of value are truncated.
8041cb0ef41Sopenharmony_ci      TNode<Number> number = TNode<Number>::UncheckedCast(value);
8051cb0ef41Sopenharmony_ci      return CheckFloat64Hole(number, CheckFloat64HoleMode::kAllowReturnHole);
8061cb0ef41Sopenharmony_ci    }
8071cb0ef41Sopenharmony_ci
8081cb0ef41Sopenharmony_ci    return ConvertTaggedHoleToUndefined(value);
8091cb0ef41Sopenharmony_ci  }
8101cb0ef41Sopenharmony_ci};
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ciclass PromiseBuiltinReducerAssembler : public JSCallReducerAssembler {
8131cb0ef41Sopenharmony_ci public:
8141cb0ef41Sopenharmony_ci  PromiseBuiltinReducerAssembler(JSCallReducer* reducer, Node* node,
8151cb0ef41Sopenharmony_ci                                 JSHeapBroker* broker)
8161cb0ef41Sopenharmony_ci      : JSCallReducerAssembler(reducer, node), broker_(broker) {
8171cb0ef41Sopenharmony_ci    DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
8181cb0ef41Sopenharmony_ci  }
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_ci  TNode<Object> ReducePromiseConstructor(
8211cb0ef41Sopenharmony_ci      const NativeContextRef& native_context);
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci  int ConstructArity() const {
8241cb0ef41Sopenharmony_ci    return JSConstructNode{node_ptr()}.ArgumentCount();
8251cb0ef41Sopenharmony_ci  }
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_ci  TNode<Object> TargetInput() const {
8281cb0ef41Sopenharmony_ci    return JSConstructNode{node_ptr()}.target();
8291cb0ef41Sopenharmony_ci  }
8301cb0ef41Sopenharmony_ci
8311cb0ef41Sopenharmony_ci  TNode<Object> NewTargetInput() const {
8321cb0ef41Sopenharmony_ci    return JSConstructNode{node_ptr()}.new_target();
8331cb0ef41Sopenharmony_ci  }
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ci private:
8361cb0ef41Sopenharmony_ci  TNode<JSPromise> CreatePromise(TNode<Context> context) {
8371cb0ef41Sopenharmony_ci    return AddNode<JSPromise>(
8381cb0ef41Sopenharmony_ci        graph()->NewNode(javascript()->CreatePromise(), context, effect()));
8391cb0ef41Sopenharmony_ci  }
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci  TNode<Context> CreateFunctionContext(const NativeContextRef& native_context,
8421cb0ef41Sopenharmony_ci                                       TNode<Context> outer_context,
8431cb0ef41Sopenharmony_ci                                       int slot_count) {
8441cb0ef41Sopenharmony_ci    return AddNode<Context>(graph()->NewNode(
8451cb0ef41Sopenharmony_ci        javascript()->CreateFunctionContext(
8461cb0ef41Sopenharmony_ci            native_context.scope_info(),
8471cb0ef41Sopenharmony_ci            slot_count - Context::MIN_CONTEXT_SLOTS, FUNCTION_SCOPE),
8481cb0ef41Sopenharmony_ci        outer_context, effect(), control()));
8491cb0ef41Sopenharmony_ci  }
8501cb0ef41Sopenharmony_ci
8511cb0ef41Sopenharmony_ci  void StoreContextSlot(TNode<Context> context, size_t slot_index,
8521cb0ef41Sopenharmony_ci                        TNode<Object> value) {
8531cb0ef41Sopenharmony_ci    StoreField(AccessBuilder::ForContextSlot(slot_index), context, value);
8541cb0ef41Sopenharmony_ci  }
8551cb0ef41Sopenharmony_ci
8561cb0ef41Sopenharmony_ci  TNode<JSFunction> CreateClosureFromBuiltinSharedFunctionInfo(
8571cb0ef41Sopenharmony_ci      SharedFunctionInfoRef shared, TNode<Context> context) {
8581cb0ef41Sopenharmony_ci    DCHECK(shared.HasBuiltinId());
8591cb0ef41Sopenharmony_ci    Handle<FeedbackCell> feedback_cell =
8601cb0ef41Sopenharmony_ci        isolate()->factory()->many_closures_cell();
8611cb0ef41Sopenharmony_ci    Callable const callable =
8621cb0ef41Sopenharmony_ci        Builtins::CallableFor(isolate(), shared.builtin_id());
8631cb0ef41Sopenharmony_ci    CodeTRef code = MakeRef(broker_, *callable.code());
8641cb0ef41Sopenharmony_ci    return AddNode<JSFunction>(graph()->NewNode(
8651cb0ef41Sopenharmony_ci        javascript()->CreateClosure(shared, code), HeapConstant(feedback_cell),
8661cb0ef41Sopenharmony_ci        context, effect(), control()));
8671cb0ef41Sopenharmony_ci  }
8681cb0ef41Sopenharmony_ci
8691cb0ef41Sopenharmony_ci  void CallPromiseExecutor(TNode<Object> executor, TNode<JSFunction> resolve,
8701cb0ef41Sopenharmony_ci                           TNode<JSFunction> reject, FrameState frame_state) {
8711cb0ef41Sopenharmony_ci    JSConstructNode n(node_ptr());
8721cb0ef41Sopenharmony_ci    const ConstructParameters& p = n.Parameters();
8731cb0ef41Sopenharmony_ci    FeedbackSource no_feedback_source{};
8741cb0ef41Sopenharmony_ci    Node* no_feedback = UndefinedConstant();
8751cb0ef41Sopenharmony_ci    MayThrow(_ {
8761cb0ef41Sopenharmony_ci      return AddNode<Object>(graph()->NewNode(
8771cb0ef41Sopenharmony_ci          javascript()->Call(JSCallNode::ArityForArgc(2), p.frequency(),
8781cb0ef41Sopenharmony_ci                             no_feedback_source,
8791cb0ef41Sopenharmony_ci                             ConvertReceiverMode::kNullOrUndefined),
8801cb0ef41Sopenharmony_ci          executor, UndefinedConstant(), resolve, reject, no_feedback,
8811cb0ef41Sopenharmony_ci          n.context(), frame_state, effect(), control()));
8821cb0ef41Sopenharmony_ci    });
8831cb0ef41Sopenharmony_ci  }
8841cb0ef41Sopenharmony_ci
8851cb0ef41Sopenharmony_ci  void CallPromiseReject(TNode<JSFunction> reject, TNode<Object> exception,
8861cb0ef41Sopenharmony_ci                         FrameState frame_state) {
8871cb0ef41Sopenharmony_ci    JSConstructNode n(node_ptr());
8881cb0ef41Sopenharmony_ci    const ConstructParameters& p = n.Parameters();
8891cb0ef41Sopenharmony_ci    FeedbackSource no_feedback_source{};
8901cb0ef41Sopenharmony_ci    Node* no_feedback = UndefinedConstant();
8911cb0ef41Sopenharmony_ci    MayThrow(_ {
8921cb0ef41Sopenharmony_ci      return AddNode<Object>(graph()->NewNode(
8931cb0ef41Sopenharmony_ci          javascript()->Call(JSCallNode::ArityForArgc(1), p.frequency(),
8941cb0ef41Sopenharmony_ci                             no_feedback_source,
8951cb0ef41Sopenharmony_ci                             ConvertReceiverMode::kNullOrUndefined),
8961cb0ef41Sopenharmony_ci          reject, UndefinedConstant(), exception, no_feedback, n.context(),
8971cb0ef41Sopenharmony_ci          frame_state, effect(), control()));
8981cb0ef41Sopenharmony_ci    });
8991cb0ef41Sopenharmony_ci  }
9001cb0ef41Sopenharmony_ci
9011cb0ef41Sopenharmony_ci  JSHeapBroker* const broker_;
9021cb0ef41Sopenharmony_ci};
9031cb0ef41Sopenharmony_ci
9041cb0ef41Sopenharmony_ciclass FastApiCallReducerAssembler : public JSCallReducerAssembler {
9051cb0ef41Sopenharmony_ci public:
9061cb0ef41Sopenharmony_ci  FastApiCallReducerAssembler(
9071cb0ef41Sopenharmony_ci      JSCallReducer* reducer, Node* node,
9081cb0ef41Sopenharmony_ci      const FunctionTemplateInfoRef function_template_info,
9091cb0ef41Sopenharmony_ci      const FastApiCallFunctionVector& c_candidate_functions, Node* receiver,
9101cb0ef41Sopenharmony_ci      Node* holder, const SharedFunctionInfoRef shared, Node* target,
9111cb0ef41Sopenharmony_ci      const int arity, Node* effect)
9121cb0ef41Sopenharmony_ci      : JSCallReducerAssembler(reducer, node),
9131cb0ef41Sopenharmony_ci        c_candidate_functions_(c_candidate_functions),
9141cb0ef41Sopenharmony_ci        function_template_info_(function_template_info),
9151cb0ef41Sopenharmony_ci        receiver_(receiver),
9161cb0ef41Sopenharmony_ci        holder_(holder),
9171cb0ef41Sopenharmony_ci        shared_(shared),
9181cb0ef41Sopenharmony_ci        target_(target),
9191cb0ef41Sopenharmony_ci        arity_(arity) {
9201cb0ef41Sopenharmony_ci    DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
9211cb0ef41Sopenharmony_ci    CHECK_GT(c_candidate_functions.size(), 0);
9221cb0ef41Sopenharmony_ci    InitializeEffectControl(effect, NodeProperties::GetControlInput(node));
9231cb0ef41Sopenharmony_ci  }
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci  TNode<Object> ReduceFastApiCall() {
9261cb0ef41Sopenharmony_ci    JSCallNode n(node_ptr());
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_ci    // C arguments include the receiver at index 0. Thus C index 1 corresponds
9291cb0ef41Sopenharmony_ci    // to the JS argument 0, etc.
9301cb0ef41Sopenharmony_ci    // All functions in c_candidate_functions_ have the same number of
9311cb0ef41Sopenharmony_ci    // arguments, so extract c_argument_count from the first function.
9321cb0ef41Sopenharmony_ci    const int c_argument_count =
9331cb0ef41Sopenharmony_ci        static_cast<int>(c_candidate_functions_[0].signature->ArgumentCount());
9341cb0ef41Sopenharmony_ci    CHECK_GE(c_argument_count, kReceiver);
9351cb0ef41Sopenharmony_ci
9361cb0ef41Sopenharmony_ci    int cursor = 0;
9371cb0ef41Sopenharmony_ci    base::SmallVector<Node*, kInlineSize> inputs(c_argument_count + arity_ +
9381cb0ef41Sopenharmony_ci                                                 kExtraInputsCount);
9391cb0ef41Sopenharmony_ci    inputs[cursor++] = n.receiver();
9401cb0ef41Sopenharmony_ci
9411cb0ef41Sopenharmony_ci    // TODO(turbofan): Consider refactoring CFunctionInfo to distinguish
9421cb0ef41Sopenharmony_ci    // between receiver and arguments, simplifying this (and related) spots.
9431cb0ef41Sopenharmony_ci    int js_args_count = c_argument_count - kReceiver;
9441cb0ef41Sopenharmony_ci    for (int i = 0; i < js_args_count; ++i) {
9451cb0ef41Sopenharmony_ci      if (i < n.ArgumentCount()) {
9461cb0ef41Sopenharmony_ci        inputs[cursor++] = n.Argument(i);
9471cb0ef41Sopenharmony_ci      } else {
9481cb0ef41Sopenharmony_ci        inputs[cursor++] = UndefinedConstant();
9491cb0ef41Sopenharmony_ci      }
9501cb0ef41Sopenharmony_ci    }
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_ci    // Here we add the arguments for the slow call, which will be
9531cb0ef41Sopenharmony_ci    // reconstructed at a later phase. Those are effectively the same
9541cb0ef41Sopenharmony_ci    // arguments as for the fast call, but we want to have them as
9551cb0ef41Sopenharmony_ci    // separate inputs, so that SimplifiedLowering can provide the best
9561cb0ef41Sopenharmony_ci    // possible UseInfos for each of them. The inputs to FastApiCall
9571cb0ef41Sopenharmony_ci    // look like:
9581cb0ef41Sopenharmony_ci    // [fast callee, receiver, ... C arguments,
9591cb0ef41Sopenharmony_ci    // call code, external constant for function, argc, call handler info data,
9601cb0ef41Sopenharmony_ci    // holder, receiver, ... JS arguments, context, new frame state]
9611cb0ef41Sopenharmony_ci    CallHandlerInfoRef call_handler_info = *function_template_info_.call_code();
9621cb0ef41Sopenharmony_ci    Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
9631cb0ef41Sopenharmony_ci    CallInterfaceDescriptor cid = call_api_callback.descriptor();
9641cb0ef41Sopenharmony_ci    CallDescriptor* call_descriptor =
9651cb0ef41Sopenharmony_ci        Linkage::GetStubCallDescriptor(graph()->zone(), cid, arity_ + kReceiver,
9661cb0ef41Sopenharmony_ci                                       CallDescriptor::kNeedsFrameState);
9671cb0ef41Sopenharmony_ci    ApiFunction api_function(call_handler_info.callback());
9681cb0ef41Sopenharmony_ci    ExternalReference function_reference = ExternalReference::Create(
9691cb0ef41Sopenharmony_ci        isolate(), &api_function, ExternalReference::DIRECT_API_CALL,
9701cb0ef41Sopenharmony_ci        function_template_info_.c_functions().data(),
9711cb0ef41Sopenharmony_ci        function_template_info_.c_signatures().data(),
9721cb0ef41Sopenharmony_ci        static_cast<unsigned>(function_template_info_.c_functions().size()));
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci    Node* continuation_frame_state =
9751cb0ef41Sopenharmony_ci        CreateGenericLazyDeoptContinuationFrameState(
9761cb0ef41Sopenharmony_ci            jsgraph(), shared_, target_, ContextInput(), receiver_,
9771cb0ef41Sopenharmony_ci            FrameStateInput());
9781cb0ef41Sopenharmony_ci
9791cb0ef41Sopenharmony_ci    inputs[cursor++] = HeapConstant(call_api_callback.code());
9801cb0ef41Sopenharmony_ci    inputs[cursor++] = ExternalConstant(function_reference);
9811cb0ef41Sopenharmony_ci    inputs[cursor++] = NumberConstant(arity_);
9821cb0ef41Sopenharmony_ci    inputs[cursor++] = Constant(call_handler_info.data());
9831cb0ef41Sopenharmony_ci    inputs[cursor++] = holder_;
9841cb0ef41Sopenharmony_ci    inputs[cursor++] = receiver_;
9851cb0ef41Sopenharmony_ci    for (int i = 0; i < arity_; ++i) {
9861cb0ef41Sopenharmony_ci      inputs[cursor++] = Argument(i);
9871cb0ef41Sopenharmony_ci    }
9881cb0ef41Sopenharmony_ci    inputs[cursor++] = ContextInput();
9891cb0ef41Sopenharmony_ci    inputs[cursor++] = continuation_frame_state;
9901cb0ef41Sopenharmony_ci    inputs[cursor++] = effect();
9911cb0ef41Sopenharmony_ci    inputs[cursor++] = control();
9921cb0ef41Sopenharmony_ci
9931cb0ef41Sopenharmony_ci    DCHECK_EQ(cursor, c_argument_count + arity_ + kExtraInputsCount);
9941cb0ef41Sopenharmony_ci
9951cb0ef41Sopenharmony_ci    return FastApiCall(call_descriptor, inputs.begin(), inputs.size());
9961cb0ef41Sopenharmony_ci  }
9971cb0ef41Sopenharmony_ci
9981cb0ef41Sopenharmony_ci private:
9991cb0ef41Sopenharmony_ci  static constexpr int kSlowTarget = 1;
10001cb0ef41Sopenharmony_ci  static constexpr int kEffectAndControl = 2;
10011cb0ef41Sopenharmony_ci  static constexpr int kContextAndFrameState = 2;
10021cb0ef41Sopenharmony_ci  static constexpr int kCallCodeDataAndArgc = 3;
10031cb0ef41Sopenharmony_ci  static constexpr int kHolder = 1, kReceiver = 1;
10041cb0ef41Sopenharmony_ci  static constexpr int kExtraInputsCount =
10051cb0ef41Sopenharmony_ci      kSlowTarget + kEffectAndControl + kContextAndFrameState +
10061cb0ef41Sopenharmony_ci      kCallCodeDataAndArgc + kHolder + kReceiver;
10071cb0ef41Sopenharmony_ci  static constexpr int kInlineSize = 12;
10081cb0ef41Sopenharmony_ci
10091cb0ef41Sopenharmony_ci  TNode<Object> FastApiCall(CallDescriptor* descriptor, Node** inputs,
10101cb0ef41Sopenharmony_ci                            size_t inputs_size) {
10111cb0ef41Sopenharmony_ci    return AddNode<Object>(
10121cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->FastApiCall(c_candidate_functions_,
10131cb0ef41Sopenharmony_ci                                                   feedback(), descriptor),
10141cb0ef41Sopenharmony_ci                         static_cast<int>(inputs_size), inputs));
10151cb0ef41Sopenharmony_ci  }
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci  const FastApiCallFunctionVector c_candidate_functions_;
10181cb0ef41Sopenharmony_ci  const FunctionTemplateInfoRef function_template_info_;
10191cb0ef41Sopenharmony_ci  Node* const receiver_;
10201cb0ef41Sopenharmony_ci  Node* const holder_;
10211cb0ef41Sopenharmony_ci  const SharedFunctionInfoRef shared_;
10221cb0ef41Sopenharmony_ci  Node* const target_;
10231cb0ef41Sopenharmony_ci  const int arity_;
10241cb0ef41Sopenharmony_ci};
10251cb0ef41Sopenharmony_ci
10261cb0ef41Sopenharmony_ciTNode<Number> JSCallReducerAssembler::SpeculativeToNumber(
10271cb0ef41Sopenharmony_ci    TNode<Object> value, NumberOperationHint hint) {
10281cb0ef41Sopenharmony_ci  return AddNode<Number>(
10291cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(hint, feedback()),
10301cb0ef41Sopenharmony_ci                       value, effect(), control()));
10311cb0ef41Sopenharmony_ci}
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_ciTNode<Smi> JSCallReducerAssembler::CheckSmi(TNode<Object> value) {
10341cb0ef41Sopenharmony_ci  return AddNode<Smi>(graph()->NewNode(simplified()->CheckSmi(feedback()),
10351cb0ef41Sopenharmony_ci                                       value, effect(), control()));
10361cb0ef41Sopenharmony_ci}
10371cb0ef41Sopenharmony_ci
10381cb0ef41Sopenharmony_ciTNode<String> JSCallReducerAssembler::CheckString(TNode<Object> value) {
10391cb0ef41Sopenharmony_ci  return AddNode<String>(graph()->NewNode(simplified()->CheckString(feedback()),
10401cb0ef41Sopenharmony_ci                                          value, effect(), control()));
10411cb0ef41Sopenharmony_ci}
10421cb0ef41Sopenharmony_ci
10431cb0ef41Sopenharmony_ciTNode<Number> JSCallReducerAssembler::CheckBounds(TNode<Number> value,
10441cb0ef41Sopenharmony_ci                                                  TNode<Number> limit) {
10451cb0ef41Sopenharmony_ci  return AddNode<Number>(graph()->NewNode(simplified()->CheckBounds(feedback()),
10461cb0ef41Sopenharmony_ci                                          value, limit, effect(), control()));
10471cb0ef41Sopenharmony_ci}
10481cb0ef41Sopenharmony_ci
10491cb0ef41Sopenharmony_ciTNode<Smi> JSCallReducerAssembler::TypeGuardUnsignedSmall(TNode<Object> value) {
10501cb0ef41Sopenharmony_ci  return TNode<Smi>::UncheckedCast(TypeGuard(Type::UnsignedSmall(), value));
10511cb0ef41Sopenharmony_ci}
10521cb0ef41Sopenharmony_ci
10531cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::TypeGuardNonInternal(
10541cb0ef41Sopenharmony_ci    TNode<Object> value) {
10551cb0ef41Sopenharmony_ci  return TNode<Object>::UncheckedCast(TypeGuard(Type::NonInternal(), value));
10561cb0ef41Sopenharmony_ci}
10571cb0ef41Sopenharmony_ci
10581cb0ef41Sopenharmony_ciTNode<Number> JSCallReducerAssembler::TypeGuardFixedArrayLength(
10591cb0ef41Sopenharmony_ci    TNode<Object> value) {
10601cb0ef41Sopenharmony_ci  DCHECK(TypeCache::Get()->kFixedDoubleArrayLengthType.Is(
10611cb0ef41Sopenharmony_ci      TypeCache::Get()->kFixedArrayLengthType));
10621cb0ef41Sopenharmony_ci  return TNode<Number>::UncheckedCast(
10631cb0ef41Sopenharmony_ci      TypeGuard(TypeCache::Get()->kFixedArrayLengthType, value));
10641cb0ef41Sopenharmony_ci}
10651cb0ef41Sopenharmony_ci
10661cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::Call4(
10671cb0ef41Sopenharmony_ci    const Callable& callable, TNode<Context> context, TNode<Object> arg0,
10681cb0ef41Sopenharmony_ci    TNode<Object> arg1, TNode<Object> arg2, TNode<Object> arg3) {
10691cb0ef41Sopenharmony_ci  // TODO(jgruber): Make this more generic. Currently it's fitted to its single
10701cb0ef41Sopenharmony_ci  // callsite.
10711cb0ef41Sopenharmony_ci  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
10721cb0ef41Sopenharmony_ci      graph()->zone(), callable.descriptor(),
10731cb0ef41Sopenharmony_ci      callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
10741cb0ef41Sopenharmony_ci      Operator::kEliminatable);
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_ci  return TNode<Object>::UncheckedCast(Call(desc, HeapConstant(callable.code()),
10771cb0ef41Sopenharmony_ci                                           arg0, arg1, arg2, arg3, context));
10781cb0ef41Sopenharmony_ci}
10791cb0ef41Sopenharmony_ci
10801cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::JSCall3(
10811cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0,
10821cb0ef41Sopenharmony_ci    TNode<Object> arg1, TNode<Object> arg2, FrameState frame_state) {
10831cb0ef41Sopenharmony_ci  JSCallNode n(node_ptr());
10841cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
10851cb0ef41Sopenharmony_ci  return MayThrow(_ {
10861cb0ef41Sopenharmony_ci    return AddNode<Object>(graph()->NewNode(
10871cb0ef41Sopenharmony_ci        javascript()->Call(JSCallNode::ArityForArgc(3), p.frequency(),
10881cb0ef41Sopenharmony_ci                           p.feedback(), ConvertReceiverMode::kAny,
10891cb0ef41Sopenharmony_ci                           p.speculation_mode(),
10901cb0ef41Sopenharmony_ci                           CallFeedbackRelation::kUnrelated),
10911cb0ef41Sopenharmony_ci        function, this_arg, arg0, arg1, arg2, n.feedback_vector(),
10921cb0ef41Sopenharmony_ci        ContextInput(), frame_state, effect(), control()));
10931cb0ef41Sopenharmony_ci  });
10941cb0ef41Sopenharmony_ci}
10951cb0ef41Sopenharmony_ci
10961cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::JSCall4(
10971cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0,
10981cb0ef41Sopenharmony_ci    TNode<Object> arg1, TNode<Object> arg2, TNode<Object> arg3,
10991cb0ef41Sopenharmony_ci    FrameState frame_state) {
11001cb0ef41Sopenharmony_ci  JSCallNode n(node_ptr());
11011cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
11021cb0ef41Sopenharmony_ci  return MayThrow(_ {
11031cb0ef41Sopenharmony_ci    return AddNode<Object>(graph()->NewNode(
11041cb0ef41Sopenharmony_ci        javascript()->Call(JSCallNode::ArityForArgc(4), p.frequency(),
11051cb0ef41Sopenharmony_ci                           p.feedback(), ConvertReceiverMode::kAny,
11061cb0ef41Sopenharmony_ci                           p.speculation_mode(),
11071cb0ef41Sopenharmony_ci                           CallFeedbackRelation::kUnrelated),
11081cb0ef41Sopenharmony_ci        function, this_arg, arg0, arg1, arg2, arg3, n.feedback_vector(),
11091cb0ef41Sopenharmony_ci        ContextInput(), frame_state, effect(), control()));
11101cb0ef41Sopenharmony_ci  });
11111cb0ef41Sopenharmony_ci}
11121cb0ef41Sopenharmony_ci
11131cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::JSCallRuntime2(
11141cb0ef41Sopenharmony_ci    Runtime::FunctionId function_id, TNode<Object> arg0, TNode<Object> arg1,
11151cb0ef41Sopenharmony_ci    FrameState frame_state) {
11161cb0ef41Sopenharmony_ci  return MayThrow(_ {
11171cb0ef41Sopenharmony_ci    return AddNode<Object>(
11181cb0ef41Sopenharmony_ci        graph()->NewNode(javascript()->CallRuntime(function_id, 2), arg0, arg1,
11191cb0ef41Sopenharmony_ci                         ContextInput(), frame_state, effect(), control()));
11201cb0ef41Sopenharmony_ci  });
11211cb0ef41Sopenharmony_ci}
11221cb0ef41Sopenharmony_ci
11231cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::CopyNode() {
11241cb0ef41Sopenharmony_ci  return MayThrow(_ {
11251cb0ef41Sopenharmony_ci    Node* copy = graph()->CloneNode(node_ptr());
11261cb0ef41Sopenharmony_ci    NodeProperties::ReplaceEffectInput(copy, effect());
11271cb0ef41Sopenharmony_ci    NodeProperties::ReplaceControlInput(copy, control());
11281cb0ef41Sopenharmony_ci    return AddNode<Object>(copy);
11291cb0ef41Sopenharmony_ci  });
11301cb0ef41Sopenharmony_ci}
11311cb0ef41Sopenharmony_ci
11321cb0ef41Sopenharmony_ciTNode<JSArray> JSCallReducerAssembler::CreateArrayNoThrow(
11331cb0ef41Sopenharmony_ci    TNode<Object> ctor, TNode<Number> size, FrameState frame_state) {
11341cb0ef41Sopenharmony_ci  return AddNode<JSArray>(
11351cb0ef41Sopenharmony_ci      graph()->NewNode(javascript()->CreateArray(1, base::nullopt), ctor, ctor,
11361cb0ef41Sopenharmony_ci                       size, ContextInput(), frame_state, effect(), control()));
11371cb0ef41Sopenharmony_ci}
11381cb0ef41Sopenharmony_ciTNode<JSArray> JSCallReducerAssembler::AllocateEmptyJSArray(
11391cb0ef41Sopenharmony_ci    ElementsKind kind, const NativeContextRef& native_context) {
11401cb0ef41Sopenharmony_ci  // TODO(jgruber): Port AllocationBuilder to JSGraphAssembler.
11411cb0ef41Sopenharmony_ci  MapRef map = native_context.GetInitialJSArrayMap(kind);
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_ci  AllocationBuilder ab(jsgraph(), effect(), control());
11441cb0ef41Sopenharmony_ci  ab.Allocate(map.instance_size(), AllocationType::kYoung, Type::Array());
11451cb0ef41Sopenharmony_ci  ab.Store(AccessBuilder::ForMap(), map);
11461cb0ef41Sopenharmony_ci  Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
11471cb0ef41Sopenharmony_ci  ab.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
11481cb0ef41Sopenharmony_ci           empty_fixed_array);
11491cb0ef41Sopenharmony_ci  ab.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
11501cb0ef41Sopenharmony_ci  ab.Store(AccessBuilder::ForJSArrayLength(kind), jsgraph()->ZeroConstant());
11511cb0ef41Sopenharmony_ci  for (int i = 0; i < map.GetInObjectProperties(); ++i) {
11521cb0ef41Sopenharmony_ci    ab.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
11531cb0ef41Sopenharmony_ci             jsgraph()->UndefinedConstant());
11541cb0ef41Sopenharmony_ci  }
11551cb0ef41Sopenharmony_ci  Node* result = ab.Finish();
11561cb0ef41Sopenharmony_ci  InitializeEffectControl(result, control());
11571cb0ef41Sopenharmony_ci  return TNode<JSArray>::UncheckedCast(result);
11581cb0ef41Sopenharmony_ci}
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::ReduceMathUnary(const Operator* op) {
11611cb0ef41Sopenharmony_ci  TNode<Object> input = Argument(0);
11621cb0ef41Sopenharmony_ci  TNode<Number> input_as_number = SpeculativeToNumber(input);
11631cb0ef41Sopenharmony_ci  return TNode<Object>::UncheckedCast(graph()->NewNode(op, input_as_number));
11641cb0ef41Sopenharmony_ci}
11651cb0ef41Sopenharmony_ci
11661cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) {
11671cb0ef41Sopenharmony_ci  TNode<Object> left = Argument(0);
11681cb0ef41Sopenharmony_ci  TNode<Object> right = ArgumentOrNaN(1);
11691cb0ef41Sopenharmony_ci  TNode<Number> left_number = SpeculativeToNumber(left);
11701cb0ef41Sopenharmony_ci  TNode<Number> right_number = SpeculativeToNumber(right);
11711cb0ef41Sopenharmony_ci  return TNode<Object>::UncheckedCast(
11721cb0ef41Sopenharmony_ci      graph()->NewNode(op, left_number, right_number));
11731cb0ef41Sopenharmony_ci}
11741cb0ef41Sopenharmony_ci
11751cb0ef41Sopenharmony_ciTNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() {
11761cb0ef41Sopenharmony_ci  TNode<Object> receiver = ReceiverInput();
11771cb0ef41Sopenharmony_ci  TNode<Object> start = Argument(0);
11781cb0ef41Sopenharmony_ci  TNode<Object> end = ArgumentOrUndefined(1);
11791cb0ef41Sopenharmony_ci
11801cb0ef41Sopenharmony_ci  TNode<String> receiver_string = CheckString(receiver);
11811cb0ef41Sopenharmony_ci  TNode<Number> start_smi = CheckSmi(start);
11821cb0ef41Sopenharmony_ci
11831cb0ef41Sopenharmony_ci  TNode<Number> length = StringLength(receiver_string);
11841cb0ef41Sopenharmony_ci
11851cb0ef41Sopenharmony_ci  TNode<Number> end_smi = SelectIf<Number>(IsUndefined(end))
11861cb0ef41Sopenharmony_ci                              .Then(_ { return length; })
11871cb0ef41Sopenharmony_ci                              .Else(_ { return CheckSmi(end); })
11881cb0ef41Sopenharmony_ci                              .ExpectFalse()
11891cb0ef41Sopenharmony_ci                              .Value();
11901cb0ef41Sopenharmony_ci
11911cb0ef41Sopenharmony_ci  TNode<Number> zero = TNode<Number>::UncheckedCast(ZeroConstant());
11921cb0ef41Sopenharmony_ci  TNode<Number> finalStart = NumberMin(NumberMax(start_smi, zero), length);
11931cb0ef41Sopenharmony_ci  TNode<Number> finalEnd = NumberMin(NumberMax(end_smi, zero), length);
11941cb0ef41Sopenharmony_ci  TNode<Number> from = NumberMin(finalStart, finalEnd);
11951cb0ef41Sopenharmony_ci  TNode<Number> to = NumberMax(finalStart, finalEnd);
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_ci  return StringSubstring(receiver_string, from, to);
11981cb0ef41Sopenharmony_ci}
11991cb0ef41Sopenharmony_ci
12001cb0ef41Sopenharmony_ciTNode<Boolean> JSCallReducerAssembler::ReduceStringPrototypeStartsWith(
12011cb0ef41Sopenharmony_ci    const StringRef& search_element_string) {
12021cb0ef41Sopenharmony_ci  TNode<Object> receiver = ReceiverInput();
12031cb0ef41Sopenharmony_ci  TNode<Object> start = ArgumentOrZero(1);
12041cb0ef41Sopenharmony_ci
12051cb0ef41Sopenharmony_ci  TNode<String> receiver_string = CheckString(receiver);
12061cb0ef41Sopenharmony_ci  TNode<Smi> start_smi = CheckSmi(start);
12071cb0ef41Sopenharmony_ci  TNode<Number> length = StringLength(receiver_string);
12081cb0ef41Sopenharmony_ci
12091cb0ef41Sopenharmony_ci  TNode<Number> zero = ZeroConstant();
12101cb0ef41Sopenharmony_ci  TNode<Number> clamped_start = NumberMin(NumberMax(start_smi, zero), length);
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_ci  int search_string_length = search_element_string.length().value();
12131cb0ef41Sopenharmony_ci  DCHECK(search_string_length <= JSCallReducer::kMaxInlineMatchSequence);
12141cb0ef41Sopenharmony_ci
12151cb0ef41Sopenharmony_ci  auto out = MakeLabel(MachineRepresentation::kTagged);
12161cb0ef41Sopenharmony_ci
12171cb0ef41Sopenharmony_ci  auto search_string_too_long =
12181cb0ef41Sopenharmony_ci      NumberLessThan(NumberSubtract(length, clamped_start),
12191cb0ef41Sopenharmony_ci                     NumberConstant(search_string_length));
12201cb0ef41Sopenharmony_ci
12211cb0ef41Sopenharmony_ci  GotoIf(search_string_too_long, &out, BranchHint::kFalse, FalseConstant());
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  STATIC_ASSERT(String::kMaxLength <= kSmiMaxValue);
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci  for (int i = 0; i < search_string_length; i++) {
12261cb0ef41Sopenharmony_ci    TNode<Number> k = NumberConstant(i);
12271cb0ef41Sopenharmony_ci    TNode<Number> receiver_string_position = TNode<Number>::UncheckedCast(
12281cb0ef41Sopenharmony_ci        TypeGuard(Type::UnsignedSmall(), NumberAdd(k, clamped_start)));
12291cb0ef41Sopenharmony_ci    Node* receiver_string_char =
12301cb0ef41Sopenharmony_ci        StringCharCodeAt(receiver_string, receiver_string_position);
12311cb0ef41Sopenharmony_ci    Node* search_string_char =
12321cb0ef41Sopenharmony_ci        jsgraph()->Constant(search_element_string.GetChar(i).value());
12331cb0ef41Sopenharmony_ci    auto is_equal = graph()->NewNode(simplified()->NumberEqual(),
12341cb0ef41Sopenharmony_ci                                     search_string_char, receiver_string_char);
12351cb0ef41Sopenharmony_ci    GotoIfNot(is_equal, &out, FalseConstant());
12361cb0ef41Sopenharmony_ci  }
12371cb0ef41Sopenharmony_ci
12381cb0ef41Sopenharmony_ci  Goto(&out, TrueConstant());
12391cb0ef41Sopenharmony_ci
12401cb0ef41Sopenharmony_ci  Bind(&out);
12411cb0ef41Sopenharmony_ci  return out.PhiAt<Boolean>(0);
12421cb0ef41Sopenharmony_ci}
12431cb0ef41Sopenharmony_ci
12441cb0ef41Sopenharmony_ciTNode<Boolean> JSCallReducerAssembler::ReduceStringPrototypeStartsWith() {
12451cb0ef41Sopenharmony_ci  TNode<Object> receiver = ReceiverInput();
12461cb0ef41Sopenharmony_ci  TNode<Object> search_element = ArgumentOrUndefined(0);
12471cb0ef41Sopenharmony_ci  TNode<Object> start = ArgumentOrZero(1);
12481cb0ef41Sopenharmony_ci
12491cb0ef41Sopenharmony_ci  TNode<String> receiver_string = CheckString(receiver);
12501cb0ef41Sopenharmony_ci  TNode<String> search_string = CheckString(search_element);
12511cb0ef41Sopenharmony_ci  TNode<Smi> start_smi = CheckSmi(start);
12521cb0ef41Sopenharmony_ci  TNode<Number> length = StringLength(receiver_string);
12531cb0ef41Sopenharmony_ci
12541cb0ef41Sopenharmony_ci  TNode<Number> zero = ZeroConstant();
12551cb0ef41Sopenharmony_ci  TNode<Number> clamped_start = NumberMin(NumberMax(start_smi, zero), length);
12561cb0ef41Sopenharmony_ci
12571cb0ef41Sopenharmony_ci  TNode<Number> search_string_length = StringLength(search_string);
12581cb0ef41Sopenharmony_ci
12591cb0ef41Sopenharmony_ci  auto out = MakeLabel(MachineRepresentation::kTagged);
12601cb0ef41Sopenharmony_ci
12611cb0ef41Sopenharmony_ci  auto search_string_too_long = NumberLessThan(
12621cb0ef41Sopenharmony_ci      NumberSubtract(length, clamped_start), search_string_length);
12631cb0ef41Sopenharmony_ci
12641cb0ef41Sopenharmony_ci  GotoIf(search_string_too_long, &out, BranchHint::kFalse, FalseConstant());
12651cb0ef41Sopenharmony_ci
12661cb0ef41Sopenharmony_ci  STATIC_ASSERT(String::kMaxLength <= kSmiMaxValue);
12671cb0ef41Sopenharmony_ci
12681cb0ef41Sopenharmony_ci  ForZeroUntil(search_string_length).Do([&](TNode<Number> k) {
12691cb0ef41Sopenharmony_ci    TNode<Number> receiver_string_position = TNode<Number>::UncheckedCast(
12701cb0ef41Sopenharmony_ci        TypeGuard(Type::UnsignedSmall(), NumberAdd(k, clamped_start)));
12711cb0ef41Sopenharmony_ci    Node* receiver_string_char =
12721cb0ef41Sopenharmony_ci        StringCharCodeAt(receiver_string, receiver_string_position);
12731cb0ef41Sopenharmony_ci    Node* search_string_char = StringCharCodeAt(search_string, k);
12741cb0ef41Sopenharmony_ci    auto is_equal = graph()->NewNode(simplified()->NumberEqual(),
12751cb0ef41Sopenharmony_ci                                     receiver_string_char, search_string_char);
12761cb0ef41Sopenharmony_ci    GotoIfNot(is_equal, &out, FalseConstant());
12771cb0ef41Sopenharmony_ci  });
12781cb0ef41Sopenharmony_ci
12791cb0ef41Sopenharmony_ci  Goto(&out, TrueConstant());
12801cb0ef41Sopenharmony_ci
12811cb0ef41Sopenharmony_ci  Bind(&out);
12821cb0ef41Sopenharmony_ci  return out.PhiAt<Boolean>(0);
12831cb0ef41Sopenharmony_ci}
12841cb0ef41Sopenharmony_ci
12851cb0ef41Sopenharmony_ciTNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() {
12861cb0ef41Sopenharmony_ci  TNode<Object> receiver = ReceiverInput();
12871cb0ef41Sopenharmony_ci  TNode<Object> start = Argument(0);
12881cb0ef41Sopenharmony_ci  TNode<Object> end = ArgumentOrUndefined(1);
12891cb0ef41Sopenharmony_ci
12901cb0ef41Sopenharmony_ci  TNode<String> receiver_string = CheckString(receiver);
12911cb0ef41Sopenharmony_ci  TNode<Number> start_smi = CheckSmi(start);
12921cb0ef41Sopenharmony_ci
12931cb0ef41Sopenharmony_ci  TNode<Number> length = StringLength(receiver_string);
12941cb0ef41Sopenharmony_ci
12951cb0ef41Sopenharmony_ci  TNode<Number> end_smi = SelectIf<Number>(IsUndefined(end))
12961cb0ef41Sopenharmony_ci                              .Then(_ { return length; })
12971cb0ef41Sopenharmony_ci                              .Else(_ { return CheckSmi(end); })
12981cb0ef41Sopenharmony_ci                              .ExpectFalse()
12991cb0ef41Sopenharmony_ci                              .Value();
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci  TNode<Number> zero = TNode<Number>::UncheckedCast(ZeroConstant());
13021cb0ef41Sopenharmony_ci  TNode<Number> from_untyped =
13031cb0ef41Sopenharmony_ci      SelectIf<Number>(NumberLessThan(start_smi, zero))
13041cb0ef41Sopenharmony_ci          .Then(_ { return NumberMax(NumberAdd(length, start_smi), zero); })
13051cb0ef41Sopenharmony_ci          .Else(_ { return NumberMin(start_smi, length); })
13061cb0ef41Sopenharmony_ci          .ExpectFalse()
13071cb0ef41Sopenharmony_ci          .Value();
13081cb0ef41Sopenharmony_ci  // {from} is always in non-negative Smi range, but our typer cannot figure
13091cb0ef41Sopenharmony_ci  // that out yet.
13101cb0ef41Sopenharmony_ci  TNode<Smi> from = TypeGuardUnsignedSmall(from_untyped);
13111cb0ef41Sopenharmony_ci
13121cb0ef41Sopenharmony_ci  TNode<Number> to_untyped =
13131cb0ef41Sopenharmony_ci      SelectIf<Number>(NumberLessThan(end_smi, zero))
13141cb0ef41Sopenharmony_ci          .Then(_ { return NumberMax(NumberAdd(length, end_smi), zero); })
13151cb0ef41Sopenharmony_ci          .Else(_ { return NumberMin(end_smi, length); })
13161cb0ef41Sopenharmony_ci          .ExpectFalse()
13171cb0ef41Sopenharmony_ci          .Value();
13181cb0ef41Sopenharmony_ci  // {to} is always in non-negative Smi range, but our typer cannot figure that
13191cb0ef41Sopenharmony_ci  // out yet.
13201cb0ef41Sopenharmony_ci  TNode<Smi> to = TypeGuardUnsignedSmall(to_untyped);
13211cb0ef41Sopenharmony_ci
13221cb0ef41Sopenharmony_ci  return SelectIf<String>(NumberLessThan(from, to))
13231cb0ef41Sopenharmony_ci      .Then(_ { return StringSubstring(receiver_string, from, to); })
13241cb0ef41Sopenharmony_ci      .Else(_ { return EmptyStringConstant(); })
13251cb0ef41Sopenharmony_ci      .ExpectTrue()
13261cb0ef41Sopenharmony_ci      .Value();
13271cb0ef41Sopenharmony_ci}
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_cinamespace {
13301cb0ef41Sopenharmony_ci
13311cb0ef41Sopenharmony_cistruct ForEachFrameStateParams {
13321cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
13331cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
13341cb0ef41Sopenharmony_ci  TNode<Context> context;
13351cb0ef41Sopenharmony_ci  TNode<Object> target;
13361cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
13371cb0ef41Sopenharmony_ci  TNode<Object> receiver;
13381cb0ef41Sopenharmony_ci  TNode<Object> callback;
13391cb0ef41Sopenharmony_ci  TNode<Object> this_arg;
13401cb0ef41Sopenharmony_ci  TNode<Object> original_length;
13411cb0ef41Sopenharmony_ci};
13421cb0ef41Sopenharmony_ci
13431cb0ef41Sopenharmony_ciFrameState ForEachLoopLazyFrameState(const ForEachFrameStateParams& params,
13441cb0ef41Sopenharmony_ci                                     TNode<Object> k) {
13451cb0ef41Sopenharmony_ci  Builtin builtin = Builtin::kArrayForEachLoopLazyDeoptContinuation;
13461cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
13471cb0ef41Sopenharmony_ci                               params.this_arg, k, params.original_length};
13481cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
13491cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
13501cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
13511cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
13521cb0ef41Sopenharmony_ci}
13531cb0ef41Sopenharmony_ci
13541cb0ef41Sopenharmony_ciFrameState ForEachLoopEagerFrameState(const ForEachFrameStateParams& params,
13551cb0ef41Sopenharmony_ci                                      TNode<Object> k) {
13561cb0ef41Sopenharmony_ci  Builtin builtin = Builtin::kArrayForEachLoopEagerDeoptContinuation;
13571cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
13581cb0ef41Sopenharmony_ci                               params.this_arg, k, params.original_length};
13591cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
13601cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
13611cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
13621cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::EAGER);
13631cb0ef41Sopenharmony_ci}
13641cb0ef41Sopenharmony_ci
13651cb0ef41Sopenharmony_ci}  // namespace
13661cb0ef41Sopenharmony_ci
13671cb0ef41Sopenharmony_ciTNode<Object>
13681cb0ef41Sopenharmony_ciIteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeForEach(
13691cb0ef41Sopenharmony_ci    MapInference* inference, const bool has_stability_dependency,
13701cb0ef41Sopenharmony_ci    ElementsKind kind, const SharedFunctionInfoRef& shared) {
13711cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
13721cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
13731cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
13741cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
13751cb0ef41Sopenharmony_ci  TNode<Object> fncallback = ArgumentOrUndefined(0);
13761cb0ef41Sopenharmony_ci  TNode<Object> this_arg = ArgumentOrUndefined(1);
13771cb0ef41Sopenharmony_ci
13781cb0ef41Sopenharmony_ci  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
13791cb0ef41Sopenharmony_ci
13801cb0ef41Sopenharmony_ci  ForEachFrameStateParams frame_state_params{
13811cb0ef41Sopenharmony_ci      jsgraph(), shared,     context,  target,         outer_frame_state,
13821cb0ef41Sopenharmony_ci      receiver,  fncallback, this_arg, original_length};
13831cb0ef41Sopenharmony_ci
13841cb0ef41Sopenharmony_ci  ThrowIfNotCallable(fncallback, ForEachLoopLazyFrameState(frame_state_params,
13851cb0ef41Sopenharmony_ci                                                           ZeroConstant()));
13861cb0ef41Sopenharmony_ci
13871cb0ef41Sopenharmony_ci  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
13881cb0ef41Sopenharmony_ci    Checkpoint(ForEachLoopEagerFrameState(frame_state_params, k));
13891cb0ef41Sopenharmony_ci
13901cb0ef41Sopenharmony_ci    // Deopt if the map has changed during the iteration.
13911cb0ef41Sopenharmony_ci    MaybeInsertMapChecks(inference, has_stability_dependency);
13921cb0ef41Sopenharmony_ci
13931cb0ef41Sopenharmony_ci    TNode<Object> element;
13941cb0ef41Sopenharmony_ci    std::tie(k, element) = SafeLoadElement(kind, receiver, k);
13951cb0ef41Sopenharmony_ci
13961cb0ef41Sopenharmony_ci    auto continue_label = MakeLabel();
13971cb0ef41Sopenharmony_ci    element = MaybeSkipHole(element, kind, &continue_label);
13981cb0ef41Sopenharmony_ci
13991cb0ef41Sopenharmony_ci    TNode<Number> next_k = NumberAdd(k, OneConstant());
14001cb0ef41Sopenharmony_ci    JSCall3(fncallback, this_arg, element, k, receiver,
14011cb0ef41Sopenharmony_ci            ForEachLoopLazyFrameState(frame_state_params, next_k));
14021cb0ef41Sopenharmony_ci
14031cb0ef41Sopenharmony_ci    Goto(&continue_label);
14041cb0ef41Sopenharmony_ci    Bind(&continue_label);
14051cb0ef41Sopenharmony_ci  });
14061cb0ef41Sopenharmony_ci
14071cb0ef41Sopenharmony_ci  return UndefinedConstant();
14081cb0ef41Sopenharmony_ci}
14091cb0ef41Sopenharmony_ci
14101cb0ef41Sopenharmony_cinamespace {
14111cb0ef41Sopenharmony_ci
14121cb0ef41Sopenharmony_cistruct ReduceFrameStateParams {
14131cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
14141cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
14151cb0ef41Sopenharmony_ci  ArrayReduceDirection direction;
14161cb0ef41Sopenharmony_ci  TNode<Context> context;
14171cb0ef41Sopenharmony_ci  TNode<Object> target;
14181cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
14191cb0ef41Sopenharmony_ci};
14201cb0ef41Sopenharmony_ci
14211cb0ef41Sopenharmony_ciFrameState ReducePreLoopLazyFrameState(const ReduceFrameStateParams& params,
14221cb0ef41Sopenharmony_ci                                       TNode<Object> receiver,
14231cb0ef41Sopenharmony_ci                                       TNode<Object> callback, TNode<Object> k,
14241cb0ef41Sopenharmony_ci                                       TNode<Number> original_length) {
14251cb0ef41Sopenharmony_ci  Builtin builtin = (params.direction == ArrayReduceDirection::kLeft)
14261cb0ef41Sopenharmony_ci                        ? Builtin::kArrayReduceLoopLazyDeoptContinuation
14271cb0ef41Sopenharmony_ci                        : Builtin::kArrayReduceRightLoopLazyDeoptContinuation;
14281cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {receiver, callback, k, original_length};
14291cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
14301cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
14311cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
14321cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
14331cb0ef41Sopenharmony_ci}
14341cb0ef41Sopenharmony_ci
14351cb0ef41Sopenharmony_ciFrameState ReducePreLoopEagerFrameState(const ReduceFrameStateParams& params,
14361cb0ef41Sopenharmony_ci                                        TNode<Object> receiver,
14371cb0ef41Sopenharmony_ci                                        TNode<Object> callback,
14381cb0ef41Sopenharmony_ci                                        TNode<Number> original_length) {
14391cb0ef41Sopenharmony_ci  Builtin builtin =
14401cb0ef41Sopenharmony_ci      (params.direction == ArrayReduceDirection::kLeft)
14411cb0ef41Sopenharmony_ci          ? Builtin::kArrayReducePreLoopEagerDeoptContinuation
14421cb0ef41Sopenharmony_ci          : Builtin::kArrayReduceRightPreLoopEagerDeoptContinuation;
14431cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {receiver, callback, original_length};
14441cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
14451cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
14461cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
14471cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::EAGER);
14481cb0ef41Sopenharmony_ci}
14491cb0ef41Sopenharmony_ci
14501cb0ef41Sopenharmony_ciFrameState ReduceLoopLazyFrameState(const ReduceFrameStateParams& params,
14511cb0ef41Sopenharmony_ci                                    TNode<Object> receiver,
14521cb0ef41Sopenharmony_ci                                    TNode<Object> callback, TNode<Object> k,
14531cb0ef41Sopenharmony_ci                                    TNode<Number> original_length) {
14541cb0ef41Sopenharmony_ci  Builtin builtin = (params.direction == ArrayReduceDirection::kLeft)
14551cb0ef41Sopenharmony_ci                        ? Builtin::kArrayReduceLoopLazyDeoptContinuation
14561cb0ef41Sopenharmony_ci                        : Builtin::kArrayReduceRightLoopLazyDeoptContinuation;
14571cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {receiver, callback, k, original_length};
14581cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
14591cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
14601cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
14611cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
14621cb0ef41Sopenharmony_ci}
14631cb0ef41Sopenharmony_ci
14641cb0ef41Sopenharmony_ciFrameState ReduceLoopEagerFrameState(const ReduceFrameStateParams& params,
14651cb0ef41Sopenharmony_ci                                     TNode<Object> receiver,
14661cb0ef41Sopenharmony_ci                                     TNode<Object> callback, TNode<Object> k,
14671cb0ef41Sopenharmony_ci                                     TNode<Number> original_length,
14681cb0ef41Sopenharmony_ci                                     TNode<Object> accumulator) {
14691cb0ef41Sopenharmony_ci  Builtin builtin = (params.direction == ArrayReduceDirection::kLeft)
14701cb0ef41Sopenharmony_ci                        ? Builtin::kArrayReduceLoopEagerDeoptContinuation
14711cb0ef41Sopenharmony_ci                        : Builtin::kArrayReduceRightLoopEagerDeoptContinuation;
14721cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {receiver, callback, k, original_length,
14731cb0ef41Sopenharmony_ci                               accumulator};
14741cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
14751cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
14761cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
14771cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::EAGER);
14781cb0ef41Sopenharmony_ci}
14791cb0ef41Sopenharmony_ci
14801cb0ef41Sopenharmony_ci}  // namespace
14811cb0ef41Sopenharmony_ci
14821cb0ef41Sopenharmony_ciTNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeReduce(
14831cb0ef41Sopenharmony_ci    MapInference* inference, const bool has_stability_dependency,
14841cb0ef41Sopenharmony_ci    ElementsKind kind, ArrayReduceDirection direction,
14851cb0ef41Sopenharmony_ci    const SharedFunctionInfoRef& shared) {
14861cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
14871cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
14881cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
14891cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
14901cb0ef41Sopenharmony_ci  TNode<Object> fncallback = ArgumentOrUndefined(0);
14911cb0ef41Sopenharmony_ci
14921cb0ef41Sopenharmony_ci  ReduceFrameStateParams frame_state_params{
14931cb0ef41Sopenharmony_ci      jsgraph(), shared, direction, context, target, outer_frame_state};
14941cb0ef41Sopenharmony_ci
14951cb0ef41Sopenharmony_ci  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
14961cb0ef41Sopenharmony_ci
14971cb0ef41Sopenharmony_ci  // Set up variable behavior depending on the reduction kind (left/right).
14981cb0ef41Sopenharmony_ci  TNode<Number> k;
14991cb0ef41Sopenharmony_ci  StepFunction1 step;
15001cb0ef41Sopenharmony_ci  ConditionFunction1 cond;
15011cb0ef41Sopenharmony_ci  TNode<Number> zero = ZeroConstant();
15021cb0ef41Sopenharmony_ci  TNode<Number> one = OneConstant();
15031cb0ef41Sopenharmony_ci  if (direction == ArrayReduceDirection::kLeft) {
15041cb0ef41Sopenharmony_ci    k = zero;
15051cb0ef41Sopenharmony_ci    step = [&](TNode<Number> i) { return NumberAdd(i, one); };
15061cb0ef41Sopenharmony_ci    cond = [&](TNode<Number> i) { return NumberLessThan(i, original_length); };
15071cb0ef41Sopenharmony_ci  } else {
15081cb0ef41Sopenharmony_ci    k = NumberSubtract(original_length, one);
15091cb0ef41Sopenharmony_ci    step = [&](TNode<Number> i) { return NumberSubtract(i, one); };
15101cb0ef41Sopenharmony_ci    cond = [&](TNode<Number> i) { return NumberLessThanOrEqual(zero, i); };
15111cb0ef41Sopenharmony_ci  }
15121cb0ef41Sopenharmony_ci
15131cb0ef41Sopenharmony_ci  ThrowIfNotCallable(
15141cb0ef41Sopenharmony_ci      fncallback, ReducePreLoopLazyFrameState(frame_state_params, receiver,
15151cb0ef41Sopenharmony_ci                                              fncallback, k, original_length));
15161cb0ef41Sopenharmony_ci
15171cb0ef41Sopenharmony_ci  // Set initial accumulator value.
15181cb0ef41Sopenharmony_ci  TNode<Object> accumulator;
15191cb0ef41Sopenharmony_ci  if (ArgumentCount() > 1) {
15201cb0ef41Sopenharmony_ci    accumulator = Argument(1);  // Initial value specified by the user.
15211cb0ef41Sopenharmony_ci  } else {
15221cb0ef41Sopenharmony_ci    // The initial value was not specified by the user. In this case, the first
15231cb0ef41Sopenharmony_ci    // (or last in the case of reduceRight) non-holey value of the array is
15241cb0ef41Sopenharmony_ci    // used. Loop until we find it. If not found, trigger a deopt.
15251cb0ef41Sopenharmony_ci    // TODO(jgruber): The deopt does not seem necessary. Instead we could simply
15261cb0ef41Sopenharmony_ci    // throw the TypeError here from optimized code.
15271cb0ef41Sopenharmony_ci    auto found_initial_element = MakeLabel(MachineRepresentation::kTagged,
15281cb0ef41Sopenharmony_ci                                           MachineRepresentation::kTagged);
15291cb0ef41Sopenharmony_ci    Forever(k, step).Do([&](TNode<Number> k) {
15301cb0ef41Sopenharmony_ci      Checkpoint(ReducePreLoopEagerFrameState(frame_state_params, receiver,
15311cb0ef41Sopenharmony_ci                                              fncallback, original_length));
15321cb0ef41Sopenharmony_ci      CheckIf(cond(k), DeoptimizeReason::kNoInitialElement);
15331cb0ef41Sopenharmony_ci
15341cb0ef41Sopenharmony_ci      TNode<Object> element;
15351cb0ef41Sopenharmony_ci      std::tie(k, element) = SafeLoadElement(kind, receiver, k);
15361cb0ef41Sopenharmony_ci
15371cb0ef41Sopenharmony_ci      auto continue_label = MakeLabel();
15381cb0ef41Sopenharmony_ci      GotoIf(HoleCheck(kind, element), &continue_label);
15391cb0ef41Sopenharmony_ci      Goto(&found_initial_element, k, TypeGuardNonInternal(element));
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_ci      Bind(&continue_label);
15421cb0ef41Sopenharmony_ci    });
15431cb0ef41Sopenharmony_ci    Unreachable();  // The loop is exited either by deopt or a jump to below.
15441cb0ef41Sopenharmony_ci
15451cb0ef41Sopenharmony_ci    // TODO(jgruber): This manual fiddling with blocks could be avoided by
15461cb0ef41Sopenharmony_ci    // implementing a `break` mechanic for loop builders.
15471cb0ef41Sopenharmony_ci    Bind(&found_initial_element);
15481cb0ef41Sopenharmony_ci    k = step(found_initial_element.PhiAt<Number>(0));
15491cb0ef41Sopenharmony_ci    accumulator = found_initial_element.PhiAt<Object>(1);
15501cb0ef41Sopenharmony_ci  }
15511cb0ef41Sopenharmony_ci
15521cb0ef41Sopenharmony_ci  TNode<Object> result =
15531cb0ef41Sopenharmony_ci      For1(k, cond, step, accumulator)
15541cb0ef41Sopenharmony_ci          .Do([&](TNode<Number> k, TNode<Object>* accumulator) {
15551cb0ef41Sopenharmony_ci            Checkpoint(ReduceLoopEagerFrameState(frame_state_params, receiver,
15561cb0ef41Sopenharmony_ci                                                 fncallback, k, original_length,
15571cb0ef41Sopenharmony_ci                                                 *accumulator));
15581cb0ef41Sopenharmony_ci
15591cb0ef41Sopenharmony_ci            // Deopt if the map has changed during the iteration.
15601cb0ef41Sopenharmony_ci            MaybeInsertMapChecks(inference, has_stability_dependency);
15611cb0ef41Sopenharmony_ci
15621cb0ef41Sopenharmony_ci            TNode<Object> element;
15631cb0ef41Sopenharmony_ci            std::tie(k, element) = SafeLoadElement(kind, receiver, k);
15641cb0ef41Sopenharmony_ci
15651cb0ef41Sopenharmony_ci            auto continue_label = MakeLabel(MachineRepresentation::kTagged);
15661cb0ef41Sopenharmony_ci            element =
15671cb0ef41Sopenharmony_ci                MaybeSkipHole(element, kind, &continue_label, *accumulator);
15681cb0ef41Sopenharmony_ci
15691cb0ef41Sopenharmony_ci            TNode<Number> next_k = step(k);
15701cb0ef41Sopenharmony_ci            TNode<Object> next_accumulator = JSCall4(
15711cb0ef41Sopenharmony_ci                fncallback, UndefinedConstant(), *accumulator, element, k,
15721cb0ef41Sopenharmony_ci                receiver,
15731cb0ef41Sopenharmony_ci                ReduceLoopLazyFrameState(frame_state_params, receiver,
15741cb0ef41Sopenharmony_ci                                         fncallback, next_k, original_length));
15751cb0ef41Sopenharmony_ci            Goto(&continue_label, next_accumulator);
15761cb0ef41Sopenharmony_ci
15771cb0ef41Sopenharmony_ci            Bind(&continue_label);
15781cb0ef41Sopenharmony_ci            *accumulator = continue_label.PhiAt<Object>(0);
15791cb0ef41Sopenharmony_ci          })
15801cb0ef41Sopenharmony_ci          .Value();
15811cb0ef41Sopenharmony_ci
15821cb0ef41Sopenharmony_ci  return result;
15831cb0ef41Sopenharmony_ci}
15841cb0ef41Sopenharmony_ci
15851cb0ef41Sopenharmony_cinamespace {
15861cb0ef41Sopenharmony_ci
15871cb0ef41Sopenharmony_cistruct MapFrameStateParams {
15881cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
15891cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
15901cb0ef41Sopenharmony_ci  TNode<Context> context;
15911cb0ef41Sopenharmony_ci  TNode<Object> target;
15921cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
15931cb0ef41Sopenharmony_ci  TNode<Object> receiver;
15941cb0ef41Sopenharmony_ci  TNode<Object> callback;
15951cb0ef41Sopenharmony_ci  TNode<Object> this_arg;
15961cb0ef41Sopenharmony_ci  base::Optional<TNode<JSArray>> a;
15971cb0ef41Sopenharmony_ci  TNode<Object> original_length;
15981cb0ef41Sopenharmony_ci};
15991cb0ef41Sopenharmony_ci
16001cb0ef41Sopenharmony_ciFrameState MapPreLoopLazyFrameState(const MapFrameStateParams& params) {
16011cb0ef41Sopenharmony_ci  DCHECK(!params.a);
16021cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
16031cb0ef41Sopenharmony_ci                               params.this_arg, params.original_length};
16041cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
16051cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
16061cb0ef41Sopenharmony_ci      Builtin::kArrayMapPreLoopLazyDeoptContinuation, params.target,
16071cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
16081cb0ef41Sopenharmony_ci      params.outer_frame_state, ContinuationFrameStateMode::LAZY);
16091cb0ef41Sopenharmony_ci}
16101cb0ef41Sopenharmony_ci
16111cb0ef41Sopenharmony_ciFrameState MapLoopLazyFrameState(const MapFrameStateParams& params,
16121cb0ef41Sopenharmony_ci                                 TNode<Number> k) {
16131cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {
16141cb0ef41Sopenharmony_ci      params.receiver,       params.callback, params.this_arg, *params.a, k,
16151cb0ef41Sopenharmony_ci      params.original_length};
16161cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
16171cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
16181cb0ef41Sopenharmony_ci      Builtin::kArrayMapLoopLazyDeoptContinuation, params.target,
16191cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
16201cb0ef41Sopenharmony_ci      params.outer_frame_state, ContinuationFrameStateMode::LAZY);
16211cb0ef41Sopenharmony_ci}
16221cb0ef41Sopenharmony_ci
16231cb0ef41Sopenharmony_ciFrameState MapLoopEagerFrameState(const MapFrameStateParams& params,
16241cb0ef41Sopenharmony_ci                                  TNode<Number> k) {
16251cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {
16261cb0ef41Sopenharmony_ci      params.receiver,       params.callback, params.this_arg, *params.a, k,
16271cb0ef41Sopenharmony_ci      params.original_length};
16281cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
16291cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
16301cb0ef41Sopenharmony_ci      Builtin::kArrayMapLoopEagerDeoptContinuation, params.target,
16311cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
16321cb0ef41Sopenharmony_ci      params.outer_frame_state, ContinuationFrameStateMode::EAGER);
16331cb0ef41Sopenharmony_ci}
16341cb0ef41Sopenharmony_ci
16351cb0ef41Sopenharmony_ci}  // namespace
16361cb0ef41Sopenharmony_ci
16371cb0ef41Sopenharmony_ciTNode<JSArray> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeMap(
16381cb0ef41Sopenharmony_ci    MapInference* inference, const bool has_stability_dependency,
16391cb0ef41Sopenharmony_ci    ElementsKind kind, const SharedFunctionInfoRef& shared,
16401cb0ef41Sopenharmony_ci    const NativeContextRef& native_context) {
16411cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
16421cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
16431cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
16441cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
16451cb0ef41Sopenharmony_ci  TNode<Object> fncallback = ArgumentOrUndefined(0);
16461cb0ef41Sopenharmony_ci  TNode<Object> this_arg = ArgumentOrUndefined(1);
16471cb0ef41Sopenharmony_ci
16481cb0ef41Sopenharmony_ci  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
16491cb0ef41Sopenharmony_ci
16501cb0ef41Sopenharmony_ci  // If the array length >= kMaxFastArrayLength, then CreateArray
16511cb0ef41Sopenharmony_ci  // will create a dictionary. We should deopt in this case, and make sure
16521cb0ef41Sopenharmony_ci  // not to attempt inlining again.
16531cb0ef41Sopenharmony_ci  original_length = CheckBounds(original_length,
16541cb0ef41Sopenharmony_ci                                NumberConstant(JSArray::kMaxFastArrayLength));
16551cb0ef41Sopenharmony_ci
16561cb0ef41Sopenharmony_ci  // Even though {JSCreateArray} is not marked as {kNoThrow}, we can elide the
16571cb0ef41Sopenharmony_ci  // exceptional projections because it cannot throw with the given
16581cb0ef41Sopenharmony_ci  // parameters.
16591cb0ef41Sopenharmony_ci  TNode<Object> array_ctor =
16601cb0ef41Sopenharmony_ci      Constant(native_context.GetInitialJSArrayMap(kind).GetConstructor());
16611cb0ef41Sopenharmony_ci
16621cb0ef41Sopenharmony_ci  MapFrameStateParams frame_state_params{
16631cb0ef41Sopenharmony_ci      jsgraph(), shared,     context,  target,       outer_frame_state,
16641cb0ef41Sopenharmony_ci      receiver,  fncallback, this_arg, {} /* TBD */, original_length};
16651cb0ef41Sopenharmony_ci
16661cb0ef41Sopenharmony_ci  TNode<JSArray> a =
16671cb0ef41Sopenharmony_ci      CreateArrayNoThrow(array_ctor, original_length,
16681cb0ef41Sopenharmony_ci                         MapPreLoopLazyFrameState(frame_state_params));
16691cb0ef41Sopenharmony_ci  frame_state_params.a = a;
16701cb0ef41Sopenharmony_ci
16711cb0ef41Sopenharmony_ci  ThrowIfNotCallable(fncallback,
16721cb0ef41Sopenharmony_ci                     MapLoopLazyFrameState(frame_state_params, ZeroConstant()));
16731cb0ef41Sopenharmony_ci
16741cb0ef41Sopenharmony_ci  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
16751cb0ef41Sopenharmony_ci    Checkpoint(MapLoopEagerFrameState(frame_state_params, k));
16761cb0ef41Sopenharmony_ci    MaybeInsertMapChecks(inference, has_stability_dependency);
16771cb0ef41Sopenharmony_ci
16781cb0ef41Sopenharmony_ci    TNode<Object> element;
16791cb0ef41Sopenharmony_ci    std::tie(k, element) = SafeLoadElement(kind, receiver, k);
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_ci    auto continue_label = MakeLabel();
16821cb0ef41Sopenharmony_ci    element = MaybeSkipHole(element, kind, &continue_label);
16831cb0ef41Sopenharmony_ci
16841cb0ef41Sopenharmony_ci    TNode<Object> v = JSCall3(fncallback, this_arg, element, k, receiver,
16851cb0ef41Sopenharmony_ci                              MapLoopLazyFrameState(frame_state_params, k));
16861cb0ef41Sopenharmony_ci
16871cb0ef41Sopenharmony_ci    // The array {a} should be HOLEY_SMI_ELEMENTS because we'd only come into
16881cb0ef41Sopenharmony_ci    // this loop if the input array length is non-zero, and "new Array({x > 0})"
16891cb0ef41Sopenharmony_ci    // always produces a HOLEY array.
16901cb0ef41Sopenharmony_ci    MapRef holey_double_map =
16911cb0ef41Sopenharmony_ci        native_context.GetInitialJSArrayMap(HOLEY_DOUBLE_ELEMENTS);
16921cb0ef41Sopenharmony_ci    MapRef holey_map = native_context.GetInitialJSArrayMap(HOLEY_ELEMENTS);
16931cb0ef41Sopenharmony_ci    TransitionAndStoreElement(holey_double_map, holey_map, a, k, v);
16941cb0ef41Sopenharmony_ci
16951cb0ef41Sopenharmony_ci    Goto(&continue_label);
16961cb0ef41Sopenharmony_ci    Bind(&continue_label);
16971cb0ef41Sopenharmony_ci  });
16981cb0ef41Sopenharmony_ci
16991cb0ef41Sopenharmony_ci  return a;
17001cb0ef41Sopenharmony_ci}
17011cb0ef41Sopenharmony_ci
17021cb0ef41Sopenharmony_cinamespace {
17031cb0ef41Sopenharmony_ci
17041cb0ef41Sopenharmony_cistruct FilterFrameStateParams {
17051cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
17061cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
17071cb0ef41Sopenharmony_ci  TNode<Context> context;
17081cb0ef41Sopenharmony_ci  TNode<Object> target;
17091cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
17101cb0ef41Sopenharmony_ci  TNode<Object> receiver;
17111cb0ef41Sopenharmony_ci  TNode<Object> callback;
17121cb0ef41Sopenharmony_ci  TNode<Object> this_arg;
17131cb0ef41Sopenharmony_ci  TNode<JSArray> a;
17141cb0ef41Sopenharmony_ci  TNode<Object> original_length;
17151cb0ef41Sopenharmony_ci};
17161cb0ef41Sopenharmony_ci
17171cb0ef41Sopenharmony_ciFrameState FilterLoopLazyFrameState(const FilterFrameStateParams& params,
17181cb0ef41Sopenharmony_ci                                    TNode<Number> k, TNode<Number> to,
17191cb0ef41Sopenharmony_ci                                    TNode<Object> element) {
17201cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver,
17211cb0ef41Sopenharmony_ci                               params.callback,
17221cb0ef41Sopenharmony_ci                               params.this_arg,
17231cb0ef41Sopenharmony_ci                               params.a,
17241cb0ef41Sopenharmony_ci                               k,
17251cb0ef41Sopenharmony_ci                               params.original_length,
17261cb0ef41Sopenharmony_ci                               element,
17271cb0ef41Sopenharmony_ci                               to};
17281cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
17291cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
17301cb0ef41Sopenharmony_ci      Builtin::kArrayFilterLoopLazyDeoptContinuation, params.target,
17311cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
17321cb0ef41Sopenharmony_ci      params.outer_frame_state, ContinuationFrameStateMode::LAZY);
17331cb0ef41Sopenharmony_ci}
17341cb0ef41Sopenharmony_ci
17351cb0ef41Sopenharmony_ciFrameState FilterLoopEagerPostCallbackFrameState(
17361cb0ef41Sopenharmony_ci    const FilterFrameStateParams& params, TNode<Number> k, TNode<Number> to,
17371cb0ef41Sopenharmony_ci    TNode<Object> element, TNode<Object> callback_value) {
17381cb0ef41Sopenharmony_ci  // Note that we are intentionally reusing the
17391cb0ef41Sopenharmony_ci  // Builtin::kArrayFilterLoopLazyDeoptContinuation as an *eager* entry
17401cb0ef41Sopenharmony_ci  // point in this case. This is safe, because re-evaluating a [ToBoolean]
17411cb0ef41Sopenharmony_ci  // coercion is safe.
17421cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver,
17431cb0ef41Sopenharmony_ci                               params.callback,
17441cb0ef41Sopenharmony_ci                               params.this_arg,
17451cb0ef41Sopenharmony_ci                               params.a,
17461cb0ef41Sopenharmony_ci                               k,
17471cb0ef41Sopenharmony_ci                               params.original_length,
17481cb0ef41Sopenharmony_ci                               element,
17491cb0ef41Sopenharmony_ci                               to,
17501cb0ef41Sopenharmony_ci                               callback_value};
17511cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
17521cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
17531cb0ef41Sopenharmony_ci      Builtin::kArrayFilterLoopLazyDeoptContinuation, params.target,
17541cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
17551cb0ef41Sopenharmony_ci      params.outer_frame_state, ContinuationFrameStateMode::EAGER);
17561cb0ef41Sopenharmony_ci}
17571cb0ef41Sopenharmony_ci
17581cb0ef41Sopenharmony_ciFrameState FilterLoopEagerFrameState(const FilterFrameStateParams& params,
17591cb0ef41Sopenharmony_ci                                     TNode<Number> k, TNode<Number> to) {
17601cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver,
17611cb0ef41Sopenharmony_ci                               params.callback,
17621cb0ef41Sopenharmony_ci                               params.this_arg,
17631cb0ef41Sopenharmony_ci                               params.a,
17641cb0ef41Sopenharmony_ci                               k,
17651cb0ef41Sopenharmony_ci                               params.original_length,
17661cb0ef41Sopenharmony_ci                               to};
17671cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
17681cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
17691cb0ef41Sopenharmony_ci      Builtin::kArrayFilterLoopEagerDeoptContinuation, params.target,
17701cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
17711cb0ef41Sopenharmony_ci      params.outer_frame_state, ContinuationFrameStateMode::EAGER);
17721cb0ef41Sopenharmony_ci}
17731cb0ef41Sopenharmony_ci
17741cb0ef41Sopenharmony_ci}  // namespace
17751cb0ef41Sopenharmony_ci
17761cb0ef41Sopenharmony_ciTNode<JSArray>
17771cb0ef41Sopenharmony_ciIteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFilter(
17781cb0ef41Sopenharmony_ci    MapInference* inference, const bool has_stability_dependency,
17791cb0ef41Sopenharmony_ci    ElementsKind kind, const SharedFunctionInfoRef& shared,
17801cb0ef41Sopenharmony_ci    const NativeContextRef& native_context) {
17811cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
17821cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
17831cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
17841cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
17851cb0ef41Sopenharmony_ci  TNode<Object> fncallback = ArgumentOrUndefined(0);
17861cb0ef41Sopenharmony_ci  TNode<Object> this_arg = ArgumentOrUndefined(1);
17871cb0ef41Sopenharmony_ci
17881cb0ef41Sopenharmony_ci  // The output array is packed (filter doesn't visit holes).
17891cb0ef41Sopenharmony_ci  const ElementsKind packed_kind = GetPackedElementsKind(kind);
17901cb0ef41Sopenharmony_ci  TNode<JSArray> a = AllocateEmptyJSArray(packed_kind, native_context);
17911cb0ef41Sopenharmony_ci
17921cb0ef41Sopenharmony_ci  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
17931cb0ef41Sopenharmony_ci
17941cb0ef41Sopenharmony_ci  FilterFrameStateParams frame_state_params{
17951cb0ef41Sopenharmony_ci      jsgraph(), shared,     context,  target, outer_frame_state,
17961cb0ef41Sopenharmony_ci      receiver,  fncallback, this_arg, a,      original_length};
17971cb0ef41Sopenharmony_ci
17981cb0ef41Sopenharmony_ci  // This frame state doesn't ever call the deopt continuation, it's only
17991cb0ef41Sopenharmony_ci  // necessary to specify a continuation in order to handle the exceptional
18001cb0ef41Sopenharmony_ci  // case. We don't have all the values available to completely fill out
18011cb0ef41Sopenharmony_ci  // the checkpoint parameters yet, but that's okay because it'll never be
18021cb0ef41Sopenharmony_ci  // called.
18031cb0ef41Sopenharmony_ci  TNode<Number> zero = ZeroConstant();
18041cb0ef41Sopenharmony_ci  ThrowIfNotCallable(fncallback, FilterLoopLazyFrameState(frame_state_params,
18051cb0ef41Sopenharmony_ci                                                          zero, zero, zero));
18061cb0ef41Sopenharmony_ci
18071cb0ef41Sopenharmony_ci  TNode<Number> initial_a_length = zero;
18081cb0ef41Sopenharmony_ci  For1ZeroUntil(original_length, initial_a_length)
18091cb0ef41Sopenharmony_ci      .Do([&](TNode<Number> k, TNode<Object>* a_length_object) {
18101cb0ef41Sopenharmony_ci        TNode<Number> a_length = TNode<Number>::UncheckedCast(*a_length_object);
18111cb0ef41Sopenharmony_ci        Checkpoint(FilterLoopEagerFrameState(frame_state_params, k, a_length));
18121cb0ef41Sopenharmony_ci        MaybeInsertMapChecks(inference, has_stability_dependency);
18131cb0ef41Sopenharmony_ci
18141cb0ef41Sopenharmony_ci        TNode<Object> element;
18151cb0ef41Sopenharmony_ci        std::tie(k, element) = SafeLoadElement(kind, receiver, k);
18161cb0ef41Sopenharmony_ci
18171cb0ef41Sopenharmony_ci        auto continue_label = MakeLabel(MachineRepresentation::kTaggedSigned);
18181cb0ef41Sopenharmony_ci        element = MaybeSkipHole(element, kind, &continue_label, a_length);
18191cb0ef41Sopenharmony_ci
18201cb0ef41Sopenharmony_ci        TNode<Object> v = JSCall3(
18211cb0ef41Sopenharmony_ci            fncallback, this_arg, element, k, receiver,
18221cb0ef41Sopenharmony_ci            FilterLoopLazyFrameState(frame_state_params, k, a_length, element));
18231cb0ef41Sopenharmony_ci
18241cb0ef41Sopenharmony_ci        // We need an eager frame state for right after the callback function
18251cb0ef41Sopenharmony_ci        // returned, just in case an attempt to grow the output array fails.
18261cb0ef41Sopenharmony_ci        Checkpoint(FilterLoopEagerPostCallbackFrameState(frame_state_params, k,
18271cb0ef41Sopenharmony_ci                                                         a_length, element, v));
18281cb0ef41Sopenharmony_ci
18291cb0ef41Sopenharmony_ci        GotoIfNot(ToBoolean(v), &continue_label, a_length);
18301cb0ef41Sopenharmony_ci
18311cb0ef41Sopenharmony_ci        // Since the callback returned a trueish value, store the element in a.
18321cb0ef41Sopenharmony_ci        {
18331cb0ef41Sopenharmony_ci          TNode<Number> a_length1 = TypeGuardFixedArrayLength(a_length);
18341cb0ef41Sopenharmony_ci          TNode<FixedArrayBase> elements = LoadElements(a);
18351cb0ef41Sopenharmony_ci          elements = MaybeGrowFastElements(kind, FeedbackSource{}, a, elements,
18361cb0ef41Sopenharmony_ci                                           a_length1,
18371cb0ef41Sopenharmony_ci                                           LoadFixedArrayBaseLength(elements));
18381cb0ef41Sopenharmony_ci
18391cb0ef41Sopenharmony_ci          TNode<Number> new_a_length = NumberInc(a_length1);
18401cb0ef41Sopenharmony_ci          StoreJSArrayLength(a, new_a_length, kind);
18411cb0ef41Sopenharmony_ci          StoreFixedArrayBaseElement(elements, a_length1, element, kind);
18421cb0ef41Sopenharmony_ci
18431cb0ef41Sopenharmony_ci          Goto(&continue_label, new_a_length);
18441cb0ef41Sopenharmony_ci        }
18451cb0ef41Sopenharmony_ci
18461cb0ef41Sopenharmony_ci        Bind(&continue_label);
18471cb0ef41Sopenharmony_ci        *a_length_object =
18481cb0ef41Sopenharmony_ci            TNode<Object>::UncheckedCast(continue_label.PhiAt(0));
18491cb0ef41Sopenharmony_ci      })
18501cb0ef41Sopenharmony_ci      .ValueIsUnused();
18511cb0ef41Sopenharmony_ci
18521cb0ef41Sopenharmony_ci  return a;
18531cb0ef41Sopenharmony_ci}
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_cinamespace {
18561cb0ef41Sopenharmony_ci
18571cb0ef41Sopenharmony_cistruct FindFrameStateParams {
18581cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
18591cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
18601cb0ef41Sopenharmony_ci  TNode<Context> context;
18611cb0ef41Sopenharmony_ci  TNode<Object> target;
18621cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
18631cb0ef41Sopenharmony_ci  TNode<Object> receiver;
18641cb0ef41Sopenharmony_ci  TNode<Object> callback;
18651cb0ef41Sopenharmony_ci  TNode<Object> this_arg;
18661cb0ef41Sopenharmony_ci  TNode<Object> original_length;
18671cb0ef41Sopenharmony_ci};
18681cb0ef41Sopenharmony_ci
18691cb0ef41Sopenharmony_ciFrameState FindLoopLazyFrameState(const FindFrameStateParams& params,
18701cb0ef41Sopenharmony_ci                                  TNode<Number> k, ArrayFindVariant variant) {
18711cb0ef41Sopenharmony_ci  Builtin builtin = (variant == ArrayFindVariant::kFind)
18721cb0ef41Sopenharmony_ci                        ? Builtin::kArrayFindLoopLazyDeoptContinuation
18731cb0ef41Sopenharmony_ci                        : Builtin::kArrayFindIndexLoopLazyDeoptContinuation;
18741cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
18751cb0ef41Sopenharmony_ci                               params.this_arg, k, params.original_length};
18761cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
18771cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
18781cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
18791cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
18801cb0ef41Sopenharmony_ci}
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ciFrameState FindLoopEagerFrameState(const FindFrameStateParams& params,
18831cb0ef41Sopenharmony_ci                                   TNode<Number> k, ArrayFindVariant variant) {
18841cb0ef41Sopenharmony_ci  Builtin builtin = (variant == ArrayFindVariant::kFind)
18851cb0ef41Sopenharmony_ci                        ? Builtin::kArrayFindLoopEagerDeoptContinuation
18861cb0ef41Sopenharmony_ci                        : Builtin::kArrayFindIndexLoopEagerDeoptContinuation;
18871cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
18881cb0ef41Sopenharmony_ci                               params.this_arg, k, params.original_length};
18891cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
18901cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
18911cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
18921cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::EAGER);
18931cb0ef41Sopenharmony_ci}
18941cb0ef41Sopenharmony_ci
18951cb0ef41Sopenharmony_ciFrameState FindLoopAfterCallbackLazyFrameState(
18961cb0ef41Sopenharmony_ci    const FindFrameStateParams& params, TNode<Number> next_k,
18971cb0ef41Sopenharmony_ci    TNode<Object> if_found_value, ArrayFindVariant variant) {
18981cb0ef41Sopenharmony_ci  Builtin builtin =
18991cb0ef41Sopenharmony_ci      (variant == ArrayFindVariant::kFind)
19001cb0ef41Sopenharmony_ci          ? Builtin::kArrayFindLoopAfterCallbackLazyDeoptContinuation
19011cb0ef41Sopenharmony_ci          : Builtin::kArrayFindIndexLoopAfterCallbackLazyDeoptContinuation;
19021cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver,        params.callback,
19031cb0ef41Sopenharmony_ci                               params.this_arg,        next_k,
19041cb0ef41Sopenharmony_ci                               params.original_length, if_found_value};
19051cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
19061cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
19071cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
19081cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
19091cb0ef41Sopenharmony_ci}
19101cb0ef41Sopenharmony_ci
19111cb0ef41Sopenharmony_ci}  // namespace
19121cb0ef41Sopenharmony_ci
19131cb0ef41Sopenharmony_ciTNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFind(
19141cb0ef41Sopenharmony_ci    MapInference* inference, const bool has_stability_dependency,
19151cb0ef41Sopenharmony_ci    ElementsKind kind, const SharedFunctionInfoRef& shared,
19161cb0ef41Sopenharmony_ci    const NativeContextRef& native_context, ArrayFindVariant variant) {
19171cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
19181cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
19191cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
19201cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
19211cb0ef41Sopenharmony_ci  TNode<Object> fncallback = ArgumentOrUndefined(0);
19221cb0ef41Sopenharmony_ci  TNode<Object> this_arg = ArgumentOrUndefined(1);
19231cb0ef41Sopenharmony_ci
19241cb0ef41Sopenharmony_ci  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
19251cb0ef41Sopenharmony_ci
19261cb0ef41Sopenharmony_ci  FindFrameStateParams frame_state_params{
19271cb0ef41Sopenharmony_ci      jsgraph(), shared,     context,  target,         outer_frame_state,
19281cb0ef41Sopenharmony_ci      receiver,  fncallback, this_arg, original_length};
19291cb0ef41Sopenharmony_ci
19301cb0ef41Sopenharmony_ci  ThrowIfNotCallable(
19311cb0ef41Sopenharmony_ci      fncallback,
19321cb0ef41Sopenharmony_ci      FindLoopLazyFrameState(frame_state_params, ZeroConstant(), variant));
19331cb0ef41Sopenharmony_ci
19341cb0ef41Sopenharmony_ci  const bool is_find_variant = (variant == ArrayFindVariant::kFind);
19351cb0ef41Sopenharmony_ci  auto out = MakeLabel(MachineRepresentation::kTagged);
19361cb0ef41Sopenharmony_ci
19371cb0ef41Sopenharmony_ci  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
19381cb0ef41Sopenharmony_ci    Checkpoint(FindLoopEagerFrameState(frame_state_params, k, variant));
19391cb0ef41Sopenharmony_ci    MaybeInsertMapChecks(inference, has_stability_dependency);
19401cb0ef41Sopenharmony_ci
19411cb0ef41Sopenharmony_ci    TNode<Object> element;
19421cb0ef41Sopenharmony_ci    std::tie(k, element) = SafeLoadElement(kind, receiver, k);
19431cb0ef41Sopenharmony_ci
19441cb0ef41Sopenharmony_ci    if (IsHoleyElementsKind(kind)) {
19451cb0ef41Sopenharmony_ci      element = TryConvertHoleToUndefined(element, kind);
19461cb0ef41Sopenharmony_ci    }
19471cb0ef41Sopenharmony_ci
19481cb0ef41Sopenharmony_ci    TNode<Object> if_found_value = is_find_variant ? element : k;
19491cb0ef41Sopenharmony_ci    TNode<Number> next_k = NumberInc(k);
19501cb0ef41Sopenharmony_ci
19511cb0ef41Sopenharmony_ci    // The callback result states whether the desired element was found.
19521cb0ef41Sopenharmony_ci    TNode<Object> v =
19531cb0ef41Sopenharmony_ci        JSCall3(fncallback, this_arg, element, k, receiver,
19541cb0ef41Sopenharmony_ci                FindLoopAfterCallbackLazyFrameState(frame_state_params, next_k,
19551cb0ef41Sopenharmony_ci                                                    if_found_value, variant));
19561cb0ef41Sopenharmony_ci
19571cb0ef41Sopenharmony_ci    GotoIf(ToBoolean(v), &out, if_found_value);
19581cb0ef41Sopenharmony_ci  });
19591cb0ef41Sopenharmony_ci
19601cb0ef41Sopenharmony_ci  // If the loop completed, the element was not found.
19611cb0ef41Sopenharmony_ci  TNode<Object> if_not_found_value =
19621cb0ef41Sopenharmony_ci      is_find_variant ? TNode<Object>::UncheckedCast(UndefinedConstant())
19631cb0ef41Sopenharmony_ci                      : TNode<Object>::UncheckedCast(MinusOneConstant());
19641cb0ef41Sopenharmony_ci  Goto(&out, if_not_found_value);
19651cb0ef41Sopenharmony_ci
19661cb0ef41Sopenharmony_ci  Bind(&out);
19671cb0ef41Sopenharmony_ci  return out.PhiAt<Object>(0);
19681cb0ef41Sopenharmony_ci}
19691cb0ef41Sopenharmony_ci
19701cb0ef41Sopenharmony_cinamespace {
19711cb0ef41Sopenharmony_ci
19721cb0ef41Sopenharmony_cistruct EverySomeFrameStateParams {
19731cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
19741cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
19751cb0ef41Sopenharmony_ci  TNode<Context> context;
19761cb0ef41Sopenharmony_ci  TNode<Object> target;
19771cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
19781cb0ef41Sopenharmony_ci  TNode<Object> receiver;
19791cb0ef41Sopenharmony_ci  TNode<Object> callback;
19801cb0ef41Sopenharmony_ci  TNode<Object> this_arg;
19811cb0ef41Sopenharmony_ci  TNode<Object> original_length;
19821cb0ef41Sopenharmony_ci};
19831cb0ef41Sopenharmony_ci
19841cb0ef41Sopenharmony_ciFrameState EverySomeLoopLazyFrameState(const EverySomeFrameStateParams& params,
19851cb0ef41Sopenharmony_ci                                       TNode<Number> k,
19861cb0ef41Sopenharmony_ci                                       ArrayEverySomeVariant variant) {
19871cb0ef41Sopenharmony_ci  Builtin builtin = (variant == ArrayEverySomeVariant::kEvery)
19881cb0ef41Sopenharmony_ci                        ? Builtin::kArrayEveryLoopLazyDeoptContinuation
19891cb0ef41Sopenharmony_ci                        : Builtin::kArraySomeLoopLazyDeoptContinuation;
19901cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
19911cb0ef41Sopenharmony_ci                               params.this_arg, k, params.original_length};
19921cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
19931cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
19941cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
19951cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
19961cb0ef41Sopenharmony_ci}
19971cb0ef41Sopenharmony_ci
19981cb0ef41Sopenharmony_ciFrameState EverySomeLoopEagerFrameState(const EverySomeFrameStateParams& params,
19991cb0ef41Sopenharmony_ci                                        TNode<Number> k,
20001cb0ef41Sopenharmony_ci                                        ArrayEverySomeVariant variant) {
20011cb0ef41Sopenharmony_ci  Builtin builtin = (variant == ArrayEverySomeVariant::kEvery)
20021cb0ef41Sopenharmony_ci                        ? Builtin::kArrayEveryLoopEagerDeoptContinuation
20031cb0ef41Sopenharmony_ci                        : Builtin::kArraySomeLoopEagerDeoptContinuation;
20041cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {params.receiver, params.callback,
20051cb0ef41Sopenharmony_ci                               params.this_arg, k, params.original_length};
20061cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
20071cb0ef41Sopenharmony_ci      params.jsgraph, params.shared, builtin, params.target, params.context,
20081cb0ef41Sopenharmony_ci      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
20091cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::EAGER);
20101cb0ef41Sopenharmony_ci}
20111cb0ef41Sopenharmony_ci
20121cb0ef41Sopenharmony_ci}  // namespace
20131cb0ef41Sopenharmony_ci
20141cb0ef41Sopenharmony_ciTNode<Boolean>
20151cb0ef41Sopenharmony_ciIteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeEverySome(
20161cb0ef41Sopenharmony_ci    MapInference* inference, const bool has_stability_dependency,
20171cb0ef41Sopenharmony_ci    ElementsKind kind, const SharedFunctionInfoRef& shared,
20181cb0ef41Sopenharmony_ci    const NativeContextRef& native_context, ArrayEverySomeVariant variant) {
20191cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
20201cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
20211cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
20221cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
20231cb0ef41Sopenharmony_ci  TNode<Object> fncallback = ArgumentOrUndefined(0);
20241cb0ef41Sopenharmony_ci  TNode<Object> this_arg = ArgumentOrUndefined(1);
20251cb0ef41Sopenharmony_ci
20261cb0ef41Sopenharmony_ci  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);
20271cb0ef41Sopenharmony_ci
20281cb0ef41Sopenharmony_ci  EverySomeFrameStateParams frame_state_params{
20291cb0ef41Sopenharmony_ci      jsgraph(), shared,     context,  target,         outer_frame_state,
20301cb0ef41Sopenharmony_ci      receiver,  fncallback, this_arg, original_length};
20311cb0ef41Sopenharmony_ci
20321cb0ef41Sopenharmony_ci  ThrowIfNotCallable(
20331cb0ef41Sopenharmony_ci      fncallback,
20341cb0ef41Sopenharmony_ci      EverySomeLoopLazyFrameState(frame_state_params, ZeroConstant(), variant));
20351cb0ef41Sopenharmony_ci
20361cb0ef41Sopenharmony_ci  auto out = MakeLabel(MachineRepresentation::kTagged);
20371cb0ef41Sopenharmony_ci
20381cb0ef41Sopenharmony_ci  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
20391cb0ef41Sopenharmony_ci    Checkpoint(EverySomeLoopEagerFrameState(frame_state_params, k, variant));
20401cb0ef41Sopenharmony_ci    MaybeInsertMapChecks(inference, has_stability_dependency);
20411cb0ef41Sopenharmony_ci
20421cb0ef41Sopenharmony_ci    TNode<Object> element;
20431cb0ef41Sopenharmony_ci    std::tie(k, element) = SafeLoadElement(kind, receiver, k);
20441cb0ef41Sopenharmony_ci
20451cb0ef41Sopenharmony_ci    auto continue_label = MakeLabel();
20461cb0ef41Sopenharmony_ci    element = MaybeSkipHole(element, kind, &continue_label);
20471cb0ef41Sopenharmony_ci
20481cb0ef41Sopenharmony_ci    TNode<Object> v =
20491cb0ef41Sopenharmony_ci        JSCall3(fncallback, this_arg, element, k, receiver,
20501cb0ef41Sopenharmony_ci                EverySomeLoopLazyFrameState(frame_state_params, k, variant));
20511cb0ef41Sopenharmony_ci
20521cb0ef41Sopenharmony_ci    if (variant == ArrayEverySomeVariant::kEvery) {
20531cb0ef41Sopenharmony_ci      GotoIfNot(ToBoolean(v), &out, FalseConstant());
20541cb0ef41Sopenharmony_ci    } else {
20551cb0ef41Sopenharmony_ci      DCHECK_EQ(variant, ArrayEverySomeVariant::kSome);
20561cb0ef41Sopenharmony_ci      GotoIf(ToBoolean(v), &out, TrueConstant());
20571cb0ef41Sopenharmony_ci    }
20581cb0ef41Sopenharmony_ci    Goto(&continue_label);
20591cb0ef41Sopenharmony_ci    Bind(&continue_label);
20601cb0ef41Sopenharmony_ci  });
20611cb0ef41Sopenharmony_ci
20621cb0ef41Sopenharmony_ci  Goto(&out, (variant == ArrayEverySomeVariant::kEvery) ? TrueConstant()
20631cb0ef41Sopenharmony_ci                                                        : FalseConstant());
20641cb0ef41Sopenharmony_ci
20651cb0ef41Sopenharmony_ci  Bind(&out);
20661cb0ef41Sopenharmony_ci  return out.PhiAt<Boolean>(0);
20671cb0ef41Sopenharmony_ci}
20681cb0ef41Sopenharmony_ci
20691cb0ef41Sopenharmony_cinamespace {
20701cb0ef41Sopenharmony_ci
20711cb0ef41Sopenharmony_ciCallable GetCallableForArrayIndexOfIncludes(ArrayIndexOfIncludesVariant variant,
20721cb0ef41Sopenharmony_ci                                            ElementsKind elements_kind,
20731cb0ef41Sopenharmony_ci                                            Isolate* isolate) {
20741cb0ef41Sopenharmony_ci  if (variant == ArrayIndexOfIncludesVariant::kIndexOf) {
20751cb0ef41Sopenharmony_ci    switch (elements_kind) {
20761cb0ef41Sopenharmony_ci      case PACKED_SMI_ELEMENTS:
20771cb0ef41Sopenharmony_ci      case HOLEY_SMI_ELEMENTS:
20781cb0ef41Sopenharmony_ci      case PACKED_ELEMENTS:
20791cb0ef41Sopenharmony_ci      case HOLEY_ELEMENTS:
20801cb0ef41Sopenharmony_ci        return Builtins::CallableFor(isolate,
20811cb0ef41Sopenharmony_ci                                     Builtin::kArrayIndexOfSmiOrObject);
20821cb0ef41Sopenharmony_ci      case PACKED_DOUBLE_ELEMENTS:
20831cb0ef41Sopenharmony_ci        return Builtins::CallableFor(isolate,
20841cb0ef41Sopenharmony_ci                                     Builtin::kArrayIndexOfPackedDoubles);
20851cb0ef41Sopenharmony_ci      default:
20861cb0ef41Sopenharmony_ci        DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
20871cb0ef41Sopenharmony_ci        return Builtins::CallableFor(isolate,
20881cb0ef41Sopenharmony_ci                                     Builtin::kArrayIndexOfHoleyDoubles);
20891cb0ef41Sopenharmony_ci    }
20901cb0ef41Sopenharmony_ci  } else {
20911cb0ef41Sopenharmony_ci    DCHECK_EQ(variant, ArrayIndexOfIncludesVariant::kIncludes);
20921cb0ef41Sopenharmony_ci    switch (elements_kind) {
20931cb0ef41Sopenharmony_ci      case PACKED_SMI_ELEMENTS:
20941cb0ef41Sopenharmony_ci      case HOLEY_SMI_ELEMENTS:
20951cb0ef41Sopenharmony_ci      case PACKED_ELEMENTS:
20961cb0ef41Sopenharmony_ci      case HOLEY_ELEMENTS:
20971cb0ef41Sopenharmony_ci        return Builtins::CallableFor(isolate,
20981cb0ef41Sopenharmony_ci                                     Builtin::kArrayIncludesSmiOrObject);
20991cb0ef41Sopenharmony_ci      case PACKED_DOUBLE_ELEMENTS:
21001cb0ef41Sopenharmony_ci        return Builtins::CallableFor(isolate,
21011cb0ef41Sopenharmony_ci                                     Builtin::kArrayIncludesPackedDoubles);
21021cb0ef41Sopenharmony_ci      default:
21031cb0ef41Sopenharmony_ci        DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
21041cb0ef41Sopenharmony_ci        return Builtins::CallableFor(isolate,
21051cb0ef41Sopenharmony_ci                                     Builtin::kArrayIncludesHoleyDoubles);
21061cb0ef41Sopenharmony_ci    }
21071cb0ef41Sopenharmony_ci  }
21081cb0ef41Sopenharmony_ci  UNREACHABLE();
21091cb0ef41Sopenharmony_ci}
21101cb0ef41Sopenharmony_ci
21111cb0ef41Sopenharmony_ci}  // namespace
21121cb0ef41Sopenharmony_ci
21131cb0ef41Sopenharmony_ciTNode<Object>
21141cb0ef41Sopenharmony_ciIteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeIndexOfIncludes(
21151cb0ef41Sopenharmony_ci    ElementsKind kind, ArrayIndexOfIncludesVariant variant) {
21161cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
21171cb0ef41Sopenharmony_ci  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
21181cb0ef41Sopenharmony_ci  TNode<Object> search_element = ArgumentOrUndefined(0);
21191cb0ef41Sopenharmony_ci  TNode<Object> from_index = ArgumentOrZero(1);
21201cb0ef41Sopenharmony_ci
21211cb0ef41Sopenharmony_ci  // TODO(jgruber): This currently only reduces to a stub call. Create a full
21221cb0ef41Sopenharmony_ci  // reduction (similar to other higher-order array builtins) instead of
21231cb0ef41Sopenharmony_ci  // lowering to a builtin call. E.g. Array.p.every and Array.p.some have almost
21241cb0ef41Sopenharmony_ci  // identical functionality.
21251cb0ef41Sopenharmony_ci
21261cb0ef41Sopenharmony_ci  TNode<Number> length = LoadJSArrayLength(receiver, kind);
21271cb0ef41Sopenharmony_ci  TNode<FixedArrayBase> elements = LoadElements(receiver);
21281cb0ef41Sopenharmony_ci
21291cb0ef41Sopenharmony_ci  const bool have_from_index = ArgumentCount() > 1;
21301cb0ef41Sopenharmony_ci  if (have_from_index) {
21311cb0ef41Sopenharmony_ci    TNode<Smi> from_index_smi = CheckSmi(from_index);
21321cb0ef41Sopenharmony_ci
21331cb0ef41Sopenharmony_ci    // If the index is negative, it means the offset from the end and
21341cb0ef41Sopenharmony_ci    // therefore needs to be added to the length. If the result is still
21351cb0ef41Sopenharmony_ci    // negative, it needs to be clamped to 0.
21361cb0ef41Sopenharmony_ci    TNode<Boolean> cond = NumberLessThan(from_index_smi, ZeroConstant());
21371cb0ef41Sopenharmony_ci    from_index = SelectIf<Number>(cond)
21381cb0ef41Sopenharmony_ci                     .Then(_ {
21391cb0ef41Sopenharmony_ci                       return NumberMax(NumberAdd(length, from_index_smi),
21401cb0ef41Sopenharmony_ci                                        ZeroConstant());
21411cb0ef41Sopenharmony_ci                     })
21421cb0ef41Sopenharmony_ci                     .Else(_ { return from_index_smi; })
21431cb0ef41Sopenharmony_ci                     .ExpectFalse()
21441cb0ef41Sopenharmony_ci                     .Value();
21451cb0ef41Sopenharmony_ci  }
21461cb0ef41Sopenharmony_ci
21471cb0ef41Sopenharmony_ci  return Call4(GetCallableForArrayIndexOfIncludes(variant, kind, isolate()),
21481cb0ef41Sopenharmony_ci               context, elements, search_element, length, from_index);
21491cb0ef41Sopenharmony_ci}
21501cb0ef41Sopenharmony_ci
21511cb0ef41Sopenharmony_cinamespace {
21521cb0ef41Sopenharmony_ci
21531cb0ef41Sopenharmony_cistruct PromiseCtorFrameStateParams {
21541cb0ef41Sopenharmony_ci  JSGraph* jsgraph;
21551cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared;
21561cb0ef41Sopenharmony_ci  Node* node_ptr;
21571cb0ef41Sopenharmony_ci  TNode<Context> context;
21581cb0ef41Sopenharmony_ci  TNode<Object> target;
21591cb0ef41Sopenharmony_ci  FrameState outer_frame_state;
21601cb0ef41Sopenharmony_ci};
21611cb0ef41Sopenharmony_ci
21621cb0ef41Sopenharmony_ci// Remnant of old-style JSCallReducer code. Could be ported to graph assembler,
21631cb0ef41Sopenharmony_ci// but probably not worth the effort.
21641cb0ef41Sopenharmony_ciFrameState CreateArtificialFrameState(
21651cb0ef41Sopenharmony_ci    Node* node, Node* outer_frame_state, int parameter_count,
21661cb0ef41Sopenharmony_ci    BytecodeOffset bailout_id, FrameStateType frame_state_type,
21671cb0ef41Sopenharmony_ci    const SharedFunctionInfoRef& shared, Node* context,
21681cb0ef41Sopenharmony_ci    CommonOperatorBuilder* common, Graph* graph) {
21691cb0ef41Sopenharmony_ci  const FrameStateFunctionInfo* state_info =
21701cb0ef41Sopenharmony_ci      common->CreateFrameStateFunctionInfo(
21711cb0ef41Sopenharmony_ci          frame_state_type, parameter_count + 1, 0, shared.object());
21721cb0ef41Sopenharmony_ci
21731cb0ef41Sopenharmony_ci  const Operator* op = common->FrameState(
21741cb0ef41Sopenharmony_ci      bailout_id, OutputFrameStateCombine::Ignore(), state_info);
21751cb0ef41Sopenharmony_ci  const Operator* op0 = common->StateValues(0, SparseInputMask::Dense());
21761cb0ef41Sopenharmony_ci  Node* node0 = graph->NewNode(op0);
21771cb0ef41Sopenharmony_ci
21781cb0ef41Sopenharmony_ci  static constexpr int kTargetInputIndex = 0;
21791cb0ef41Sopenharmony_ci  static constexpr int kReceiverInputIndex = 1;
21801cb0ef41Sopenharmony_ci  const int parameter_count_with_receiver = parameter_count + 1;
21811cb0ef41Sopenharmony_ci  std::vector<Node*> params;
21821cb0ef41Sopenharmony_ci  params.reserve(parameter_count_with_receiver);
21831cb0ef41Sopenharmony_ci  for (int i = 0; i < parameter_count_with_receiver; i++) {
21841cb0ef41Sopenharmony_ci    params.push_back(node->InputAt(kReceiverInputIndex + i));
21851cb0ef41Sopenharmony_ci  }
21861cb0ef41Sopenharmony_ci  const Operator* op_param = common->StateValues(
21871cb0ef41Sopenharmony_ci      static_cast<int>(params.size()), SparseInputMask::Dense());
21881cb0ef41Sopenharmony_ci  Node* params_node = graph->NewNode(op_param, static_cast<int>(params.size()),
21891cb0ef41Sopenharmony_ci                                     &params.front());
21901cb0ef41Sopenharmony_ci  DCHECK(context);
21911cb0ef41Sopenharmony_ci  return FrameState(graph->NewNode(op, params_node, node0, node0, context,
21921cb0ef41Sopenharmony_ci                                   node->InputAt(kTargetInputIndex),
21931cb0ef41Sopenharmony_ci                                   outer_frame_state));
21941cb0ef41Sopenharmony_ci}
21951cb0ef41Sopenharmony_ci
21961cb0ef41Sopenharmony_ciFrameState PromiseConstructorFrameState(
21971cb0ef41Sopenharmony_ci    const PromiseCtorFrameStateParams& params, CommonOperatorBuilder* common,
21981cb0ef41Sopenharmony_ci    Graph* graph) {
21991cb0ef41Sopenharmony_ci  DCHECK_EQ(1,
22001cb0ef41Sopenharmony_ci            params.shared.internal_formal_parameter_count_without_receiver());
22011cb0ef41Sopenharmony_ci  return CreateArtificialFrameState(
22021cb0ef41Sopenharmony_ci      params.node_ptr, params.outer_frame_state, 1,
22031cb0ef41Sopenharmony_ci      BytecodeOffset::ConstructStubInvoke(), FrameStateType::kConstructStub,
22041cb0ef41Sopenharmony_ci      params.shared, params.context, common, graph);
22051cb0ef41Sopenharmony_ci}
22061cb0ef41Sopenharmony_ci
22071cb0ef41Sopenharmony_ciFrameState PromiseConstructorLazyFrameState(
22081cb0ef41Sopenharmony_ci    const PromiseCtorFrameStateParams& params,
22091cb0ef41Sopenharmony_ci    FrameState constructor_frame_state) {
22101cb0ef41Sopenharmony_ci  // The deopt continuation of this frame state is never called; the frame state
22111cb0ef41Sopenharmony_ci  // is only necessary to obtain the right stack trace.
22121cb0ef41Sopenharmony_ci  JSGraph* jsgraph = params.jsgraph;
22131cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {
22141cb0ef41Sopenharmony_ci      jsgraph->UndefinedConstant(), /* receiver */
22151cb0ef41Sopenharmony_ci      jsgraph->UndefinedConstant(), /* promise */
22161cb0ef41Sopenharmony_ci      jsgraph->UndefinedConstant(), /* reject function */
22171cb0ef41Sopenharmony_ci      jsgraph->TheHoleConstant()    /* exception */
22181cb0ef41Sopenharmony_ci  };
22191cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
22201cb0ef41Sopenharmony_ci      jsgraph, params.shared, Builtin::kPromiseConstructorLazyDeoptContinuation,
22211cb0ef41Sopenharmony_ci      params.target, params.context, checkpoint_params,
22221cb0ef41Sopenharmony_ci      arraysize(checkpoint_params), constructor_frame_state,
22231cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
22241cb0ef41Sopenharmony_ci}
22251cb0ef41Sopenharmony_ci
22261cb0ef41Sopenharmony_ciFrameState PromiseConstructorLazyWithCatchFrameState(
22271cb0ef41Sopenharmony_ci    const PromiseCtorFrameStateParams& params,
22281cb0ef41Sopenharmony_ci    FrameState constructor_frame_state, TNode<JSPromise> promise,
22291cb0ef41Sopenharmony_ci    TNode<JSFunction> reject) {
22301cb0ef41Sopenharmony_ci  // This continuation just returns the created promise and takes care of
22311cb0ef41Sopenharmony_ci  // exceptions thrown by the executor.
22321cb0ef41Sopenharmony_ci  Node* checkpoint_params[] = {
22331cb0ef41Sopenharmony_ci      params.jsgraph->UndefinedConstant(), /* receiver */
22341cb0ef41Sopenharmony_ci      promise, reject};
22351cb0ef41Sopenharmony_ci  return CreateJavaScriptBuiltinContinuationFrameState(
22361cb0ef41Sopenharmony_ci      params.jsgraph, params.shared,
22371cb0ef41Sopenharmony_ci      Builtin::kPromiseConstructorLazyDeoptContinuation, params.target,
22381cb0ef41Sopenharmony_ci      params.context, checkpoint_params, arraysize(checkpoint_params),
22391cb0ef41Sopenharmony_ci      constructor_frame_state, ContinuationFrameStateMode::LAZY_WITH_CATCH);
22401cb0ef41Sopenharmony_ci}
22411cb0ef41Sopenharmony_ci
22421cb0ef41Sopenharmony_ci}  // namespace
22431cb0ef41Sopenharmony_ci
22441cb0ef41Sopenharmony_ciTNode<Object> PromiseBuiltinReducerAssembler::ReducePromiseConstructor(
22451cb0ef41Sopenharmony_ci    const NativeContextRef& native_context) {
22461cb0ef41Sopenharmony_ci  DCHECK_GE(ConstructArity(), 1);
22471cb0ef41Sopenharmony_ci
22481cb0ef41Sopenharmony_ci  JSConstructNode n(node_ptr());
22491cb0ef41Sopenharmony_ci  FrameState outer_frame_state = FrameStateInput();
22501cb0ef41Sopenharmony_ci  TNode<Context> context = ContextInput();
22511cb0ef41Sopenharmony_ci  TNode<Object> target = TargetInput();
22521cb0ef41Sopenharmony_ci  TNode<Object> executor = n.Argument(0);
22531cb0ef41Sopenharmony_ci  DCHECK_EQ(target, NewTargetInput());
22541cb0ef41Sopenharmony_ci
22551cb0ef41Sopenharmony_ci  SharedFunctionInfoRef promise_shared =
22561cb0ef41Sopenharmony_ci      native_context.promise_function().shared();
22571cb0ef41Sopenharmony_ci
22581cb0ef41Sopenharmony_ci  PromiseCtorFrameStateParams frame_state_params{jsgraph(),  promise_shared,
22591cb0ef41Sopenharmony_ci                                                 node_ptr(), context,
22601cb0ef41Sopenharmony_ci                                                 target,     outer_frame_state};
22611cb0ef41Sopenharmony_ci
22621cb0ef41Sopenharmony_ci  // Insert a construct stub frame into the chain of frame states. This will
22631cb0ef41Sopenharmony_ci  // reconstruct the proper frame when deoptimizing within the constructor.
22641cb0ef41Sopenharmony_ci  // For the frame state, we only provide the executor parameter, even if more
22651cb0ef41Sopenharmony_ci  // arguments were passed. This is not observable from JS.
22661cb0ef41Sopenharmony_ci  FrameState constructor_frame_state =
22671cb0ef41Sopenharmony_ci      PromiseConstructorFrameState(frame_state_params, common(), graph());
22681cb0ef41Sopenharmony_ci
22691cb0ef41Sopenharmony_ci  ThrowIfNotCallable(executor,
22701cb0ef41Sopenharmony_ci                     PromiseConstructorLazyFrameState(frame_state_params,
22711cb0ef41Sopenharmony_ci                                                      constructor_frame_state));
22721cb0ef41Sopenharmony_ci
22731cb0ef41Sopenharmony_ci  TNode<JSPromise> promise = CreatePromise(context);
22741cb0ef41Sopenharmony_ci
22751cb0ef41Sopenharmony_ci  // 8. CreatePromiseResolvingFunctions
22761cb0ef41Sopenharmony_ci  // Allocate a promise context for the closures below.
22771cb0ef41Sopenharmony_ci  TNode<Context> promise_context = CreateFunctionContext(
22781cb0ef41Sopenharmony_ci      native_context, context, PromiseBuiltins::kPromiseContextLength);
22791cb0ef41Sopenharmony_ci  StoreContextSlot(promise_context, PromiseBuiltins::kPromiseSlot, promise);
22801cb0ef41Sopenharmony_ci  StoreContextSlot(promise_context, PromiseBuiltins::kAlreadyResolvedSlot,
22811cb0ef41Sopenharmony_ci                   FalseConstant());
22821cb0ef41Sopenharmony_ci  StoreContextSlot(promise_context, PromiseBuiltins::kDebugEventSlot,
22831cb0ef41Sopenharmony_ci                   TrueConstant());
22841cb0ef41Sopenharmony_ci
22851cb0ef41Sopenharmony_ci  // Allocate closures for the resolve and reject cases.
22861cb0ef41Sopenharmony_ci  SharedFunctionInfoRef resolve_sfi =
22871cb0ef41Sopenharmony_ci      MakeRef(broker_, broker_->isolate()
22881cb0ef41Sopenharmony_ci                           ->factory()
22891cb0ef41Sopenharmony_ci                           ->promise_capability_default_resolve_shared_fun());
22901cb0ef41Sopenharmony_ci  TNode<JSFunction> resolve =
22911cb0ef41Sopenharmony_ci      CreateClosureFromBuiltinSharedFunctionInfo(resolve_sfi, promise_context);
22921cb0ef41Sopenharmony_ci
22931cb0ef41Sopenharmony_ci  SharedFunctionInfoRef reject_sfi =
22941cb0ef41Sopenharmony_ci      MakeRef(broker_, broker_->isolate()
22951cb0ef41Sopenharmony_ci                           ->factory()
22961cb0ef41Sopenharmony_ci                           ->promise_capability_default_reject_shared_fun());
22971cb0ef41Sopenharmony_ci  TNode<JSFunction> reject =
22981cb0ef41Sopenharmony_ci      CreateClosureFromBuiltinSharedFunctionInfo(reject_sfi, promise_context);
22991cb0ef41Sopenharmony_ci
23001cb0ef41Sopenharmony_ci  FrameState lazy_with_catch_frame_state =
23011cb0ef41Sopenharmony_ci      PromiseConstructorLazyWithCatchFrameState(
23021cb0ef41Sopenharmony_ci          frame_state_params, constructor_frame_state, promise, reject);
23031cb0ef41Sopenharmony_ci
23041cb0ef41Sopenharmony_ci  // 9. Call executor with both resolving functions.
23051cb0ef41Sopenharmony_ci  // 10a. Call reject if the call to executor threw.
23061cb0ef41Sopenharmony_ci  Try(_ {
23071cb0ef41Sopenharmony_ci    CallPromiseExecutor(executor, resolve, reject, lazy_with_catch_frame_state);
23081cb0ef41Sopenharmony_ci  }).Catch([&](TNode<Object> exception) {
23091cb0ef41Sopenharmony_ci    CallPromiseReject(reject, exception, lazy_with_catch_frame_state);
23101cb0ef41Sopenharmony_ci  });
23111cb0ef41Sopenharmony_ci
23121cb0ef41Sopenharmony_ci  return promise;
23131cb0ef41Sopenharmony_ci}
23141cb0ef41Sopenharmony_ci
23151cb0ef41Sopenharmony_ci#undef _
23161cb0ef41Sopenharmony_ci
23171cb0ef41Sopenharmony_ciReduction JSCallReducer::ReplaceWithSubgraph(JSCallReducerAssembler* gasm,
23181cb0ef41Sopenharmony_ci                                             Node* subgraph) {
23191cb0ef41Sopenharmony_ci  // TODO(jgruber): Consider a less fiddly way of integrating the new subgraph
23201cb0ef41Sopenharmony_ci  // into the outer graph. For instance, the subgraph could be created in
23211cb0ef41Sopenharmony_ci  // complete isolation, and then plugged into the outer graph in one go.
23221cb0ef41Sopenharmony_ci  // Instead of manually tracking IfException nodes, we could iterate the
23231cb0ef41Sopenharmony_ci  // subgraph.
23241cb0ef41Sopenharmony_ci
23251cb0ef41Sopenharmony_ci  // Replace the Call node with the newly-produced subgraph.
23261cb0ef41Sopenharmony_ci  ReplaceWithValue(gasm->node_ptr(), subgraph, gasm->effect(), gasm->control());
23271cb0ef41Sopenharmony_ci
23281cb0ef41Sopenharmony_ci  // Wire exception edges contained in the newly-produced subgraph into the
23291cb0ef41Sopenharmony_ci  // outer graph.
23301cb0ef41Sopenharmony_ci  auto catch_scope = gasm->catch_scope();
23311cb0ef41Sopenharmony_ci  DCHECK(catch_scope->is_outermost());
23321cb0ef41Sopenharmony_ci
23331cb0ef41Sopenharmony_ci  if (catch_scope->has_handler() &&
23341cb0ef41Sopenharmony_ci      catch_scope->has_exceptional_control_flow()) {
23351cb0ef41Sopenharmony_ci    TNode<Object> handler_exception;
23361cb0ef41Sopenharmony_ci    Effect handler_effect{nullptr};
23371cb0ef41Sopenharmony_ci    Control handler_control{nullptr};
23381cb0ef41Sopenharmony_ci    gasm->catch_scope()->MergeExceptionalPaths(
23391cb0ef41Sopenharmony_ci        &handler_exception, &handler_effect, &handler_control);
23401cb0ef41Sopenharmony_ci
23411cb0ef41Sopenharmony_ci    ReplaceWithValue(gasm->outermost_handler(), handler_exception,
23421cb0ef41Sopenharmony_ci                     handler_effect, handler_control);
23431cb0ef41Sopenharmony_ci  }
23441cb0ef41Sopenharmony_ci
23451cb0ef41Sopenharmony_ci  return Replace(subgraph);
23461cb0ef41Sopenharmony_ci}
23471cb0ef41Sopenharmony_ci
23481cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
23491cb0ef41Sopenharmony_ci  JSCallNode n(node);
23501cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
23511cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
23521cb0ef41Sopenharmony_ci    return NoChange();
23531cb0ef41Sopenharmony_ci  }
23541cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
23551cb0ef41Sopenharmony_ci    Node* value = jsgraph()->NaNConstant();
23561cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
23571cb0ef41Sopenharmony_ci    return Replace(value);
23581cb0ef41Sopenharmony_ci  }
23591cb0ef41Sopenharmony_ci
23601cb0ef41Sopenharmony_ci  JSCallReducerAssembler a(this, node);
23611cb0ef41Sopenharmony_ci  Node* subgraph = a.ReduceMathUnary(op);
23621cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
23631cb0ef41Sopenharmony_ci}
23641cb0ef41Sopenharmony_ci
23651cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) {
23661cb0ef41Sopenharmony_ci  JSCallNode n(node);
23671cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
23681cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
23691cb0ef41Sopenharmony_ci    return NoChange();
23701cb0ef41Sopenharmony_ci  }
23711cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
23721cb0ef41Sopenharmony_ci    Node* value = jsgraph()->NaNConstant();
23731cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
23741cb0ef41Sopenharmony_ci    return Replace(value);
23751cb0ef41Sopenharmony_ci  }
23761cb0ef41Sopenharmony_ci
23771cb0ef41Sopenharmony_ci  JSCallReducerAssembler a(this, node);
23781cb0ef41Sopenharmony_ci  Node* subgraph = a.ReduceMathBinary(op);
23791cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
23801cb0ef41Sopenharmony_ci}
23811cb0ef41Sopenharmony_ci
23821cb0ef41Sopenharmony_ci// ES6 section 20.2.2.19 Math.imul ( x, y )
23831cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMathImul(Node* node) {
23841cb0ef41Sopenharmony_ci  JSCallNode n(node);
23851cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
23861cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
23871cb0ef41Sopenharmony_ci    return NoChange();
23881cb0ef41Sopenharmony_ci  }
23891cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
23901cb0ef41Sopenharmony_ci    Node* value = jsgraph()->ZeroConstant();
23911cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
23921cb0ef41Sopenharmony_ci    return Replace(value);
23931cb0ef41Sopenharmony_ci  }
23941cb0ef41Sopenharmony_ci  Node* left = n.Argument(0);
23951cb0ef41Sopenharmony_ci  Node* right = n.ArgumentOr(1, jsgraph()->ZeroConstant());
23961cb0ef41Sopenharmony_ci  Effect effect = n.effect();
23971cb0ef41Sopenharmony_ci  Control control = n.control();
23981cb0ef41Sopenharmony_ci
23991cb0ef41Sopenharmony_ci  left = effect =
24001cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(
24011cb0ef41Sopenharmony_ci                           NumberOperationHint::kNumberOrOddball, p.feedback()),
24021cb0ef41Sopenharmony_ci                       left, effect, control);
24031cb0ef41Sopenharmony_ci  right = effect =
24041cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(
24051cb0ef41Sopenharmony_ci                           NumberOperationHint::kNumberOrOddball, p.feedback()),
24061cb0ef41Sopenharmony_ci                       right, effect, control);
24071cb0ef41Sopenharmony_ci  left = graph()->NewNode(simplified()->NumberToUint32(), left);
24081cb0ef41Sopenharmony_ci  right = graph()->NewNode(simplified()->NumberToUint32(), right);
24091cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
24101cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect);
24111cb0ef41Sopenharmony_ci  return Replace(value);
24121cb0ef41Sopenharmony_ci}
24131cb0ef41Sopenharmony_ci
24141cb0ef41Sopenharmony_ci// ES6 section 20.2.2.11 Math.clz32 ( x )
24151cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMathClz32(Node* node) {
24161cb0ef41Sopenharmony_ci  JSCallNode n(node);
24171cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
24181cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
24191cb0ef41Sopenharmony_ci    return NoChange();
24201cb0ef41Sopenharmony_ci  }
24211cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
24221cb0ef41Sopenharmony_ci    Node* value = jsgraph()->Constant(32);
24231cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
24241cb0ef41Sopenharmony_ci    return Replace(value);
24251cb0ef41Sopenharmony_ci  }
24261cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
24271cb0ef41Sopenharmony_ci  Effect effect = n.effect();
24281cb0ef41Sopenharmony_ci  Control control = n.control();
24291cb0ef41Sopenharmony_ci
24301cb0ef41Sopenharmony_ci  input = effect =
24311cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(
24321cb0ef41Sopenharmony_ci                           NumberOperationHint::kNumberOrOddball, p.feedback()),
24331cb0ef41Sopenharmony_ci                       input, effect, control);
24341cb0ef41Sopenharmony_ci  input = graph()->NewNode(simplified()->NumberToUint32(), input);
24351cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
24361cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect);
24371cb0ef41Sopenharmony_ci  return Replace(value);
24381cb0ef41Sopenharmony_ci}
24391cb0ef41Sopenharmony_ci
24401cb0ef41Sopenharmony_ci// ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
24411cb0ef41Sopenharmony_ci// ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
24421cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op,
24431cb0ef41Sopenharmony_ci                                          Node* empty_value) {
24441cb0ef41Sopenharmony_ci  JSCallNode n(node);
24451cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
24461cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
24471cb0ef41Sopenharmony_ci    return NoChange();
24481cb0ef41Sopenharmony_ci  }
24491cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
24501cb0ef41Sopenharmony_ci    ReplaceWithValue(node, empty_value);
24511cb0ef41Sopenharmony_ci    return Replace(empty_value);
24521cb0ef41Sopenharmony_ci  }
24531cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
24541cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
24551cb0ef41Sopenharmony_ci
24561cb0ef41Sopenharmony_ci  Node* value = effect =
24571cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(
24581cb0ef41Sopenharmony_ci                           NumberOperationHint::kNumberOrOddball, p.feedback()),
24591cb0ef41Sopenharmony_ci                       n.Argument(0), effect, control);
24601cb0ef41Sopenharmony_ci  for (int i = 1; i < n.ArgumentCount(); i++) {
24611cb0ef41Sopenharmony_ci    Node* input = effect = graph()->NewNode(
24621cb0ef41Sopenharmony_ci        simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
24631cb0ef41Sopenharmony_ci                                          p.feedback()),
24641cb0ef41Sopenharmony_ci        n.Argument(i), effect, control);
24651cb0ef41Sopenharmony_ci    value = graph()->NewNode(op, value, input);
24661cb0ef41Sopenharmony_ci  }
24671cb0ef41Sopenharmony_ci
24681cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect);
24691cb0ef41Sopenharmony_ci  return Replace(value);
24701cb0ef41Sopenharmony_ci}
24711cb0ef41Sopenharmony_ci
24721cb0ef41Sopenharmony_ciReduction JSCallReducer::Reduce(Node* node) {
24731cb0ef41Sopenharmony_ci  switch (node->opcode()) {
24741cb0ef41Sopenharmony_ci    case IrOpcode::kJSConstruct:
24751cb0ef41Sopenharmony_ci      return ReduceJSConstruct(node);
24761cb0ef41Sopenharmony_ci    case IrOpcode::kJSConstructWithArrayLike:
24771cb0ef41Sopenharmony_ci      return ReduceJSConstructWithArrayLike(node);
24781cb0ef41Sopenharmony_ci    case IrOpcode::kJSConstructWithSpread:
24791cb0ef41Sopenharmony_ci      return ReduceJSConstructWithSpread(node);
24801cb0ef41Sopenharmony_ci    case IrOpcode::kJSCall:
24811cb0ef41Sopenharmony_ci      return ReduceJSCall(node);
24821cb0ef41Sopenharmony_ci    case IrOpcode::kJSCallWithArrayLike:
24831cb0ef41Sopenharmony_ci      return ReduceJSCallWithArrayLike(node);
24841cb0ef41Sopenharmony_ci    case IrOpcode::kJSCallWithSpread:
24851cb0ef41Sopenharmony_ci      return ReduceJSCallWithSpread(node);
24861cb0ef41Sopenharmony_ci    default:
24871cb0ef41Sopenharmony_ci      break;
24881cb0ef41Sopenharmony_ci  }
24891cb0ef41Sopenharmony_ci  return NoChange();
24901cb0ef41Sopenharmony_ci}
24911cb0ef41Sopenharmony_ci
24921cb0ef41Sopenharmony_civoid JSCallReducer::Finalize() {
24931cb0ef41Sopenharmony_ci  // TODO(turbofan): This is not the best solution; ideally we would be able
24941cb0ef41Sopenharmony_ci  // to teach the GraphReducer about arbitrary dependencies between different
24951cb0ef41Sopenharmony_ci  // nodes, even if they don't show up in the use list of the other node.
24961cb0ef41Sopenharmony_ci  std::set<Node*> const waitlist = std::move(waitlist_);
24971cb0ef41Sopenharmony_ci  for (Node* node : waitlist) {
24981cb0ef41Sopenharmony_ci    if (!node->IsDead()) {
24991cb0ef41Sopenharmony_ci      Reduction const reduction = Reduce(node);
25001cb0ef41Sopenharmony_ci      if (reduction.Changed()) {
25011cb0ef41Sopenharmony_ci        Node* replacement = reduction.replacement();
25021cb0ef41Sopenharmony_ci        if (replacement != node) {
25031cb0ef41Sopenharmony_ci          Replace(node, replacement);
25041cb0ef41Sopenharmony_ci        }
25051cb0ef41Sopenharmony_ci      }
25061cb0ef41Sopenharmony_ci    }
25071cb0ef41Sopenharmony_ci  }
25081cb0ef41Sopenharmony_ci}
25091cb0ef41Sopenharmony_ci
25101cb0ef41Sopenharmony_ci// ES6 section 22.1.1 The Array Constructor
25111cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayConstructor(Node* node) {
25121cb0ef41Sopenharmony_ci  JSCallNode n(node);
25131cb0ef41Sopenharmony_ci  Node* target = n.target();
25141cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
25151cb0ef41Sopenharmony_ci
25161cb0ef41Sopenharmony_ci  // Turn the {node} into a {JSCreateArray} call.
25171cb0ef41Sopenharmony_ci  size_t const arity = p.arity_without_implicit_args();
25181cb0ef41Sopenharmony_ci  node->RemoveInput(n.FeedbackVectorIndex());
25191cb0ef41Sopenharmony_ci  NodeProperties::ReplaceValueInput(node, target, 0);
25201cb0ef41Sopenharmony_ci  NodeProperties::ReplaceValueInput(node, target, 1);
25211cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node,
25221cb0ef41Sopenharmony_ci                           javascript()->CreateArray(arity, base::nullopt));
25231cb0ef41Sopenharmony_ci  return Changed(node);
25241cb0ef41Sopenharmony_ci}
25251cb0ef41Sopenharmony_ci
25261cb0ef41Sopenharmony_ci// ES6 section 19.3.1.1 Boolean ( value )
25271cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceBooleanConstructor(Node* node) {
25281cb0ef41Sopenharmony_ci  // Replace the {node} with a proper {ToBoolean} operator.
25291cb0ef41Sopenharmony_ci  JSCallNode n(node);
25301cb0ef41Sopenharmony_ci  Node* value = n.ArgumentOrUndefined(0, jsgraph());
25311cb0ef41Sopenharmony_ci  value = graph()->NewNode(simplified()->ToBoolean(), value);
25321cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
25331cb0ef41Sopenharmony_ci  return Replace(value);
25341cb0ef41Sopenharmony_ci}
25351cb0ef41Sopenharmony_ci
25361cb0ef41Sopenharmony_ci// ES section #sec-object-constructor
25371cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectConstructor(Node* node) {
25381cb0ef41Sopenharmony_ci  JSCallNode n(node);
25391cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) return NoChange();
25401cb0ef41Sopenharmony_ci  Node* value = n.Argument(0);
25411cb0ef41Sopenharmony_ci  Effect effect = n.effect();
25421cb0ef41Sopenharmony_ci
25431cb0ef41Sopenharmony_ci  // We can fold away the Object(x) call if |x| is definitely not a primitive.
25441cb0ef41Sopenharmony_ci  if (NodeProperties::CanBePrimitive(broker(), value, effect)) {
25451cb0ef41Sopenharmony_ci    if (!NodeProperties::CanBeNullOrUndefined(broker(), value, effect)) {
25461cb0ef41Sopenharmony_ci      // Turn the {node} into a {JSToObject} call if we know that
25471cb0ef41Sopenharmony_ci      // the {value} cannot be null or undefined.
25481cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInputs(node, value);
25491cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, javascript()->ToObject());
25501cb0ef41Sopenharmony_ci      return Changed(node);
25511cb0ef41Sopenharmony_ci    }
25521cb0ef41Sopenharmony_ci  } else {
25531cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
25541cb0ef41Sopenharmony_ci    return Replace(value);
25551cb0ef41Sopenharmony_ci  }
25561cb0ef41Sopenharmony_ci  return NoChange();
25571cb0ef41Sopenharmony_ci}
25581cb0ef41Sopenharmony_ci
25591cb0ef41Sopenharmony_ci// ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
25601cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
25611cb0ef41Sopenharmony_ci  JSCallNode n(node);
25621cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
25631cb0ef41Sopenharmony_ci  CallFeedbackRelation new_feedback_relation =
25641cb0ef41Sopenharmony_ci      p.feedback_relation() == CallFeedbackRelation::kReceiver
25651cb0ef41Sopenharmony_ci          ? CallFeedbackRelation::kTarget
25661cb0ef41Sopenharmony_ci          : CallFeedbackRelation::kUnrelated;
25671cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
25681cb0ef41Sopenharmony_ci
25691cb0ef41Sopenharmony_ci  if (arity < 2) {
25701cb0ef41Sopenharmony_ci    // Degenerate cases.
25711cb0ef41Sopenharmony_ci    ConvertReceiverMode convert_mode;
25721cb0ef41Sopenharmony_ci    if (arity == 0) {
25731cb0ef41Sopenharmony_ci      // Neither thisArg nor argArray was provided.
25741cb0ef41Sopenharmony_ci      convert_mode = ConvertReceiverMode::kNullOrUndefined;
25751cb0ef41Sopenharmony_ci      node->ReplaceInput(n.TargetIndex(), n.receiver());
25761cb0ef41Sopenharmony_ci      node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
25771cb0ef41Sopenharmony_ci    } else {
25781cb0ef41Sopenharmony_ci      DCHECK_EQ(arity, 1);
25791cb0ef41Sopenharmony_ci      // The argArray was not provided, just remove the {target}.
25801cb0ef41Sopenharmony_ci      convert_mode = ConvertReceiverMode::kAny;
25811cb0ef41Sopenharmony_ci      node->RemoveInput(n.TargetIndex());
25821cb0ef41Sopenharmony_ci      --arity;
25831cb0ef41Sopenharmony_ci    }
25841cb0ef41Sopenharmony_ci    // Change {node} to a {JSCall} and try to reduce further.
25851cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
25861cb0ef41Sopenharmony_ci        node, javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
25871cb0ef41Sopenharmony_ci                                 p.feedback(), convert_mode,
25881cb0ef41Sopenharmony_ci                                 p.speculation_mode(), new_feedback_relation));
25891cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSCall(node));
25901cb0ef41Sopenharmony_ci  }
25911cb0ef41Sopenharmony_ci
25921cb0ef41Sopenharmony_ci  // Turn the JSCall into a JSCallWithArrayLike.
25931cb0ef41Sopenharmony_ci  // If {argArray} can be null or undefined, we have to generate branches since
25941cb0ef41Sopenharmony_ci  // JSCallWithArrayLike would throw for null or undefined.
25951cb0ef41Sopenharmony_ci
25961cb0ef41Sopenharmony_ci  Node* target = n.receiver();
25971cb0ef41Sopenharmony_ci  Node* this_argument = n.Argument(0);
25981cb0ef41Sopenharmony_ci  Node* arguments_list = n.Argument(1);
25991cb0ef41Sopenharmony_ci  Node* context = n.context();
26001cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
26011cb0ef41Sopenharmony_ci  Effect effect = n.effect();
26021cb0ef41Sopenharmony_ci  Control control = n.control();
26031cb0ef41Sopenharmony_ci
26041cb0ef41Sopenharmony_ci  // If {arguments_list} cannot be null or undefined, we don't need
26051cb0ef41Sopenharmony_ci  // to expand this {node} to control-flow.
26061cb0ef41Sopenharmony_ci  if (!NodeProperties::CanBeNullOrUndefined(broker(), arguments_list, effect)) {
26071cb0ef41Sopenharmony_ci    // Massage the value inputs appropriately.
26081cb0ef41Sopenharmony_ci    node->ReplaceInput(n.TargetIndex(), target);
26091cb0ef41Sopenharmony_ci    node->ReplaceInput(n.ReceiverIndex(), this_argument);
26101cb0ef41Sopenharmony_ci    node->ReplaceInput(n.ArgumentIndex(0), arguments_list);
26111cb0ef41Sopenharmony_ci    while (arity-- > 1) node->RemoveInput(n.ArgumentIndex(1));
26121cb0ef41Sopenharmony_ci
26131cb0ef41Sopenharmony_ci    // Morph the {node} to a {JSCallWithArrayLike}.
26141cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
26151cb0ef41Sopenharmony_ci        node, javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
26161cb0ef41Sopenharmony_ci                                              p.speculation_mode(),
26171cb0ef41Sopenharmony_ci                                              new_feedback_relation));
26181cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSCallWithArrayLike(node));
26191cb0ef41Sopenharmony_ci  }
26201cb0ef41Sopenharmony_ci
26211cb0ef41Sopenharmony_ci  // Check whether {arguments_list} is null.
26221cb0ef41Sopenharmony_ci  Node* check_null =
26231cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
26241cb0ef41Sopenharmony_ci                       jsgraph()->NullConstant());
26251cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Branch(BranchHint::kFalse), check_null,
26261cb0ef41Sopenharmony_ci                             control);
26271cb0ef41Sopenharmony_ci  Node* if_null = graph()->NewNode(common()->IfTrue(), control);
26281cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->IfFalse(), control);
26291cb0ef41Sopenharmony_ci
26301cb0ef41Sopenharmony_ci  // Check whether {arguments_list} is undefined.
26311cb0ef41Sopenharmony_ci  Node* check_undefined =
26321cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
26331cb0ef41Sopenharmony_ci                       jsgraph()->UndefinedConstant());
26341cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
26351cb0ef41Sopenharmony_ci                             check_undefined, control);
26361cb0ef41Sopenharmony_ci  Node* if_undefined = graph()->NewNode(common()->IfTrue(), control);
26371cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->IfFalse(), control);
26381cb0ef41Sopenharmony_ci
26391cb0ef41Sopenharmony_ci  // Lower to {JSCallWithArrayLike} if {arguments_list} is neither null
26401cb0ef41Sopenharmony_ci  // nor undefined.
26411cb0ef41Sopenharmony_ci  Node* effect0 = effect;
26421cb0ef41Sopenharmony_ci  Node* control0 = control;
26431cb0ef41Sopenharmony_ci  Node* value0 = effect0 = control0 = graph()->NewNode(
26441cb0ef41Sopenharmony_ci      javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
26451cb0ef41Sopenharmony_ci                                      p.speculation_mode(),
26461cb0ef41Sopenharmony_ci                                      new_feedback_relation),
26471cb0ef41Sopenharmony_ci      target, this_argument, arguments_list, n.feedback_vector(), context,
26481cb0ef41Sopenharmony_ci      frame_state, effect0, control0);
26491cb0ef41Sopenharmony_ci
26501cb0ef41Sopenharmony_ci  // Lower to {JSCall} if {arguments_list} is either null or undefined.
26511cb0ef41Sopenharmony_ci  Node* effect1 = effect;
26521cb0ef41Sopenharmony_ci  Node* control1 = graph()->NewNode(common()->Merge(2), if_null, if_undefined);
26531cb0ef41Sopenharmony_ci  Node* value1 = effect1 = control1 = graph()->NewNode(
26541cb0ef41Sopenharmony_ci      javascript()->Call(JSCallNode::ArityForArgc(0)), target, this_argument,
26551cb0ef41Sopenharmony_ci      n.feedback_vector(), context, frame_state, effect1, control1);
26561cb0ef41Sopenharmony_ci
26571cb0ef41Sopenharmony_ci  // Rewire potential exception edges.
26581cb0ef41Sopenharmony_ci  Node* if_exception = nullptr;
26591cb0ef41Sopenharmony_ci  if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
26601cb0ef41Sopenharmony_ci    // Create appropriate {IfException} and {IfSuccess} nodes.
26611cb0ef41Sopenharmony_ci    Node* if_exception0 =
26621cb0ef41Sopenharmony_ci        graph()->NewNode(common()->IfException(), control0, effect0);
26631cb0ef41Sopenharmony_ci    control0 = graph()->NewNode(common()->IfSuccess(), control0);
26641cb0ef41Sopenharmony_ci    Node* if_exception1 =
26651cb0ef41Sopenharmony_ci        graph()->NewNode(common()->IfException(), control1, effect1);
26661cb0ef41Sopenharmony_ci    control1 = graph()->NewNode(common()->IfSuccess(), control1);
26671cb0ef41Sopenharmony_ci
26681cb0ef41Sopenharmony_ci    // Join the exception edges.
26691cb0ef41Sopenharmony_ci    Node* merge =
26701cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Merge(2), if_exception0, if_exception1);
26711cb0ef41Sopenharmony_ci    Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception0,
26721cb0ef41Sopenharmony_ci                                  if_exception1, merge);
26731cb0ef41Sopenharmony_ci    Node* phi =
26741cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
26751cb0ef41Sopenharmony_ci                         if_exception0, if_exception1, merge);
26761cb0ef41Sopenharmony_ci    ReplaceWithValue(if_exception, phi, ephi, merge);
26771cb0ef41Sopenharmony_ci  }
26781cb0ef41Sopenharmony_ci
26791cb0ef41Sopenharmony_ci  // Join control paths.
26801cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Merge(2), control0, control1);
26811cb0ef41Sopenharmony_ci  effect = graph()->NewNode(common()->EffectPhi(2), effect0, effect1, control);
26821cb0ef41Sopenharmony_ci  Node* value =
26831cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), value0,
26841cb0ef41Sopenharmony_ci                       value1, control);
26851cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
26861cb0ef41Sopenharmony_ci  return Replace(value);
26871cb0ef41Sopenharmony_ci}
26881cb0ef41Sopenharmony_ci
26891cb0ef41Sopenharmony_ci// ES section #sec-function.prototype.bind
26901cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
26911cb0ef41Sopenharmony_ci  JSCallNode n(node);
26921cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
26931cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
26941cb0ef41Sopenharmony_ci    return NoChange();
26951cb0ef41Sopenharmony_ci  }
26961cb0ef41Sopenharmony_ci
26971cb0ef41Sopenharmony_ci  // Value inputs to the {node} are as follows:
26981cb0ef41Sopenharmony_ci  //
26991cb0ef41Sopenharmony_ci  //  - target, which is Function.prototype.bind JSFunction
27001cb0ef41Sopenharmony_ci  //  - receiver, which is the [[BoundTargetFunction]]
27011cb0ef41Sopenharmony_ci  //  - bound_this (optional), which is the [[BoundThis]]
27021cb0ef41Sopenharmony_ci  //  - and all the remaining value inputs are [[BoundArguments]]
27031cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
27041cb0ef41Sopenharmony_ci  Node* context = n.context();
27051cb0ef41Sopenharmony_ci  Effect effect = n.effect();
27061cb0ef41Sopenharmony_ci  Control control = n.control();
27071cb0ef41Sopenharmony_ci
27081cb0ef41Sopenharmony_ci  // Ensure that the {receiver} is known to be a JSBoundFunction or
27091cb0ef41Sopenharmony_ci  // a JSFunction with the same [[Prototype]], and all maps we've
27101cb0ef41Sopenharmony_ci  // seen for the {receiver} so far indicate that {receiver} is
27111cb0ef41Sopenharmony_ci  // definitely a constructor or not a constructor.
27121cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
27131cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
27141cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
27151cb0ef41Sopenharmony_ci
27161cb0ef41Sopenharmony_ci  MapRef first_receiver_map = receiver_maps[0];
27171cb0ef41Sopenharmony_ci  bool const is_constructor = first_receiver_map.is_constructor();
27181cb0ef41Sopenharmony_ci
27191cb0ef41Sopenharmony_ci  HeapObjectRef prototype = first_receiver_map.prototype();
27201cb0ef41Sopenharmony_ci
27211cb0ef41Sopenharmony_ci  for (const MapRef& receiver_map : receiver_maps) {
27221cb0ef41Sopenharmony_ci    HeapObjectRef map_prototype = receiver_map.prototype();
27231cb0ef41Sopenharmony_ci
27241cb0ef41Sopenharmony_ci    // Check for consistency among the {receiver_maps}.
27251cb0ef41Sopenharmony_ci    if (!map_prototype.equals(prototype) ||
27261cb0ef41Sopenharmony_ci        receiver_map.is_constructor() != is_constructor ||
27271cb0ef41Sopenharmony_ci        !InstanceTypeChecker::IsJSFunctionOrBoundFunctionOrWrappedFunction(
27281cb0ef41Sopenharmony_ci            receiver_map.instance_type())) {
27291cb0ef41Sopenharmony_ci      return inference.NoChange();
27301cb0ef41Sopenharmony_ci    }
27311cb0ef41Sopenharmony_ci
27321cb0ef41Sopenharmony_ci    // Disallow binding of slow-mode functions. We need to figure out
27331cb0ef41Sopenharmony_ci    // whether the length and name property are in the original state.
27341cb0ef41Sopenharmony_ci    if (receiver_map.is_dictionary_map()) return inference.NoChange();
27351cb0ef41Sopenharmony_ci
27361cb0ef41Sopenharmony_ci    // Check whether the length and name properties are still present
27371cb0ef41Sopenharmony_ci    // as AccessorInfo objects. In that case, their values can be
27381cb0ef41Sopenharmony_ci    // recomputed even if the actual value of the object changes.
27391cb0ef41Sopenharmony_ci    // This mirrors the checks done in builtins-function-gen.cc at
27401cb0ef41Sopenharmony_ci    // runtime otherwise.
27411cb0ef41Sopenharmony_ci    int minimum_nof_descriptors =
27421cb0ef41Sopenharmony_ci        std::max(
27431cb0ef41Sopenharmony_ci            {JSFunctionOrBoundFunctionOrWrappedFunction::kLengthDescriptorIndex,
27441cb0ef41Sopenharmony_ci             JSFunctionOrBoundFunctionOrWrappedFunction::
27451cb0ef41Sopenharmony_ci                 kNameDescriptorIndex}) +
27461cb0ef41Sopenharmony_ci        1;
27471cb0ef41Sopenharmony_ci    if (receiver_map.NumberOfOwnDescriptors() < minimum_nof_descriptors) {
27481cb0ef41Sopenharmony_ci      return inference.NoChange();
27491cb0ef41Sopenharmony_ci    }
27501cb0ef41Sopenharmony_ci    const InternalIndex kLengthIndex(
27511cb0ef41Sopenharmony_ci        JSFunctionOrBoundFunctionOrWrappedFunction::kLengthDescriptorIndex);
27521cb0ef41Sopenharmony_ci    const InternalIndex kNameIndex(
27531cb0ef41Sopenharmony_ci        JSFunctionOrBoundFunctionOrWrappedFunction::kNameDescriptorIndex);
27541cb0ef41Sopenharmony_ci    ReadOnlyRoots roots(isolate());
27551cb0ef41Sopenharmony_ci    StringRef length_string = MakeRef(broker(), roots.length_string_handle());
27561cb0ef41Sopenharmony_ci    StringRef name_string = MakeRef(broker(), roots.name_string_handle());
27571cb0ef41Sopenharmony_ci
27581cb0ef41Sopenharmony_ci    base::Optional<ObjectRef> length_value(
27591cb0ef41Sopenharmony_ci        receiver_map.GetStrongValue(kLengthIndex));
27601cb0ef41Sopenharmony_ci    base::Optional<ObjectRef> name_value(
27611cb0ef41Sopenharmony_ci        receiver_map.GetStrongValue(kNameIndex));
27621cb0ef41Sopenharmony_ci    if (!length_value || !name_value) {
27631cb0ef41Sopenharmony_ci      TRACE_BROKER_MISSING(
27641cb0ef41Sopenharmony_ci          broker(), "name or length descriptors on map " << receiver_map);
27651cb0ef41Sopenharmony_ci      return inference.NoChange();
27661cb0ef41Sopenharmony_ci    }
27671cb0ef41Sopenharmony_ci    if (!receiver_map.GetPropertyKey(kLengthIndex).equals(length_string) ||
27681cb0ef41Sopenharmony_ci        !length_value->IsAccessorInfo() ||
27691cb0ef41Sopenharmony_ci        !receiver_map.GetPropertyKey(kNameIndex).equals(name_string) ||
27701cb0ef41Sopenharmony_ci        !name_value->IsAccessorInfo()) {
27711cb0ef41Sopenharmony_ci      return inference.NoChange();
27721cb0ef41Sopenharmony_ci    }
27731cb0ef41Sopenharmony_ci  }
27741cb0ef41Sopenharmony_ci
27751cb0ef41Sopenharmony_ci  // Choose the map for the resulting JSBoundFunction (but bail out in case of a
27761cb0ef41Sopenharmony_ci  // custom prototype).
27771cb0ef41Sopenharmony_ci  MapRef map = is_constructor
27781cb0ef41Sopenharmony_ci                   ? native_context().bound_function_with_constructor_map()
27791cb0ef41Sopenharmony_ci                   : native_context().bound_function_without_constructor_map();
27801cb0ef41Sopenharmony_ci  if (!map.prototype().equals(prototype)) return inference.NoChange();
27811cb0ef41Sopenharmony_ci
27821cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
27831cb0ef41Sopenharmony_ci                                      control, p.feedback());
27841cb0ef41Sopenharmony_ci
27851cb0ef41Sopenharmony_ci  // Replace the {node} with a JSCreateBoundFunction.
27861cb0ef41Sopenharmony_ci  static constexpr int kBoundThis = 1;
27871cb0ef41Sopenharmony_ci  static constexpr int kReceiverContextEffectAndControl = 4;
27881cb0ef41Sopenharmony_ci  int const arity = n.ArgumentCount();
27891cb0ef41Sopenharmony_ci
27901cb0ef41Sopenharmony_ci  if (arity > 0) {
27911cb0ef41Sopenharmony_ci    MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map());
27921cb0ef41Sopenharmony_ci    AllocationBuilder ab(jsgraph(), effect, control);
27931cb0ef41Sopenharmony_ci    if (!ab.CanAllocateArray(arity, fixed_array_map)) {
27941cb0ef41Sopenharmony_ci      return NoChange();
27951cb0ef41Sopenharmony_ci    }
27961cb0ef41Sopenharmony_ci  }
27971cb0ef41Sopenharmony_ci
27981cb0ef41Sopenharmony_ci  int const arity_with_bound_this = std::max(arity, kBoundThis);
27991cb0ef41Sopenharmony_ci  int const input_count =
28001cb0ef41Sopenharmony_ci      arity_with_bound_this + kReceiverContextEffectAndControl;
28011cb0ef41Sopenharmony_ci  Node** inputs = graph()->zone()->NewArray<Node*>(input_count);
28021cb0ef41Sopenharmony_ci  int cursor = 0;
28031cb0ef41Sopenharmony_ci  inputs[cursor++] = receiver;
28041cb0ef41Sopenharmony_ci  inputs[cursor++] = n.ArgumentOrUndefined(0, jsgraph());  // bound_this.
28051cb0ef41Sopenharmony_ci  for (int i = 1; i < arity; ++i) {
28061cb0ef41Sopenharmony_ci    inputs[cursor++] = n.Argument(i);
28071cb0ef41Sopenharmony_ci  }
28081cb0ef41Sopenharmony_ci  inputs[cursor++] = context;
28091cb0ef41Sopenharmony_ci  inputs[cursor++] = effect;
28101cb0ef41Sopenharmony_ci  inputs[cursor++] = control;
28111cb0ef41Sopenharmony_ci  DCHECK_EQ(cursor, input_count);
28121cb0ef41Sopenharmony_ci  Node* value = effect =
28131cb0ef41Sopenharmony_ci      graph()->NewNode(javascript()->CreateBoundFunction(
28141cb0ef41Sopenharmony_ci                           arity_with_bound_this - kBoundThis, map),
28151cb0ef41Sopenharmony_ci                       input_count, inputs);
28161cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
28171cb0ef41Sopenharmony_ci  return Replace(value);
28181cb0ef41Sopenharmony_ci}
28191cb0ef41Sopenharmony_ci
28201cb0ef41Sopenharmony_ci// ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
28211cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
28221cb0ef41Sopenharmony_ci  JSCallNode n(node);
28231cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
28241cb0ef41Sopenharmony_ci  Node* target = n.target();
28251cb0ef41Sopenharmony_ci  Effect effect = n.effect();
28261cb0ef41Sopenharmony_ci  Control control = n.control();
28271cb0ef41Sopenharmony_ci
28281cb0ef41Sopenharmony_ci  // Change context of {node} to the Function.prototype.call context,
28291cb0ef41Sopenharmony_ci  // to ensure any exception is thrown in the correct context.
28301cb0ef41Sopenharmony_ci  Node* context;
28311cb0ef41Sopenharmony_ci  HeapObjectMatcher m(target);
28321cb0ef41Sopenharmony_ci  if (m.HasResolvedValue() && m.Ref(broker()).IsJSFunction()) {
28331cb0ef41Sopenharmony_ci    JSFunctionRef function = m.Ref(broker()).AsJSFunction();
28341cb0ef41Sopenharmony_ci    context = jsgraph()->Constant(function.context());
28351cb0ef41Sopenharmony_ci  } else {
28361cb0ef41Sopenharmony_ci    context = effect = graph()->NewNode(
28371cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
28381cb0ef41Sopenharmony_ci        effect, control);
28391cb0ef41Sopenharmony_ci  }
28401cb0ef41Sopenharmony_ci  NodeProperties::ReplaceContextInput(node, context);
28411cb0ef41Sopenharmony_ci  NodeProperties::ReplaceEffectInput(node, effect);
28421cb0ef41Sopenharmony_ci
28431cb0ef41Sopenharmony_ci  // Remove the target from {node} and use the receiver as target instead, and
28441cb0ef41Sopenharmony_ci  // the thisArg becomes the new target.  If thisArg was not provided, insert
28451cb0ef41Sopenharmony_ci  // undefined instead.
28461cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
28471cb0ef41Sopenharmony_ci  ConvertReceiverMode convert_mode;
28481cb0ef41Sopenharmony_ci  if (arity == 0) {
28491cb0ef41Sopenharmony_ci    // The thisArg was not provided, use undefined as receiver.
28501cb0ef41Sopenharmony_ci    convert_mode = ConvertReceiverMode::kNullOrUndefined;
28511cb0ef41Sopenharmony_ci    node->ReplaceInput(n.TargetIndex(), n.receiver());
28521cb0ef41Sopenharmony_ci    node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
28531cb0ef41Sopenharmony_ci  } else {
28541cb0ef41Sopenharmony_ci    // Just remove the target, which is the first value input.
28551cb0ef41Sopenharmony_ci    convert_mode = ConvertReceiverMode::kAny;
28561cb0ef41Sopenharmony_ci    node->RemoveInput(n.TargetIndex());
28571cb0ef41Sopenharmony_ci    --arity;
28581cb0ef41Sopenharmony_ci  }
28591cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
28601cb0ef41Sopenharmony_ci      node, javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
28611cb0ef41Sopenharmony_ci                               p.feedback(), convert_mode, p.speculation_mode(),
28621cb0ef41Sopenharmony_ci                               CallFeedbackRelation::kUnrelated));
28631cb0ef41Sopenharmony_ci  // Try to further reduce the JSCall {node}.
28641cb0ef41Sopenharmony_ci  return Changed(node).FollowedBy(ReduceJSCall(node));
28651cb0ef41Sopenharmony_ci}
28661cb0ef41Sopenharmony_ci
28671cb0ef41Sopenharmony_ci// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V)
28681cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) {
28691cb0ef41Sopenharmony_ci  JSCallNode n(node);
28701cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
28711cb0ef41Sopenharmony_ci  Node* object = n.ArgumentOrUndefined(0, jsgraph());
28721cb0ef41Sopenharmony_ci  Node* context = n.context();
28731cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
28741cb0ef41Sopenharmony_ci  Effect effect = n.effect();
28751cb0ef41Sopenharmony_ci  Control control = n.control();
28761cb0ef41Sopenharmony_ci
28771cb0ef41Sopenharmony_ci  // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the
28781cb0ef41Sopenharmony_ci  // stack trace doesn't contain the @@hasInstance call; we have the
28791cb0ef41Sopenharmony_ci  // corresponding bug in the baseline case. Some massaging of the frame
28801cb0ef41Sopenharmony_ci  // state would be necessary here.
28811cb0ef41Sopenharmony_ci
28821cb0ef41Sopenharmony_ci  // Morph this {node} into a JSOrdinaryHasInstance node.
28831cb0ef41Sopenharmony_ci  node->ReplaceInput(0, receiver);
28841cb0ef41Sopenharmony_ci  node->ReplaceInput(1, object);
28851cb0ef41Sopenharmony_ci  node->ReplaceInput(2, context);
28861cb0ef41Sopenharmony_ci  node->ReplaceInput(3, frame_state);
28871cb0ef41Sopenharmony_ci  node->ReplaceInput(4, effect);
28881cb0ef41Sopenharmony_ci  node->ReplaceInput(5, control);
28891cb0ef41Sopenharmony_ci  node->TrimInputCount(6);
28901cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
28911cb0ef41Sopenharmony_ci  return Changed(node);
28921cb0ef41Sopenharmony_ci}
28931cb0ef41Sopenharmony_ci
28941cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
28951cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
28961cb0ef41Sopenharmony_ci
28971cb0ef41Sopenharmony_ci  // Try to determine the {object} map.
28981cb0ef41Sopenharmony_ci  MapInference inference(broker(), object, effect);
28991cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
29001cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& object_maps = inference.GetMaps();
29011cb0ef41Sopenharmony_ci
29021cb0ef41Sopenharmony_ci  MapRef candidate_map = object_maps[0];
29031cb0ef41Sopenharmony_ci  HeapObjectRef candidate_prototype = candidate_map.prototype();
29041cb0ef41Sopenharmony_ci
29051cb0ef41Sopenharmony_ci  // Check if we can constant-fold the {candidate_prototype}.
29061cb0ef41Sopenharmony_ci  for (size_t i = 0; i < object_maps.size(); ++i) {
29071cb0ef41Sopenharmony_ci    MapRef object_map = object_maps[i];
29081cb0ef41Sopenharmony_ci    HeapObjectRef map_prototype = object_map.prototype();
29091cb0ef41Sopenharmony_ci    if (IsSpecialReceiverInstanceType(object_map.instance_type()) ||
29101cb0ef41Sopenharmony_ci        !map_prototype.equals(candidate_prototype)) {
29111cb0ef41Sopenharmony_ci      // We exclude special receivers, like JSProxy or API objects that
29121cb0ef41Sopenharmony_ci      // might require access checks here; we also don't want to deal
29131cb0ef41Sopenharmony_ci      // with hidden prototypes at this point.
29141cb0ef41Sopenharmony_ci      return inference.NoChange();
29151cb0ef41Sopenharmony_ci    }
29161cb0ef41Sopenharmony_ci    // The above check also excludes maps for primitive values, which is
29171cb0ef41Sopenharmony_ci    // important because we are not applying [[ToObject]] here as expected.
29181cb0ef41Sopenharmony_ci    DCHECK(!object_map.IsPrimitiveMap() && object_map.IsJSReceiverMap());
29191cb0ef41Sopenharmony_ci  }
29201cb0ef41Sopenharmony_ci  if (!inference.RelyOnMapsViaStability(dependencies())) {
29211cb0ef41Sopenharmony_ci    return inference.NoChange();
29221cb0ef41Sopenharmony_ci  }
29231cb0ef41Sopenharmony_ci  Node* value = jsgraph()->Constant(candidate_prototype);
29241cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
29251cb0ef41Sopenharmony_ci  return Replace(value);
29261cb0ef41Sopenharmony_ci}
29271cb0ef41Sopenharmony_ci
29281cb0ef41Sopenharmony_ci// ES6 section 19.1.2.11 Object.getPrototypeOf ( O )
29291cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectGetPrototypeOf(Node* node) {
29301cb0ef41Sopenharmony_ci  JSCallNode n(node);
29311cb0ef41Sopenharmony_ci  Node* object = n.ArgumentOrUndefined(0, jsgraph());
29321cb0ef41Sopenharmony_ci  return ReduceObjectGetPrototype(node, object);
29331cb0ef41Sopenharmony_ci}
29341cb0ef41Sopenharmony_ci
29351cb0ef41Sopenharmony_ci// ES section #sec-object.is
29361cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectIs(Node* node) {
29371cb0ef41Sopenharmony_ci  JSCallNode n(node);
29381cb0ef41Sopenharmony_ci  Node* lhs = n.ArgumentOrUndefined(0, jsgraph());
29391cb0ef41Sopenharmony_ci  Node* rhs = n.ArgumentOrUndefined(1, jsgraph());
29401cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->SameValue(), lhs, rhs);
29411cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
29421cb0ef41Sopenharmony_ci  return Replace(value);
29431cb0ef41Sopenharmony_ci}
29441cb0ef41Sopenharmony_ci
29451cb0ef41Sopenharmony_ci// ES6 section B.2.2.1.1 get Object.prototype.__proto__
29461cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
29471cb0ef41Sopenharmony_ci  JSCallNode n(node);
29481cb0ef41Sopenharmony_ci  return ReduceObjectGetPrototype(node, n.receiver());
29491cb0ef41Sopenharmony_ci}
29501cb0ef41Sopenharmony_ci
29511cb0ef41Sopenharmony_ci// ES #sec-object.prototype.hasownproperty
29521cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) {
29531cb0ef41Sopenharmony_ci  JSCallNode call_node(node);
29541cb0ef41Sopenharmony_ci  Node* receiver = call_node.receiver();
29551cb0ef41Sopenharmony_ci  Node* name = call_node.ArgumentOrUndefined(0, jsgraph());
29561cb0ef41Sopenharmony_ci  Effect effect = call_node.effect();
29571cb0ef41Sopenharmony_ci  Control control = call_node.control();
29581cb0ef41Sopenharmony_ci
29591cb0ef41Sopenharmony_ci  // We can optimize a call to Object.prototype.hasOwnProperty if it's being
29601cb0ef41Sopenharmony_ci  // used inside a fast-mode for..in, so for code like this:
29611cb0ef41Sopenharmony_ci  //
29621cb0ef41Sopenharmony_ci  //   for (name in receiver) {
29631cb0ef41Sopenharmony_ci  //     if (receiver.hasOwnProperty(name)) {
29641cb0ef41Sopenharmony_ci  //        ...
29651cb0ef41Sopenharmony_ci  //     }
29661cb0ef41Sopenharmony_ci  //   }
29671cb0ef41Sopenharmony_ci  //
29681cb0ef41Sopenharmony_ci  // If the for..in is in fast-mode, we know that the {receiver} has {name}
29691cb0ef41Sopenharmony_ci  // as own property, otherwise the enumeration wouldn't include it. The graph
29701cb0ef41Sopenharmony_ci  // constructed by the BytecodeGraphBuilder in this case looks like this:
29711cb0ef41Sopenharmony_ci
29721cb0ef41Sopenharmony_ci  // receiver
29731cb0ef41Sopenharmony_ci  //  ^    ^
29741cb0ef41Sopenharmony_ci  //  |    |
29751cb0ef41Sopenharmony_ci  //  |    +-+
29761cb0ef41Sopenharmony_ci  //  |      |
29771cb0ef41Sopenharmony_ci  //  |   JSToObject
29781cb0ef41Sopenharmony_ci  //  |      ^
29791cb0ef41Sopenharmony_ci  //  |      |
29801cb0ef41Sopenharmony_ci  //  |   JSForInNext
29811cb0ef41Sopenharmony_ci  //  |      ^
29821cb0ef41Sopenharmony_ci  //  +----+ |
29831cb0ef41Sopenharmony_ci  //       | |
29841cb0ef41Sopenharmony_ci  //  JSCall[hasOwnProperty]
29851cb0ef41Sopenharmony_ci
29861cb0ef41Sopenharmony_ci  // We can constant-fold the {node} to True in this case, and insert
29871cb0ef41Sopenharmony_ci  // a (potentially redundant) map check to guard the fact that the
29881cb0ef41Sopenharmony_ci  // {receiver} map didn't change since the dominating JSForInNext. This
29891cb0ef41Sopenharmony_ci  // map check is only necessary when TurboFan cannot prove that there
29901cb0ef41Sopenharmony_ci  // is no observable side effect between the {JSForInNext} and the
29911cb0ef41Sopenharmony_ci  // {JSCall} to Object.prototype.hasOwnProperty.
29921cb0ef41Sopenharmony_ci  //
29931cb0ef41Sopenharmony_ci  // Also note that it's safe to look through the {JSToObject}, since the
29941cb0ef41Sopenharmony_ci  // Object.prototype.hasOwnProperty does an implicit ToObject anyway, and
29951cb0ef41Sopenharmony_ci  // these operations are not observable.
29961cb0ef41Sopenharmony_ci  if (name->opcode() == IrOpcode::kJSForInNext) {
29971cb0ef41Sopenharmony_ci    JSForInNextNode n(name);
29981cb0ef41Sopenharmony_ci    if (n.Parameters().mode() != ForInMode::kGeneric) {
29991cb0ef41Sopenharmony_ci      Node* object = n.receiver();
30001cb0ef41Sopenharmony_ci      Node* cache_type = n.cache_type();
30011cb0ef41Sopenharmony_ci      if (object->opcode() == IrOpcode::kJSToObject) {
30021cb0ef41Sopenharmony_ci        object = NodeProperties::GetValueInput(object, 0);
30031cb0ef41Sopenharmony_ci      }
30041cb0ef41Sopenharmony_ci      if (object == receiver) {
30051cb0ef41Sopenharmony_ci        // No need to repeat the map check if we can prove that there's no
30061cb0ef41Sopenharmony_ci        // observable side effect between {effect} and {name].
30071cb0ef41Sopenharmony_ci        if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
30081cb0ef41Sopenharmony_ci          Node* receiver_map = effect =
30091cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
30101cb0ef41Sopenharmony_ci                               receiver, effect, control);
30111cb0ef41Sopenharmony_ci          Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
30121cb0ef41Sopenharmony_ci                                         receiver_map, cache_type);
30131cb0ef41Sopenharmony_ci          effect = graph()->NewNode(
30141cb0ef41Sopenharmony_ci              simplified()->CheckIf(DeoptimizeReason::kWrongMap), check, effect,
30151cb0ef41Sopenharmony_ci              control);
30161cb0ef41Sopenharmony_ci        }
30171cb0ef41Sopenharmony_ci        Node* value = jsgraph()->TrueConstant();
30181cb0ef41Sopenharmony_ci        ReplaceWithValue(node, value, effect, control);
30191cb0ef41Sopenharmony_ci        return Replace(value);
30201cb0ef41Sopenharmony_ci      }
30211cb0ef41Sopenharmony_ci    }
30221cb0ef41Sopenharmony_ci  }
30231cb0ef41Sopenharmony_ci
30241cb0ef41Sopenharmony_ci  return NoChange();
30251cb0ef41Sopenharmony_ci}
30261cb0ef41Sopenharmony_ci
30271cb0ef41Sopenharmony_ci// ES #sec-object.prototype.isprototypeof
30281cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
30291cb0ef41Sopenharmony_ci  JSCallNode n(node);
30301cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
30311cb0ef41Sopenharmony_ci  Node* value = n.ArgumentOrUndefined(0, jsgraph());
30321cb0ef41Sopenharmony_ci  Effect effect = n.effect();
30331cb0ef41Sopenharmony_ci
30341cb0ef41Sopenharmony_ci  // Ensure that the {receiver} is known to be a JSReceiver (so that
30351cb0ef41Sopenharmony_ci  // the ToObject step of Object.prototype.isPrototypeOf is a no-op).
30361cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
30371cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAreJSReceiver()) {
30381cb0ef41Sopenharmony_ci    return NoChange();
30391cb0ef41Sopenharmony_ci  }
30401cb0ef41Sopenharmony_ci
30411cb0ef41Sopenharmony_ci  // We don't check whether {value} is a proper JSReceiver here explicitly,
30421cb0ef41Sopenharmony_ci  // and don't explicitly rule out Primitive {value}s, since all of them
30431cb0ef41Sopenharmony_ci  // have null as their prototype, so the prototype chain walk inside the
30441cb0ef41Sopenharmony_ci  // JSHasInPrototypeChain operator immediately aborts and yields false.
30451cb0ef41Sopenharmony_ci  NodeProperties::ReplaceValueInput(node, value, n.TargetIndex());
30461cb0ef41Sopenharmony_ci  for (int i = node->op()->ValueInputCount(); i > 2; i--) {
30471cb0ef41Sopenharmony_ci    node->RemoveInput(2);
30481cb0ef41Sopenharmony_ci  }
30491cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
30501cb0ef41Sopenharmony_ci  return Changed(node);
30511cb0ef41Sopenharmony_ci}
30521cb0ef41Sopenharmony_ci
30531cb0ef41Sopenharmony_ci// ES6 section 26.1.1 Reflect.apply ( target, thisArgument, argumentsList )
30541cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceReflectApply(Node* node) {
30551cb0ef41Sopenharmony_ci  JSCallNode n(node);
30561cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
30571cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
30581cb0ef41Sopenharmony_ci  // Massage value inputs appropriately.
30591cb0ef41Sopenharmony_ci  STATIC_ASSERT(n.ReceiverIndex() > n.TargetIndex());
30601cb0ef41Sopenharmony_ci  node->RemoveInput(n.ReceiverIndex());
30611cb0ef41Sopenharmony_ci  node->RemoveInput(n.TargetIndex());
30621cb0ef41Sopenharmony_ci  while (arity < 3) {
30631cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
30641cb0ef41Sopenharmony_ci  }
30651cb0ef41Sopenharmony_ci  while (arity-- > 3) {
30661cb0ef41Sopenharmony_ci    node->RemoveInput(arity);
30671cb0ef41Sopenharmony_ci  }
30681cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
30691cb0ef41Sopenharmony_ci      node, javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
30701cb0ef41Sopenharmony_ci                                            p.speculation_mode(),
30711cb0ef41Sopenharmony_ci                                            CallFeedbackRelation::kUnrelated));
30721cb0ef41Sopenharmony_ci  return Changed(node).FollowedBy(ReduceJSCallWithArrayLike(node));
30731cb0ef41Sopenharmony_ci}
30741cb0ef41Sopenharmony_ci
30751cb0ef41Sopenharmony_ci// ES6 section 26.1.2 Reflect.construct ( target, argumentsList [, newTarget] )
30761cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceReflectConstruct(Node* node) {
30771cb0ef41Sopenharmony_ci  JSCallNode n(node);
30781cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
30791cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
30801cb0ef41Sopenharmony_ci  // Massage value inputs appropriately.
30811cb0ef41Sopenharmony_ci  Node* arg_target = n.ArgumentOrUndefined(0, jsgraph());
30821cb0ef41Sopenharmony_ci  Node* arg_argument_list = n.ArgumentOrUndefined(1, jsgraph());
30831cb0ef41Sopenharmony_ci  Node* arg_new_target = n.ArgumentOr(2, arg_target);
30841cb0ef41Sopenharmony_ci
30851cb0ef41Sopenharmony_ci  STATIC_ASSERT(n.ReceiverIndex() > n.TargetIndex());
30861cb0ef41Sopenharmony_ci  node->RemoveInput(n.ReceiverIndex());
30871cb0ef41Sopenharmony_ci  node->RemoveInput(n.TargetIndex());
30881cb0ef41Sopenharmony_ci
30891cb0ef41Sopenharmony_ci  // TODO(jgruber): This pattern essentially ensures that we have the correct
30901cb0ef41Sopenharmony_ci  // number of inputs for a given argument count. Wrap it in a helper function.
30911cb0ef41Sopenharmony_ci  STATIC_ASSERT(JSConstructNode::FirstArgumentIndex() == 2);
30921cb0ef41Sopenharmony_ci  while (arity < 3) {
30931cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
30941cb0ef41Sopenharmony_ci  }
30951cb0ef41Sopenharmony_ci  while (arity-- > 3) {
30961cb0ef41Sopenharmony_ci    node->RemoveInput(arity);
30971cb0ef41Sopenharmony_ci  }
30981cb0ef41Sopenharmony_ci
30991cb0ef41Sopenharmony_ci  STATIC_ASSERT(JSConstructNode::TargetIndex() == 0);
31001cb0ef41Sopenharmony_ci  STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
31011cb0ef41Sopenharmony_ci  STATIC_ASSERT(JSConstructNode::kFeedbackVectorIsLastInput);
31021cb0ef41Sopenharmony_ci  node->ReplaceInput(JSConstructNode::TargetIndex(), arg_target);
31031cb0ef41Sopenharmony_ci  node->ReplaceInput(JSConstructNode::NewTargetIndex(), arg_new_target);
31041cb0ef41Sopenharmony_ci  node->ReplaceInput(JSConstructNode::ArgumentIndex(0), arg_argument_list);
31051cb0ef41Sopenharmony_ci
31061cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
31071cb0ef41Sopenharmony_ci      node, javascript()->ConstructWithArrayLike(p.frequency(), p.feedback()));
31081cb0ef41Sopenharmony_ci  return Changed(node).FollowedBy(ReduceJSConstructWithArrayLike(node));
31091cb0ef41Sopenharmony_ci}
31101cb0ef41Sopenharmony_ci
31111cb0ef41Sopenharmony_ci// ES6 section 26.1.7 Reflect.getPrototypeOf ( target )
31121cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
31131cb0ef41Sopenharmony_ci  JSCallNode n(node);
31141cb0ef41Sopenharmony_ci  Node* target = n.ArgumentOrUndefined(0, jsgraph());
31151cb0ef41Sopenharmony_ci  return ReduceObjectGetPrototype(node, target);
31161cb0ef41Sopenharmony_ci}
31171cb0ef41Sopenharmony_ci
31181cb0ef41Sopenharmony_ci// ES6 section #sec-object.create Object.create(proto, properties)
31191cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceObjectCreate(Node* node) {
31201cb0ef41Sopenharmony_ci  JSCallNode n(node);
31211cb0ef41Sopenharmony_ci  Node* properties = n.ArgumentOrUndefined(1, jsgraph());
31221cb0ef41Sopenharmony_ci  if (properties != jsgraph()->UndefinedConstant()) return NoChange();
31231cb0ef41Sopenharmony_ci
31241cb0ef41Sopenharmony_ci  Node* context = n.context();
31251cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
31261cb0ef41Sopenharmony_ci  Effect effect = n.effect();
31271cb0ef41Sopenharmony_ci  Control control = n.control();
31281cb0ef41Sopenharmony_ci  Node* prototype = n.ArgumentOrUndefined(0, jsgraph());
31291cb0ef41Sopenharmony_ci  node->ReplaceInput(0, prototype);
31301cb0ef41Sopenharmony_ci  node->ReplaceInput(1, context);
31311cb0ef41Sopenharmony_ci  node->ReplaceInput(2, frame_state);
31321cb0ef41Sopenharmony_ci  node->ReplaceInput(3, effect);
31331cb0ef41Sopenharmony_ci  node->ReplaceInput(4, control);
31341cb0ef41Sopenharmony_ci  node->TrimInputCount(5);
31351cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->CreateObject());
31361cb0ef41Sopenharmony_ci  return Changed(node);
31371cb0ef41Sopenharmony_ci}
31381cb0ef41Sopenharmony_ci
31391cb0ef41Sopenharmony_ci// ES section #sec-reflect.get
31401cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceReflectGet(Node* node) {
31411cb0ef41Sopenharmony_ci  JSCallNode n(node);
31421cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
31431cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
31441cb0ef41Sopenharmony_ci  if (arity != 2) return NoChange();
31451cb0ef41Sopenharmony_ci  Node* target = n.Argument(0);
31461cb0ef41Sopenharmony_ci  Node* key = n.Argument(1);
31471cb0ef41Sopenharmony_ci  Node* context = n.context();
31481cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
31491cb0ef41Sopenharmony_ci  Effect effect = n.effect();
31501cb0ef41Sopenharmony_ci  Control control = n.control();
31511cb0ef41Sopenharmony_ci
31521cb0ef41Sopenharmony_ci  // Check whether {target} is a JSReceiver.
31531cb0ef41Sopenharmony_ci  Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
31541cb0ef41Sopenharmony_ci  Node* branch =
31551cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
31561cb0ef41Sopenharmony_ci
31571cb0ef41Sopenharmony_ci  // Throw an appropriate TypeError if the {target} is not a JSReceiver.
31581cb0ef41Sopenharmony_ci  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
31591cb0ef41Sopenharmony_ci  Node* efalse = effect;
31601cb0ef41Sopenharmony_ci  {
31611cb0ef41Sopenharmony_ci    if_false = efalse = graph()->NewNode(
31621cb0ef41Sopenharmony_ci        javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
31631cb0ef41Sopenharmony_ci        jsgraph()->Constant(
31641cb0ef41Sopenharmony_ci            static_cast<int>(MessageTemplate::kCalledOnNonObject)),
31651cb0ef41Sopenharmony_ci        jsgraph()->HeapConstant(factory()->ReflectGet_string()), context,
31661cb0ef41Sopenharmony_ci        frame_state, efalse, if_false);
31671cb0ef41Sopenharmony_ci  }
31681cb0ef41Sopenharmony_ci
31691cb0ef41Sopenharmony_ci  // Otherwise just use the existing GetPropertyStub.
31701cb0ef41Sopenharmony_ci  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
31711cb0ef41Sopenharmony_ci  Node* etrue = effect;
31721cb0ef41Sopenharmony_ci  Node* vtrue;
31731cb0ef41Sopenharmony_ci  {
31741cb0ef41Sopenharmony_ci    Callable callable = Builtins::CallableFor(isolate(), Builtin::kGetProperty);
31751cb0ef41Sopenharmony_ci    auto call_descriptor = Linkage::GetStubCallDescriptor(
31761cb0ef41Sopenharmony_ci        graph()->zone(), callable.descriptor(),
31771cb0ef41Sopenharmony_ci        callable.descriptor().GetStackParameterCount(),
31781cb0ef41Sopenharmony_ci        CallDescriptor::kNeedsFrameState, Operator::kNoProperties);
31791cb0ef41Sopenharmony_ci    Node* stub_code = jsgraph()->HeapConstant(callable.code());
31801cb0ef41Sopenharmony_ci    vtrue = etrue = if_true =
31811cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Call(call_descriptor), stub_code, target,
31821cb0ef41Sopenharmony_ci                         key, context, frame_state, etrue, if_true);
31831cb0ef41Sopenharmony_ci  }
31841cb0ef41Sopenharmony_ci
31851cb0ef41Sopenharmony_ci  // Rewire potential exception edges.
31861cb0ef41Sopenharmony_ci  Node* on_exception = nullptr;
31871cb0ef41Sopenharmony_ci  if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
31881cb0ef41Sopenharmony_ci    // Create appropriate {IfException} and {IfSuccess} nodes.
31891cb0ef41Sopenharmony_ci    Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
31901cb0ef41Sopenharmony_ci    if_true = graph()->NewNode(common()->IfSuccess(), if_true);
31911cb0ef41Sopenharmony_ci    Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
31921cb0ef41Sopenharmony_ci    if_false = graph()->NewNode(common()->IfSuccess(), if_false);
31931cb0ef41Sopenharmony_ci
31941cb0ef41Sopenharmony_ci    // Join the exception edges.
31951cb0ef41Sopenharmony_ci    Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
31961cb0ef41Sopenharmony_ci    Node* ephi =
31971cb0ef41Sopenharmony_ci        graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
31981cb0ef41Sopenharmony_ci    Node* phi =
31991cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
32001cb0ef41Sopenharmony_ci                         extrue, exfalse, merge);
32011cb0ef41Sopenharmony_ci    ReplaceWithValue(on_exception, phi, ephi, merge);
32021cb0ef41Sopenharmony_ci  }
32031cb0ef41Sopenharmony_ci
32041cb0ef41Sopenharmony_ci  // Connect the throwing path to end.
32051cb0ef41Sopenharmony_ci  if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
32061cb0ef41Sopenharmony_ci  NodeProperties::MergeControlToEnd(graph(), common(), if_false);
32071cb0ef41Sopenharmony_ci
32081cb0ef41Sopenharmony_ci  // Continue on the regular path.
32091cb0ef41Sopenharmony_ci  ReplaceWithValue(node, vtrue, etrue, if_true);
32101cb0ef41Sopenharmony_ci  return Changed(vtrue);
32111cb0ef41Sopenharmony_ci}
32121cb0ef41Sopenharmony_ci
32131cb0ef41Sopenharmony_ci// ES section #sec-reflect.has
32141cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceReflectHas(Node* node) {
32151cb0ef41Sopenharmony_ci  JSCallNode n(node);
32161cb0ef41Sopenharmony_ci  Node* target = n.ArgumentOrUndefined(0, jsgraph());
32171cb0ef41Sopenharmony_ci  Node* key = n.ArgumentOrUndefined(1, jsgraph());
32181cb0ef41Sopenharmony_ci  Node* context = n.context();
32191cb0ef41Sopenharmony_ci  Effect effect = n.effect();
32201cb0ef41Sopenharmony_ci  Control control = n.control();
32211cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
32221cb0ef41Sopenharmony_ci
32231cb0ef41Sopenharmony_ci  // Check whether {target} is a JSReceiver.
32241cb0ef41Sopenharmony_ci  Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
32251cb0ef41Sopenharmony_ci  Node* branch =
32261cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
32271cb0ef41Sopenharmony_ci
32281cb0ef41Sopenharmony_ci  // Throw an appropriate TypeError if the {target} is not a JSReceiver.
32291cb0ef41Sopenharmony_ci  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
32301cb0ef41Sopenharmony_ci  Node* efalse = effect;
32311cb0ef41Sopenharmony_ci  {
32321cb0ef41Sopenharmony_ci    if_false = efalse = graph()->NewNode(
32331cb0ef41Sopenharmony_ci        javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
32341cb0ef41Sopenharmony_ci        jsgraph()->Constant(
32351cb0ef41Sopenharmony_ci            static_cast<int>(MessageTemplate::kCalledOnNonObject)),
32361cb0ef41Sopenharmony_ci        jsgraph()->HeapConstant(factory()->ReflectHas_string()), context,
32371cb0ef41Sopenharmony_ci        frame_state, efalse, if_false);
32381cb0ef41Sopenharmony_ci  }
32391cb0ef41Sopenharmony_ci
32401cb0ef41Sopenharmony_ci  // Otherwise just use the existing {JSHasProperty} logic.
32411cb0ef41Sopenharmony_ci  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
32421cb0ef41Sopenharmony_ci  Node* etrue = effect;
32431cb0ef41Sopenharmony_ci  Node* vtrue;
32441cb0ef41Sopenharmony_ci  {
32451cb0ef41Sopenharmony_ci    // TODO(magardn): collect feedback so this can be optimized
32461cb0ef41Sopenharmony_ci    vtrue = etrue = if_true = graph()->NewNode(
32471cb0ef41Sopenharmony_ci        javascript()->HasProperty(FeedbackSource()), target, key,
32481cb0ef41Sopenharmony_ci        jsgraph()->UndefinedConstant(), context, frame_state, etrue, if_true);
32491cb0ef41Sopenharmony_ci  }
32501cb0ef41Sopenharmony_ci
32511cb0ef41Sopenharmony_ci  // Rewire potential exception edges.
32521cb0ef41Sopenharmony_ci  Node* on_exception = nullptr;
32531cb0ef41Sopenharmony_ci  if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
32541cb0ef41Sopenharmony_ci    // Create appropriate {IfException} and {IfSuccess} nodes.
32551cb0ef41Sopenharmony_ci    Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
32561cb0ef41Sopenharmony_ci    if_true = graph()->NewNode(common()->IfSuccess(), if_true);
32571cb0ef41Sopenharmony_ci    Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
32581cb0ef41Sopenharmony_ci    if_false = graph()->NewNode(common()->IfSuccess(), if_false);
32591cb0ef41Sopenharmony_ci
32601cb0ef41Sopenharmony_ci    // Join the exception edges.
32611cb0ef41Sopenharmony_ci    Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
32621cb0ef41Sopenharmony_ci    Node* ephi =
32631cb0ef41Sopenharmony_ci        graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
32641cb0ef41Sopenharmony_ci    Node* phi =
32651cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
32661cb0ef41Sopenharmony_ci                         extrue, exfalse, merge);
32671cb0ef41Sopenharmony_ci    ReplaceWithValue(on_exception, phi, ephi, merge);
32681cb0ef41Sopenharmony_ci  }
32691cb0ef41Sopenharmony_ci
32701cb0ef41Sopenharmony_ci  // Connect the throwing path to end.
32711cb0ef41Sopenharmony_ci  if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
32721cb0ef41Sopenharmony_ci  NodeProperties::MergeControlToEnd(graph(), common(), if_false);
32731cb0ef41Sopenharmony_ci
32741cb0ef41Sopenharmony_ci  // Continue on the regular path.
32751cb0ef41Sopenharmony_ci  ReplaceWithValue(node, vtrue, etrue, if_true);
32761cb0ef41Sopenharmony_ci  return Changed(vtrue);
32771cb0ef41Sopenharmony_ci}
32781cb0ef41Sopenharmony_ci
32791cb0ef41Sopenharmony_cinamespace {
32801cb0ef41Sopenharmony_ci
32811cb0ef41Sopenharmony_cibool CanInlineArrayIteratingBuiltin(JSHeapBroker* broker,
32821cb0ef41Sopenharmony_ci                                    ZoneVector<MapRef> const& receiver_maps,
32831cb0ef41Sopenharmony_ci                                    ElementsKind* kind_return) {
32841cb0ef41Sopenharmony_ci  DCHECK_NE(0, receiver_maps.size());
32851cb0ef41Sopenharmony_ci  *kind_return = receiver_maps[0].elements_kind();
32861cb0ef41Sopenharmony_ci  for (const MapRef& map : receiver_maps) {
32871cb0ef41Sopenharmony_ci    if (!map.supports_fast_array_iteration() ||
32881cb0ef41Sopenharmony_ci        !UnionElementsKindUptoSize(kind_return, map.elements_kind())) {
32891cb0ef41Sopenharmony_ci      return false;
32901cb0ef41Sopenharmony_ci    }
32911cb0ef41Sopenharmony_ci  }
32921cb0ef41Sopenharmony_ci  return true;
32931cb0ef41Sopenharmony_ci}
32941cb0ef41Sopenharmony_ci
32951cb0ef41Sopenharmony_cibool CanInlineArrayResizingBuiltin(JSHeapBroker* broker,
32961cb0ef41Sopenharmony_ci                                   ZoneVector<MapRef> const& receiver_maps,
32971cb0ef41Sopenharmony_ci                                   std::vector<ElementsKind>* kinds,
32981cb0ef41Sopenharmony_ci                                   bool builtin_is_push = false) {
32991cb0ef41Sopenharmony_ci  DCHECK_NE(0, receiver_maps.size());
33001cb0ef41Sopenharmony_ci  for (const MapRef& map : receiver_maps) {
33011cb0ef41Sopenharmony_ci    if (!map.supports_fast_array_resize()) return false;
33021cb0ef41Sopenharmony_ci    // TODO(turbofan): We should also handle fast holey double elements once
33031cb0ef41Sopenharmony_ci    // we got the hole NaN mess sorted out in TurboFan/V8.
33041cb0ef41Sopenharmony_ci    if (map.elements_kind() == HOLEY_DOUBLE_ELEMENTS && !builtin_is_push) {
33051cb0ef41Sopenharmony_ci      return false;
33061cb0ef41Sopenharmony_ci    }
33071cb0ef41Sopenharmony_ci    ElementsKind current_kind = map.elements_kind();
33081cb0ef41Sopenharmony_ci    auto kind_ptr = kinds->data();
33091cb0ef41Sopenharmony_ci    size_t i;
33101cb0ef41Sopenharmony_ci    for (i = 0; i < kinds->size(); i++, kind_ptr++) {
33111cb0ef41Sopenharmony_ci      if (UnionElementsKindUptoPackedness(kind_ptr, current_kind)) {
33121cb0ef41Sopenharmony_ci        break;
33131cb0ef41Sopenharmony_ci      }
33141cb0ef41Sopenharmony_ci    }
33151cb0ef41Sopenharmony_ci    if (i == kinds->size()) kinds->push_back(current_kind);
33161cb0ef41Sopenharmony_ci  }
33171cb0ef41Sopenharmony_ci  return true;
33181cb0ef41Sopenharmony_ci}
33191cb0ef41Sopenharmony_ci
33201cb0ef41Sopenharmony_ci// Wraps common setup code for iterating array builtins.
33211cb0ef41Sopenharmony_ciclass IteratingArrayBuiltinHelper {
33221cb0ef41Sopenharmony_ci public:
33231cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper(Node* node, JSHeapBroker* broker,
33241cb0ef41Sopenharmony_ci                              JSGraph* jsgraph,
33251cb0ef41Sopenharmony_ci                              CompilationDependencies* dependencies)
33261cb0ef41Sopenharmony_ci      : receiver_(NodeProperties::GetValueInput(node, 1)),
33271cb0ef41Sopenharmony_ci        effect_(NodeProperties::GetEffectInput(node)),
33281cb0ef41Sopenharmony_ci        control_(NodeProperties::GetControlInput(node)),
33291cb0ef41Sopenharmony_ci        inference_(broker, receiver_, effect_) {
33301cb0ef41Sopenharmony_ci    if (!FLAG_turbo_inline_array_builtins) return;
33311cb0ef41Sopenharmony_ci
33321cb0ef41Sopenharmony_ci    DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
33331cb0ef41Sopenharmony_ci    const CallParameters& p = CallParametersOf(node->op());
33341cb0ef41Sopenharmony_ci    if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
33351cb0ef41Sopenharmony_ci      return;
33361cb0ef41Sopenharmony_ci    }
33371cb0ef41Sopenharmony_ci
33381cb0ef41Sopenharmony_ci    // Try to determine the {receiver} map.
33391cb0ef41Sopenharmony_ci    if (!inference_.HaveMaps()) return;
33401cb0ef41Sopenharmony_ci    ZoneVector<MapRef> const& receiver_maps = inference_.GetMaps();
33411cb0ef41Sopenharmony_ci
33421cb0ef41Sopenharmony_ci    if (!CanInlineArrayIteratingBuiltin(broker, receiver_maps,
33431cb0ef41Sopenharmony_ci                                        &elements_kind_)) {
33441cb0ef41Sopenharmony_ci      return;
33451cb0ef41Sopenharmony_ci    }
33461cb0ef41Sopenharmony_ci
33471cb0ef41Sopenharmony_ci    // TODO(jgruber): May only be needed for holey elements kinds.
33481cb0ef41Sopenharmony_ci    if (!dependencies->DependOnNoElementsProtector()) return;
33491cb0ef41Sopenharmony_ci
33501cb0ef41Sopenharmony_ci    has_stability_dependency_ = inference_.RelyOnMapsPreferStability(
33511cb0ef41Sopenharmony_ci        dependencies, jsgraph, &effect_, control_, p.feedback());
33521cb0ef41Sopenharmony_ci
33531cb0ef41Sopenharmony_ci    can_reduce_ = true;
33541cb0ef41Sopenharmony_ci  }
33551cb0ef41Sopenharmony_ci
33561cb0ef41Sopenharmony_ci  bool can_reduce() const { return can_reduce_; }
33571cb0ef41Sopenharmony_ci  bool has_stability_dependency() const { return has_stability_dependency_; }
33581cb0ef41Sopenharmony_ci  Effect effect() const { return effect_; }
33591cb0ef41Sopenharmony_ci  Control control() const { return control_; }
33601cb0ef41Sopenharmony_ci  MapInference* inference() { return &inference_; }
33611cb0ef41Sopenharmony_ci  ElementsKind elements_kind() const { return elements_kind_; }
33621cb0ef41Sopenharmony_ci
33631cb0ef41Sopenharmony_ci private:
33641cb0ef41Sopenharmony_ci  bool can_reduce_ = false;
33651cb0ef41Sopenharmony_ci  bool has_stability_dependency_ = false;
33661cb0ef41Sopenharmony_ci  Node* receiver_;
33671cb0ef41Sopenharmony_ci  Effect effect_;
33681cb0ef41Sopenharmony_ci  Control control_;
33691cb0ef41Sopenharmony_ci  MapInference inference_;
33701cb0ef41Sopenharmony_ci  ElementsKind elements_kind_;
33711cb0ef41Sopenharmony_ci};
33721cb0ef41Sopenharmony_ci
33731cb0ef41Sopenharmony_ci}  // namespace
33741cb0ef41Sopenharmony_ci
33751cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayForEach(
33761cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
33771cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
33781cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
33791cb0ef41Sopenharmony_ci
33801cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
33811cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
33821cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeForEach(
33831cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared);
33841cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
33851cb0ef41Sopenharmony_ci}
33861cb0ef41Sopenharmony_ci
33871cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayReduce(
33881cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
33891cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
33901cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
33911cb0ef41Sopenharmony_ci
33921cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
33931cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
33941cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeReduce(
33951cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(),
33961cb0ef41Sopenharmony_ci      ArrayReduceDirection::kLeft, shared);
33971cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
33981cb0ef41Sopenharmony_ci}
33991cb0ef41Sopenharmony_ci
34001cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayReduceRight(
34011cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
34021cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34031cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34041cb0ef41Sopenharmony_ci
34051cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
34061cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
34071cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeReduce(
34081cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(),
34091cb0ef41Sopenharmony_ci      ArrayReduceDirection::kRight, shared);
34101cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
34111cb0ef41Sopenharmony_ci}
34121cb0ef41Sopenharmony_ci
34131cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayMap(Node* node,
34141cb0ef41Sopenharmony_ci                                        const SharedFunctionInfoRef& shared) {
34151cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34161cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34171cb0ef41Sopenharmony_ci
34181cb0ef41Sopenharmony_ci  // Calls CreateArray and thus requires this additional protector dependency.
34191cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnArraySpeciesProtector()) {
34201cb0ef41Sopenharmony_ci    return h.inference()->NoChange();
34211cb0ef41Sopenharmony_ci  }
34221cb0ef41Sopenharmony_ci
34231cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
34241cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
34251cb0ef41Sopenharmony_ci
34261cb0ef41Sopenharmony_ci  TNode<Object> subgraph =
34271cb0ef41Sopenharmony_ci      a.ReduceArrayPrototypeMap(h.inference(), h.has_stability_dependency(),
34281cb0ef41Sopenharmony_ci                                h.elements_kind(), shared, native_context());
34291cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
34301cb0ef41Sopenharmony_ci}
34311cb0ef41Sopenharmony_ci
34321cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayFilter(
34331cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
34341cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34351cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34361cb0ef41Sopenharmony_ci
34371cb0ef41Sopenharmony_ci  // Calls CreateArray and thus requires this additional protector dependency.
34381cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnArraySpeciesProtector()) {
34391cb0ef41Sopenharmony_ci    return h.inference()->NoChange();
34401cb0ef41Sopenharmony_ci  }
34411cb0ef41Sopenharmony_ci
34421cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
34431cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
34441cb0ef41Sopenharmony_ci
34451cb0ef41Sopenharmony_ci  TNode<Object> subgraph =
34461cb0ef41Sopenharmony_ci      a.ReduceArrayPrototypeFilter(h.inference(), h.has_stability_dependency(),
34471cb0ef41Sopenharmony_ci                                   h.elements_kind(), shared, native_context());
34481cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
34491cb0ef41Sopenharmony_ci}
34501cb0ef41Sopenharmony_ci
34511cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayFind(Node* node,
34521cb0ef41Sopenharmony_ci                                         const SharedFunctionInfoRef& shared) {
34531cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34541cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34551cb0ef41Sopenharmony_ci
34561cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
34571cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
34581cb0ef41Sopenharmony_ci
34591cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeFind(
34601cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
34611cb0ef41Sopenharmony_ci      native_context(), ArrayFindVariant::kFind);
34621cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
34631cb0ef41Sopenharmony_ci}
34641cb0ef41Sopenharmony_ci
34651cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayFindIndex(
34661cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
34671cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34681cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34691cb0ef41Sopenharmony_ci
34701cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
34711cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
34721cb0ef41Sopenharmony_ci
34731cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeFind(
34741cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
34751cb0ef41Sopenharmony_ci      native_context(), ArrayFindVariant::kFindIndex);
34761cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
34771cb0ef41Sopenharmony_ci}
34781cb0ef41Sopenharmony_ci
34791cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayEvery(Node* node,
34801cb0ef41Sopenharmony_ci                                          const SharedFunctionInfoRef& shared) {
34811cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34821cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34831cb0ef41Sopenharmony_ci
34841cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
34851cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
34861cb0ef41Sopenharmony_ci
34871cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeEverySome(
34881cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
34891cb0ef41Sopenharmony_ci      native_context(), ArrayEverySomeVariant::kEvery);
34901cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
34911cb0ef41Sopenharmony_ci}
34921cb0ef41Sopenharmony_ci
34931cb0ef41Sopenharmony_ci// ES7 Array.prototype.inludes(searchElement[, fromIndex])
34941cb0ef41Sopenharmony_ci// #sec-array.prototype.includes
34951cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayIncludes(Node* node) {
34961cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
34971cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
34981cb0ef41Sopenharmony_ci
34991cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
35001cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
35011cb0ef41Sopenharmony_ci
35021cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeIndexOfIncludes(
35031cb0ef41Sopenharmony_ci      h.elements_kind(), ArrayIndexOfIncludesVariant::kIncludes);
35041cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
35051cb0ef41Sopenharmony_ci}
35061cb0ef41Sopenharmony_ci
35071cb0ef41Sopenharmony_ci// ES6 Array.prototype.indexOf(searchElement[, fromIndex])
35081cb0ef41Sopenharmony_ci// #sec-array.prototype.indexof
35091cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayIndexOf(Node* node) {
35101cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
35111cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
35121cb0ef41Sopenharmony_ci
35131cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
35141cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
35151cb0ef41Sopenharmony_ci
35161cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeIndexOfIncludes(
35171cb0ef41Sopenharmony_ci      h.elements_kind(), ArrayIndexOfIncludesVariant::kIndexOf);
35181cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
35191cb0ef41Sopenharmony_ci}
35201cb0ef41Sopenharmony_ci
35211cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArraySome(Node* node,
35221cb0ef41Sopenharmony_ci                                         const SharedFunctionInfoRef& shared) {
35231cb0ef41Sopenharmony_ci  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
35241cb0ef41Sopenharmony_ci  if (!h.can_reduce()) return h.inference()->NoChange();
35251cb0ef41Sopenharmony_ci
35261cb0ef41Sopenharmony_ci  IteratingArrayBuiltinReducerAssembler a(this, node);
35271cb0ef41Sopenharmony_ci  a.InitializeEffectControl(h.effect(), h.control());
35281cb0ef41Sopenharmony_ci
35291cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReduceArrayPrototypeEverySome(
35301cb0ef41Sopenharmony_ci      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
35311cb0ef41Sopenharmony_ci      native_context(), ArrayEverySomeVariant::kSome);
35321cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
35331cb0ef41Sopenharmony_ci}
35341cb0ef41Sopenharmony_ci
35351cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
35361cb0ef41Sopenharmony_ci
35371cb0ef41Sopenharmony_cinamespace {
35381cb0ef41Sopenharmony_ci
35391cb0ef41Sopenharmony_cibool CanInlineJSToWasmCall(const wasm::FunctionSig* wasm_signature) {
35401cb0ef41Sopenharmony_ci  if (wasm_signature->return_count() > 1) {
35411cb0ef41Sopenharmony_ci    return false;
35421cb0ef41Sopenharmony_ci  }
35431cb0ef41Sopenharmony_ci
35441cb0ef41Sopenharmony_ci  for (auto type : wasm_signature->all()) {
35451cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_32_BIT)
35461cb0ef41Sopenharmony_ci    if (type == wasm::kWasmI64) return false;
35471cb0ef41Sopenharmony_ci#endif
35481cb0ef41Sopenharmony_ci    if (type != wasm::kWasmI32 && type != wasm::kWasmI64 &&
35491cb0ef41Sopenharmony_ci        type != wasm::kWasmF32 && type != wasm::kWasmF64) {
35501cb0ef41Sopenharmony_ci      return false;
35511cb0ef41Sopenharmony_ci    }
35521cb0ef41Sopenharmony_ci  }
35531cb0ef41Sopenharmony_ci
35541cb0ef41Sopenharmony_ci  return true;
35551cb0ef41Sopenharmony_ci}
35561cb0ef41Sopenharmony_ci
35571cb0ef41Sopenharmony_ci}  // namespace
35581cb0ef41Sopenharmony_ci
35591cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceCallWasmFunction(
35601cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
35611cb0ef41Sopenharmony_ci  DCHECK(flags() & kInlineJSToWasmCalls);
35621cb0ef41Sopenharmony_ci
35631cb0ef41Sopenharmony_ci  JSCallNode n(node);
35641cb0ef41Sopenharmony_ci  const CallParameters& p = n.Parameters();
35651cb0ef41Sopenharmony_ci
35661cb0ef41Sopenharmony_ci  // Avoid deoptimization loops
35671cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
35681cb0ef41Sopenharmony_ci    return NoChange();
35691cb0ef41Sopenharmony_ci  }
35701cb0ef41Sopenharmony_ci
35711cb0ef41Sopenharmony_ci  const wasm::FunctionSig* wasm_signature = shared.wasm_function_signature();
35721cb0ef41Sopenharmony_ci  if (!CanInlineJSToWasmCall(wasm_signature)) {
35731cb0ef41Sopenharmony_ci    return NoChange();
35741cb0ef41Sopenharmony_ci  }
35751cb0ef41Sopenharmony_ci
35761cb0ef41Sopenharmony_ci  // Signal TurboFan that it should run the 'wasm-inlining' phase.
35771cb0ef41Sopenharmony_ci  has_wasm_calls_ = true;
35781cb0ef41Sopenharmony_ci
35791cb0ef41Sopenharmony_ci  const wasm::WasmModule* wasm_module = shared.wasm_module();
35801cb0ef41Sopenharmony_ci  const Operator* op =
35811cb0ef41Sopenharmony_ci      javascript()->CallWasm(wasm_module, wasm_signature, p.feedback());
35821cb0ef41Sopenharmony_ci
35831cb0ef41Sopenharmony_ci  // Remove additional inputs
35841cb0ef41Sopenharmony_ci  size_t actual_arity = n.ArgumentCount();
35851cb0ef41Sopenharmony_ci  DCHECK(JSCallNode::kFeedbackVectorIsLastInput);
35861cb0ef41Sopenharmony_ci  DCHECK_EQ(actual_arity + JSWasmCallNode::kExtraInputCount - 1,
35871cb0ef41Sopenharmony_ci            n.FeedbackVectorIndex());
35881cb0ef41Sopenharmony_ci  size_t expected_arity = wasm_signature->parameter_count();
35891cb0ef41Sopenharmony_ci
35901cb0ef41Sopenharmony_ci  while (actual_arity > expected_arity) {
35911cb0ef41Sopenharmony_ci    int removal_index =
35921cb0ef41Sopenharmony_ci        static_cast<int>(n.FirstArgumentIndex() + expected_arity);
35931cb0ef41Sopenharmony_ci    DCHECK_LT(removal_index, static_cast<int>(node->InputCount()));
35941cb0ef41Sopenharmony_ci    node->RemoveInput(removal_index);
35951cb0ef41Sopenharmony_ci    actual_arity--;
35961cb0ef41Sopenharmony_ci  }
35971cb0ef41Sopenharmony_ci
35981cb0ef41Sopenharmony_ci  // Add missing inputs
35991cb0ef41Sopenharmony_ci  while (actual_arity < expected_arity) {
36001cb0ef41Sopenharmony_ci    int insertion_index = n.ArgumentIndex(n.ArgumentCount());
36011cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), insertion_index,
36021cb0ef41Sopenharmony_ci                      jsgraph()->UndefinedConstant());
36031cb0ef41Sopenharmony_ci    actual_arity++;
36041cb0ef41Sopenharmony_ci  }
36051cb0ef41Sopenharmony_ci
36061cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, op);
36071cb0ef41Sopenharmony_ci  return Changed(node);
36081cb0ef41Sopenharmony_ci}
36091cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
36101cb0ef41Sopenharmony_ci
36111cb0ef41Sopenharmony_ci// Given a FunctionTemplateInfo, checks whether the fast API call can be
36121cb0ef41Sopenharmony_ci// optimized, applying the initial step of the overload resolution algorithm:
36131cb0ef41Sopenharmony_ci// Given an overload set function_template_info.c_signatures, and a list of
36141cb0ef41Sopenharmony_ci// arguments of size argc:
36151cb0ef41Sopenharmony_ci// 1. Let max_arg be the length of the longest type list of the entries in
36161cb0ef41Sopenharmony_ci//    function_template_info.c_signatures.
36171cb0ef41Sopenharmony_ci// 2. Let argc be the size of the arguments list.
36181cb0ef41Sopenharmony_ci// 3. Initialize arg_count = min(max_arg, argc).
36191cb0ef41Sopenharmony_ci// 4. Remove from the set all entries whose type list is not of length
36201cb0ef41Sopenharmony_ci//    arg_count.
36211cb0ef41Sopenharmony_ci// Returns an array with the indexes of the remaining entries in S, which
36221cb0ef41Sopenharmony_ci// represents the set of "optimizable" function overloads.
36231cb0ef41Sopenharmony_ci
36241cb0ef41Sopenharmony_ciFastApiCallFunctionVector CanOptimizeFastCall(
36251cb0ef41Sopenharmony_ci    Zone* zone, const FunctionTemplateInfoRef& function_template_info,
36261cb0ef41Sopenharmony_ci    size_t argc) {
36271cb0ef41Sopenharmony_ci  FastApiCallFunctionVector result(zone);
36281cb0ef41Sopenharmony_ci  if (!FLAG_turbo_fast_api_calls) return result;
36291cb0ef41Sopenharmony_ci
36301cb0ef41Sopenharmony_ci  static constexpr int kReceiver = 1;
36311cb0ef41Sopenharmony_ci
36321cb0ef41Sopenharmony_ci  ZoneVector<Address> functions = function_template_info.c_functions();
36331cb0ef41Sopenharmony_ci  ZoneVector<const CFunctionInfo*> signatures =
36341cb0ef41Sopenharmony_ci      function_template_info.c_signatures();
36351cb0ef41Sopenharmony_ci  const size_t overloads_count = signatures.size();
36361cb0ef41Sopenharmony_ci
36371cb0ef41Sopenharmony_ci  // Calculates the length of the longest type list of the entries in
36381cb0ef41Sopenharmony_ci  // function_template_info.
36391cb0ef41Sopenharmony_ci  size_t max_arg = 0;
36401cb0ef41Sopenharmony_ci  for (size_t i = 0; i < overloads_count; i++) {
36411cb0ef41Sopenharmony_ci    const CFunctionInfo* c_signature = signatures[i];
36421cb0ef41Sopenharmony_ci    // C arguments should include the receiver at index 0.
36431cb0ef41Sopenharmony_ci    DCHECK_GE(c_signature->ArgumentCount(), kReceiver);
36441cb0ef41Sopenharmony_ci    const size_t len = c_signature->ArgumentCount() - kReceiver;
36451cb0ef41Sopenharmony_ci    if (len > max_arg) max_arg = len;
36461cb0ef41Sopenharmony_ci  }
36471cb0ef41Sopenharmony_ci  const size_t arg_count = std::min(max_arg, argc);
36481cb0ef41Sopenharmony_ci
36491cb0ef41Sopenharmony_ci  // Only considers entries whose type list length matches arg_count.
36501cb0ef41Sopenharmony_ci  for (size_t i = 0; i < overloads_count; i++) {
36511cb0ef41Sopenharmony_ci    const CFunctionInfo* c_signature = signatures[i];
36521cb0ef41Sopenharmony_ci    const size_t len = c_signature->ArgumentCount() - kReceiver;
36531cb0ef41Sopenharmony_ci    bool optimize_to_fast_call = (len == arg_count);
36541cb0ef41Sopenharmony_ci
36551cb0ef41Sopenharmony_ci    optimize_to_fast_call =
36561cb0ef41Sopenharmony_ci        optimize_to_fast_call &&
36571cb0ef41Sopenharmony_ci        fast_api_call::CanOptimizeFastSignature(c_signature);
36581cb0ef41Sopenharmony_ci
36591cb0ef41Sopenharmony_ci    if (optimize_to_fast_call) {
36601cb0ef41Sopenharmony_ci      result.push_back({functions[i], c_signature});
36611cb0ef41Sopenharmony_ci    }
36621cb0ef41Sopenharmony_ci  }
36631cb0ef41Sopenharmony_ci
36641cb0ef41Sopenharmony_ci  return result;
36651cb0ef41Sopenharmony_ci}
36661cb0ef41Sopenharmony_ci
36671cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceCallApiFunction(
36681cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
36691cb0ef41Sopenharmony_ci  JSCallNode n(node);
36701cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
36711cb0ef41Sopenharmony_ci  int const argc = p.arity_without_implicit_args();
36721cb0ef41Sopenharmony_ci  Node* target = n.target();
36731cb0ef41Sopenharmony_ci  Node* global_proxy =
36741cb0ef41Sopenharmony_ci      jsgraph()->Constant(native_context().global_proxy_object());
36751cb0ef41Sopenharmony_ci  Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
36761cb0ef41Sopenharmony_ci                       ? global_proxy
36771cb0ef41Sopenharmony_ci                       : n.receiver();
36781cb0ef41Sopenharmony_ci  Node* holder;
36791cb0ef41Sopenharmony_ci  Node* context = n.context();
36801cb0ef41Sopenharmony_ci  Effect effect = n.effect();
36811cb0ef41Sopenharmony_ci  Control control = n.control();
36821cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
36831cb0ef41Sopenharmony_ci
36841cb0ef41Sopenharmony_ci  if (!shared.function_template_info().has_value()) {
36851cb0ef41Sopenharmony_ci    TRACE_BROKER_MISSING(
36861cb0ef41Sopenharmony_ci        broker(), "FunctionTemplateInfo for function with SFI " << shared);
36871cb0ef41Sopenharmony_ci    return NoChange();
36881cb0ef41Sopenharmony_ci  }
36891cb0ef41Sopenharmony_ci
36901cb0ef41Sopenharmony_ci  // See if we can optimize this API call to {shared}.
36911cb0ef41Sopenharmony_ci  FunctionTemplateInfoRef function_template_info(
36921cb0ef41Sopenharmony_ci      shared.function_template_info().value());
36931cb0ef41Sopenharmony_ci
36941cb0ef41Sopenharmony_ci  if (function_template_info.accept_any_receiver() &&
36951cb0ef41Sopenharmony_ci      function_template_info.is_signature_undefined()) {
36961cb0ef41Sopenharmony_ci    // We might be able to
36971cb0ef41Sopenharmony_ci    // optimize the API call depending on the {function_template_info}.
36981cb0ef41Sopenharmony_ci    // If the API function accepts any kind of {receiver}, we only need to
36991cb0ef41Sopenharmony_ci    // ensure that the {receiver} is actually a JSReceiver at this point,
37001cb0ef41Sopenharmony_ci    // and also pass that as the {holder}. There are two independent bits
37011cb0ef41Sopenharmony_ci    // here:
37021cb0ef41Sopenharmony_ci    //
37031cb0ef41Sopenharmony_ci    //  a. When the "accept any receiver" bit is set, it means we don't
37041cb0ef41Sopenharmony_ci    //     need to perform access checks, even if the {receiver}'s map
37051cb0ef41Sopenharmony_ci    //     has the "needs access check" bit set.
37061cb0ef41Sopenharmony_ci    //  b. When the {function_template_info} has no signature, we don't
37071cb0ef41Sopenharmony_ci    //     need to do the compatible receiver check, since all receivers
37081cb0ef41Sopenharmony_ci    //     are considered compatible at that point, and the {receiver}
37091cb0ef41Sopenharmony_ci    //     will be pass as the {holder}.
37101cb0ef41Sopenharmony_ci    //
37111cb0ef41Sopenharmony_ci    receiver = holder = effect =
37121cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()),
37131cb0ef41Sopenharmony_ci                         receiver, global_proxy, effect, control);
37141cb0ef41Sopenharmony_ci  } else {
37151cb0ef41Sopenharmony_ci    // Try to infer the {receiver} maps from the graph.
37161cb0ef41Sopenharmony_ci    MapInference inference(broker(), receiver, effect);
37171cb0ef41Sopenharmony_ci    if (inference.HaveMaps()) {
37181cb0ef41Sopenharmony_ci      ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
37191cb0ef41Sopenharmony_ci      MapRef first_receiver_map = receiver_maps[0];
37201cb0ef41Sopenharmony_ci
37211cb0ef41Sopenharmony_ci      // See if we can constant-fold the compatible receiver checks.
37221cb0ef41Sopenharmony_ci      HolderLookupResult api_holder =
37231cb0ef41Sopenharmony_ci          function_template_info.LookupHolderOfExpectedType(first_receiver_map);
37241cb0ef41Sopenharmony_ci      if (api_holder.lookup == CallOptimization::kHolderNotFound) {
37251cb0ef41Sopenharmony_ci        return inference.NoChange();
37261cb0ef41Sopenharmony_ci      }
37271cb0ef41Sopenharmony_ci
37281cb0ef41Sopenharmony_ci      // Check that all {receiver_maps} are actually JSReceiver maps and
37291cb0ef41Sopenharmony_ci      // that the {function_template_info} accepts them without access
37301cb0ef41Sopenharmony_ci      // checks (even if "access check needed" is set for {receiver}).
37311cb0ef41Sopenharmony_ci      //
37321cb0ef41Sopenharmony_ci      // Note that we don't need to know the concrete {receiver} maps here,
37331cb0ef41Sopenharmony_ci      // meaning it's fine if the {receiver_maps} are unreliable, and we also
37341cb0ef41Sopenharmony_ci      // don't need to install any stability dependencies, since the only
37351cb0ef41Sopenharmony_ci      // relevant information regarding the {receiver} is the Map::constructor
37361cb0ef41Sopenharmony_ci      // field on the root map (which is different from the JavaScript exposed
37371cb0ef41Sopenharmony_ci      // "constructor" property) and that field cannot change.
37381cb0ef41Sopenharmony_ci      //
37391cb0ef41Sopenharmony_ci      // So if we know that {receiver} had a certain constructor at some point
37401cb0ef41Sopenharmony_ci      // in the past (i.e. it had a certain map), then this constructor is going
37411cb0ef41Sopenharmony_ci      // to be the same later, since this information cannot change with map
37421cb0ef41Sopenharmony_ci      // transitions.
37431cb0ef41Sopenharmony_ci      //
37441cb0ef41Sopenharmony_ci      // The same is true for the instance type, e.g. we still know that the
37451cb0ef41Sopenharmony_ci      // instance type is JSObject even if that information is unreliable, and
37461cb0ef41Sopenharmony_ci      // the "access check needed" bit, which also cannot change later.
37471cb0ef41Sopenharmony_ci      CHECK(first_receiver_map.IsJSReceiverMap());
37481cb0ef41Sopenharmony_ci      CHECK(!first_receiver_map.is_access_check_needed() ||
37491cb0ef41Sopenharmony_ci            function_template_info.accept_any_receiver());
37501cb0ef41Sopenharmony_ci
37511cb0ef41Sopenharmony_ci      for (size_t i = 1; i < receiver_maps.size(); ++i) {
37521cb0ef41Sopenharmony_ci        MapRef receiver_map = receiver_maps[i];
37531cb0ef41Sopenharmony_ci        HolderLookupResult holder_i =
37541cb0ef41Sopenharmony_ci            function_template_info.LookupHolderOfExpectedType(receiver_map);
37551cb0ef41Sopenharmony_ci
37561cb0ef41Sopenharmony_ci        if (api_holder.lookup != holder_i.lookup) return inference.NoChange();
37571cb0ef41Sopenharmony_ci        DCHECK(holder_i.lookup == CallOptimization::kHolderFound ||
37581cb0ef41Sopenharmony_ci               holder_i.lookup == CallOptimization::kHolderIsReceiver);
37591cb0ef41Sopenharmony_ci        if (holder_i.lookup == CallOptimization::kHolderFound) {
37601cb0ef41Sopenharmony_ci          DCHECK(api_holder.holder.has_value() && holder_i.holder.has_value());
37611cb0ef41Sopenharmony_ci          if (!api_holder.holder->equals(*holder_i.holder)) {
37621cb0ef41Sopenharmony_ci            return inference.NoChange();
37631cb0ef41Sopenharmony_ci          }
37641cb0ef41Sopenharmony_ci        }
37651cb0ef41Sopenharmony_ci
37661cb0ef41Sopenharmony_ci        CHECK(receiver_map.IsJSReceiverMap());
37671cb0ef41Sopenharmony_ci        CHECK(!receiver_map.is_access_check_needed() ||
37681cb0ef41Sopenharmony_ci              function_template_info.accept_any_receiver());
37691cb0ef41Sopenharmony_ci      }
37701cb0ef41Sopenharmony_ci
37711cb0ef41Sopenharmony_ci      if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation &&
37721cb0ef41Sopenharmony_ci          !inference.RelyOnMapsViaStability(dependencies())) {
37731cb0ef41Sopenharmony_ci        // We were not able to make the receiver maps reliable without map
37741cb0ef41Sopenharmony_ci        // checks but doing map checks would lead to deopt loops, so give up.
37751cb0ef41Sopenharmony_ci        return inference.NoChange();
37761cb0ef41Sopenharmony_ci      }
37771cb0ef41Sopenharmony_ci
37781cb0ef41Sopenharmony_ci      // TODO(neis): The maps were used in a way that does not actually require
37791cb0ef41Sopenharmony_ci      // map checks or stability dependencies.
37801cb0ef41Sopenharmony_ci      inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
37811cb0ef41Sopenharmony_ci                                          control, p.feedback());
37821cb0ef41Sopenharmony_ci
37831cb0ef41Sopenharmony_ci      // Determine the appropriate holder for the {lookup}.
37841cb0ef41Sopenharmony_ci      holder = api_holder.lookup == CallOptimization::kHolderFound
37851cb0ef41Sopenharmony_ci                   ? jsgraph()->Constant(*api_holder.holder)
37861cb0ef41Sopenharmony_ci                   : receiver;
37871cb0ef41Sopenharmony_ci    } else {
37881cb0ef41Sopenharmony_ci      // We don't have enough information to eliminate the access check
37891cb0ef41Sopenharmony_ci      // and/or the compatible receiver check, so use the generic builtin
37901cb0ef41Sopenharmony_ci      // that does those checks dynamically. This is still significantly
37911cb0ef41Sopenharmony_ci      // faster than the generic call sequence.
37921cb0ef41Sopenharmony_ci      Builtin builtin_name;
37931cb0ef41Sopenharmony_ci      if (function_template_info.accept_any_receiver()) {
37941cb0ef41Sopenharmony_ci        builtin_name = Builtin::kCallFunctionTemplate_CheckCompatibleReceiver;
37951cb0ef41Sopenharmony_ci      } else if (function_template_info.is_signature_undefined()) {
37961cb0ef41Sopenharmony_ci        builtin_name = Builtin::kCallFunctionTemplate_CheckAccess;
37971cb0ef41Sopenharmony_ci      } else {
37981cb0ef41Sopenharmony_ci        builtin_name =
37991cb0ef41Sopenharmony_ci            Builtin::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver;
38001cb0ef41Sopenharmony_ci      }
38011cb0ef41Sopenharmony_ci
38021cb0ef41Sopenharmony_ci      // The CallFunctionTemplate builtin requires the {receiver} to be
38031cb0ef41Sopenharmony_ci      // an actual JSReceiver, so make sure we do the proper conversion
38041cb0ef41Sopenharmony_ci      // first if necessary.
38051cb0ef41Sopenharmony_ci      receiver = holder = effect =
38061cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()),
38071cb0ef41Sopenharmony_ci                           receiver, global_proxy, effect, control);
38081cb0ef41Sopenharmony_ci
38091cb0ef41Sopenharmony_ci      Callable callable = Builtins::CallableFor(isolate(), builtin_name);
38101cb0ef41Sopenharmony_ci      auto call_descriptor = Linkage::GetStubCallDescriptor(
38111cb0ef41Sopenharmony_ci          graph()->zone(), callable.descriptor(),
38121cb0ef41Sopenharmony_ci          argc + 1 /* implicit receiver */, CallDescriptor::kNeedsFrameState);
38131cb0ef41Sopenharmony_ci      node->RemoveInput(n.FeedbackVectorIndex());
38141cb0ef41Sopenharmony_ci      node->InsertInput(graph()->zone(), 0,
38151cb0ef41Sopenharmony_ci                        jsgraph()->HeapConstant(callable.code()));
38161cb0ef41Sopenharmony_ci      node->ReplaceInput(1, jsgraph()->Constant(function_template_info));
38171cb0ef41Sopenharmony_ci      node->InsertInput(graph()->zone(), 2,
38181cb0ef41Sopenharmony_ci                        jsgraph()->Constant(JSParameterCount(argc)));
38191cb0ef41Sopenharmony_ci      node->ReplaceInput(3, receiver);       // Update receiver input.
38201cb0ef41Sopenharmony_ci      node->ReplaceInput(6 + argc, effect);  // Update effect input.
38211cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
38221cb0ef41Sopenharmony_ci      return Changed(node);
38231cb0ef41Sopenharmony_ci    }
38241cb0ef41Sopenharmony_ci  }
38251cb0ef41Sopenharmony_ci
38261cb0ef41Sopenharmony_ci  // TODO(turbofan): Consider introducing a JSCallApiCallback operator for
38271cb0ef41Sopenharmony_ci  // this and lower it during JSGenericLowering, and unify this with the
38281cb0ef41Sopenharmony_ci  // JSNativeContextSpecialization::InlineApiCall method a bit.
38291cb0ef41Sopenharmony_ci  if (!function_template_info.call_code().has_value()) {
38301cb0ef41Sopenharmony_ci    TRACE_BROKER_MISSING(broker(), "call code for function template info "
38311cb0ef41Sopenharmony_ci                                       << function_template_info);
38321cb0ef41Sopenharmony_ci    return NoChange();
38331cb0ef41Sopenharmony_ci  }
38341cb0ef41Sopenharmony_ci
38351cb0ef41Sopenharmony_ci  // Handles overloaded functions.
38361cb0ef41Sopenharmony_ci
38371cb0ef41Sopenharmony_ci  FastApiCallFunctionVector c_candidate_functions =
38381cb0ef41Sopenharmony_ci      CanOptimizeFastCall(graph()->zone(), function_template_info, argc);
38391cb0ef41Sopenharmony_ci  DCHECK_LE(c_candidate_functions.size(), 2);
38401cb0ef41Sopenharmony_ci
38411cb0ef41Sopenharmony_ci  if (!c_candidate_functions.empty()) {
38421cb0ef41Sopenharmony_ci    FastApiCallReducerAssembler a(this, node, function_template_info,
38431cb0ef41Sopenharmony_ci                                  c_candidate_functions, receiver, holder,
38441cb0ef41Sopenharmony_ci                                  shared, target, argc, effect);
38451cb0ef41Sopenharmony_ci    Node* fast_call_subgraph = a.ReduceFastApiCall();
38461cb0ef41Sopenharmony_ci    ReplaceWithSubgraph(&a, fast_call_subgraph);
38471cb0ef41Sopenharmony_ci
38481cb0ef41Sopenharmony_ci    return Replace(fast_call_subgraph);
38491cb0ef41Sopenharmony_ci  }
38501cb0ef41Sopenharmony_ci
38511cb0ef41Sopenharmony_ci  // Slow call
38521cb0ef41Sopenharmony_ci
38531cb0ef41Sopenharmony_ci  CallHandlerInfoRef call_handler_info = *function_template_info.call_code();
38541cb0ef41Sopenharmony_ci  Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
38551cb0ef41Sopenharmony_ci  CallInterfaceDescriptor cid = call_api_callback.descriptor();
38561cb0ef41Sopenharmony_ci  auto call_descriptor =
38571cb0ef41Sopenharmony_ci      Linkage::GetStubCallDescriptor(graph()->zone(), cid, argc + 1 /*
38581cb0ef41Sopenharmony_ci     implicit receiver */, CallDescriptor::kNeedsFrameState);
38591cb0ef41Sopenharmony_ci  ApiFunction api_function(call_handler_info.callback());
38601cb0ef41Sopenharmony_ci  ExternalReference function_reference = ExternalReference::Create(
38611cb0ef41Sopenharmony_ci      &api_function, ExternalReference::DIRECT_API_CALL);
38621cb0ef41Sopenharmony_ci
38631cb0ef41Sopenharmony_ci  Node* continuation_frame_state = CreateGenericLazyDeoptContinuationFrameState(
38641cb0ef41Sopenharmony_ci      jsgraph(), shared, target, context, receiver, frame_state);
38651cb0ef41Sopenharmony_ci
38661cb0ef41Sopenharmony_ci  node->RemoveInput(n.FeedbackVectorIndex());
38671cb0ef41Sopenharmony_ci  node->InsertInput(graph()->zone(), 0,
38681cb0ef41Sopenharmony_ci                    jsgraph()->HeapConstant(call_api_callback.code()));
38691cb0ef41Sopenharmony_ci  node->ReplaceInput(1, jsgraph()->ExternalConstant(function_reference));
38701cb0ef41Sopenharmony_ci  node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(argc));
38711cb0ef41Sopenharmony_ci  node->InsertInput(graph()->zone(), 3,
38721cb0ef41Sopenharmony_ci                    jsgraph()->Constant(call_handler_info.data()));
38731cb0ef41Sopenharmony_ci  node->InsertInput(graph()->zone(), 4, holder);
38741cb0ef41Sopenharmony_ci  node->ReplaceInput(5, receiver);  // Update receiver input.
38751cb0ef41Sopenharmony_ci  // 6 + argc is context input.
38761cb0ef41Sopenharmony_ci  node->ReplaceInput(6 + argc + 1, continuation_frame_state);
38771cb0ef41Sopenharmony_ci  node->ReplaceInput(6 + argc + 2, effect);
38781cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
38791cb0ef41Sopenharmony_ci  return Changed(node);
38801cb0ef41Sopenharmony_ci}
38811cb0ef41Sopenharmony_ci
38821cb0ef41Sopenharmony_cinamespace {
38831cb0ef41Sopenharmony_ci
38841cb0ef41Sopenharmony_ci// Check whether elements aren't mutated; we play it extremely safe here by
38851cb0ef41Sopenharmony_ci// explicitly checking that {node} is only used by {LoadField} or
38861cb0ef41Sopenharmony_ci// {LoadElement}.
38871cb0ef41Sopenharmony_cibool IsSafeArgumentsElements(Node* node) {
38881cb0ef41Sopenharmony_ci  for (Edge const edge : node->use_edges()) {
38891cb0ef41Sopenharmony_ci    if (!NodeProperties::IsValueEdge(edge)) continue;
38901cb0ef41Sopenharmony_ci    if (edge.from()->opcode() != IrOpcode::kLoadField &&
38911cb0ef41Sopenharmony_ci        edge.from()->opcode() != IrOpcode::kLoadElement) {
38921cb0ef41Sopenharmony_ci      return false;
38931cb0ef41Sopenharmony_ci    }
38941cb0ef41Sopenharmony_ci  }
38951cb0ef41Sopenharmony_ci  return true;
38961cb0ef41Sopenharmony_ci}
38971cb0ef41Sopenharmony_ci
38981cb0ef41Sopenharmony_ci#ifdef DEBUG
38991cb0ef41Sopenharmony_cibool IsCallOrConstructWithArrayLike(Node* node) {
39001cb0ef41Sopenharmony_ci  return node->opcode() == IrOpcode::kJSCallWithArrayLike ||
39011cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kJSConstructWithArrayLike;
39021cb0ef41Sopenharmony_ci}
39031cb0ef41Sopenharmony_ci#endif
39041cb0ef41Sopenharmony_ci
39051cb0ef41Sopenharmony_cibool IsCallOrConstructWithSpread(Node* node) {
39061cb0ef41Sopenharmony_ci  return node->opcode() == IrOpcode::kJSCallWithSpread ||
39071cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kJSConstructWithSpread;
39081cb0ef41Sopenharmony_ci}
39091cb0ef41Sopenharmony_ci
39101cb0ef41Sopenharmony_cibool IsCallWithArrayLikeOrSpread(Node* node) {
39111cb0ef41Sopenharmony_ci  return node->opcode() == IrOpcode::kJSCallWithArrayLike ||
39121cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kJSCallWithSpread;
39131cb0ef41Sopenharmony_ci}
39141cb0ef41Sopenharmony_ci
39151cb0ef41Sopenharmony_ci}  // namespace
39161cb0ef41Sopenharmony_ci
39171cb0ef41Sopenharmony_civoid JSCallReducer::CheckIfConstructor(Node* construct) {
39181cb0ef41Sopenharmony_ci  JSConstructNode n(construct);
39191cb0ef41Sopenharmony_ci  Node* new_target = n.new_target();
39201cb0ef41Sopenharmony_ci  Control control = n.control();
39211cb0ef41Sopenharmony_ci
39221cb0ef41Sopenharmony_ci  Node* check =
39231cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->ObjectIsConstructor(), new_target);
39241cb0ef41Sopenharmony_ci  Node* check_branch =
39251cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
39261cb0ef41Sopenharmony_ci  Node* check_fail = graph()->NewNode(common()->IfFalse(), check_branch);
39271cb0ef41Sopenharmony_ci  Node* check_throw = check_fail = graph()->NewNode(
39281cb0ef41Sopenharmony_ci      javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
39291cb0ef41Sopenharmony_ci      jsgraph()->Constant(static_cast<int>(MessageTemplate::kNotConstructor)),
39301cb0ef41Sopenharmony_ci      new_target, n.context(), n.frame_state(), n.effect(), check_fail);
39311cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->IfTrue(), check_branch);
39321cb0ef41Sopenharmony_ci  NodeProperties::ReplaceControlInput(construct, control);
39331cb0ef41Sopenharmony_ci
39341cb0ef41Sopenharmony_ci  // Rewire potential exception edges.
39351cb0ef41Sopenharmony_ci  Node* on_exception = nullptr;
39361cb0ef41Sopenharmony_ci  if (NodeProperties::IsExceptionalCall(construct, &on_exception)) {
39371cb0ef41Sopenharmony_ci    // Create appropriate {IfException}  and {IfSuccess} nodes.
39381cb0ef41Sopenharmony_ci    Node* if_exception =
39391cb0ef41Sopenharmony_ci        graph()->NewNode(common()->IfException(), check_throw, check_fail);
39401cb0ef41Sopenharmony_ci    check_fail = graph()->NewNode(common()->IfSuccess(), check_fail);
39411cb0ef41Sopenharmony_ci
39421cb0ef41Sopenharmony_ci    // Join the exception edges.
39431cb0ef41Sopenharmony_ci    Node* merge =
39441cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Merge(2), if_exception, on_exception);
39451cb0ef41Sopenharmony_ci    Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception,
39461cb0ef41Sopenharmony_ci                                  on_exception, merge);
39471cb0ef41Sopenharmony_ci    Node* phi =
39481cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
39491cb0ef41Sopenharmony_ci                         if_exception, on_exception, merge);
39501cb0ef41Sopenharmony_ci    ReplaceWithValue(on_exception, phi, ephi, merge);
39511cb0ef41Sopenharmony_ci    merge->ReplaceInput(1, on_exception);
39521cb0ef41Sopenharmony_ci    ephi->ReplaceInput(1, on_exception);
39531cb0ef41Sopenharmony_ci    phi->ReplaceInput(1, on_exception);
39541cb0ef41Sopenharmony_ci  }
39551cb0ef41Sopenharmony_ci
39561cb0ef41Sopenharmony_ci  // The above %ThrowTypeError runtime call is an unconditional throw,
39571cb0ef41Sopenharmony_ci  // making it impossible to return a successful completion in this case. We
39581cb0ef41Sopenharmony_ci  // simply connect the successful completion to the graph end.
39591cb0ef41Sopenharmony_ci  Node* throw_node =
39601cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Throw(), check_throw, check_fail);
39611cb0ef41Sopenharmony_ci  NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
39621cb0ef41Sopenharmony_ci}
39631cb0ef41Sopenharmony_ci
39641cb0ef41Sopenharmony_cinamespace {
39651cb0ef41Sopenharmony_ci
39661cb0ef41Sopenharmony_cibool ShouldUseCallICFeedback(Node* node) {
39671cb0ef41Sopenharmony_ci  HeapObjectMatcher m(node);
39681cb0ef41Sopenharmony_ci  if (m.HasResolvedValue() || m.IsCheckClosure() || m.IsJSCreateClosure()) {
39691cb0ef41Sopenharmony_ci    // Don't use CallIC feedback when we know the function
39701cb0ef41Sopenharmony_ci    // being called, i.e. either know the closure itself or
39711cb0ef41Sopenharmony_ci    // at least the SharedFunctionInfo.
39721cb0ef41Sopenharmony_ci    return false;
39731cb0ef41Sopenharmony_ci  } else if (m.IsPhi()) {
39741cb0ef41Sopenharmony_ci    // Protect against endless loops here.
39751cb0ef41Sopenharmony_ci    Node* control = NodeProperties::GetControlInput(node);
39761cb0ef41Sopenharmony_ci    if (control->opcode() == IrOpcode::kLoop ||
39771cb0ef41Sopenharmony_ci        control->opcode() == IrOpcode::kDead)
39781cb0ef41Sopenharmony_ci      return false;
39791cb0ef41Sopenharmony_ci    // Check if {node} is a Phi of nodes which shouldn't
39801cb0ef41Sopenharmony_ci    // use CallIC feedback (not looking through loops).
39811cb0ef41Sopenharmony_ci    int const value_input_count = m.node()->op()->ValueInputCount();
39821cb0ef41Sopenharmony_ci    for (int n = 0; n < value_input_count; ++n) {
39831cb0ef41Sopenharmony_ci      if (ShouldUseCallICFeedback(node->InputAt(n))) return true;
39841cb0ef41Sopenharmony_ci    }
39851cb0ef41Sopenharmony_ci    return false;
39861cb0ef41Sopenharmony_ci  }
39871cb0ef41Sopenharmony_ci  return true;
39881cb0ef41Sopenharmony_ci}
39891cb0ef41Sopenharmony_ci
39901cb0ef41Sopenharmony_ci}  // namespace
39911cb0ef41Sopenharmony_ci
39921cb0ef41Sopenharmony_ciNode* JSCallReducer::CheckArrayLength(Node* array, ElementsKind elements_kind,
39931cb0ef41Sopenharmony_ci                                      uint32_t array_length,
39941cb0ef41Sopenharmony_ci                                      const FeedbackSource& feedback_source,
39951cb0ef41Sopenharmony_ci                                      Effect effect, Control control) {
39961cb0ef41Sopenharmony_ci  Node* length = effect = graph()->NewNode(
39971cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
39981cb0ef41Sopenharmony_ci      array, effect, control);
39991cb0ef41Sopenharmony_ci  Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
40001cb0ef41Sopenharmony_ci                                 jsgraph()->Constant(array_length));
40011cb0ef41Sopenharmony_ci  return graph()->NewNode(
40021cb0ef41Sopenharmony_ci      simplified()->CheckIf(DeoptimizeReason::kArrayLengthChanged,
40031cb0ef41Sopenharmony_ci                            feedback_source),
40041cb0ef41Sopenharmony_ci      check, effect, control);
40051cb0ef41Sopenharmony_ci}
40061cb0ef41Sopenharmony_ci
40071cb0ef41Sopenharmony_ciReduction
40081cb0ef41Sopenharmony_ciJSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpreadOfCreateArguments(
40091cb0ef41Sopenharmony_ci    Node* node, Node* arguments_list, int arraylike_or_spread_index,
40101cb0ef41Sopenharmony_ci    CallFrequency const& frequency, FeedbackSource const& feedback,
40111cb0ef41Sopenharmony_ci    SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation) {
40121cb0ef41Sopenharmony_ci  DCHECK_EQ(arguments_list->opcode(), IrOpcode::kJSCreateArguments);
40131cb0ef41Sopenharmony_ci
40141cb0ef41Sopenharmony_ci  // Check if {node} is the only value user of {arguments_list} (except for
40151cb0ef41Sopenharmony_ci  // value uses in frame states). If not, we give up for now.
40161cb0ef41Sopenharmony_ci  for (Edge edge : arguments_list->use_edges()) {
40171cb0ef41Sopenharmony_ci    if (!NodeProperties::IsValueEdge(edge)) continue;
40181cb0ef41Sopenharmony_ci    Node* const user = edge.from();
40191cb0ef41Sopenharmony_ci    switch (user->opcode()) {
40201cb0ef41Sopenharmony_ci      case IrOpcode::kCheckMaps:
40211cb0ef41Sopenharmony_ci      case IrOpcode::kFrameState:
40221cb0ef41Sopenharmony_ci      case IrOpcode::kStateValues:
40231cb0ef41Sopenharmony_ci      case IrOpcode::kReferenceEqual:
40241cb0ef41Sopenharmony_ci      case IrOpcode::kReturn:
40251cb0ef41Sopenharmony_ci        // Ignore safe uses that definitely don't mess with the arguments.
40261cb0ef41Sopenharmony_ci        continue;
40271cb0ef41Sopenharmony_ci      case IrOpcode::kLoadField: {
40281cb0ef41Sopenharmony_ci        DCHECK_EQ(arguments_list, user->InputAt(0));
40291cb0ef41Sopenharmony_ci        FieldAccess const& access = FieldAccessOf(user->op());
40301cb0ef41Sopenharmony_ci        if (access.offset == JSArray::kLengthOffset) {
40311cb0ef41Sopenharmony_ci          // Ignore uses for arguments#length.
40321cb0ef41Sopenharmony_ci          STATIC_ASSERT(
40331cb0ef41Sopenharmony_ci              static_cast<int>(JSArray::kLengthOffset) ==
40341cb0ef41Sopenharmony_ci              static_cast<int>(JSStrictArgumentsObject::kLengthOffset));
40351cb0ef41Sopenharmony_ci          STATIC_ASSERT(
40361cb0ef41Sopenharmony_ci              static_cast<int>(JSArray::kLengthOffset) ==
40371cb0ef41Sopenharmony_ci              static_cast<int>(JSSloppyArgumentsObject::kLengthOffset));
40381cb0ef41Sopenharmony_ci          continue;
40391cb0ef41Sopenharmony_ci        } else if (access.offset == JSObject::kElementsOffset) {
40401cb0ef41Sopenharmony_ci          // Ignore safe uses for arguments#elements.
40411cb0ef41Sopenharmony_ci          if (IsSafeArgumentsElements(user)) continue;
40421cb0ef41Sopenharmony_ci        }
40431cb0ef41Sopenharmony_ci        break;
40441cb0ef41Sopenharmony_ci      }
40451cb0ef41Sopenharmony_ci      case IrOpcode::kJSCallWithArrayLike: {
40461cb0ef41Sopenharmony_ci        // Ignore uses as argumentsList input to calls with array like.
40471cb0ef41Sopenharmony_ci        JSCallWithArrayLikeNode n(user);
40481cb0ef41Sopenharmony_ci        if (n.Argument(0) == arguments_list) continue;
40491cb0ef41Sopenharmony_ci        break;
40501cb0ef41Sopenharmony_ci      }
40511cb0ef41Sopenharmony_ci      case IrOpcode::kJSConstructWithArrayLike: {
40521cb0ef41Sopenharmony_ci        // Ignore uses as argumentsList input to calls with array like.
40531cb0ef41Sopenharmony_ci        JSConstructWithArrayLikeNode n(user);
40541cb0ef41Sopenharmony_ci        if (n.Argument(0) == arguments_list) continue;
40551cb0ef41Sopenharmony_ci        break;
40561cb0ef41Sopenharmony_ci      }
40571cb0ef41Sopenharmony_ci      case IrOpcode::kJSCallWithSpread: {
40581cb0ef41Sopenharmony_ci        // Ignore uses as spread input to calls with spread.
40591cb0ef41Sopenharmony_ci        JSCallWithSpreadNode n(user);
40601cb0ef41Sopenharmony_ci        if (n.LastArgument() == arguments_list) continue;
40611cb0ef41Sopenharmony_ci        break;
40621cb0ef41Sopenharmony_ci      }
40631cb0ef41Sopenharmony_ci      case IrOpcode::kJSConstructWithSpread: {
40641cb0ef41Sopenharmony_ci        // Ignore uses as spread input to construct with spread.
40651cb0ef41Sopenharmony_ci        JSConstructWithSpreadNode n(user);
40661cb0ef41Sopenharmony_ci        if (n.LastArgument() == arguments_list) continue;
40671cb0ef41Sopenharmony_ci        break;
40681cb0ef41Sopenharmony_ci      }
40691cb0ef41Sopenharmony_ci      default:
40701cb0ef41Sopenharmony_ci        break;
40711cb0ef41Sopenharmony_ci    }
40721cb0ef41Sopenharmony_ci    // We cannot currently reduce the {node} to something better than what
40731cb0ef41Sopenharmony_ci    // it already is, but we might be able to do something about the {node}
40741cb0ef41Sopenharmony_ci    // later, so put it on the waitlist and try again during finalization.
40751cb0ef41Sopenharmony_ci    waitlist_.insert(node);
40761cb0ef41Sopenharmony_ci    return NoChange();
40771cb0ef41Sopenharmony_ci  }
40781cb0ef41Sopenharmony_ci
40791cb0ef41Sopenharmony_ci  // Get to the actual frame state from which to extract the arguments;
40801cb0ef41Sopenharmony_ci  // we can only optimize this in case the {node} was already inlined into
40811cb0ef41Sopenharmony_ci  // some other function (and same for the {arguments_list}).
40821cb0ef41Sopenharmony_ci  CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op());
40831cb0ef41Sopenharmony_ci  FrameState frame_state =
40841cb0ef41Sopenharmony_ci      FrameState{NodeProperties::GetFrameStateInput(arguments_list)};
40851cb0ef41Sopenharmony_ci
40861cb0ef41Sopenharmony_ci  int formal_parameter_count;
40871cb0ef41Sopenharmony_ci  {
40881cb0ef41Sopenharmony_ci    Handle<SharedFunctionInfo> shared;
40891cb0ef41Sopenharmony_ci    if (!frame_state.frame_state_info().shared_info().ToHandle(&shared)) {
40901cb0ef41Sopenharmony_ci      return NoChange();
40911cb0ef41Sopenharmony_ci    }
40921cb0ef41Sopenharmony_ci    formal_parameter_count =
40931cb0ef41Sopenharmony_ci        MakeRef(broker(), shared)
40941cb0ef41Sopenharmony_ci            .internal_formal_parameter_count_without_receiver();
40951cb0ef41Sopenharmony_ci  }
40961cb0ef41Sopenharmony_ci
40971cb0ef41Sopenharmony_ci  if (type == CreateArgumentsType::kMappedArguments) {
40981cb0ef41Sopenharmony_ci    // Mapped arguments (sloppy mode) that are aliased can only be handled
40991cb0ef41Sopenharmony_ci    // here if there's no side-effect between the {node} and the {arg_array}.
41001cb0ef41Sopenharmony_ci    // TODO(turbofan): Further relax this constraint.
41011cb0ef41Sopenharmony_ci    if (formal_parameter_count != 0) {
41021cb0ef41Sopenharmony_ci      Node* effect = NodeProperties::GetEffectInput(node);
41031cb0ef41Sopenharmony_ci      if (!NodeProperties::NoObservableSideEffectBetween(effect,
41041cb0ef41Sopenharmony_ci                                                         arguments_list)) {
41051cb0ef41Sopenharmony_ci        return NoChange();
41061cb0ef41Sopenharmony_ci      }
41071cb0ef41Sopenharmony_ci    }
41081cb0ef41Sopenharmony_ci  }
41091cb0ef41Sopenharmony_ci
41101cb0ef41Sopenharmony_ci  // For call/construct with spread, we need to also install a code
41111cb0ef41Sopenharmony_ci  // dependency on the array iterator lookup protector cell to ensure
41121cb0ef41Sopenharmony_ci  // that no one messed with the %ArrayIteratorPrototype%.next method.
41131cb0ef41Sopenharmony_ci  if (IsCallOrConstructWithSpread(node)) {
41141cb0ef41Sopenharmony_ci    if (!dependencies()->DependOnArrayIteratorProtector()) return NoChange();
41151cb0ef41Sopenharmony_ci  }
41161cb0ef41Sopenharmony_ci
41171cb0ef41Sopenharmony_ci  // Remove the {arguments_list} input from the {node}.
41181cb0ef41Sopenharmony_ci  node->RemoveInput(arraylike_or_spread_index);
41191cb0ef41Sopenharmony_ci
41201cb0ef41Sopenharmony_ci  // The index of the first relevant parameter. Only non-zero when looking at
41211cb0ef41Sopenharmony_ci  // rest parameters, in which case it is set to the index of the first rest
41221cb0ef41Sopenharmony_ci  // parameter.
41231cb0ef41Sopenharmony_ci  const int start_index = (type == CreateArgumentsType::kRestParameter)
41241cb0ef41Sopenharmony_ci                              ? formal_parameter_count
41251cb0ef41Sopenharmony_ci                              : 0;
41261cb0ef41Sopenharmony_ci
41271cb0ef41Sopenharmony_ci  // After removing the arraylike or spread object, the argument count is:
41281cb0ef41Sopenharmony_ci  int argc =
41291cb0ef41Sopenharmony_ci      arraylike_or_spread_index - JSCallOrConstructNode::FirstArgumentIndex();
41301cb0ef41Sopenharmony_ci  // Check if are spreading to inlined arguments or to the arguments of
41311cb0ef41Sopenharmony_ci  // the outermost function.
41321cb0ef41Sopenharmony_ci  if (frame_state.outer_frame_state()->opcode() != IrOpcode::kFrameState) {
41331cb0ef41Sopenharmony_ci    Operator const* op;
41341cb0ef41Sopenharmony_ci    if (IsCallWithArrayLikeOrSpread(node)) {
41351cb0ef41Sopenharmony_ci      static constexpr int kTargetAndReceiver = 2;
41361cb0ef41Sopenharmony_ci      op = javascript()->CallForwardVarargs(argc + kTargetAndReceiver,
41371cb0ef41Sopenharmony_ci                                            start_index);
41381cb0ef41Sopenharmony_ci    } else {
41391cb0ef41Sopenharmony_ci      static constexpr int kTargetAndNewTarget = 2;
41401cb0ef41Sopenharmony_ci      op = javascript()->ConstructForwardVarargs(argc + kTargetAndNewTarget,
41411cb0ef41Sopenharmony_ci                                                 start_index);
41421cb0ef41Sopenharmony_ci    }
41431cb0ef41Sopenharmony_ci    node->RemoveInput(JSCallOrConstructNode::FeedbackVectorIndexForArgc(argc));
41441cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, op);
41451cb0ef41Sopenharmony_ci    return Changed(node);
41461cb0ef41Sopenharmony_ci  }
41471cb0ef41Sopenharmony_ci  // Get to the actual frame state from which to extract the arguments;
41481cb0ef41Sopenharmony_ci  // we can only optimize this in case the {node} was already inlined into
41491cb0ef41Sopenharmony_ci  // some other function (and same for the {arg_array}).
41501cb0ef41Sopenharmony_ci  FrameState outer_state{frame_state.outer_frame_state()};
41511cb0ef41Sopenharmony_ci  FrameStateInfo outer_info = outer_state.frame_state_info();
41521cb0ef41Sopenharmony_ci  if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
41531cb0ef41Sopenharmony_ci    // Need to take the parameters from the arguments adaptor.
41541cb0ef41Sopenharmony_ci    frame_state = outer_state;
41551cb0ef41Sopenharmony_ci  }
41561cb0ef41Sopenharmony_ci  // Add the actual parameters to the {node}, skipping the receiver.
41571cb0ef41Sopenharmony_ci  StateValuesAccess parameters_access(frame_state.parameters());
41581cb0ef41Sopenharmony_ci  for (auto it = parameters_access.begin_without_receiver_and_skip(start_index);
41591cb0ef41Sopenharmony_ci       !it.done(); ++it) {
41601cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(it.node());
41611cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(),
41621cb0ef41Sopenharmony_ci                      JSCallOrConstructNode::ArgumentIndex(argc++), it.node());
41631cb0ef41Sopenharmony_ci  }
41641cb0ef41Sopenharmony_ci
41651cb0ef41Sopenharmony_ci  if (IsCallWithArrayLikeOrSpread(node)) {
41661cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
41671cb0ef41Sopenharmony_ci        node, javascript()->Call(JSCallNode::ArityForArgc(argc), frequency,
41681cb0ef41Sopenharmony_ci                                 feedback, ConvertReceiverMode::kAny,
41691cb0ef41Sopenharmony_ci                                 speculation_mode, feedback_relation));
41701cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSCall(node));
41711cb0ef41Sopenharmony_ci  } else {
41721cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
41731cb0ef41Sopenharmony_ci        node, javascript()->Construct(JSConstructNode::ArityForArgc(argc),
41741cb0ef41Sopenharmony_ci                                      frequency, feedback));
41751cb0ef41Sopenharmony_ci
41761cb0ef41Sopenharmony_ci    // Check whether the given new target value is a constructor function. The
41771cb0ef41Sopenharmony_ci    // replacement {JSConstruct} operator only checks the passed target value
41781cb0ef41Sopenharmony_ci    // but relies on the new target value to be implicitly valid.
41791cb0ef41Sopenharmony_ci    CheckIfConstructor(node);
41801cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSConstruct(node));
41811cb0ef41Sopenharmony_ci  }
41821cb0ef41Sopenharmony_ci}
41831cb0ef41Sopenharmony_ci
41841cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
41851cb0ef41Sopenharmony_ci    Node* node, int argument_count, int arraylike_or_spread_index,
41861cb0ef41Sopenharmony_ci    CallFrequency const& frequency, FeedbackSource const& feedback_source,
41871cb0ef41Sopenharmony_ci    SpeculationMode speculation_mode, CallFeedbackRelation feedback_relation,
41881cb0ef41Sopenharmony_ci    Node* target, Effect effect, Control control) {
41891cb0ef41Sopenharmony_ci  DCHECK(IsCallOrConstructWithArrayLike(node) ||
41901cb0ef41Sopenharmony_ci         IsCallOrConstructWithSpread(node));
41911cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
41921cb0ef41Sopenharmony_ci                 feedback_source.IsValid());
41931cb0ef41Sopenharmony_ci
41941cb0ef41Sopenharmony_ci  Node* arguments_list =
41951cb0ef41Sopenharmony_ci      NodeProperties::GetValueInput(node, arraylike_or_spread_index);
41961cb0ef41Sopenharmony_ci
41971cb0ef41Sopenharmony_ci  if (arguments_list->opcode() == IrOpcode::kJSCreateArguments) {
41981cb0ef41Sopenharmony_ci    return ReduceCallOrConstructWithArrayLikeOrSpreadOfCreateArguments(
41991cb0ef41Sopenharmony_ci        node, arguments_list, arraylike_or_spread_index, frequency,
42001cb0ef41Sopenharmony_ci        feedback_source, speculation_mode, feedback_relation);
42011cb0ef41Sopenharmony_ci  }
42021cb0ef41Sopenharmony_ci
42031cb0ef41Sopenharmony_ci  if (!FLAG_turbo_optimize_apply) return NoChange();
42041cb0ef41Sopenharmony_ci
42051cb0ef41Sopenharmony_ci  // Optimization of construct nodes not supported yet.
42061cb0ef41Sopenharmony_ci  if (!IsCallWithArrayLikeOrSpread(node)) return NoChange();
42071cb0ef41Sopenharmony_ci
42081cb0ef41Sopenharmony_ci  // Avoid deoptimization loops.
42091cb0ef41Sopenharmony_ci  if (speculation_mode != SpeculationMode::kAllowSpeculation) return NoChange();
42101cb0ef41Sopenharmony_ci
42111cb0ef41Sopenharmony_ci  // Only optimize with array literals.
42121cb0ef41Sopenharmony_ci  if (arguments_list->opcode() != IrOpcode::kJSCreateLiteralArray &&
42131cb0ef41Sopenharmony_ci      arguments_list->opcode() != IrOpcode::kJSCreateEmptyLiteralArray) {
42141cb0ef41Sopenharmony_ci    return NoChange();
42151cb0ef41Sopenharmony_ci  }
42161cb0ef41Sopenharmony_ci
42171cb0ef41Sopenharmony_ci  // For call/construct with spread, we need to also install a code
42181cb0ef41Sopenharmony_ci  // dependency on the array iterator lookup protector cell to ensure
42191cb0ef41Sopenharmony_ci  // that no one messed with the %ArrayIteratorPrototype%.next method.
42201cb0ef41Sopenharmony_ci  if (IsCallOrConstructWithSpread(node)) {
42211cb0ef41Sopenharmony_ci    if (!dependencies()->DependOnArrayIteratorProtector()) return NoChange();
42221cb0ef41Sopenharmony_ci  }
42231cb0ef41Sopenharmony_ci
42241cb0ef41Sopenharmony_ci  if (arguments_list->opcode() == IrOpcode::kJSCreateEmptyLiteralArray) {
42251cb0ef41Sopenharmony_ci    if (generated_calls_with_array_like_or_spread_.count(node)) {
42261cb0ef41Sopenharmony_ci      return NoChange();  // Avoid infinite recursion.
42271cb0ef41Sopenharmony_ci    }
42281cb0ef41Sopenharmony_ci    JSCallReducerAssembler a(this, node);
42291cb0ef41Sopenharmony_ci    Node* subgraph = a.ReduceJSCallWithArrayLikeOrSpreadOfEmpty(
42301cb0ef41Sopenharmony_ci        &generated_calls_with_array_like_or_spread_);
42311cb0ef41Sopenharmony_ci    return ReplaceWithSubgraph(&a, subgraph);
42321cb0ef41Sopenharmony_ci  }
42331cb0ef41Sopenharmony_ci
42341cb0ef41Sopenharmony_ci  DCHECK_EQ(arguments_list->opcode(), IrOpcode::kJSCreateLiteralArray);
42351cb0ef41Sopenharmony_ci  int new_argument_count;
42361cb0ef41Sopenharmony_ci
42371cb0ef41Sopenharmony_ci  // Find array length and elements' kind from the feedback's allocation
42381cb0ef41Sopenharmony_ci  // site's boilerplate JSArray.
42391cb0ef41Sopenharmony_ci  JSCreateLiteralOpNode args_node(arguments_list);
42401cb0ef41Sopenharmony_ci  CreateLiteralParameters const& args_params = args_node.Parameters();
42411cb0ef41Sopenharmony_ci  const FeedbackSource& array_feedback = args_params.feedback();
42421cb0ef41Sopenharmony_ci  const ProcessedFeedback& feedback =
42431cb0ef41Sopenharmony_ci      broker()->GetFeedbackForArrayOrObjectLiteral(array_feedback);
42441cb0ef41Sopenharmony_ci  if (feedback.IsInsufficient()) return NoChange();
42451cb0ef41Sopenharmony_ci
42461cb0ef41Sopenharmony_ci  AllocationSiteRef site = feedback.AsLiteral().value();
42471cb0ef41Sopenharmony_ci  if (!site.boilerplate().has_value()) return NoChange();
42481cb0ef41Sopenharmony_ci
42491cb0ef41Sopenharmony_ci  JSArrayRef boilerplate_array = site.boilerplate()->AsJSArray();
42501cb0ef41Sopenharmony_ci  int const array_length = boilerplate_array.GetBoilerplateLength().AsSmi();
42511cb0ef41Sopenharmony_ci
42521cb0ef41Sopenharmony_ci  // We'll replace the arguments_list input with {array_length} element loads.
42531cb0ef41Sopenharmony_ci  new_argument_count = argument_count - 1 + array_length;
42541cb0ef41Sopenharmony_ci
42551cb0ef41Sopenharmony_ci  // Do not optimize calls with a large number of arguments.
42561cb0ef41Sopenharmony_ci  // Arbitrarily sets the limit to 32 arguments.
42571cb0ef41Sopenharmony_ci  const int kMaxArityForOptimizedFunctionApply = 32;
42581cb0ef41Sopenharmony_ci  if (new_argument_count > kMaxArityForOptimizedFunctionApply) {
42591cb0ef41Sopenharmony_ci    return NoChange();
42601cb0ef41Sopenharmony_ci  }
42611cb0ef41Sopenharmony_ci
42621cb0ef41Sopenharmony_ci  // Determine the array's map.
42631cb0ef41Sopenharmony_ci  MapRef array_map = boilerplate_array.map();
42641cb0ef41Sopenharmony_ci  if (!array_map.supports_fast_array_iteration()) {
42651cb0ef41Sopenharmony_ci    return NoChange();
42661cb0ef41Sopenharmony_ci  }
42671cb0ef41Sopenharmony_ci
42681cb0ef41Sopenharmony_ci  // Check and depend on NoElementsProtector.
42691cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnNoElementsProtector()) {
42701cb0ef41Sopenharmony_ci    return NoChange();
42711cb0ef41Sopenharmony_ci  }
42721cb0ef41Sopenharmony_ci
42731cb0ef41Sopenharmony_ci  // Remove the {arguments_list} node which will be replaced by a sequence of
42741cb0ef41Sopenharmony_ci  // LoadElement nodes.
42751cb0ef41Sopenharmony_ci  node->RemoveInput(arraylike_or_spread_index);
42761cb0ef41Sopenharmony_ci
42771cb0ef41Sopenharmony_ci  // Speculate on that array's map is still equal to the dynamic map of
42781cb0ef41Sopenharmony_ci  // arguments_list; generate a map check.
42791cb0ef41Sopenharmony_ci  effect = graph()->NewNode(
42801cb0ef41Sopenharmony_ci      simplified()->CheckMaps(CheckMapsFlag::kNone,
42811cb0ef41Sopenharmony_ci                              ZoneHandleSet<Map>(array_map.object()),
42821cb0ef41Sopenharmony_ci                              feedback_source),
42831cb0ef41Sopenharmony_ci      arguments_list, effect, control);
42841cb0ef41Sopenharmony_ci
42851cb0ef41Sopenharmony_ci  // Speculate on that array's length being equal to the dynamic length of
42861cb0ef41Sopenharmony_ci  // arguments_list; generate a deopt check.
42871cb0ef41Sopenharmony_ci  ElementsKind elements_kind = array_map.elements_kind();
42881cb0ef41Sopenharmony_ci  effect = CheckArrayLength(arguments_list, elements_kind, array_length,
42891cb0ef41Sopenharmony_ci                            feedback_source, effect, control);
42901cb0ef41Sopenharmony_ci
42911cb0ef41Sopenharmony_ci  // Generate N element loads to replace the {arguments_list} node with a set
42921cb0ef41Sopenharmony_ci  // of arguments loaded from it.
42931cb0ef41Sopenharmony_ci  Node* elements = effect = graph()->NewNode(
42941cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
42951cb0ef41Sopenharmony_ci      arguments_list, effect, control);
42961cb0ef41Sopenharmony_ci  for (int i = 0; i < array_length; i++) {
42971cb0ef41Sopenharmony_ci    // Load the i-th element from the array.
42981cb0ef41Sopenharmony_ci    Node* index = jsgraph()->Constant(i);
42991cb0ef41Sopenharmony_ci    Node* load = effect = graph()->NewNode(
43001cb0ef41Sopenharmony_ci        simplified()->LoadElement(
43011cb0ef41Sopenharmony_ci            AccessBuilder::ForFixedArrayElement(elements_kind)),
43021cb0ef41Sopenharmony_ci        elements, index, effect, control);
43031cb0ef41Sopenharmony_ci
43041cb0ef41Sopenharmony_ci    // In "holey" arrays some arguments might be missing and we pass
43051cb0ef41Sopenharmony_ci    // 'undefined' instead.
43061cb0ef41Sopenharmony_ci    if (IsHoleyElementsKind(elements_kind)) {
43071cb0ef41Sopenharmony_ci      if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
43081cb0ef41Sopenharmony_ci        // May deopt for holey double elements.
43091cb0ef41Sopenharmony_ci        load = effect = graph()->NewNode(
43101cb0ef41Sopenharmony_ci            simplified()->CheckFloat64Hole(
43111cb0ef41Sopenharmony_ci                CheckFloat64HoleMode::kAllowReturnHole, feedback_source),
43121cb0ef41Sopenharmony_ci            load, effect, control);
43131cb0ef41Sopenharmony_ci      } else {
43141cb0ef41Sopenharmony_ci        load = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
43151cb0ef41Sopenharmony_ci                                load);
43161cb0ef41Sopenharmony_ci      }
43171cb0ef41Sopenharmony_ci    }
43181cb0ef41Sopenharmony_ci
43191cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), arraylike_or_spread_index + i, load);
43201cb0ef41Sopenharmony_ci  }
43211cb0ef41Sopenharmony_ci
43221cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
43231cb0ef41Sopenharmony_ci      node,
43241cb0ef41Sopenharmony_ci      javascript()->Call(JSCallNode::ArityForArgc(new_argument_count),
43251cb0ef41Sopenharmony_ci                         frequency, feedback_source, ConvertReceiverMode::kAny,
43261cb0ef41Sopenharmony_ci                         speculation_mode, CallFeedbackRelation::kUnrelated));
43271cb0ef41Sopenharmony_ci  NodeProperties::ReplaceEffectInput(node, effect);
43281cb0ef41Sopenharmony_ci  return Changed(node).FollowedBy(ReduceJSCall(node));
43291cb0ef41Sopenharmony_ci}
43301cb0ef41Sopenharmony_ci
43311cb0ef41Sopenharmony_cibool JSCallReducer::IsBuiltinOrApiFunction(JSFunctionRef function) const {
43321cb0ef41Sopenharmony_ci  // TODO(neis): Add a way to check if function template info isn't serialized
43331cb0ef41Sopenharmony_ci  // and add a warning in such cases. Currently we can't tell if function
43341cb0ef41Sopenharmony_ci  // template info doesn't exist or wasn't serialized.
43351cb0ef41Sopenharmony_ci  return function.shared().HasBuiltinId() ||
43361cb0ef41Sopenharmony_ci         function.shared().function_template_info().has_value();
43371cb0ef41Sopenharmony_ci}
43381cb0ef41Sopenharmony_ci
43391cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSCall(Node* node) {
43401cb0ef41Sopenharmony_ci  if (broker()->StackHasOverflowed()) return NoChange();
43411cb0ef41Sopenharmony_ci
43421cb0ef41Sopenharmony_ci  JSCallNode n(node);
43431cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
43441cb0ef41Sopenharmony_ci  Node* target = n.target();
43451cb0ef41Sopenharmony_ci  Effect effect = n.effect();
43461cb0ef41Sopenharmony_ci  Control control = n.control();
43471cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
43481cb0ef41Sopenharmony_ci
43491cb0ef41Sopenharmony_ci  // Try to specialize JSCall {node}s with constant {target}s.
43501cb0ef41Sopenharmony_ci  HeapObjectMatcher m(target);
43511cb0ef41Sopenharmony_ci  if (m.HasResolvedValue()) {
43521cb0ef41Sopenharmony_ci    ObjectRef target_ref = m.Ref(broker());
43531cb0ef41Sopenharmony_ci    if (target_ref.IsJSFunction()) {
43541cb0ef41Sopenharmony_ci      JSFunctionRef function = target_ref.AsJSFunction();
43551cb0ef41Sopenharmony_ci
43561cb0ef41Sopenharmony_ci      // Don't inline cross native context.
43571cb0ef41Sopenharmony_ci      if (!function.native_context().equals(native_context())) {
43581cb0ef41Sopenharmony_ci        return NoChange();
43591cb0ef41Sopenharmony_ci      }
43601cb0ef41Sopenharmony_ci
43611cb0ef41Sopenharmony_ci      return ReduceJSCall(node, function.shared());
43621cb0ef41Sopenharmony_ci    } else if (target_ref.IsJSBoundFunction()) {
43631cb0ef41Sopenharmony_ci      JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
43641cb0ef41Sopenharmony_ci      ObjectRef bound_this = function.bound_this();
43651cb0ef41Sopenharmony_ci      ConvertReceiverMode const convert_mode =
43661cb0ef41Sopenharmony_ci          bound_this.IsNullOrUndefined()
43671cb0ef41Sopenharmony_ci              ? ConvertReceiverMode::kNullOrUndefined
43681cb0ef41Sopenharmony_ci              : ConvertReceiverMode::kNotNullOrUndefined;
43691cb0ef41Sopenharmony_ci
43701cb0ef41Sopenharmony_ci      // TODO(jgruber): Inline this block below once TryGet is guaranteed to
43711cb0ef41Sopenharmony_ci      // succeed.
43721cb0ef41Sopenharmony_ci      FixedArrayRef bound_arguments = function.bound_arguments();
43731cb0ef41Sopenharmony_ci      const int bound_arguments_length = bound_arguments.length();
43741cb0ef41Sopenharmony_ci      static constexpr int kInlineSize = 16;  // Arbitrary.
43751cb0ef41Sopenharmony_ci      base::SmallVector<Node*, kInlineSize> args;
43761cb0ef41Sopenharmony_ci      for (int i = 0; i < bound_arguments_length; ++i) {
43771cb0ef41Sopenharmony_ci        base::Optional<ObjectRef> maybe_arg = bound_arguments.TryGet(i);
43781cb0ef41Sopenharmony_ci        if (!maybe_arg.has_value()) {
43791cb0ef41Sopenharmony_ci          TRACE_BROKER_MISSING(broker(), "bound argument");
43801cb0ef41Sopenharmony_ci          return NoChange();
43811cb0ef41Sopenharmony_ci        }
43821cb0ef41Sopenharmony_ci        args.emplace_back(jsgraph()->Constant(maybe_arg.value()));
43831cb0ef41Sopenharmony_ci      }
43841cb0ef41Sopenharmony_ci
43851cb0ef41Sopenharmony_ci      // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
43861cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInput(
43871cb0ef41Sopenharmony_ci          node, jsgraph()->Constant(function.bound_target_function()),
43881cb0ef41Sopenharmony_ci          JSCallNode::TargetIndex());
43891cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
43901cb0ef41Sopenharmony_ci                                        JSCallNode::ReceiverIndex());
43911cb0ef41Sopenharmony_ci
43921cb0ef41Sopenharmony_ci      // Insert the [[BoundArguments]] for {node}.
43931cb0ef41Sopenharmony_ci      for (int i = 0; i < bound_arguments_length; ++i) {
43941cb0ef41Sopenharmony_ci        node->InsertInput(graph()->zone(), i + 2, args[i]);
43951cb0ef41Sopenharmony_ci        arity++;
43961cb0ef41Sopenharmony_ci      }
43971cb0ef41Sopenharmony_ci
43981cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(
43991cb0ef41Sopenharmony_ci          node,
44001cb0ef41Sopenharmony_ci          javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
44011cb0ef41Sopenharmony_ci                             p.feedback(), convert_mode, p.speculation_mode(),
44021cb0ef41Sopenharmony_ci                             CallFeedbackRelation::kUnrelated));
44031cb0ef41Sopenharmony_ci
44041cb0ef41Sopenharmony_ci      // Try to further reduce the JSCall {node}.
44051cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceJSCall(node));
44061cb0ef41Sopenharmony_ci    }
44071cb0ef41Sopenharmony_ci
44081cb0ef41Sopenharmony_ci    // Don't mess with other {node}s that have a constant {target}.
44091cb0ef41Sopenharmony_ci    // TODO(bmeurer): Also support proxies here.
44101cb0ef41Sopenharmony_ci    return NoChange();
44111cb0ef41Sopenharmony_ci  }
44121cb0ef41Sopenharmony_ci
44131cb0ef41Sopenharmony_ci  // If {target} is the result of a JSCreateClosure operation, we can
44141cb0ef41Sopenharmony_ci  // just immediately try to inline based on the SharedFunctionInfo,
44151cb0ef41Sopenharmony_ci  // since TurboFan generally doesn't inline cross-context, and hence
44161cb0ef41Sopenharmony_ci  // the {target} must have the same native context as the call site.
44171cb0ef41Sopenharmony_ci  // Same if the {target} is the result of a CheckClosure operation.
44181cb0ef41Sopenharmony_ci  if (target->opcode() == IrOpcode::kJSCreateClosure) {
44191cb0ef41Sopenharmony_ci    CreateClosureParameters const& params =
44201cb0ef41Sopenharmony_ci        JSCreateClosureNode{target}.Parameters();
44211cb0ef41Sopenharmony_ci    return ReduceJSCall(node, params.shared_info(broker()));
44221cb0ef41Sopenharmony_ci  } else if (target->opcode() == IrOpcode::kCheckClosure) {
44231cb0ef41Sopenharmony_ci    FeedbackCellRef cell = MakeRef(broker(), FeedbackCellOf(target->op()));
44241cb0ef41Sopenharmony_ci    base::Optional<SharedFunctionInfoRef> shared = cell.shared_function_info();
44251cb0ef41Sopenharmony_ci    if (!shared.has_value()) {
44261cb0ef41Sopenharmony_ci      TRACE_BROKER_MISSING(broker(), "Unable to reduce JSCall. FeedbackCell "
44271cb0ef41Sopenharmony_ci                                         << cell << " has no FeedbackVector");
44281cb0ef41Sopenharmony_ci      return NoChange();
44291cb0ef41Sopenharmony_ci    }
44301cb0ef41Sopenharmony_ci    return ReduceJSCall(node, *shared);
44311cb0ef41Sopenharmony_ci  }
44321cb0ef41Sopenharmony_ci
44331cb0ef41Sopenharmony_ci  // If {target} is the result of a JSCreateBoundFunction operation,
44341cb0ef41Sopenharmony_ci  // we can just fold the construction and call the bound target
44351cb0ef41Sopenharmony_ci  // function directly instead.
44361cb0ef41Sopenharmony_ci  if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
44371cb0ef41Sopenharmony_ci    Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
44381cb0ef41Sopenharmony_ci    Node* bound_this = NodeProperties::GetValueInput(target, 1);
44391cb0ef41Sopenharmony_ci    int const bound_arguments_length =
44401cb0ef41Sopenharmony_ci        static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
44411cb0ef41Sopenharmony_ci
44421cb0ef41Sopenharmony_ci    // Patch the {node} to use [[BoundTargetFunction]] and [[BoundThis]].
44431cb0ef41Sopenharmony_ci    NodeProperties::ReplaceValueInput(node, bound_target_function,
44441cb0ef41Sopenharmony_ci                                      n.TargetIndex());
44451cb0ef41Sopenharmony_ci    NodeProperties::ReplaceValueInput(node, bound_this, n.ReceiverIndex());
44461cb0ef41Sopenharmony_ci
44471cb0ef41Sopenharmony_ci    // Insert the [[BoundArguments]] for {node}.
44481cb0ef41Sopenharmony_ci    for (int i = 0; i < bound_arguments_length; ++i) {
44491cb0ef41Sopenharmony_ci      Node* value = NodeProperties::GetValueInput(target, 2 + i);
44501cb0ef41Sopenharmony_ci      node->InsertInput(graph()->zone(), n.ArgumentIndex(i), value);
44511cb0ef41Sopenharmony_ci      arity++;
44521cb0ef41Sopenharmony_ci    }
44531cb0ef41Sopenharmony_ci
44541cb0ef41Sopenharmony_ci    // Update the JSCall operator on {node}.
44551cb0ef41Sopenharmony_ci    ConvertReceiverMode const convert_mode =
44561cb0ef41Sopenharmony_ci        NodeProperties::CanBeNullOrUndefined(broker(), bound_this, effect)
44571cb0ef41Sopenharmony_ci            ? ConvertReceiverMode::kAny
44581cb0ef41Sopenharmony_ci            : ConvertReceiverMode::kNotNullOrUndefined;
44591cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
44601cb0ef41Sopenharmony_ci        node,
44611cb0ef41Sopenharmony_ci        javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
44621cb0ef41Sopenharmony_ci                           p.feedback(), convert_mode, p.speculation_mode(),
44631cb0ef41Sopenharmony_ci                           CallFeedbackRelation::kUnrelated));
44641cb0ef41Sopenharmony_ci
44651cb0ef41Sopenharmony_ci    // Try to further reduce the JSCall {node}.
44661cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSCall(node));
44671cb0ef41Sopenharmony_ci  }
44681cb0ef41Sopenharmony_ci
44691cb0ef41Sopenharmony_ci  if (!ShouldUseCallICFeedback(target) ||
44701cb0ef41Sopenharmony_ci      p.feedback_relation() == CallFeedbackRelation::kUnrelated ||
44711cb0ef41Sopenharmony_ci      !p.feedback().IsValid()) {
44721cb0ef41Sopenharmony_ci    return NoChange();
44731cb0ef41Sopenharmony_ci  }
44741cb0ef41Sopenharmony_ci
44751cb0ef41Sopenharmony_ci  ProcessedFeedback const& feedback =
44761cb0ef41Sopenharmony_ci      broker()->GetFeedbackForCall(p.feedback());
44771cb0ef41Sopenharmony_ci  if (feedback.IsInsufficient()) {
44781cb0ef41Sopenharmony_ci    return ReduceForInsufficientFeedback(
44791cb0ef41Sopenharmony_ci        node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
44801cb0ef41Sopenharmony_ci  }
44811cb0ef41Sopenharmony_ci
44821cb0ef41Sopenharmony_ci  base::Optional<HeapObjectRef> feedback_target;
44831cb0ef41Sopenharmony_ci  if (p.feedback_relation() == CallFeedbackRelation::kTarget) {
44841cb0ef41Sopenharmony_ci    feedback_target = feedback.AsCall().target();
44851cb0ef41Sopenharmony_ci  } else {
44861cb0ef41Sopenharmony_ci    DCHECK_EQ(p.feedback_relation(), CallFeedbackRelation::kReceiver);
44871cb0ef41Sopenharmony_ci    feedback_target = native_context().function_prototype_apply();
44881cb0ef41Sopenharmony_ci  }
44891cb0ef41Sopenharmony_ci
44901cb0ef41Sopenharmony_ci  if (feedback_target.has_value() && feedback_target->map().is_callable()) {
44911cb0ef41Sopenharmony_ci    Node* target_function = jsgraph()->Constant(*feedback_target);
44921cb0ef41Sopenharmony_ci
44931cb0ef41Sopenharmony_ci    // Check that the {target} is still the {target_function}.
44941cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
44951cb0ef41Sopenharmony_ci                                   target_function);
44961cb0ef41Sopenharmony_ci    effect = graph()->NewNode(
44971cb0ef41Sopenharmony_ci        simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
44981cb0ef41Sopenharmony_ci        effect, control);
44991cb0ef41Sopenharmony_ci
45001cb0ef41Sopenharmony_ci    // Specialize the JSCall node to the {target_function}.
45011cb0ef41Sopenharmony_ci    NodeProperties::ReplaceValueInput(node, target_function, n.TargetIndex());
45021cb0ef41Sopenharmony_ci    NodeProperties::ReplaceEffectInput(node, effect);
45031cb0ef41Sopenharmony_ci
45041cb0ef41Sopenharmony_ci    // Try to further reduce the JSCall {node}.
45051cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSCall(node));
45061cb0ef41Sopenharmony_ci  } else if (feedback_target.has_value() && feedback_target->IsFeedbackCell()) {
45071cb0ef41Sopenharmony_ci    FeedbackCellRef feedback_cell = feedback_target.value().AsFeedbackCell();
45081cb0ef41Sopenharmony_ci    // TODO(neis): This check seems unnecessary.
45091cb0ef41Sopenharmony_ci    if (feedback_cell.feedback_vector().has_value()) {
45101cb0ef41Sopenharmony_ci      // Check that {target} is a closure with given {feedback_cell},
45111cb0ef41Sopenharmony_ci      // which uniquely identifies a given function inside a native context.
45121cb0ef41Sopenharmony_ci      Node* target_closure = effect =
45131cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->CheckClosure(feedback_cell.object()),
45141cb0ef41Sopenharmony_ci                           target, effect, control);
45151cb0ef41Sopenharmony_ci
45161cb0ef41Sopenharmony_ci      // Specialize the JSCall node to the {target_closure}.
45171cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInput(node, target_closure, n.TargetIndex());
45181cb0ef41Sopenharmony_ci      NodeProperties::ReplaceEffectInput(node, effect);
45191cb0ef41Sopenharmony_ci
45201cb0ef41Sopenharmony_ci      // Try to further reduce the JSCall {node}.
45211cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceJSCall(node));
45221cb0ef41Sopenharmony_ci    }
45231cb0ef41Sopenharmony_ci  }
45241cb0ef41Sopenharmony_ci  return NoChange();
45251cb0ef41Sopenharmony_ci}
45261cb0ef41Sopenharmony_ci
45271cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSCall(Node* node,
45281cb0ef41Sopenharmony_ci                                      const SharedFunctionInfoRef& shared) {
45291cb0ef41Sopenharmony_ci  JSCallNode n(node);
45301cb0ef41Sopenharmony_ci  Node* target = n.target();
45311cb0ef41Sopenharmony_ci
45321cb0ef41Sopenharmony_ci  // Do not reduce calls to functions with break points.
45331cb0ef41Sopenharmony_ci  // If this state changes during background compilation, the compilation
45341cb0ef41Sopenharmony_ci  // job will be aborted from the main thread (see
45351cb0ef41Sopenharmony_ci  // Debug::PrepareFunctionForDebugExecution()).
45361cb0ef41Sopenharmony_ci  if (shared.HasBreakInfo()) return NoChange();
45371cb0ef41Sopenharmony_ci
45381cb0ef41Sopenharmony_ci  // Class constructors are callable, but [[Call]] will raise an exception.
45391cb0ef41Sopenharmony_ci  // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
45401cb0ef41Sopenharmony_ci  if (IsClassConstructor(shared.kind())) {
45411cb0ef41Sopenharmony_ci    NodeProperties::ReplaceValueInputs(node, target);
45421cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
45431cb0ef41Sopenharmony_ci        node, javascript()->CallRuntime(
45441cb0ef41Sopenharmony_ci                  Runtime::kThrowConstructorNonCallableError, 1));
45451cb0ef41Sopenharmony_ci    return Changed(node);
45461cb0ef41Sopenharmony_ci  }
45471cb0ef41Sopenharmony_ci
45481cb0ef41Sopenharmony_ci  // Check for known builtin functions.
45491cb0ef41Sopenharmony_ci
45501cb0ef41Sopenharmony_ci  Builtin builtin =
45511cb0ef41Sopenharmony_ci      shared.HasBuiltinId() ? shared.builtin_id() : Builtin::kNoBuiltinId;
45521cb0ef41Sopenharmony_ci  switch (builtin) {
45531cb0ef41Sopenharmony_ci    case Builtin::kArrayConstructor:
45541cb0ef41Sopenharmony_ci      return ReduceArrayConstructor(node);
45551cb0ef41Sopenharmony_ci    case Builtin::kBooleanConstructor:
45561cb0ef41Sopenharmony_ci      return ReduceBooleanConstructor(node);
45571cb0ef41Sopenharmony_ci    case Builtin::kFunctionPrototypeApply:
45581cb0ef41Sopenharmony_ci      return ReduceFunctionPrototypeApply(node);
45591cb0ef41Sopenharmony_ci    case Builtin::kFastFunctionPrototypeBind:
45601cb0ef41Sopenharmony_ci      return ReduceFunctionPrototypeBind(node);
45611cb0ef41Sopenharmony_ci    case Builtin::kFunctionPrototypeCall:
45621cb0ef41Sopenharmony_ci      return ReduceFunctionPrototypeCall(node);
45631cb0ef41Sopenharmony_ci    case Builtin::kFunctionPrototypeHasInstance:
45641cb0ef41Sopenharmony_ci      return ReduceFunctionPrototypeHasInstance(node);
45651cb0ef41Sopenharmony_ci    case Builtin::kObjectConstructor:
45661cb0ef41Sopenharmony_ci      return ReduceObjectConstructor(node);
45671cb0ef41Sopenharmony_ci    case Builtin::kObjectCreate:
45681cb0ef41Sopenharmony_ci      return ReduceObjectCreate(node);
45691cb0ef41Sopenharmony_ci    case Builtin::kObjectGetPrototypeOf:
45701cb0ef41Sopenharmony_ci      return ReduceObjectGetPrototypeOf(node);
45711cb0ef41Sopenharmony_ci    case Builtin::kObjectIs:
45721cb0ef41Sopenharmony_ci      return ReduceObjectIs(node);
45731cb0ef41Sopenharmony_ci    case Builtin::kObjectPrototypeGetProto:
45741cb0ef41Sopenharmony_ci      return ReduceObjectPrototypeGetProto(node);
45751cb0ef41Sopenharmony_ci    case Builtin::kObjectPrototypeHasOwnProperty:
45761cb0ef41Sopenharmony_ci      return ReduceObjectPrototypeHasOwnProperty(node);
45771cb0ef41Sopenharmony_ci    case Builtin::kObjectPrototypeIsPrototypeOf:
45781cb0ef41Sopenharmony_ci      return ReduceObjectPrototypeIsPrototypeOf(node);
45791cb0ef41Sopenharmony_ci    case Builtin::kReflectApply:
45801cb0ef41Sopenharmony_ci      return ReduceReflectApply(node);
45811cb0ef41Sopenharmony_ci    case Builtin::kReflectConstruct:
45821cb0ef41Sopenharmony_ci      return ReduceReflectConstruct(node);
45831cb0ef41Sopenharmony_ci    case Builtin::kReflectGet:
45841cb0ef41Sopenharmony_ci      return ReduceReflectGet(node);
45851cb0ef41Sopenharmony_ci    case Builtin::kReflectGetPrototypeOf:
45861cb0ef41Sopenharmony_ci      return ReduceReflectGetPrototypeOf(node);
45871cb0ef41Sopenharmony_ci    case Builtin::kReflectHas:
45881cb0ef41Sopenharmony_ci      return ReduceReflectHas(node);
45891cb0ef41Sopenharmony_ci    case Builtin::kArrayForEach:
45901cb0ef41Sopenharmony_ci      return ReduceArrayForEach(node, shared);
45911cb0ef41Sopenharmony_ci    case Builtin::kArrayMap:
45921cb0ef41Sopenharmony_ci      return ReduceArrayMap(node, shared);
45931cb0ef41Sopenharmony_ci    case Builtin::kArrayFilter:
45941cb0ef41Sopenharmony_ci      return ReduceArrayFilter(node, shared);
45951cb0ef41Sopenharmony_ci    case Builtin::kArrayReduce:
45961cb0ef41Sopenharmony_ci      return ReduceArrayReduce(node, shared);
45971cb0ef41Sopenharmony_ci    case Builtin::kArrayReduceRight:
45981cb0ef41Sopenharmony_ci      return ReduceArrayReduceRight(node, shared);
45991cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeFind:
46001cb0ef41Sopenharmony_ci      return ReduceArrayFind(node, shared);
46011cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeFindIndex:
46021cb0ef41Sopenharmony_ci      return ReduceArrayFindIndex(node, shared);
46031cb0ef41Sopenharmony_ci    case Builtin::kArrayEvery:
46041cb0ef41Sopenharmony_ci      return ReduceArrayEvery(node, shared);
46051cb0ef41Sopenharmony_ci    case Builtin::kArrayIndexOf:
46061cb0ef41Sopenharmony_ci      return ReduceArrayIndexOf(node);
46071cb0ef41Sopenharmony_ci    case Builtin::kArrayIncludes:
46081cb0ef41Sopenharmony_ci      return ReduceArrayIncludes(node);
46091cb0ef41Sopenharmony_ci    case Builtin::kArraySome:
46101cb0ef41Sopenharmony_ci      return ReduceArraySome(node, shared);
46111cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypePush:
46121cb0ef41Sopenharmony_ci      return ReduceArrayPrototypePush(node);
46131cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypePop:
46141cb0ef41Sopenharmony_ci      return ReduceArrayPrototypePop(node);
46151cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeShift:
46161cb0ef41Sopenharmony_ci      return ReduceArrayPrototypeShift(node);
46171cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeSlice:
46181cb0ef41Sopenharmony_ci      return ReduceArrayPrototypeSlice(node);
46191cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeEntries:
46201cb0ef41Sopenharmony_ci      return ReduceArrayIterator(node, ArrayIteratorKind::kArrayLike,
46211cb0ef41Sopenharmony_ci                                 IterationKind::kEntries);
46221cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeKeys:
46231cb0ef41Sopenharmony_ci      return ReduceArrayIterator(node, ArrayIteratorKind::kArrayLike,
46241cb0ef41Sopenharmony_ci                                 IterationKind::kKeys);
46251cb0ef41Sopenharmony_ci    case Builtin::kArrayPrototypeValues:
46261cb0ef41Sopenharmony_ci      return ReduceArrayIterator(node, ArrayIteratorKind::kArrayLike,
46271cb0ef41Sopenharmony_ci                                 IterationKind::kValues);
46281cb0ef41Sopenharmony_ci    case Builtin::kArrayIteratorPrototypeNext:
46291cb0ef41Sopenharmony_ci      return ReduceArrayIteratorPrototypeNext(node);
46301cb0ef41Sopenharmony_ci    case Builtin::kArrayIsArray:
46311cb0ef41Sopenharmony_ci      return ReduceArrayIsArray(node);
46321cb0ef41Sopenharmony_ci    case Builtin::kArrayBufferIsView:
46331cb0ef41Sopenharmony_ci      return ReduceArrayBufferIsView(node);
46341cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetByteLength:
46351cb0ef41Sopenharmony_ci      return ReduceArrayBufferViewAccessor(
46361cb0ef41Sopenharmony_ci          node, JS_DATA_VIEW_TYPE,
46371cb0ef41Sopenharmony_ci          AccessBuilder::ForJSArrayBufferViewByteLength());
46381cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetByteOffset:
46391cb0ef41Sopenharmony_ci      return ReduceArrayBufferViewAccessor(
46401cb0ef41Sopenharmony_ci          node, JS_DATA_VIEW_TYPE,
46411cb0ef41Sopenharmony_ci          AccessBuilder::ForJSArrayBufferViewByteOffset());
46421cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetUint8:
46431cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46441cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalUint8Array);
46451cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetInt8:
46461cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46471cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalInt8Array);
46481cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetUint16:
46491cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46501cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalUint16Array);
46511cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetInt16:
46521cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46531cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalInt16Array);
46541cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetUint32:
46551cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46561cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalUint32Array);
46571cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetInt32:
46581cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46591cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalInt32Array);
46601cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetFloat32:
46611cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46621cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalFloat32Array);
46631cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeGetFloat64:
46641cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kGet,
46651cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalFloat64Array);
46661cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetUint8:
46671cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46681cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalUint8Array);
46691cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetInt8:
46701cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46711cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalInt8Array);
46721cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetUint16:
46731cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46741cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalUint16Array);
46751cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetInt16:
46761cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46771cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalInt16Array);
46781cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetUint32:
46791cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46801cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalUint32Array);
46811cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetInt32:
46821cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46831cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalInt32Array);
46841cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetFloat32:
46851cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46861cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalFloat32Array);
46871cb0ef41Sopenharmony_ci    case Builtin::kDataViewPrototypeSetFloat64:
46881cb0ef41Sopenharmony_ci      return ReduceDataViewAccess(node, DataViewAccess::kSet,
46891cb0ef41Sopenharmony_ci                                  ExternalArrayType::kExternalFloat64Array);
46901cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeByteLength:
46911cb0ef41Sopenharmony_ci      return ReduceArrayBufferViewAccessor(
46921cb0ef41Sopenharmony_ci          node, JS_TYPED_ARRAY_TYPE,
46931cb0ef41Sopenharmony_ci          AccessBuilder::ForJSArrayBufferViewByteLength());
46941cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeByteOffset:
46951cb0ef41Sopenharmony_ci      return ReduceArrayBufferViewAccessor(
46961cb0ef41Sopenharmony_ci          node, JS_TYPED_ARRAY_TYPE,
46971cb0ef41Sopenharmony_ci          AccessBuilder::ForJSArrayBufferViewByteOffset());
46981cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeLength:
46991cb0ef41Sopenharmony_ci      return ReduceArrayBufferViewAccessor(
47001cb0ef41Sopenharmony_ci          node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
47011cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeToStringTag:
47021cb0ef41Sopenharmony_ci      return ReduceTypedArrayPrototypeToStringTag(node);
47031cb0ef41Sopenharmony_ci    case Builtin::kMathAbs:
47041cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAbs());
47051cb0ef41Sopenharmony_ci    case Builtin::kMathAcos:
47061cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAcos());
47071cb0ef41Sopenharmony_ci    case Builtin::kMathAcosh:
47081cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAcosh());
47091cb0ef41Sopenharmony_ci    case Builtin::kMathAsin:
47101cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAsin());
47111cb0ef41Sopenharmony_ci    case Builtin::kMathAsinh:
47121cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAsinh());
47131cb0ef41Sopenharmony_ci    case Builtin::kMathAtan:
47141cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAtan());
47151cb0ef41Sopenharmony_ci    case Builtin::kMathAtanh:
47161cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberAtanh());
47171cb0ef41Sopenharmony_ci    case Builtin::kMathCbrt:
47181cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberCbrt());
47191cb0ef41Sopenharmony_ci    case Builtin::kMathCeil:
47201cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberCeil());
47211cb0ef41Sopenharmony_ci    case Builtin::kMathCos:
47221cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberCos());
47231cb0ef41Sopenharmony_ci    case Builtin::kMathCosh:
47241cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberCosh());
47251cb0ef41Sopenharmony_ci    case Builtin::kMathExp:
47261cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberExp());
47271cb0ef41Sopenharmony_ci    case Builtin::kMathExpm1:
47281cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberExpm1());
47291cb0ef41Sopenharmony_ci    case Builtin::kMathFloor:
47301cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberFloor());
47311cb0ef41Sopenharmony_ci    case Builtin::kMathFround:
47321cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberFround());
47331cb0ef41Sopenharmony_ci    case Builtin::kMathLog:
47341cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberLog());
47351cb0ef41Sopenharmony_ci    case Builtin::kMathLog1p:
47361cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberLog1p());
47371cb0ef41Sopenharmony_ci    case Builtin::kMathLog10:
47381cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberLog10());
47391cb0ef41Sopenharmony_ci    case Builtin::kMathLog2:
47401cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberLog2());
47411cb0ef41Sopenharmony_ci    case Builtin::kMathRound:
47421cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberRound());
47431cb0ef41Sopenharmony_ci    case Builtin::kMathSign:
47441cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberSign());
47451cb0ef41Sopenharmony_ci    case Builtin::kMathSin:
47461cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberSin());
47471cb0ef41Sopenharmony_ci    case Builtin::kMathSinh:
47481cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberSinh());
47491cb0ef41Sopenharmony_ci    case Builtin::kMathSqrt:
47501cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberSqrt());
47511cb0ef41Sopenharmony_ci    case Builtin::kMathTan:
47521cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberTan());
47531cb0ef41Sopenharmony_ci    case Builtin::kMathTanh:
47541cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberTanh());
47551cb0ef41Sopenharmony_ci    case Builtin::kMathTrunc:
47561cb0ef41Sopenharmony_ci      return ReduceMathUnary(node, simplified()->NumberTrunc());
47571cb0ef41Sopenharmony_ci    case Builtin::kMathAtan2:
47581cb0ef41Sopenharmony_ci      return ReduceMathBinary(node, simplified()->NumberAtan2());
47591cb0ef41Sopenharmony_ci    case Builtin::kMathPow:
47601cb0ef41Sopenharmony_ci      return ReduceMathBinary(node, simplified()->NumberPow());
47611cb0ef41Sopenharmony_ci    case Builtin::kMathClz32:
47621cb0ef41Sopenharmony_ci      return ReduceMathClz32(node);
47631cb0ef41Sopenharmony_ci    case Builtin::kMathImul:
47641cb0ef41Sopenharmony_ci      return ReduceMathImul(node);
47651cb0ef41Sopenharmony_ci    case Builtin::kMathMax:
47661cb0ef41Sopenharmony_ci      return ReduceMathMinMax(node, simplified()->NumberMax(),
47671cb0ef41Sopenharmony_ci                              jsgraph()->Constant(-V8_INFINITY));
47681cb0ef41Sopenharmony_ci    case Builtin::kMathMin:
47691cb0ef41Sopenharmony_ci      return ReduceMathMinMax(node, simplified()->NumberMin(),
47701cb0ef41Sopenharmony_ci                              jsgraph()->Constant(V8_INFINITY));
47711cb0ef41Sopenharmony_ci    case Builtin::kNumberIsFinite:
47721cb0ef41Sopenharmony_ci      return ReduceNumberIsFinite(node);
47731cb0ef41Sopenharmony_ci    case Builtin::kNumberIsInteger:
47741cb0ef41Sopenharmony_ci      return ReduceNumberIsInteger(node);
47751cb0ef41Sopenharmony_ci    case Builtin::kNumberIsSafeInteger:
47761cb0ef41Sopenharmony_ci      return ReduceNumberIsSafeInteger(node);
47771cb0ef41Sopenharmony_ci    case Builtin::kNumberIsNaN:
47781cb0ef41Sopenharmony_ci      return ReduceNumberIsNaN(node);
47791cb0ef41Sopenharmony_ci    case Builtin::kNumberParseInt:
47801cb0ef41Sopenharmony_ci      return ReduceNumberParseInt(node);
47811cb0ef41Sopenharmony_ci    case Builtin::kGlobalIsFinite:
47821cb0ef41Sopenharmony_ci      return ReduceGlobalIsFinite(node);
47831cb0ef41Sopenharmony_ci    case Builtin::kGlobalIsNaN:
47841cb0ef41Sopenharmony_ci      return ReduceGlobalIsNaN(node);
47851cb0ef41Sopenharmony_ci    case Builtin::kMapPrototypeGet:
47861cb0ef41Sopenharmony_ci      return ReduceMapPrototypeGet(node);
47871cb0ef41Sopenharmony_ci    case Builtin::kMapPrototypeHas:
47881cb0ef41Sopenharmony_ci      return ReduceMapPrototypeHas(node);
47891cb0ef41Sopenharmony_ci    case Builtin::kRegExpPrototypeTest:
47901cb0ef41Sopenharmony_ci      return ReduceRegExpPrototypeTest(node);
47911cb0ef41Sopenharmony_ci    case Builtin::kReturnReceiver:
47921cb0ef41Sopenharmony_ci      return ReduceReturnReceiver(node);
47931cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeIndexOf:
47941cb0ef41Sopenharmony_ci      return ReduceStringPrototypeIndexOfIncludes(
47951cb0ef41Sopenharmony_ci          node, StringIndexOfIncludesVariant::kIndexOf);
47961cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeIncludes:
47971cb0ef41Sopenharmony_ci      return ReduceStringPrototypeIndexOfIncludes(
47981cb0ef41Sopenharmony_ci          node, StringIndexOfIncludesVariant::kIncludes);
47991cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeCharAt:
48001cb0ef41Sopenharmony_ci      return ReduceStringPrototypeCharAt(node);
48011cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeCharCodeAt:
48021cb0ef41Sopenharmony_ci      return ReduceStringPrototypeStringAt(simplified()->StringCharCodeAt(),
48031cb0ef41Sopenharmony_ci                                           node);
48041cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeCodePointAt:
48051cb0ef41Sopenharmony_ci      return ReduceStringPrototypeStringAt(simplified()->StringCodePointAt(),
48061cb0ef41Sopenharmony_ci                                           node);
48071cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeSubstring:
48081cb0ef41Sopenharmony_ci      return ReduceStringPrototypeSubstring(node);
48091cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeSlice:
48101cb0ef41Sopenharmony_ci      return ReduceStringPrototypeSlice(node);
48111cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeSubstr:
48121cb0ef41Sopenharmony_ci      return ReduceStringPrototypeSubstr(node);
48131cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeStartsWith:
48141cb0ef41Sopenharmony_ci      return ReduceStringPrototypeStartsWith(node);
48151cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT
48161cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeToLowerCaseIntl:
48171cb0ef41Sopenharmony_ci      return ReduceStringPrototypeToLowerCaseIntl(node);
48181cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeToUpperCaseIntl:
48191cb0ef41Sopenharmony_ci      return ReduceStringPrototypeToUpperCaseIntl(node);
48201cb0ef41Sopenharmony_ci#endif  // V8_INTL_SUPPORT
48211cb0ef41Sopenharmony_ci    case Builtin::kStringFromCharCode:
48221cb0ef41Sopenharmony_ci      return ReduceStringFromCharCode(node);
48231cb0ef41Sopenharmony_ci    case Builtin::kStringFromCodePoint:
48241cb0ef41Sopenharmony_ci      return ReduceStringFromCodePoint(node);
48251cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeIterator:
48261cb0ef41Sopenharmony_ci      return ReduceStringPrototypeIterator(node);
48271cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeLocaleCompare:
48281cb0ef41Sopenharmony_ci      return ReduceStringPrototypeLocaleCompare(node);
48291cb0ef41Sopenharmony_ci    case Builtin::kStringIteratorPrototypeNext:
48301cb0ef41Sopenharmony_ci      return ReduceStringIteratorPrototypeNext(node);
48311cb0ef41Sopenharmony_ci    case Builtin::kStringPrototypeConcat:
48321cb0ef41Sopenharmony_ci      return ReduceStringPrototypeConcat(node);
48331cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeEntries:
48341cb0ef41Sopenharmony_ci      return ReduceArrayIterator(node, ArrayIteratorKind::kTypedArray,
48351cb0ef41Sopenharmony_ci                                 IterationKind::kEntries);
48361cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeKeys:
48371cb0ef41Sopenharmony_ci      return ReduceArrayIterator(node, ArrayIteratorKind::kTypedArray,
48381cb0ef41Sopenharmony_ci                                 IterationKind::kKeys);
48391cb0ef41Sopenharmony_ci    case Builtin::kTypedArrayPrototypeValues:
48401cb0ef41Sopenharmony_ci      return ReduceArrayIterator(node, ArrayIteratorKind::kTypedArray,
48411cb0ef41Sopenharmony_ci                                 IterationKind::kValues);
48421cb0ef41Sopenharmony_ci    case Builtin::kPromisePrototypeCatch:
48431cb0ef41Sopenharmony_ci      return ReducePromisePrototypeCatch(node);
48441cb0ef41Sopenharmony_ci    case Builtin::kPromisePrototypeFinally:
48451cb0ef41Sopenharmony_ci      return ReducePromisePrototypeFinally(node);
48461cb0ef41Sopenharmony_ci    case Builtin::kPromisePrototypeThen:
48471cb0ef41Sopenharmony_ci      return ReducePromisePrototypeThen(node);
48481cb0ef41Sopenharmony_ci    case Builtin::kPromiseResolveTrampoline:
48491cb0ef41Sopenharmony_ci      return ReducePromiseResolveTrampoline(node);
48501cb0ef41Sopenharmony_ci    case Builtin::kMapPrototypeEntries:
48511cb0ef41Sopenharmony_ci      return ReduceCollectionIteration(node, CollectionKind::kMap,
48521cb0ef41Sopenharmony_ci                                       IterationKind::kEntries);
48531cb0ef41Sopenharmony_ci    case Builtin::kMapPrototypeKeys:
48541cb0ef41Sopenharmony_ci      return ReduceCollectionIteration(node, CollectionKind::kMap,
48551cb0ef41Sopenharmony_ci                                       IterationKind::kKeys);
48561cb0ef41Sopenharmony_ci    case Builtin::kMapPrototypeGetSize:
48571cb0ef41Sopenharmony_ci      return ReduceCollectionPrototypeSize(node, CollectionKind::kMap);
48581cb0ef41Sopenharmony_ci    case Builtin::kMapPrototypeValues:
48591cb0ef41Sopenharmony_ci      return ReduceCollectionIteration(node, CollectionKind::kMap,
48601cb0ef41Sopenharmony_ci                                       IterationKind::kValues);
48611cb0ef41Sopenharmony_ci    case Builtin::kMapIteratorPrototypeNext:
48621cb0ef41Sopenharmony_ci      return ReduceCollectionIteratorPrototypeNext(
48631cb0ef41Sopenharmony_ci          node, OrderedHashMap::kEntrySize, factory()->empty_ordered_hash_map(),
48641cb0ef41Sopenharmony_ci          FIRST_JS_MAP_ITERATOR_TYPE, LAST_JS_MAP_ITERATOR_TYPE);
48651cb0ef41Sopenharmony_ci    case Builtin::kSetPrototypeEntries:
48661cb0ef41Sopenharmony_ci      return ReduceCollectionIteration(node, CollectionKind::kSet,
48671cb0ef41Sopenharmony_ci                                       IterationKind::kEntries);
48681cb0ef41Sopenharmony_ci    case Builtin::kSetPrototypeGetSize:
48691cb0ef41Sopenharmony_ci      return ReduceCollectionPrototypeSize(node, CollectionKind::kSet);
48701cb0ef41Sopenharmony_ci    case Builtin::kSetPrototypeValues:
48711cb0ef41Sopenharmony_ci      return ReduceCollectionIteration(node, CollectionKind::kSet,
48721cb0ef41Sopenharmony_ci                                       IterationKind::kValues);
48731cb0ef41Sopenharmony_ci    case Builtin::kSetIteratorPrototypeNext:
48741cb0ef41Sopenharmony_ci      return ReduceCollectionIteratorPrototypeNext(
48751cb0ef41Sopenharmony_ci          node, OrderedHashSet::kEntrySize, factory()->empty_ordered_hash_set(),
48761cb0ef41Sopenharmony_ci          FIRST_JS_SET_ITERATOR_TYPE, LAST_JS_SET_ITERATOR_TYPE);
48771cb0ef41Sopenharmony_ci    case Builtin::kDatePrototypeGetTime:
48781cb0ef41Sopenharmony_ci      return ReduceDatePrototypeGetTime(node);
48791cb0ef41Sopenharmony_ci    case Builtin::kDateNow:
48801cb0ef41Sopenharmony_ci      return ReduceDateNow(node);
48811cb0ef41Sopenharmony_ci    case Builtin::kNumberConstructor:
48821cb0ef41Sopenharmony_ci      return ReduceNumberConstructor(node);
48831cb0ef41Sopenharmony_ci    case Builtin::kBigIntAsIntN:
48841cb0ef41Sopenharmony_ci    case Builtin::kBigIntAsUintN:
48851cb0ef41Sopenharmony_ci      return ReduceBigIntAsN(node, builtin);
48861cb0ef41Sopenharmony_ci    default:
48871cb0ef41Sopenharmony_ci      break;
48881cb0ef41Sopenharmony_ci  }
48891cb0ef41Sopenharmony_ci
48901cb0ef41Sopenharmony_ci  if (shared.function_template_info().has_value()) {
48911cb0ef41Sopenharmony_ci    return ReduceCallApiFunction(node, shared);
48921cb0ef41Sopenharmony_ci  }
48931cb0ef41Sopenharmony_ci
48941cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
48951cb0ef41Sopenharmony_ci  if ((flags() & kInlineJSToWasmCalls) && shared.wasm_function_signature()) {
48961cb0ef41Sopenharmony_ci    return ReduceCallWasmFunction(node, shared);
48971cb0ef41Sopenharmony_ci  }
48981cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
48991cb0ef41Sopenharmony_ci
49001cb0ef41Sopenharmony_ci  return NoChange();
49011cb0ef41Sopenharmony_ci}
49021cb0ef41Sopenharmony_ci
49031cb0ef41Sopenharmony_ciTNode<Object> JSCallReducerAssembler::ReduceJSCallWithArrayLikeOrSpreadOfEmpty(
49041cb0ef41Sopenharmony_ci    std::unordered_set<Node*>* generated_calls_with_array_like_or_spread) {
49051cb0ef41Sopenharmony_ci  DCHECK_EQ(generated_calls_with_array_like_or_spread->count(node_ptr()), 0);
49061cb0ef41Sopenharmony_ci  JSCallWithArrayLikeOrSpreadNode n(node_ptr());
49071cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
49081cb0ef41Sopenharmony_ci  TNode<Object> arguments_list = n.LastArgument();
49091cb0ef41Sopenharmony_ci  DCHECK_EQ(static_cast<Node*>(arguments_list)->opcode(),
49101cb0ef41Sopenharmony_ci            IrOpcode::kJSCreateEmptyLiteralArray);
49111cb0ef41Sopenharmony_ci
49121cb0ef41Sopenharmony_ci  // Turn the JSCallWithArrayLike or JSCallWithSpread roughly into:
49131cb0ef41Sopenharmony_ci  //
49141cb0ef41Sopenharmony_ci  //      "arguments_list array is still empty?"
49151cb0ef41Sopenharmony_ci  //               |
49161cb0ef41Sopenharmony_ci  //               |
49171cb0ef41Sopenharmony_ci  //            Branch
49181cb0ef41Sopenharmony_ci  //           /      \
49191cb0ef41Sopenharmony_ci  //          /        \
49201cb0ef41Sopenharmony_ci  //      IfTrue      IfFalse
49211cb0ef41Sopenharmony_ci  //         |          |
49221cb0ef41Sopenharmony_ci  //         |          |
49231cb0ef41Sopenharmony_ci  //      JSCall    JSCallWithArrayLike/JSCallWithSpread
49241cb0ef41Sopenharmony_ci  //          \        /
49251cb0ef41Sopenharmony_ci  //           \      /
49261cb0ef41Sopenharmony_ci  //            Merge
49271cb0ef41Sopenharmony_ci
49281cb0ef41Sopenharmony_ci  TNode<Number> length = TNode<Number>::UncheckedCast(
49291cb0ef41Sopenharmony_ci      LoadField(AccessBuilder::ForJSArrayLength(NO_ELEMENTS), arguments_list));
49301cb0ef41Sopenharmony_ci  return SelectIf<Object>(NumberEqual(length, ZeroConstant()))
49311cb0ef41Sopenharmony_ci      .Then([&]() {
49321cb0ef41Sopenharmony_ci        TNode<Object> call = CopyNode();
49331cb0ef41Sopenharmony_ci        static_cast<Node*>(call)->RemoveInput(n.LastArgumentIndex());
49341cb0ef41Sopenharmony_ci        NodeProperties::ChangeOp(
49351cb0ef41Sopenharmony_ci            call, javascript()->Call(p.arity() - 1, p.frequency(), p.feedback(),
49361cb0ef41Sopenharmony_ci                                     p.convert_mode(), p.speculation_mode(),
49371cb0ef41Sopenharmony_ci                                     p.feedback_relation()));
49381cb0ef41Sopenharmony_ci        return call;
49391cb0ef41Sopenharmony_ci      })
49401cb0ef41Sopenharmony_ci      .Else([&]() {
49411cb0ef41Sopenharmony_ci        TNode<Object> call = CopyNode();
49421cb0ef41Sopenharmony_ci        generated_calls_with_array_like_or_spread->insert(call);
49431cb0ef41Sopenharmony_ci        return call;
49441cb0ef41Sopenharmony_ci      })
49451cb0ef41Sopenharmony_ci      .ExpectFalse()
49461cb0ef41Sopenharmony_ci      .Value();
49471cb0ef41Sopenharmony_ci}
49481cb0ef41Sopenharmony_ci
49491cb0ef41Sopenharmony_cinamespace {
49501cb0ef41Sopenharmony_ci
49511cb0ef41Sopenharmony_ci// Check if the target is a class constructor.
49521cb0ef41Sopenharmony_ci// We need to check all cases where the target will be typed as Function
49531cb0ef41Sopenharmony_ci// to prevent later optimizations from using the CallFunction trampoline,
49541cb0ef41Sopenharmony_ci// skipping the instance type check.
49551cb0ef41Sopenharmony_cibool TargetIsClassConstructor(Node* node, JSHeapBroker* broker) {
49561cb0ef41Sopenharmony_ci  Node* target = NodeProperties::GetValueInput(node, 0);
49571cb0ef41Sopenharmony_ci  base::Optional<SharedFunctionInfoRef> shared;
49581cb0ef41Sopenharmony_ci  HeapObjectMatcher m(target);
49591cb0ef41Sopenharmony_ci  if (m.HasResolvedValue()) {
49601cb0ef41Sopenharmony_ci    ObjectRef target_ref = m.Ref(broker);
49611cb0ef41Sopenharmony_ci    if (target_ref.IsJSFunction()) {
49621cb0ef41Sopenharmony_ci      JSFunctionRef function = target_ref.AsJSFunction();
49631cb0ef41Sopenharmony_ci      shared = function.shared();
49641cb0ef41Sopenharmony_ci    }
49651cb0ef41Sopenharmony_ci  } else if (target->opcode() == IrOpcode::kJSCreateClosure) {
49661cb0ef41Sopenharmony_ci    CreateClosureParameters const& ccp =
49671cb0ef41Sopenharmony_ci        JSCreateClosureNode{target}.Parameters();
49681cb0ef41Sopenharmony_ci    shared = ccp.shared_info(broker);
49691cb0ef41Sopenharmony_ci  } else if (target->opcode() == IrOpcode::kCheckClosure) {
49701cb0ef41Sopenharmony_ci    FeedbackCellRef cell = MakeRef(broker, FeedbackCellOf(target->op()));
49711cb0ef41Sopenharmony_ci    shared = cell.shared_function_info();
49721cb0ef41Sopenharmony_ci  }
49731cb0ef41Sopenharmony_ci
49741cb0ef41Sopenharmony_ci  if (shared.has_value() && IsClassConstructor(shared->kind())) return true;
49751cb0ef41Sopenharmony_ci
49761cb0ef41Sopenharmony_ci  return false;
49771cb0ef41Sopenharmony_ci}
49781cb0ef41Sopenharmony_ci
49791cb0ef41Sopenharmony_ci}  // namespace
49801cb0ef41Sopenharmony_ci
49811cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSCallWithArrayLike(Node* node) {
49821cb0ef41Sopenharmony_ci  JSCallWithArrayLikeNode n(node);
49831cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
49841cb0ef41Sopenharmony_ci  DCHECK_EQ(p.arity_without_implicit_args(), 1);  // The arraylike object.
49851cb0ef41Sopenharmony_ci  // Class constructors are callable, but [[Call]] will raise an exception.
49861cb0ef41Sopenharmony_ci  // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
49871cb0ef41Sopenharmony_ci  if (TargetIsClassConstructor(node, broker())) {
49881cb0ef41Sopenharmony_ci    return NoChange();
49891cb0ef41Sopenharmony_ci  }
49901cb0ef41Sopenharmony_ci  return ReduceCallOrConstructWithArrayLikeOrSpread(
49911cb0ef41Sopenharmony_ci      node, n.ArgumentCount(), n.LastArgumentIndex(), p.frequency(),
49921cb0ef41Sopenharmony_ci      p.feedback(), p.speculation_mode(), p.feedback_relation(), n.target(),
49931cb0ef41Sopenharmony_ci      n.effect(), n.control());
49941cb0ef41Sopenharmony_ci}
49951cb0ef41Sopenharmony_ci
49961cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
49971cb0ef41Sopenharmony_ci  JSCallWithSpreadNode n(node);
49981cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
49991cb0ef41Sopenharmony_ci  DCHECK_GE(p.arity_without_implicit_args(), 1);  // At least the spread.
50001cb0ef41Sopenharmony_ci  // Class constructors are callable, but [[Call]] will raise an exception.
50011cb0ef41Sopenharmony_ci  // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
50021cb0ef41Sopenharmony_ci  if (TargetIsClassConstructor(node, broker())) {
50031cb0ef41Sopenharmony_ci    return NoChange();
50041cb0ef41Sopenharmony_ci  }
50051cb0ef41Sopenharmony_ci  return ReduceCallOrConstructWithArrayLikeOrSpread(
50061cb0ef41Sopenharmony_ci      node, n.ArgumentCount(), n.LastArgumentIndex(), p.frequency(),
50071cb0ef41Sopenharmony_ci      p.feedback(), p.speculation_mode(), p.feedback_relation(), n.target(),
50081cb0ef41Sopenharmony_ci      n.effect(), n.control());
50091cb0ef41Sopenharmony_ci}
50101cb0ef41Sopenharmony_ci
50111cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSConstruct(Node* node) {
50121cb0ef41Sopenharmony_ci  if (broker()->StackHasOverflowed()) return NoChange();
50131cb0ef41Sopenharmony_ci
50141cb0ef41Sopenharmony_ci  JSConstructNode n(node);
50151cb0ef41Sopenharmony_ci  ConstructParameters const& p = n.Parameters();
50161cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
50171cb0ef41Sopenharmony_ci  Node* target = n.target();
50181cb0ef41Sopenharmony_ci  Node* new_target = n.new_target();
50191cb0ef41Sopenharmony_ci  Effect effect = n.effect();
50201cb0ef41Sopenharmony_ci  Control control = n.control();
50211cb0ef41Sopenharmony_ci
50221cb0ef41Sopenharmony_ci  if (p.feedback().IsValid()) {
50231cb0ef41Sopenharmony_ci    ProcessedFeedback const& feedback =
50241cb0ef41Sopenharmony_ci        broker()->GetFeedbackForCall(p.feedback());
50251cb0ef41Sopenharmony_ci    if (feedback.IsInsufficient()) {
50261cb0ef41Sopenharmony_ci      return ReduceForInsufficientFeedback(
50271cb0ef41Sopenharmony_ci          node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
50281cb0ef41Sopenharmony_ci    }
50291cb0ef41Sopenharmony_ci
50301cb0ef41Sopenharmony_ci    base::Optional<HeapObjectRef> feedback_target = feedback.AsCall().target();
50311cb0ef41Sopenharmony_ci    if (feedback_target.has_value() && feedback_target->IsAllocationSite()) {
50321cb0ef41Sopenharmony_ci      // The feedback is an AllocationSite, which means we have called the
50331cb0ef41Sopenharmony_ci      // Array function and collected transition (and pretenuring) feedback
50341cb0ef41Sopenharmony_ci      // for the resulting arrays.  This has to be kept in sync with the
50351cb0ef41Sopenharmony_ci      // implementation in Ignition.
50361cb0ef41Sopenharmony_ci
50371cb0ef41Sopenharmony_ci      Node* array_function =
50381cb0ef41Sopenharmony_ci          jsgraph()->Constant(native_context().array_function());
50391cb0ef41Sopenharmony_ci
50401cb0ef41Sopenharmony_ci      // Check that the {target} is still the {array_function}.
50411cb0ef41Sopenharmony_ci      Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
50421cb0ef41Sopenharmony_ci                                     array_function);
50431cb0ef41Sopenharmony_ci      effect = graph()->NewNode(
50441cb0ef41Sopenharmony_ci          simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
50451cb0ef41Sopenharmony_ci          effect, control);
50461cb0ef41Sopenharmony_ci
50471cb0ef41Sopenharmony_ci      // Turn the {node} into a {JSCreateArray} call.
50481cb0ef41Sopenharmony_ci      NodeProperties::ReplaceEffectInput(node, effect);
50491cb0ef41Sopenharmony_ci      STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
50501cb0ef41Sopenharmony_ci      node->ReplaceInput(n.NewTargetIndex(), array_function);
50511cb0ef41Sopenharmony_ci      node->RemoveInput(n.FeedbackVectorIndex());
50521cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(
50531cb0ef41Sopenharmony_ci          node, javascript()->CreateArray(arity,
50541cb0ef41Sopenharmony_ci                                          feedback_target->AsAllocationSite()));
50551cb0ef41Sopenharmony_ci      return Changed(node);
50561cb0ef41Sopenharmony_ci    } else if (feedback_target.has_value() &&
50571cb0ef41Sopenharmony_ci               !HeapObjectMatcher(new_target).HasResolvedValue() &&
50581cb0ef41Sopenharmony_ci               feedback_target->map().is_constructor()) {
50591cb0ef41Sopenharmony_ci      Node* new_target_feedback = jsgraph()->Constant(*feedback_target);
50601cb0ef41Sopenharmony_ci
50611cb0ef41Sopenharmony_ci      // Check that the {new_target} is still the {new_target_feedback}.
50621cb0ef41Sopenharmony_ci      Node* check = graph()->NewNode(simplified()->ReferenceEqual(), new_target,
50631cb0ef41Sopenharmony_ci                                     new_target_feedback);
50641cb0ef41Sopenharmony_ci      effect = graph()->NewNode(
50651cb0ef41Sopenharmony_ci          simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
50661cb0ef41Sopenharmony_ci          effect, control);
50671cb0ef41Sopenharmony_ci
50681cb0ef41Sopenharmony_ci      // Specialize the JSConstruct node to the {new_target_feedback}.
50691cb0ef41Sopenharmony_ci      node->ReplaceInput(n.NewTargetIndex(), new_target_feedback);
50701cb0ef41Sopenharmony_ci      NodeProperties::ReplaceEffectInput(node, effect);
50711cb0ef41Sopenharmony_ci      if (target == new_target) {
50721cb0ef41Sopenharmony_ci        node->ReplaceInput(n.TargetIndex(), new_target_feedback);
50731cb0ef41Sopenharmony_ci      }
50741cb0ef41Sopenharmony_ci
50751cb0ef41Sopenharmony_ci      // Try to further reduce the JSConstruct {node}.
50761cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceJSConstruct(node));
50771cb0ef41Sopenharmony_ci    }
50781cb0ef41Sopenharmony_ci  }
50791cb0ef41Sopenharmony_ci
50801cb0ef41Sopenharmony_ci  // Try to specialize JSConstruct {node}s with constant {target}s.
50811cb0ef41Sopenharmony_ci  HeapObjectMatcher m(target);
50821cb0ef41Sopenharmony_ci  if (m.HasResolvedValue()) {
50831cb0ef41Sopenharmony_ci    HeapObjectRef target_ref = m.Ref(broker());
50841cb0ef41Sopenharmony_ci
50851cb0ef41Sopenharmony_ci    // Raise a TypeError if the {target} is not a constructor.
50861cb0ef41Sopenharmony_ci    if (!target_ref.map().is_constructor()) {
50871cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInputs(node, target);
50881cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(node,
50891cb0ef41Sopenharmony_ci                               javascript()->CallRuntime(
50901cb0ef41Sopenharmony_ci                                   Runtime::kThrowConstructedNonConstructable));
50911cb0ef41Sopenharmony_ci      return Changed(node);
50921cb0ef41Sopenharmony_ci    }
50931cb0ef41Sopenharmony_ci
50941cb0ef41Sopenharmony_ci    if (target_ref.IsJSFunction()) {
50951cb0ef41Sopenharmony_ci      JSFunctionRef function = target_ref.AsJSFunction();
50961cb0ef41Sopenharmony_ci
50971cb0ef41Sopenharmony_ci      // Do not reduce constructors with break points.
50981cb0ef41Sopenharmony_ci      // If this state changes during background compilation, the compilation
50991cb0ef41Sopenharmony_ci      // job will be aborted from the main thread (see
51001cb0ef41Sopenharmony_ci      // Debug::PrepareFunctionForDebugExecution()).
51011cb0ef41Sopenharmony_ci      SharedFunctionInfoRef sfi = function.shared();
51021cb0ef41Sopenharmony_ci      if (sfi.HasBreakInfo()) return NoChange();
51031cb0ef41Sopenharmony_ci
51041cb0ef41Sopenharmony_ci      // Don't inline cross native context.
51051cb0ef41Sopenharmony_ci      if (!function.native_context().equals(native_context())) {
51061cb0ef41Sopenharmony_ci        return NoChange();
51071cb0ef41Sopenharmony_ci      }
51081cb0ef41Sopenharmony_ci
51091cb0ef41Sopenharmony_ci      // Check for known builtin functions.
51101cb0ef41Sopenharmony_ci      Builtin builtin =
51111cb0ef41Sopenharmony_ci          sfi.HasBuiltinId() ? sfi.builtin_id() : Builtin::kNoBuiltinId;
51121cb0ef41Sopenharmony_ci      switch (builtin) {
51131cb0ef41Sopenharmony_ci        case Builtin::kArrayConstructor: {
51141cb0ef41Sopenharmony_ci          // TODO(bmeurer): Deal with Array subclasses here.
51151cb0ef41Sopenharmony_ci          // Turn the {node} into a {JSCreateArray} call.
51161cb0ef41Sopenharmony_ci          STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
51171cb0ef41Sopenharmony_ci          node->ReplaceInput(n.NewTargetIndex(), new_target);
51181cb0ef41Sopenharmony_ci          node->RemoveInput(n.FeedbackVectorIndex());
51191cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(
51201cb0ef41Sopenharmony_ci              node, javascript()->CreateArray(arity, base::nullopt));
51211cb0ef41Sopenharmony_ci          return Changed(node);
51221cb0ef41Sopenharmony_ci        }
51231cb0ef41Sopenharmony_ci        case Builtin::kObjectConstructor: {
51241cb0ef41Sopenharmony_ci          // If no value is passed, we can immediately lower to a simple
51251cb0ef41Sopenharmony_ci          // JSCreate and don't need to do any massaging of the {node}.
51261cb0ef41Sopenharmony_ci          if (arity == 0) {
51271cb0ef41Sopenharmony_ci            node->RemoveInput(n.FeedbackVectorIndex());
51281cb0ef41Sopenharmony_ci            NodeProperties::ChangeOp(node, javascript()->Create());
51291cb0ef41Sopenharmony_ci            return Changed(node);
51301cb0ef41Sopenharmony_ci          }
51311cb0ef41Sopenharmony_ci
51321cb0ef41Sopenharmony_ci          // If {target} is not the same as {new_target} (i.e. the Object
51331cb0ef41Sopenharmony_ci          // constructor), {value} will be ignored and therefore we can lower
51341cb0ef41Sopenharmony_ci          // to {JSCreate}. See https://tc39.es/ecma262/#sec-object-value.
51351cb0ef41Sopenharmony_ci          HeapObjectMatcher mnew_target(new_target);
51361cb0ef41Sopenharmony_ci          if (mnew_target.HasResolvedValue() &&
51371cb0ef41Sopenharmony_ci              !mnew_target.Ref(broker()).equals(function)) {
51381cb0ef41Sopenharmony_ci            // Drop the value inputs.
51391cb0ef41Sopenharmony_ci            node->RemoveInput(n.FeedbackVectorIndex());
51401cb0ef41Sopenharmony_ci            for (int i = n.ArgumentCount() - 1; i >= 0; i--) {
51411cb0ef41Sopenharmony_ci              node->RemoveInput(n.ArgumentIndex(i));
51421cb0ef41Sopenharmony_ci            }
51431cb0ef41Sopenharmony_ci            NodeProperties::ChangeOp(node, javascript()->Create());
51441cb0ef41Sopenharmony_ci            return Changed(node);
51451cb0ef41Sopenharmony_ci          }
51461cb0ef41Sopenharmony_ci          break;
51471cb0ef41Sopenharmony_ci        }
51481cb0ef41Sopenharmony_ci        case Builtin::kPromiseConstructor:
51491cb0ef41Sopenharmony_ci          return ReducePromiseConstructor(node);
51501cb0ef41Sopenharmony_ci        case Builtin::kTypedArrayConstructor:
51511cb0ef41Sopenharmony_ci          return ReduceTypedArrayConstructor(node, function.shared());
51521cb0ef41Sopenharmony_ci        default:
51531cb0ef41Sopenharmony_ci          break;
51541cb0ef41Sopenharmony_ci      }
51551cb0ef41Sopenharmony_ci    } else if (target_ref.IsJSBoundFunction()) {
51561cb0ef41Sopenharmony_ci      JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
51571cb0ef41Sopenharmony_ci      JSReceiverRef bound_target_function = function.bound_target_function();
51581cb0ef41Sopenharmony_ci      FixedArrayRef bound_arguments = function.bound_arguments();
51591cb0ef41Sopenharmony_ci      const int bound_arguments_length = bound_arguments.length();
51601cb0ef41Sopenharmony_ci
51611cb0ef41Sopenharmony_ci      // TODO(jgruber): Inline this block below once TryGet is guaranteed to
51621cb0ef41Sopenharmony_ci      // succeed.
51631cb0ef41Sopenharmony_ci      static constexpr int kInlineSize = 16;  // Arbitrary.
51641cb0ef41Sopenharmony_ci      base::SmallVector<Node*, kInlineSize> args;
51651cb0ef41Sopenharmony_ci      for (int i = 0; i < bound_arguments_length; ++i) {
51661cb0ef41Sopenharmony_ci        base::Optional<ObjectRef> maybe_arg = bound_arguments.TryGet(i);
51671cb0ef41Sopenharmony_ci        if (!maybe_arg.has_value()) {
51681cb0ef41Sopenharmony_ci          TRACE_BROKER_MISSING(broker(), "bound argument");
51691cb0ef41Sopenharmony_ci          return NoChange();
51701cb0ef41Sopenharmony_ci        }
51711cb0ef41Sopenharmony_ci        args.emplace_back(jsgraph()->Constant(maybe_arg.value()));
51721cb0ef41Sopenharmony_ci      }
51731cb0ef41Sopenharmony_ci
51741cb0ef41Sopenharmony_ci      // Patch {node} to use [[BoundTargetFunction]].
51751cb0ef41Sopenharmony_ci      node->ReplaceInput(n.TargetIndex(),
51761cb0ef41Sopenharmony_ci                         jsgraph()->Constant(bound_target_function));
51771cb0ef41Sopenharmony_ci
51781cb0ef41Sopenharmony_ci      // Patch {node} to use [[BoundTargetFunction]]
51791cb0ef41Sopenharmony_ci      // as new.target if {new_target} equals {target}.
51801cb0ef41Sopenharmony_ci      if (target == new_target) {
51811cb0ef41Sopenharmony_ci        node->ReplaceInput(n.NewTargetIndex(),
51821cb0ef41Sopenharmony_ci                           jsgraph()->Constant(bound_target_function));
51831cb0ef41Sopenharmony_ci      } else {
51841cb0ef41Sopenharmony_ci        node->ReplaceInput(
51851cb0ef41Sopenharmony_ci            n.NewTargetIndex(),
51861cb0ef41Sopenharmony_ci            graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
51871cb0ef41Sopenharmony_ci                             graph()->NewNode(simplified()->ReferenceEqual(),
51881cb0ef41Sopenharmony_ci                                              target, new_target),
51891cb0ef41Sopenharmony_ci                             jsgraph()->Constant(bound_target_function),
51901cb0ef41Sopenharmony_ci                             new_target));
51911cb0ef41Sopenharmony_ci      }
51921cb0ef41Sopenharmony_ci
51931cb0ef41Sopenharmony_ci      // Insert the [[BoundArguments]] for {node}.
51941cb0ef41Sopenharmony_ci      for (int i = 0; i < bound_arguments_length; ++i) {
51951cb0ef41Sopenharmony_ci        node->InsertInput(graph()->zone(), n.ArgumentIndex(i), args[i]);
51961cb0ef41Sopenharmony_ci        arity++;
51971cb0ef41Sopenharmony_ci      }
51981cb0ef41Sopenharmony_ci
51991cb0ef41Sopenharmony_ci      // Update the JSConstruct operator on {node}.
52001cb0ef41Sopenharmony_ci      NodeProperties::ChangeOp(
52011cb0ef41Sopenharmony_ci          node, javascript()->Construct(JSConstructNode::ArityForArgc(arity),
52021cb0ef41Sopenharmony_ci                                        p.frequency(), FeedbackSource()));
52031cb0ef41Sopenharmony_ci
52041cb0ef41Sopenharmony_ci      // Try to further reduce the JSConstruct {node}.
52051cb0ef41Sopenharmony_ci      return Changed(node).FollowedBy(ReduceJSConstruct(node));
52061cb0ef41Sopenharmony_ci    }
52071cb0ef41Sopenharmony_ci
52081cb0ef41Sopenharmony_ci    // TODO(bmeurer): Also support optimizing proxies here.
52091cb0ef41Sopenharmony_ci  }
52101cb0ef41Sopenharmony_ci
52111cb0ef41Sopenharmony_ci  // If {target} is the result of a JSCreateBoundFunction operation,
52121cb0ef41Sopenharmony_ci  // we can just fold the construction and construct the bound target
52131cb0ef41Sopenharmony_ci  // function directly instead.
52141cb0ef41Sopenharmony_ci  if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
52151cb0ef41Sopenharmony_ci    Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
52161cb0ef41Sopenharmony_ci    int const bound_arguments_length =
52171cb0ef41Sopenharmony_ci        static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());
52181cb0ef41Sopenharmony_ci
52191cb0ef41Sopenharmony_ci    // Patch the {node} to use [[BoundTargetFunction]].
52201cb0ef41Sopenharmony_ci    node->ReplaceInput(n.TargetIndex(), bound_target_function);
52211cb0ef41Sopenharmony_ci
52221cb0ef41Sopenharmony_ci    // Patch {node} to use [[BoundTargetFunction]]
52231cb0ef41Sopenharmony_ci    // as new.target if {new_target} equals {target}.
52241cb0ef41Sopenharmony_ci    if (target == new_target) {
52251cb0ef41Sopenharmony_ci      node->ReplaceInput(n.NewTargetIndex(), bound_target_function);
52261cb0ef41Sopenharmony_ci    } else {
52271cb0ef41Sopenharmony_ci      node->ReplaceInput(
52281cb0ef41Sopenharmony_ci          n.NewTargetIndex(),
52291cb0ef41Sopenharmony_ci          graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
52301cb0ef41Sopenharmony_ci                           graph()->NewNode(simplified()->ReferenceEqual(),
52311cb0ef41Sopenharmony_ci                                            target, new_target),
52321cb0ef41Sopenharmony_ci                           bound_target_function, new_target));
52331cb0ef41Sopenharmony_ci    }
52341cb0ef41Sopenharmony_ci
52351cb0ef41Sopenharmony_ci    // Insert the [[BoundArguments]] for {node}.
52361cb0ef41Sopenharmony_ci    for (int i = 0; i < bound_arguments_length; ++i) {
52371cb0ef41Sopenharmony_ci      Node* value = NodeProperties::GetValueInput(target, 2 + i);
52381cb0ef41Sopenharmony_ci      node->InsertInput(graph()->zone(), n.ArgumentIndex(i), value);
52391cb0ef41Sopenharmony_ci      arity++;
52401cb0ef41Sopenharmony_ci    }
52411cb0ef41Sopenharmony_ci
52421cb0ef41Sopenharmony_ci    // Update the JSConstruct operator on {node}.
52431cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
52441cb0ef41Sopenharmony_ci        node, javascript()->Construct(JSConstructNode::ArityForArgc(arity),
52451cb0ef41Sopenharmony_ci                                      p.frequency(), FeedbackSource()));
52461cb0ef41Sopenharmony_ci
52471cb0ef41Sopenharmony_ci    // Try to further reduce the JSConstruct {node}.
52481cb0ef41Sopenharmony_ci    return Changed(node).FollowedBy(ReduceJSConstruct(node));
52491cb0ef41Sopenharmony_ci  }
52501cb0ef41Sopenharmony_ci
52511cb0ef41Sopenharmony_ci  return NoChange();
52521cb0ef41Sopenharmony_ci}
52531cb0ef41Sopenharmony_ci
52541cb0ef41Sopenharmony_ci// ES #sec-string.prototype.indexof
52551cb0ef41Sopenharmony_ci// ES #sec-string.prototype.includes
52561cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeIndexOfIncludes(
52571cb0ef41Sopenharmony_ci    Node* node, StringIndexOfIncludesVariant variant) {
52581cb0ef41Sopenharmony_ci  JSCallNode n(node);
52591cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
52601cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
52611cb0ef41Sopenharmony_ci    return NoChange();
52621cb0ef41Sopenharmony_ci  }
52631cb0ef41Sopenharmony_ci
52641cb0ef41Sopenharmony_ci  Effect effect = n.effect();
52651cb0ef41Sopenharmony_ci  Control control = n.control();
52661cb0ef41Sopenharmony_ci  if (n.ArgumentCount() > 0) {
52671cb0ef41Sopenharmony_ci    Node* receiver = n.receiver();
52681cb0ef41Sopenharmony_ci    Node* new_receiver = effect = graph()->NewNode(
52691cb0ef41Sopenharmony_ci        simplified()->CheckString(p.feedback()), receiver, effect, control);
52701cb0ef41Sopenharmony_ci
52711cb0ef41Sopenharmony_ci    Node* search_string = n.Argument(0);
52721cb0ef41Sopenharmony_ci    Node* new_search_string = effect =
52731cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->CheckString(p.feedback()), search_string,
52741cb0ef41Sopenharmony_ci                         effect, control);
52751cb0ef41Sopenharmony_ci
52761cb0ef41Sopenharmony_ci    Node* new_position = jsgraph()->ZeroConstant();
52771cb0ef41Sopenharmony_ci    if (n.ArgumentCount() > 1) {
52781cb0ef41Sopenharmony_ci      Node* position = n.Argument(1);
52791cb0ef41Sopenharmony_ci      new_position = effect = graph()->NewNode(
52801cb0ef41Sopenharmony_ci          simplified()->CheckSmi(p.feedback()), position, effect, control);
52811cb0ef41Sopenharmony_ci
52821cb0ef41Sopenharmony_ci      Node* receiver_length =
52831cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->StringLength(), new_receiver);
52841cb0ef41Sopenharmony_ci      new_position = graph()->NewNode(
52851cb0ef41Sopenharmony_ci          simplified()->NumberMin(),
52861cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->NumberMax(), new_position,
52871cb0ef41Sopenharmony_ci                           jsgraph()->ZeroConstant()),
52881cb0ef41Sopenharmony_ci          receiver_length);
52891cb0ef41Sopenharmony_ci    }
52901cb0ef41Sopenharmony_ci
52911cb0ef41Sopenharmony_ci    NodeProperties::ReplaceEffectInput(node, effect);
52921cb0ef41Sopenharmony_ci    RelaxEffectsAndControls(node);
52931cb0ef41Sopenharmony_ci    node->ReplaceInput(0, new_receiver);
52941cb0ef41Sopenharmony_ci    node->ReplaceInput(1, new_search_string);
52951cb0ef41Sopenharmony_ci    node->ReplaceInput(2, new_position);
52961cb0ef41Sopenharmony_ci    node->TrimInputCount(3);
52971cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, simplified()->StringIndexOf());
52981cb0ef41Sopenharmony_ci
52991cb0ef41Sopenharmony_ci    if (variant == StringIndexOfIncludesVariant::kIndexOf) {
53001cb0ef41Sopenharmony_ci      return Changed(node);
53011cb0ef41Sopenharmony_ci    } else {
53021cb0ef41Sopenharmony_ci      DCHECK(variant == StringIndexOfIncludesVariant::kIncludes);
53031cb0ef41Sopenharmony_ci      Node* result =
53041cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->BooleanNot(),
53051cb0ef41Sopenharmony_ci                           graph()->NewNode(simplified()->NumberEqual(), node,
53061cb0ef41Sopenharmony_ci                                            jsgraph()->SmiConstant(-1)));
53071cb0ef41Sopenharmony_ci      return Replace(result);
53081cb0ef41Sopenharmony_ci    }
53091cb0ef41Sopenharmony_ci  }
53101cb0ef41Sopenharmony_ci  return NoChange();
53111cb0ef41Sopenharmony_ci}
53121cb0ef41Sopenharmony_ci
53131cb0ef41Sopenharmony_ci// ES #sec-string.prototype.substring
53141cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
53151cb0ef41Sopenharmony_ci  JSCallNode n(node);
53161cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
53171cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) return NoChange();
53181cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
53191cb0ef41Sopenharmony_ci    return NoChange();
53201cb0ef41Sopenharmony_ci  }
53211cb0ef41Sopenharmony_ci
53221cb0ef41Sopenharmony_ci  JSCallReducerAssembler a(this, node);
53231cb0ef41Sopenharmony_ci  Node* subgraph = a.ReduceStringPrototypeSubstring();
53241cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
53251cb0ef41Sopenharmony_ci}
53261cb0ef41Sopenharmony_ci
53271cb0ef41Sopenharmony_ci// ES #sec-string.prototype.slice
53281cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
53291cb0ef41Sopenharmony_ci  JSCallNode n(node);
53301cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
53311cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) return NoChange();
53321cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
53331cb0ef41Sopenharmony_ci    return NoChange();
53341cb0ef41Sopenharmony_ci  }
53351cb0ef41Sopenharmony_ci
53361cb0ef41Sopenharmony_ci  JSCallReducerAssembler a(this, node);
53371cb0ef41Sopenharmony_ci  Node* subgraph = a.ReduceStringPrototypeSlice();
53381cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
53391cb0ef41Sopenharmony_ci}
53401cb0ef41Sopenharmony_ci
53411cb0ef41Sopenharmony_ci// ES #sec-string.prototype.substr
53421cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) {
53431cb0ef41Sopenharmony_ci  JSCallNode n(node);
53441cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
53451cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) return NoChange();
53461cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
53471cb0ef41Sopenharmony_ci    return NoChange();
53481cb0ef41Sopenharmony_ci  }
53491cb0ef41Sopenharmony_ci
53501cb0ef41Sopenharmony_ci  Effect effect = n.effect();
53511cb0ef41Sopenharmony_ci  Control control = n.control();
53521cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
53531cb0ef41Sopenharmony_ci  Node* start = n.Argument(0);
53541cb0ef41Sopenharmony_ci  Node* end = n.ArgumentOrUndefined(1, jsgraph());
53551cb0ef41Sopenharmony_ci
53561cb0ef41Sopenharmony_ci  receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
53571cb0ef41Sopenharmony_ci                                       receiver, effect, control);
53581cb0ef41Sopenharmony_ci
53591cb0ef41Sopenharmony_ci  start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
53601cb0ef41Sopenharmony_ci                                    effect, control);
53611cb0ef41Sopenharmony_ci
53621cb0ef41Sopenharmony_ci  Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
53631cb0ef41Sopenharmony_ci
53641cb0ef41Sopenharmony_ci  // Replace {end} argument with {length} if it is undefined.
53651cb0ef41Sopenharmony_ci  {
53661cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
53671cb0ef41Sopenharmony_ci                                   jsgraph()->UndefinedConstant());
53681cb0ef41Sopenharmony_ci    Node* branch =
53691cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
53701cb0ef41Sopenharmony_ci
53711cb0ef41Sopenharmony_ci    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
53721cb0ef41Sopenharmony_ci    Node* etrue = effect;
53731cb0ef41Sopenharmony_ci    Node* vtrue = length;
53741cb0ef41Sopenharmony_ci
53751cb0ef41Sopenharmony_ci    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
53761cb0ef41Sopenharmony_ci    Node* efalse = effect;
53771cb0ef41Sopenharmony_ci    Node* vfalse = efalse = graph()->NewNode(
53781cb0ef41Sopenharmony_ci        simplified()->CheckSmi(p.feedback()), end, efalse, if_false);
53791cb0ef41Sopenharmony_ci
53801cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
53811cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
53821cb0ef41Sopenharmony_ci    end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
53831cb0ef41Sopenharmony_ci                           vtrue, vfalse, control);
53841cb0ef41Sopenharmony_ci  }
53851cb0ef41Sopenharmony_ci
53861cb0ef41Sopenharmony_ci  Node* initStart = graph()->NewNode(
53871cb0ef41Sopenharmony_ci      common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
53881cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->NumberLessThan(), start,
53891cb0ef41Sopenharmony_ci                       jsgraph()->ZeroConstant()),
53901cb0ef41Sopenharmony_ci      graph()->NewNode(
53911cb0ef41Sopenharmony_ci          simplified()->NumberMax(),
53921cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->NumberAdd(), length, start),
53931cb0ef41Sopenharmony_ci          jsgraph()->ZeroConstant()),
53941cb0ef41Sopenharmony_ci      start);
53951cb0ef41Sopenharmony_ci  // The select above guarantees that initStart is non-negative, but
53961cb0ef41Sopenharmony_ci  // our typer can't figure that out yet.
53971cb0ef41Sopenharmony_ci  initStart = effect = graph()->NewNode(
53981cb0ef41Sopenharmony_ci      common()->TypeGuard(Type::UnsignedSmall()), initStart, effect, control);
53991cb0ef41Sopenharmony_ci
54001cb0ef41Sopenharmony_ci  Node* resultLength = graph()->NewNode(
54011cb0ef41Sopenharmony_ci      simplified()->NumberMin(),
54021cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->NumberMax(), end,
54031cb0ef41Sopenharmony_ci                       jsgraph()->ZeroConstant()),
54041cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->NumberSubtract(), length, initStart));
54051cb0ef41Sopenharmony_ci
54061cb0ef41Sopenharmony_ci  // The the select below uses {resultLength} only if {resultLength > 0},
54071cb0ef41Sopenharmony_ci  // but our typer can't figure that out yet.
54081cb0ef41Sopenharmony_ci  Node* to = effect = graph()->NewNode(
54091cb0ef41Sopenharmony_ci      common()->TypeGuard(Type::UnsignedSmall()),
54101cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->NumberAdd(), initStart, resultLength),
54111cb0ef41Sopenharmony_ci      effect, control);
54121cb0ef41Sopenharmony_ci
54131cb0ef41Sopenharmony_ci  Node* result_string = nullptr;
54141cb0ef41Sopenharmony_ci  // Return empty string if {from} is smaller than {to}.
54151cb0ef41Sopenharmony_ci  {
54161cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(simplified()->NumberLessThan(),
54171cb0ef41Sopenharmony_ci                                   jsgraph()->ZeroConstant(), resultLength);
54181cb0ef41Sopenharmony_ci
54191cb0ef41Sopenharmony_ci    Node* branch =
54201cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
54211cb0ef41Sopenharmony_ci
54221cb0ef41Sopenharmony_ci    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
54231cb0ef41Sopenharmony_ci    Node* etrue = effect;
54241cb0ef41Sopenharmony_ci    Node* vtrue = etrue =
54251cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->StringSubstring(), receiver, initStart,
54261cb0ef41Sopenharmony_ci                         to, etrue, if_true);
54271cb0ef41Sopenharmony_ci
54281cb0ef41Sopenharmony_ci    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
54291cb0ef41Sopenharmony_ci    Node* efalse = effect;
54301cb0ef41Sopenharmony_ci    Node* vfalse = jsgraph()->EmptyStringConstant();
54311cb0ef41Sopenharmony_ci
54321cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
54331cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
54341cb0ef41Sopenharmony_ci    result_string =
54351cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
54361cb0ef41Sopenharmony_ci                         vtrue, vfalse, control);
54371cb0ef41Sopenharmony_ci  }
54381cb0ef41Sopenharmony_ci
54391cb0ef41Sopenharmony_ci  ReplaceWithValue(node, result_string, effect, control);
54401cb0ef41Sopenharmony_ci  return Replace(result_string);
54411cb0ef41Sopenharmony_ci}
54421cb0ef41Sopenharmony_ci
54431cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSConstructWithArrayLike(Node* node) {
54441cb0ef41Sopenharmony_ci  JSConstructWithArrayLikeNode n(node);
54451cb0ef41Sopenharmony_ci  ConstructParameters const& p = n.Parameters();
54461cb0ef41Sopenharmony_ci  const int arraylike_index = n.LastArgumentIndex();
54471cb0ef41Sopenharmony_ci  DCHECK_EQ(n.ArgumentCount(), 1);  // The arraylike object.
54481cb0ef41Sopenharmony_ci  return ReduceCallOrConstructWithArrayLikeOrSpread(
54491cb0ef41Sopenharmony_ci      node, n.ArgumentCount(), arraylike_index, p.frequency(), p.feedback(),
54501cb0ef41Sopenharmony_ci      SpeculationMode::kDisallowSpeculation, CallFeedbackRelation::kTarget,
54511cb0ef41Sopenharmony_ci      n.target(), n.effect(), n.control());
54521cb0ef41Sopenharmony_ci}
54531cb0ef41Sopenharmony_ci
54541cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
54551cb0ef41Sopenharmony_ci  JSConstructWithSpreadNode n(node);
54561cb0ef41Sopenharmony_ci  ConstructParameters const& p = n.Parameters();
54571cb0ef41Sopenharmony_ci  const int spread_index = n.LastArgumentIndex();
54581cb0ef41Sopenharmony_ci  DCHECK_GE(n.ArgumentCount(), 1);  // At least the spread.
54591cb0ef41Sopenharmony_ci  return ReduceCallOrConstructWithArrayLikeOrSpread(
54601cb0ef41Sopenharmony_ci      node, n.ArgumentCount(), spread_index, p.frequency(), p.feedback(),
54611cb0ef41Sopenharmony_ci      SpeculationMode::kDisallowSpeculation, CallFeedbackRelation::kTarget,
54621cb0ef41Sopenharmony_ci      n.target(), n.effect(), n.control());
54631cb0ef41Sopenharmony_ci}
54641cb0ef41Sopenharmony_ci
54651cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceReturnReceiver(Node* node) {
54661cb0ef41Sopenharmony_ci  JSCallNode n(node);
54671cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
54681cb0ef41Sopenharmony_ci  ReplaceWithValue(node, receiver);
54691cb0ef41Sopenharmony_ci  return Replace(receiver);
54701cb0ef41Sopenharmony_ci}
54711cb0ef41Sopenharmony_ci
54721cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceForInsufficientFeedback(
54731cb0ef41Sopenharmony_ci    Node* node, DeoptimizeReason reason) {
54741cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kJSCall ||
54751cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kJSConstruct);
54761cb0ef41Sopenharmony_ci  if (!(flags() & kBailoutOnUninitialized)) return NoChange();
54771cb0ef41Sopenharmony_ci
54781cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
54791cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
54801cb0ef41Sopenharmony_ci  Node* frame_state =
54811cb0ef41Sopenharmony_ci      NodeProperties::FindFrameStateBefore(node, jsgraph()->Dead());
54821cb0ef41Sopenharmony_ci  Node* deoptimize =
54831cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Deoptimize(reason, FeedbackSource()),
54841cb0ef41Sopenharmony_ci                       frame_state, effect, control);
54851cb0ef41Sopenharmony_ci  // TODO(bmeurer): This should be on the AdvancedReducer somehow.
54861cb0ef41Sopenharmony_ci  NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
54871cb0ef41Sopenharmony_ci  Revisit(graph()->end());
54881cb0ef41Sopenharmony_ci  node->TrimInputCount(0);
54891cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, common()->Dead());
54901cb0ef41Sopenharmony_ci  return Changed(node);
54911cb0ef41Sopenharmony_ci}
54921cb0ef41Sopenharmony_ci
54931cb0ef41Sopenharmony_ciNode* JSCallReducer::LoadReceiverElementsKind(Node* receiver, Effect* effect,
54941cb0ef41Sopenharmony_ci                                              Control control) {
54951cb0ef41Sopenharmony_ci  Node* effect_node = *effect;
54961cb0ef41Sopenharmony_ci  Node* receiver_map = effect_node =
54971cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
54981cb0ef41Sopenharmony_ci                       receiver, effect_node, control);
54991cb0ef41Sopenharmony_ci  Node* receiver_bit_field2 = effect_node = graph()->NewNode(
55001cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
55011cb0ef41Sopenharmony_ci      effect_node, control);
55021cb0ef41Sopenharmony_ci  Node* receiver_elements_kind = graph()->NewNode(
55031cb0ef41Sopenharmony_ci      simplified()->NumberShiftRightLogical(),
55041cb0ef41Sopenharmony_ci      graph()->NewNode(
55051cb0ef41Sopenharmony_ci          simplified()->NumberBitwiseAnd(), receiver_bit_field2,
55061cb0ef41Sopenharmony_ci          jsgraph()->Constant(Map::Bits2::ElementsKindBits::kMask)),
55071cb0ef41Sopenharmony_ci      jsgraph()->Constant(Map::Bits2::ElementsKindBits::kShift));
55081cb0ef41Sopenharmony_ci  *effect = effect_node;
55091cb0ef41Sopenharmony_ci  return receiver_elements_kind;
55101cb0ef41Sopenharmony_ci}
55111cb0ef41Sopenharmony_ci
55121cb0ef41Sopenharmony_civoid JSCallReducer::CheckIfElementsKind(Node* receiver_elements_kind,
55131cb0ef41Sopenharmony_ci                                        ElementsKind kind, Node* control,
55141cb0ef41Sopenharmony_ci                                        Node** if_true, Node** if_false) {
55151cb0ef41Sopenharmony_ci  Node* is_packed_kind =
55161cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->NumberEqual(), receiver_elements_kind,
55171cb0ef41Sopenharmony_ci                       jsgraph()->Constant(GetPackedElementsKind(kind)));
55181cb0ef41Sopenharmony_ci  Node* packed_branch =
55191cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(), is_packed_kind, control);
55201cb0ef41Sopenharmony_ci  Node* if_packed = graph()->NewNode(common()->IfTrue(), packed_branch);
55211cb0ef41Sopenharmony_ci
55221cb0ef41Sopenharmony_ci  if (IsHoleyElementsKind(kind)) {
55231cb0ef41Sopenharmony_ci    Node* if_not_packed = graph()->NewNode(common()->IfFalse(), packed_branch);
55241cb0ef41Sopenharmony_ci    Node* is_holey_kind =
55251cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->NumberEqual(), receiver_elements_kind,
55261cb0ef41Sopenharmony_ci                         jsgraph()->Constant(GetHoleyElementsKind(kind)));
55271cb0ef41Sopenharmony_ci    Node* holey_branch =
55281cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Branch(), is_holey_kind, if_not_packed);
55291cb0ef41Sopenharmony_ci    Node* if_holey = graph()->NewNode(common()->IfTrue(), holey_branch);
55301cb0ef41Sopenharmony_ci
55311cb0ef41Sopenharmony_ci    Node* if_not_packed_not_holey =
55321cb0ef41Sopenharmony_ci        graph()->NewNode(common()->IfFalse(), holey_branch);
55331cb0ef41Sopenharmony_ci
55341cb0ef41Sopenharmony_ci    *if_true = graph()->NewNode(common()->Merge(2), if_packed, if_holey);
55351cb0ef41Sopenharmony_ci    *if_false = if_not_packed_not_holey;
55361cb0ef41Sopenharmony_ci  } else {
55371cb0ef41Sopenharmony_ci    *if_true = if_packed;
55381cb0ef41Sopenharmony_ci    *if_false = graph()->NewNode(common()->IfFalse(), packed_branch);
55391cb0ef41Sopenharmony_ci  }
55401cb0ef41Sopenharmony_ci}
55411cb0ef41Sopenharmony_ci
55421cb0ef41Sopenharmony_ci// ES6 section 22.1.3.18 Array.prototype.push ( )
55431cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
55441cb0ef41Sopenharmony_ci  JSCallNode n(node);
55451cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
55461cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
55471cb0ef41Sopenharmony_ci    return NoChange();
55481cb0ef41Sopenharmony_ci  }
55491cb0ef41Sopenharmony_ci
55501cb0ef41Sopenharmony_ci  int const num_values = n.ArgumentCount();
55511cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
55521cb0ef41Sopenharmony_ci  Effect effect = n.effect();
55531cb0ef41Sopenharmony_ci  Control control = n.control();
55541cb0ef41Sopenharmony_ci
55551cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
55561cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
55571cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
55581cb0ef41Sopenharmony_ci
55591cb0ef41Sopenharmony_ci  std::vector<ElementsKind> kinds;
55601cb0ef41Sopenharmony_ci  if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kinds, true)) {
55611cb0ef41Sopenharmony_ci    return inference.NoChange();
55621cb0ef41Sopenharmony_ci  }
55631cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnNoElementsProtector()) {
55641cb0ef41Sopenharmony_ci    return inference.NoChange();
55651cb0ef41Sopenharmony_ci  }
55661cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
55671cb0ef41Sopenharmony_ci                                      control, p.feedback());
55681cb0ef41Sopenharmony_ci
55691cb0ef41Sopenharmony_ci  std::vector<Node*> controls_to_merge;
55701cb0ef41Sopenharmony_ci  std::vector<Node*> effects_to_merge;
55711cb0ef41Sopenharmony_ci  std::vector<Node*> values_to_merge;
55721cb0ef41Sopenharmony_ci  Node* return_value = jsgraph()->UndefinedConstant();
55731cb0ef41Sopenharmony_ci
55741cb0ef41Sopenharmony_ci  Node* receiver_elements_kind =
55751cb0ef41Sopenharmony_ci      LoadReceiverElementsKind(receiver, &effect, control);
55761cb0ef41Sopenharmony_ci  Node* next_control = control;
55771cb0ef41Sopenharmony_ci  Node* next_effect = effect;
55781cb0ef41Sopenharmony_ci  for (size_t i = 0; i < kinds.size(); i++) {
55791cb0ef41Sopenharmony_ci    ElementsKind kind = kinds[i];
55801cb0ef41Sopenharmony_ci    control = next_control;
55811cb0ef41Sopenharmony_ci    effect = next_effect;
55821cb0ef41Sopenharmony_ci    // We do not need branch for the last elements kind.
55831cb0ef41Sopenharmony_ci    if (i != kinds.size() - 1) {
55841cb0ef41Sopenharmony_ci      Node* control_node = control;
55851cb0ef41Sopenharmony_ci      CheckIfElementsKind(receiver_elements_kind, kind, control_node,
55861cb0ef41Sopenharmony_ci                          &control_node, &next_control);
55871cb0ef41Sopenharmony_ci      control = control_node;
55881cb0ef41Sopenharmony_ci    }
55891cb0ef41Sopenharmony_ci
55901cb0ef41Sopenharmony_ci    // Collect the value inputs to push.
55911cb0ef41Sopenharmony_ci    std::vector<Node*> values(num_values);
55921cb0ef41Sopenharmony_ci    for (int j = 0; j < num_values; ++j) {
55931cb0ef41Sopenharmony_ci      values[j] = n.Argument(j);
55941cb0ef41Sopenharmony_ci    }
55951cb0ef41Sopenharmony_ci
55961cb0ef41Sopenharmony_ci    for (auto& value : values) {
55971cb0ef41Sopenharmony_ci      if (IsSmiElementsKind(kind)) {
55981cb0ef41Sopenharmony_ci        value = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
55991cb0ef41Sopenharmony_ci                                          value, effect, control);
56001cb0ef41Sopenharmony_ci      } else if (IsDoubleElementsKind(kind)) {
56011cb0ef41Sopenharmony_ci        value = effect = graph()->NewNode(
56021cb0ef41Sopenharmony_ci            simplified()->CheckNumber(p.feedback()), value, effect, control);
56031cb0ef41Sopenharmony_ci        // Make sure we do not store signaling NaNs into double arrays.
56041cb0ef41Sopenharmony_ci        value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
56051cb0ef41Sopenharmony_ci      }
56061cb0ef41Sopenharmony_ci    }
56071cb0ef41Sopenharmony_ci
56081cb0ef41Sopenharmony_ci    // Load the "length" property of the {receiver}.
56091cb0ef41Sopenharmony_ci    Node* length = effect = graph()->NewNode(
56101cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)),
56111cb0ef41Sopenharmony_ci        receiver, effect, control);
56121cb0ef41Sopenharmony_ci    return_value = length;
56131cb0ef41Sopenharmony_ci
56141cb0ef41Sopenharmony_ci    // Check if we have any {values} to push.
56151cb0ef41Sopenharmony_ci    if (num_values > 0) {
56161cb0ef41Sopenharmony_ci      // Compute the resulting "length" of the {receiver}.
56171cb0ef41Sopenharmony_ci      Node* new_length = return_value = graph()->NewNode(
56181cb0ef41Sopenharmony_ci          simplified()->NumberAdd(), length, jsgraph()->Constant(num_values));
56191cb0ef41Sopenharmony_ci
56201cb0ef41Sopenharmony_ci      // Load the elements backing store of the {receiver}.
56211cb0ef41Sopenharmony_ci      Node* elements = effect = graph()->NewNode(
56221cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
56231cb0ef41Sopenharmony_ci          receiver, effect, control);
56241cb0ef41Sopenharmony_ci      Node* elements_length = effect = graph()->NewNode(
56251cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
56261cb0ef41Sopenharmony_ci          elements, effect, control);
56271cb0ef41Sopenharmony_ci
56281cb0ef41Sopenharmony_ci      GrowFastElementsMode mode =
56291cb0ef41Sopenharmony_ci          IsDoubleElementsKind(kind)
56301cb0ef41Sopenharmony_ci              ? GrowFastElementsMode::kDoubleElements
56311cb0ef41Sopenharmony_ci              : GrowFastElementsMode::kSmiOrObjectElements;
56321cb0ef41Sopenharmony_ci      elements = effect = graph()->NewNode(
56331cb0ef41Sopenharmony_ci          simplified()->MaybeGrowFastElements(mode, p.feedback()), receiver,
56341cb0ef41Sopenharmony_ci          elements,
56351cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->NumberAdd(), length,
56361cb0ef41Sopenharmony_ci                           jsgraph()->Constant(num_values - 1)),
56371cb0ef41Sopenharmony_ci          elements_length, effect, control);
56381cb0ef41Sopenharmony_ci
56391cb0ef41Sopenharmony_ci      // Update the JSArray::length field. Since this is observable,
56401cb0ef41Sopenharmony_ci      // there must be no other check after this.
56411cb0ef41Sopenharmony_ci      effect = graph()->NewNode(
56421cb0ef41Sopenharmony_ci          simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
56431cb0ef41Sopenharmony_ci          receiver, new_length, effect, control);
56441cb0ef41Sopenharmony_ci
56451cb0ef41Sopenharmony_ci      // Append the {values} to the {elements}.
56461cb0ef41Sopenharmony_ci      for (int j = 0; j < num_values; ++j) {
56471cb0ef41Sopenharmony_ci        Node* value = values[j];
56481cb0ef41Sopenharmony_ci        Node* index = graph()->NewNode(simplified()->NumberAdd(), length,
56491cb0ef41Sopenharmony_ci                                       jsgraph()->Constant(j));
56501cb0ef41Sopenharmony_ci        effect =
56511cb0ef41Sopenharmony_ci            graph()->NewNode(simplified()->StoreElement(
56521cb0ef41Sopenharmony_ci                                 AccessBuilder::ForFixedArrayElement(kind)),
56531cb0ef41Sopenharmony_ci                             elements, index, value, effect, control);
56541cb0ef41Sopenharmony_ci      }
56551cb0ef41Sopenharmony_ci    }
56561cb0ef41Sopenharmony_ci
56571cb0ef41Sopenharmony_ci    controls_to_merge.push_back(control);
56581cb0ef41Sopenharmony_ci    effects_to_merge.push_back(effect);
56591cb0ef41Sopenharmony_ci    values_to_merge.push_back(return_value);
56601cb0ef41Sopenharmony_ci  }
56611cb0ef41Sopenharmony_ci
56621cb0ef41Sopenharmony_ci  if (controls_to_merge.size() > 1) {
56631cb0ef41Sopenharmony_ci    int const count = static_cast<int>(controls_to_merge.size());
56641cb0ef41Sopenharmony_ci
56651cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(count), count,
56661cb0ef41Sopenharmony_ci                               &controls_to_merge.front());
56671cb0ef41Sopenharmony_ci    effects_to_merge.push_back(control);
56681cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(count), count + 1,
56691cb0ef41Sopenharmony_ci                              &effects_to_merge.front());
56701cb0ef41Sopenharmony_ci    values_to_merge.push_back(control);
56711cb0ef41Sopenharmony_ci    return_value =
56721cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
56731cb0ef41Sopenharmony_ci                         count + 1, &values_to_merge.front());
56741cb0ef41Sopenharmony_ci  }
56751cb0ef41Sopenharmony_ci
56761cb0ef41Sopenharmony_ci  ReplaceWithValue(node, return_value, effect, control);
56771cb0ef41Sopenharmony_ci  return Replace(return_value);
56781cb0ef41Sopenharmony_ci}
56791cb0ef41Sopenharmony_ci
56801cb0ef41Sopenharmony_ci// ES6 section 22.1.3.17 Array.prototype.pop ( )
56811cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
56821cb0ef41Sopenharmony_ci  JSCallNode n(node);
56831cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
56841cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
56851cb0ef41Sopenharmony_ci    return NoChange();
56861cb0ef41Sopenharmony_ci  }
56871cb0ef41Sopenharmony_ci
56881cb0ef41Sopenharmony_ci  Effect effect = n.effect();
56891cb0ef41Sopenharmony_ci  Control control = n.control();
56901cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
56911cb0ef41Sopenharmony_ci
56921cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
56931cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
56941cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
56951cb0ef41Sopenharmony_ci
56961cb0ef41Sopenharmony_ci  std::vector<ElementsKind> kinds;
56971cb0ef41Sopenharmony_ci  if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kinds)) {
56981cb0ef41Sopenharmony_ci    return inference.NoChange();
56991cb0ef41Sopenharmony_ci  }
57001cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnNoElementsProtector()) {
57011cb0ef41Sopenharmony_ci    return inference.NoChange();
57021cb0ef41Sopenharmony_ci  }
57031cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
57041cb0ef41Sopenharmony_ci                                      control, p.feedback());
57051cb0ef41Sopenharmony_ci
57061cb0ef41Sopenharmony_ci  std::vector<Node*> controls_to_merge;
57071cb0ef41Sopenharmony_ci  std::vector<Node*> effects_to_merge;
57081cb0ef41Sopenharmony_ci  std::vector<Node*> values_to_merge;
57091cb0ef41Sopenharmony_ci  Node* value = jsgraph()->UndefinedConstant();
57101cb0ef41Sopenharmony_ci
57111cb0ef41Sopenharmony_ci  Node* receiver_elements_kind =
57121cb0ef41Sopenharmony_ci      LoadReceiverElementsKind(receiver, &effect, control);
57131cb0ef41Sopenharmony_ci  Node* next_control = control;
57141cb0ef41Sopenharmony_ci  Node* next_effect = effect;
57151cb0ef41Sopenharmony_ci  for (size_t i = 0; i < kinds.size(); i++) {
57161cb0ef41Sopenharmony_ci    ElementsKind kind = kinds[i];
57171cb0ef41Sopenharmony_ci    control = next_control;
57181cb0ef41Sopenharmony_ci    effect = next_effect;
57191cb0ef41Sopenharmony_ci    // We do not need branch for the last elements kind.
57201cb0ef41Sopenharmony_ci    if (i != kinds.size() - 1) {
57211cb0ef41Sopenharmony_ci      Node* control_node = control;
57221cb0ef41Sopenharmony_ci      CheckIfElementsKind(receiver_elements_kind, kind, control_node,
57231cb0ef41Sopenharmony_ci                          &control_node, &next_control);
57241cb0ef41Sopenharmony_ci      control = control_node;
57251cb0ef41Sopenharmony_ci    }
57261cb0ef41Sopenharmony_ci
57271cb0ef41Sopenharmony_ci    // Load the "length" property of the {receiver}.
57281cb0ef41Sopenharmony_ci    Node* length = effect = graph()->NewNode(
57291cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)),
57301cb0ef41Sopenharmony_ci        receiver, effect, control);
57311cb0ef41Sopenharmony_ci
57321cb0ef41Sopenharmony_ci    // Check if the {receiver} has any elements.
57331cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
57341cb0ef41Sopenharmony_ci                                   jsgraph()->ZeroConstant());
57351cb0ef41Sopenharmony_ci    Node* branch =
57361cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
57371cb0ef41Sopenharmony_ci
57381cb0ef41Sopenharmony_ci    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
57391cb0ef41Sopenharmony_ci    Node* etrue = effect;
57401cb0ef41Sopenharmony_ci    Node* vtrue = jsgraph()->UndefinedConstant();
57411cb0ef41Sopenharmony_ci
57421cb0ef41Sopenharmony_ci    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
57431cb0ef41Sopenharmony_ci    Node* efalse = effect;
57441cb0ef41Sopenharmony_ci    Node* vfalse;
57451cb0ef41Sopenharmony_ci    {
57461cb0ef41Sopenharmony_ci      // TODO(turbofan): We should trim the backing store if the capacity is too
57471cb0ef41Sopenharmony_ci      // big, as implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.
57481cb0ef41Sopenharmony_ci
57491cb0ef41Sopenharmony_ci      // Load the elements backing store from the {receiver}.
57501cb0ef41Sopenharmony_ci      Node* elements = efalse = graph()->NewNode(
57511cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
57521cb0ef41Sopenharmony_ci          receiver, efalse, if_false);
57531cb0ef41Sopenharmony_ci
57541cb0ef41Sopenharmony_ci      // Ensure that we aren't popping from a copy-on-write backing store.
57551cb0ef41Sopenharmony_ci      if (IsSmiOrObjectElementsKind(kind)) {
57561cb0ef41Sopenharmony_ci        elements = efalse =
57571cb0ef41Sopenharmony_ci            graph()->NewNode(simplified()->EnsureWritableFastElements(),
57581cb0ef41Sopenharmony_ci                             receiver, elements, efalse, if_false);
57591cb0ef41Sopenharmony_ci      }
57601cb0ef41Sopenharmony_ci
57611cb0ef41Sopenharmony_ci      // Compute the new {length}.
57621cb0ef41Sopenharmony_ci      Node* new_length = graph()->NewNode(simplified()->NumberSubtract(),
57631cb0ef41Sopenharmony_ci                                          length, jsgraph()->OneConstant());
57641cb0ef41Sopenharmony_ci
57651cb0ef41Sopenharmony_ci      // This extra check exists solely to break an exploitation technique
57661cb0ef41Sopenharmony_ci      // that abuses typer mismatches.
57671cb0ef41Sopenharmony_ci      new_length = efalse = graph()->NewNode(
57681cb0ef41Sopenharmony_ci          simplified()->CheckBounds(p.feedback(),
57691cb0ef41Sopenharmony_ci                                    CheckBoundsFlag::kAbortOnOutOfBounds),
57701cb0ef41Sopenharmony_ci          new_length, length, efalse, if_false);
57711cb0ef41Sopenharmony_ci
57721cb0ef41Sopenharmony_ci      // Store the new {length} to the {receiver}.
57731cb0ef41Sopenharmony_ci      efalse = graph()->NewNode(
57741cb0ef41Sopenharmony_ci          simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
57751cb0ef41Sopenharmony_ci          receiver, new_length, efalse, if_false);
57761cb0ef41Sopenharmony_ci
57771cb0ef41Sopenharmony_ci      // Load the last entry from the {elements}.
57781cb0ef41Sopenharmony_ci      vfalse = efalse = graph()->NewNode(
57791cb0ef41Sopenharmony_ci          simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
57801cb0ef41Sopenharmony_ci          elements, new_length, efalse, if_false);
57811cb0ef41Sopenharmony_ci
57821cb0ef41Sopenharmony_ci      // Store a hole to the element we just removed from the {receiver}.
57831cb0ef41Sopenharmony_ci      efalse = graph()->NewNode(
57841cb0ef41Sopenharmony_ci          simplified()->StoreElement(
57851cb0ef41Sopenharmony_ci              AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
57861cb0ef41Sopenharmony_ci          elements, new_length, jsgraph()->TheHoleConstant(), efalse, if_false);
57871cb0ef41Sopenharmony_ci    }
57881cb0ef41Sopenharmony_ci
57891cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
57901cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
57911cb0ef41Sopenharmony_ci    value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
57921cb0ef41Sopenharmony_ci                             vtrue, vfalse, control);
57931cb0ef41Sopenharmony_ci
57941cb0ef41Sopenharmony_ci    // Convert the hole to undefined. Do this last, so that we can optimize
57951cb0ef41Sopenharmony_ci    // conversion operator via some smart strength reduction in many cases.
57961cb0ef41Sopenharmony_ci    if (IsHoleyElementsKind(kind)) {
57971cb0ef41Sopenharmony_ci      value =
57981cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
57991cb0ef41Sopenharmony_ci    }
58001cb0ef41Sopenharmony_ci
58011cb0ef41Sopenharmony_ci    controls_to_merge.push_back(control);
58021cb0ef41Sopenharmony_ci    effects_to_merge.push_back(effect);
58031cb0ef41Sopenharmony_ci    values_to_merge.push_back(value);
58041cb0ef41Sopenharmony_ci  }
58051cb0ef41Sopenharmony_ci
58061cb0ef41Sopenharmony_ci  if (controls_to_merge.size() > 1) {
58071cb0ef41Sopenharmony_ci    int const count = static_cast<int>(controls_to_merge.size());
58081cb0ef41Sopenharmony_ci
58091cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(count), count,
58101cb0ef41Sopenharmony_ci                               &controls_to_merge.front());
58111cb0ef41Sopenharmony_ci    effects_to_merge.push_back(control);
58121cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(count), count + 1,
58131cb0ef41Sopenharmony_ci                              &effects_to_merge.front());
58141cb0ef41Sopenharmony_ci    values_to_merge.push_back(control);
58151cb0ef41Sopenharmony_ci    value =
58161cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
58171cb0ef41Sopenharmony_ci                         count + 1, &values_to_merge.front());
58181cb0ef41Sopenharmony_ci  }
58191cb0ef41Sopenharmony_ci
58201cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
58211cb0ef41Sopenharmony_ci  return Replace(value);
58221cb0ef41Sopenharmony_ci}
58231cb0ef41Sopenharmony_ci
58241cb0ef41Sopenharmony_ci// ES6 section 22.1.3.22 Array.prototype.shift ( )
58251cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
58261cb0ef41Sopenharmony_ci  JSCallNode n(node);
58271cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
58281cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
58291cb0ef41Sopenharmony_ci    return NoChange();
58301cb0ef41Sopenharmony_ci  }
58311cb0ef41Sopenharmony_ci
58321cb0ef41Sopenharmony_ci  Node* target = n.target();
58331cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
58341cb0ef41Sopenharmony_ci  Node* context = n.context();
58351cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
58361cb0ef41Sopenharmony_ci  Effect effect = n.effect();
58371cb0ef41Sopenharmony_ci  Control control = n.control();
58381cb0ef41Sopenharmony_ci
58391cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
58401cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
58411cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
58421cb0ef41Sopenharmony_ci
58431cb0ef41Sopenharmony_ci  std::vector<ElementsKind> kinds;
58441cb0ef41Sopenharmony_ci  if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kinds)) {
58451cb0ef41Sopenharmony_ci    return inference.NoChange();
58461cb0ef41Sopenharmony_ci  }
58471cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnNoElementsProtector()) {
58481cb0ef41Sopenharmony_ci    return inference.NoChange();
58491cb0ef41Sopenharmony_ci  }
58501cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
58511cb0ef41Sopenharmony_ci                                      control, p.feedback());
58521cb0ef41Sopenharmony_ci
58531cb0ef41Sopenharmony_ci  std::vector<Node*> controls_to_merge;
58541cb0ef41Sopenharmony_ci  std::vector<Node*> effects_to_merge;
58551cb0ef41Sopenharmony_ci  std::vector<Node*> values_to_merge;
58561cb0ef41Sopenharmony_ci  Node* value = jsgraph()->UndefinedConstant();
58571cb0ef41Sopenharmony_ci
58581cb0ef41Sopenharmony_ci  Node* receiver_elements_kind =
58591cb0ef41Sopenharmony_ci      LoadReceiverElementsKind(receiver, &effect, control);
58601cb0ef41Sopenharmony_ci  Node* next_control = control;
58611cb0ef41Sopenharmony_ci  Node* next_effect = effect;
58621cb0ef41Sopenharmony_ci  for (size_t i = 0; i < kinds.size(); i++) {
58631cb0ef41Sopenharmony_ci    ElementsKind kind = kinds[i];
58641cb0ef41Sopenharmony_ci    control = next_control;
58651cb0ef41Sopenharmony_ci    effect = next_effect;
58661cb0ef41Sopenharmony_ci    // We do not need branch for the last elements kind.
58671cb0ef41Sopenharmony_ci    if (i != kinds.size() - 1) {
58681cb0ef41Sopenharmony_ci      Node* control_node = control;
58691cb0ef41Sopenharmony_ci      CheckIfElementsKind(receiver_elements_kind, kind, control_node,
58701cb0ef41Sopenharmony_ci                          &control_node, &next_control);
58711cb0ef41Sopenharmony_ci      control = control_node;
58721cb0ef41Sopenharmony_ci    }
58731cb0ef41Sopenharmony_ci
58741cb0ef41Sopenharmony_ci    // Load length of the {receiver}.
58751cb0ef41Sopenharmony_ci    Node* length = effect = graph()->NewNode(
58761cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)),
58771cb0ef41Sopenharmony_ci        receiver, effect, control);
58781cb0ef41Sopenharmony_ci
58791cb0ef41Sopenharmony_ci    // Return undefined if {receiver} has no elements.
58801cb0ef41Sopenharmony_ci    Node* check0 = graph()->NewNode(simplified()->NumberEqual(), length,
58811cb0ef41Sopenharmony_ci                                    jsgraph()->ZeroConstant());
58821cb0ef41Sopenharmony_ci    Node* branch0 =
58831cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
58841cb0ef41Sopenharmony_ci
58851cb0ef41Sopenharmony_ci    Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
58861cb0ef41Sopenharmony_ci    Node* etrue0 = effect;
58871cb0ef41Sopenharmony_ci    Node* vtrue0 = jsgraph()->UndefinedConstant();
58881cb0ef41Sopenharmony_ci
58891cb0ef41Sopenharmony_ci    Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
58901cb0ef41Sopenharmony_ci    Node* efalse0 = effect;
58911cb0ef41Sopenharmony_ci    Node* vfalse0;
58921cb0ef41Sopenharmony_ci    {
58931cb0ef41Sopenharmony_ci      // Check if we should take the fast-path.
58941cb0ef41Sopenharmony_ci      Node* check1 =
58951cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
58961cb0ef41Sopenharmony_ci                           jsgraph()->Constant(JSArray::kMaxCopyElements));
58971cb0ef41Sopenharmony_ci      Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
58981cb0ef41Sopenharmony_ci                                       check1, if_false0);
58991cb0ef41Sopenharmony_ci
59001cb0ef41Sopenharmony_ci      Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
59011cb0ef41Sopenharmony_ci      Node* etrue1 = efalse0;
59021cb0ef41Sopenharmony_ci      Node* vtrue1;
59031cb0ef41Sopenharmony_ci      {
59041cb0ef41Sopenharmony_ci        Node* elements = etrue1 = graph()->NewNode(
59051cb0ef41Sopenharmony_ci            simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
59061cb0ef41Sopenharmony_ci            receiver, etrue1, if_true1);
59071cb0ef41Sopenharmony_ci
59081cb0ef41Sopenharmony_ci        // Load the first element here, which we return below.
59091cb0ef41Sopenharmony_ci        vtrue1 = etrue1 = graph()->NewNode(
59101cb0ef41Sopenharmony_ci            simplified()->LoadElement(
59111cb0ef41Sopenharmony_ci                AccessBuilder::ForFixedArrayElement(kind)),
59121cb0ef41Sopenharmony_ci            elements, jsgraph()->ZeroConstant(), etrue1, if_true1);
59131cb0ef41Sopenharmony_ci
59141cb0ef41Sopenharmony_ci        // Ensure that we aren't shifting a copy-on-write backing store.
59151cb0ef41Sopenharmony_ci        if (IsSmiOrObjectElementsKind(kind)) {
59161cb0ef41Sopenharmony_ci          elements = etrue1 =
59171cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->EnsureWritableFastElements(),
59181cb0ef41Sopenharmony_ci                               receiver, elements, etrue1, if_true1);
59191cb0ef41Sopenharmony_ci        }
59201cb0ef41Sopenharmony_ci
59211cb0ef41Sopenharmony_ci        // Shift the remaining {elements} by one towards the start.
59221cb0ef41Sopenharmony_ci        Node* loop = graph()->NewNode(common()->Loop(2), if_true1, if_true1);
59231cb0ef41Sopenharmony_ci        Node* eloop =
59241cb0ef41Sopenharmony_ci            graph()->NewNode(common()->EffectPhi(2), etrue1, etrue1, loop);
59251cb0ef41Sopenharmony_ci        Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
59261cb0ef41Sopenharmony_ci        NodeProperties::MergeControlToEnd(graph(), common(), terminate);
59271cb0ef41Sopenharmony_ci
59281cb0ef41Sopenharmony_ci        Node* index = graph()->NewNode(
59291cb0ef41Sopenharmony_ci            common()->Phi(MachineRepresentation::kTagged, 2),
59301cb0ef41Sopenharmony_ci            jsgraph()->OneConstant(),
59311cb0ef41Sopenharmony_ci            jsgraph()->Constant(JSArray::kMaxCopyElements - 1), loop);
59321cb0ef41Sopenharmony_ci
59331cb0ef41Sopenharmony_ci        {
59341cb0ef41Sopenharmony_ci          Node* check2 =
59351cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->NumberLessThan(), index, length);
59361cb0ef41Sopenharmony_ci          Node* branch2 = graph()->NewNode(common()->Branch(), check2, loop);
59371cb0ef41Sopenharmony_ci
59381cb0ef41Sopenharmony_ci          if_true1 = graph()->NewNode(common()->IfFalse(), branch2);
59391cb0ef41Sopenharmony_ci          etrue1 = eloop;
59401cb0ef41Sopenharmony_ci
59411cb0ef41Sopenharmony_ci          Node* control2 = graph()->NewNode(common()->IfTrue(), branch2);
59421cb0ef41Sopenharmony_ci          Node* effect2 = etrue1;
59431cb0ef41Sopenharmony_ci
59441cb0ef41Sopenharmony_ci          ElementAccess const access =
59451cb0ef41Sopenharmony_ci              AccessBuilder::ForFixedArrayElement(kind);
59461cb0ef41Sopenharmony_ci
59471cb0ef41Sopenharmony_ci          // When disable FLAG_turbo_loop_variable, typer cannot infer index
59481cb0ef41Sopenharmony_ci          // is in [1, kMaxCopyElements-1], and will break in representing
59491cb0ef41Sopenharmony_ci          // kRepFloat64 (Range(1, inf)) to kRepWord64 when converting
59501cb0ef41Sopenharmony_ci          // input for kLoadElement. So we need to add type guard here.
59511cb0ef41Sopenharmony_ci          // And we need to use index when using NumberLessThan to check
59521cb0ef41Sopenharmony_ci          // terminate and updating index, otherwise which will break inducing
59531cb0ef41Sopenharmony_ci          // variables in LoopVariableOptimizer.
59541cb0ef41Sopenharmony_ci          STATIC_ASSERT(JSArray::kMaxCopyElements < kSmiMaxValue);
59551cb0ef41Sopenharmony_ci          Node* index_retyped = effect2 =
59561cb0ef41Sopenharmony_ci              graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()),
59571cb0ef41Sopenharmony_ci                               index, effect2, control2);
59581cb0ef41Sopenharmony_ci
59591cb0ef41Sopenharmony_ci          Node* value2 = effect2 =
59601cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->LoadElement(access), elements,
59611cb0ef41Sopenharmony_ci                               index_retyped, effect2, control2);
59621cb0ef41Sopenharmony_ci          effect2 = graph()->NewNode(
59631cb0ef41Sopenharmony_ci              simplified()->StoreElement(access), elements,
59641cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->NumberSubtract(), index_retyped,
59651cb0ef41Sopenharmony_ci                               jsgraph()->OneConstant()),
59661cb0ef41Sopenharmony_ci              value2, effect2, control2);
59671cb0ef41Sopenharmony_ci
59681cb0ef41Sopenharmony_ci          loop->ReplaceInput(1, control2);
59691cb0ef41Sopenharmony_ci          eloop->ReplaceInput(1, effect2);
59701cb0ef41Sopenharmony_ci          index->ReplaceInput(1,
59711cb0ef41Sopenharmony_ci                              graph()->NewNode(simplified()->NumberAdd(), index,
59721cb0ef41Sopenharmony_ci                                               jsgraph()->OneConstant()));
59731cb0ef41Sopenharmony_ci        }
59741cb0ef41Sopenharmony_ci
59751cb0ef41Sopenharmony_ci        // Compute the new {length}.
59761cb0ef41Sopenharmony_ci        Node* new_length = graph()->NewNode(simplified()->NumberSubtract(),
59771cb0ef41Sopenharmony_ci                                            length, jsgraph()->OneConstant());
59781cb0ef41Sopenharmony_ci
59791cb0ef41Sopenharmony_ci        // This extra check exists solely to break an exploitation technique
59801cb0ef41Sopenharmony_ci        // that abuses typer mismatches.
59811cb0ef41Sopenharmony_ci        new_length = etrue1 = graph()->NewNode(
59821cb0ef41Sopenharmony_ci            simplified()->CheckBounds(p.feedback(),
59831cb0ef41Sopenharmony_ci                                      CheckBoundsFlag::kAbortOnOutOfBounds),
59841cb0ef41Sopenharmony_ci            new_length, length, etrue1, if_true1);
59851cb0ef41Sopenharmony_ci
59861cb0ef41Sopenharmony_ci        // Store the new {length} to the {receiver}.
59871cb0ef41Sopenharmony_ci        etrue1 = graph()->NewNode(
59881cb0ef41Sopenharmony_ci            simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
59891cb0ef41Sopenharmony_ci            receiver, new_length, etrue1, if_true1);
59901cb0ef41Sopenharmony_ci
59911cb0ef41Sopenharmony_ci        // Store a hole to the element we just removed from the {receiver}.
59921cb0ef41Sopenharmony_ci        etrue1 = graph()->NewNode(
59931cb0ef41Sopenharmony_ci            simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
59941cb0ef41Sopenharmony_ci                GetHoleyElementsKind(kind))),
59951cb0ef41Sopenharmony_ci            elements, new_length, jsgraph()->TheHoleConstant(), etrue1,
59961cb0ef41Sopenharmony_ci            if_true1);
59971cb0ef41Sopenharmony_ci      }
59981cb0ef41Sopenharmony_ci
59991cb0ef41Sopenharmony_ci      Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
60001cb0ef41Sopenharmony_ci      Node* efalse1 = efalse0;
60011cb0ef41Sopenharmony_ci      Node* vfalse1;
60021cb0ef41Sopenharmony_ci      {
60031cb0ef41Sopenharmony_ci        // Call the generic C++ implementation.
60041cb0ef41Sopenharmony_ci        const Builtin builtin = Builtin::kArrayShift;
60051cb0ef41Sopenharmony_ci        auto call_descriptor = Linkage::GetCEntryStubCallDescriptor(
60061cb0ef41Sopenharmony_ci            graph()->zone(), 1, BuiltinArguments::kNumExtraArgsWithReceiver,
60071cb0ef41Sopenharmony_ci            Builtins::name(builtin), node->op()->properties(),
60081cb0ef41Sopenharmony_ci            CallDescriptor::kNeedsFrameState);
60091cb0ef41Sopenharmony_ci        Node* stub_code = jsgraph()->CEntryStubConstant(
60101cb0ef41Sopenharmony_ci            1, SaveFPRegsMode::kIgnore, ArgvMode::kStack, true);
60111cb0ef41Sopenharmony_ci        Address builtin_entry = Builtins::CppEntryOf(builtin);
60121cb0ef41Sopenharmony_ci        Node* entry = jsgraph()->ExternalConstant(
60131cb0ef41Sopenharmony_ci            ExternalReference::Create(builtin_entry));
60141cb0ef41Sopenharmony_ci        Node* argc =
60151cb0ef41Sopenharmony_ci            jsgraph()->Constant(BuiltinArguments::kNumExtraArgsWithReceiver);
60161cb0ef41Sopenharmony_ci        if_false1 = efalse1 = vfalse1 =
60171cb0ef41Sopenharmony_ci            graph()->NewNode(common()->Call(call_descriptor), stub_code,
60181cb0ef41Sopenharmony_ci                             receiver, jsgraph()->PaddingConstant(), argc,
60191cb0ef41Sopenharmony_ci                             target, jsgraph()->UndefinedConstant(), entry,
60201cb0ef41Sopenharmony_ci                             argc, context, frame_state, efalse1, if_false1);
60211cb0ef41Sopenharmony_ci      }
60221cb0ef41Sopenharmony_ci
60231cb0ef41Sopenharmony_ci      if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
60241cb0ef41Sopenharmony_ci      efalse0 =
60251cb0ef41Sopenharmony_ci          graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
60261cb0ef41Sopenharmony_ci      vfalse0 =
60271cb0ef41Sopenharmony_ci          graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
60281cb0ef41Sopenharmony_ci                           vtrue1, vfalse1, if_false0);
60291cb0ef41Sopenharmony_ci    }
60301cb0ef41Sopenharmony_ci
60311cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
60321cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
60331cb0ef41Sopenharmony_ci    value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
60341cb0ef41Sopenharmony_ci                             vtrue0, vfalse0, control);
60351cb0ef41Sopenharmony_ci
60361cb0ef41Sopenharmony_ci    // Convert the hole to undefined. Do this last, so that we can optimize
60371cb0ef41Sopenharmony_ci    // conversion operator via some smart strength reduction in many cases.
60381cb0ef41Sopenharmony_ci    if (IsHoleyElementsKind(kind)) {
60391cb0ef41Sopenharmony_ci      value =
60401cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
60411cb0ef41Sopenharmony_ci    }
60421cb0ef41Sopenharmony_ci
60431cb0ef41Sopenharmony_ci    controls_to_merge.push_back(control);
60441cb0ef41Sopenharmony_ci    effects_to_merge.push_back(effect);
60451cb0ef41Sopenharmony_ci    values_to_merge.push_back(value);
60461cb0ef41Sopenharmony_ci  }
60471cb0ef41Sopenharmony_ci
60481cb0ef41Sopenharmony_ci  if (controls_to_merge.size() > 1) {
60491cb0ef41Sopenharmony_ci    int const count = static_cast<int>(controls_to_merge.size());
60501cb0ef41Sopenharmony_ci
60511cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Merge(count), count,
60521cb0ef41Sopenharmony_ci                               &controls_to_merge.front());
60531cb0ef41Sopenharmony_ci    effects_to_merge.push_back(control);
60541cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(count), count + 1,
60551cb0ef41Sopenharmony_ci                              &effects_to_merge.front());
60561cb0ef41Sopenharmony_ci    values_to_merge.push_back(control);
60571cb0ef41Sopenharmony_ci    value =
60581cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
60591cb0ef41Sopenharmony_ci                         count + 1, &values_to_merge.front());
60601cb0ef41Sopenharmony_ci  }
60611cb0ef41Sopenharmony_ci
60621cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
60631cb0ef41Sopenharmony_ci  return Replace(value);
60641cb0ef41Sopenharmony_ci}
60651cb0ef41Sopenharmony_ci
60661cb0ef41Sopenharmony_ci// ES6 section 22.1.3.23 Array.prototype.slice ( )
60671cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
60681cb0ef41Sopenharmony_ci  if (!FLAG_turbo_inline_array_builtins) return NoChange();
60691cb0ef41Sopenharmony_ci  JSCallNode n(node);
60701cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
60711cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
60721cb0ef41Sopenharmony_ci    return NoChange();
60731cb0ef41Sopenharmony_ci  }
60741cb0ef41Sopenharmony_ci
60751cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
60761cb0ef41Sopenharmony_ci  Node* start = n.ArgumentOr(0, jsgraph()->ZeroConstant());
60771cb0ef41Sopenharmony_ci  Node* end = n.ArgumentOrUndefined(1, jsgraph());
60781cb0ef41Sopenharmony_ci  Node* context = n.context();
60791cb0ef41Sopenharmony_ci  Effect effect = n.effect();
60801cb0ef41Sopenharmony_ci  Control control = n.control();
60811cb0ef41Sopenharmony_ci
60821cb0ef41Sopenharmony_ci  // Optimize for the case where we simply clone the {receiver}, i.e. when the
60831cb0ef41Sopenharmony_ci  // {start} is zero and the {end} is undefined (meaning it will be set to
60841cb0ef41Sopenharmony_ci  // {receiver}s "length" property). This logic should be in sync with
60851cb0ef41Sopenharmony_ci  // ReduceArrayPrototypeSlice (to a reasonable degree). This is because
60861cb0ef41Sopenharmony_ci  // CloneFastJSArray produces arrays which are potentially COW. If there's a
60871cb0ef41Sopenharmony_ci  // discrepancy, TF generates code which produces a COW array and then expects
60881cb0ef41Sopenharmony_ci  // it to be non-COW (or the other way around) -> immediate deopt.
60891cb0ef41Sopenharmony_ci  if (!NumberMatcher(start).Is(0) ||
60901cb0ef41Sopenharmony_ci      !HeapObjectMatcher(end).Is(factory()->undefined_value())) {
60911cb0ef41Sopenharmony_ci    return NoChange();
60921cb0ef41Sopenharmony_ci  }
60931cb0ef41Sopenharmony_ci
60941cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
60951cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
60961cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
60971cb0ef41Sopenharmony_ci
60981cb0ef41Sopenharmony_ci  // Check that the maps are of JSArray (and more).
60991cb0ef41Sopenharmony_ci  // TODO(turbofan): Consider adding special case for the common pattern
61001cb0ef41Sopenharmony_ci  // `slice.call(arguments)`, for example jQuery makes heavy use of that.
61011cb0ef41Sopenharmony_ci  bool can_be_holey = false;
61021cb0ef41Sopenharmony_ci  for (const MapRef& receiver_map : receiver_maps) {
61031cb0ef41Sopenharmony_ci    if (!receiver_map.supports_fast_array_iteration()) {
61041cb0ef41Sopenharmony_ci      return inference.NoChange();
61051cb0ef41Sopenharmony_ci    }
61061cb0ef41Sopenharmony_ci    if (IsHoleyElementsKind(receiver_map.elements_kind())) {
61071cb0ef41Sopenharmony_ci      can_be_holey = true;
61081cb0ef41Sopenharmony_ci    }
61091cb0ef41Sopenharmony_ci  }
61101cb0ef41Sopenharmony_ci
61111cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnArraySpeciesProtector()) {
61121cb0ef41Sopenharmony_ci    return inference.NoChange();
61131cb0ef41Sopenharmony_ci  }
61141cb0ef41Sopenharmony_ci  if (can_be_holey && !dependencies()->DependOnNoElementsProtector()) {
61151cb0ef41Sopenharmony_ci    return inference.NoChange();
61161cb0ef41Sopenharmony_ci  }
61171cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
61181cb0ef41Sopenharmony_ci                                      control, p.feedback());
61191cb0ef41Sopenharmony_ci
61201cb0ef41Sopenharmony_ci  // TODO(turbofan): We can do even better here, either adding a CloneArray
61211cb0ef41Sopenharmony_ci  // simplified operator, whose output type indicates that it's an Array,
61221cb0ef41Sopenharmony_ci  // saving subsequent checks, or yet better, by introducing new operators
61231cb0ef41Sopenharmony_ci  // CopySmiOrObjectElements / CopyDoubleElements and inlining the JSArray
61241cb0ef41Sopenharmony_ci  // allocation in here. That way we'd even get escape analysis and scalar
61251cb0ef41Sopenharmony_ci  // replacement to help in some cases.
61261cb0ef41Sopenharmony_ci  Callable callable =
61271cb0ef41Sopenharmony_ci      Builtins::CallableFor(isolate(), Builtin::kCloneFastJSArray);
61281cb0ef41Sopenharmony_ci  auto call_descriptor = Linkage::GetStubCallDescriptor(
61291cb0ef41Sopenharmony_ci      graph()->zone(), callable.descriptor(),
61301cb0ef41Sopenharmony_ci      callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
61311cb0ef41Sopenharmony_ci      Operator::kNoThrow | Operator::kNoDeopt);
61321cb0ef41Sopenharmony_ci
61331cb0ef41Sopenharmony_ci  // Calls to Builtin::kCloneFastJSArray produce COW arrays
61341cb0ef41Sopenharmony_ci  // if the original array is COW
61351cb0ef41Sopenharmony_ci  Node* clone = effect = graph()->NewNode(
61361cb0ef41Sopenharmony_ci      common()->Call(call_descriptor), jsgraph()->HeapConstant(callable.code()),
61371cb0ef41Sopenharmony_ci      receiver, context, effect, control);
61381cb0ef41Sopenharmony_ci
61391cb0ef41Sopenharmony_ci  ReplaceWithValue(node, clone, effect, control);
61401cb0ef41Sopenharmony_ci  return Replace(clone);
61411cb0ef41Sopenharmony_ci}
61421cb0ef41Sopenharmony_ci
61431cb0ef41Sopenharmony_ci// ES6 section 22.1.2.2 Array.isArray ( arg )
61441cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayIsArray(Node* node) {
61451cb0ef41Sopenharmony_ci  // We certainly know that undefined is not an array.
61461cb0ef41Sopenharmony_ci  JSCallNode n(node);
61471cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
61481cb0ef41Sopenharmony_ci    Node* value = jsgraph()->FalseConstant();
61491cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
61501cb0ef41Sopenharmony_ci    return Replace(value);
61511cb0ef41Sopenharmony_ci  }
61521cb0ef41Sopenharmony_ci
61531cb0ef41Sopenharmony_ci  Effect effect = n.effect();
61541cb0ef41Sopenharmony_ci  Control control = n.control();
61551cb0ef41Sopenharmony_ci  Node* context = n.context();
61561cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
61571cb0ef41Sopenharmony_ci  Node* object = n.Argument(0);
61581cb0ef41Sopenharmony_ci  node->ReplaceInput(0, object);
61591cb0ef41Sopenharmony_ci  node->ReplaceInput(1, context);
61601cb0ef41Sopenharmony_ci  node->ReplaceInput(2, frame_state);
61611cb0ef41Sopenharmony_ci  node->ReplaceInput(3, effect);
61621cb0ef41Sopenharmony_ci  node->ReplaceInput(4, control);
61631cb0ef41Sopenharmony_ci  node->TrimInputCount(5);
61641cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->ObjectIsArray());
61651cb0ef41Sopenharmony_ci  return Changed(node);
61661cb0ef41Sopenharmony_ci}
61671cb0ef41Sopenharmony_ci
61681cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayIterator(Node* node,
61691cb0ef41Sopenharmony_ci                                             ArrayIteratorKind array_kind,
61701cb0ef41Sopenharmony_ci                                             IterationKind iteration_kind) {
61711cb0ef41Sopenharmony_ci  JSCallNode n(node);
61721cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
61731cb0ef41Sopenharmony_ci  Node* context = n.context();
61741cb0ef41Sopenharmony_ci  Effect effect = n.effect();
61751cb0ef41Sopenharmony_ci  Control control = n.control();
61761cb0ef41Sopenharmony_ci
61771cb0ef41Sopenharmony_ci  // Check if we know that {receiver} is a valid JSReceiver.
61781cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
61791cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAreJSReceiver()) {
61801cb0ef41Sopenharmony_ci    return NoChange();
61811cb0ef41Sopenharmony_ci  }
61821cb0ef41Sopenharmony_ci
61831cb0ef41Sopenharmony_ci  // TypedArray iteration is stricter: it throws if the receiver is not a typed
61841cb0ef41Sopenharmony_ci  // array. So don't bother optimizing in that case.
61851cb0ef41Sopenharmony_ci  if (array_kind == ArrayIteratorKind::kTypedArray &&
61861cb0ef41Sopenharmony_ci      !inference.AllOfInstanceTypesAre(InstanceType::JS_TYPED_ARRAY_TYPE)) {
61871cb0ef41Sopenharmony_ci    return NoChange();
61881cb0ef41Sopenharmony_ci  }
61891cb0ef41Sopenharmony_ci
61901cb0ef41Sopenharmony_ci  if (array_kind == ArrayIteratorKind::kTypedArray) {
61911cb0ef41Sopenharmony_ci    // Make sure we deopt when the JSArrayBuffer is detached.
61921cb0ef41Sopenharmony_ci    if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
61931cb0ef41Sopenharmony_ci      CallParameters const& p = CallParametersOf(node->op());
61941cb0ef41Sopenharmony_ci      if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
61951cb0ef41Sopenharmony_ci        return NoChange();
61961cb0ef41Sopenharmony_ci      }
61971cb0ef41Sopenharmony_ci      Node* buffer = effect = graph()->NewNode(
61981cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
61991cb0ef41Sopenharmony_ci          receiver, effect, control);
62001cb0ef41Sopenharmony_ci      Node* buffer_bit_field = effect = graph()->NewNode(
62011cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
62021cb0ef41Sopenharmony_ci          buffer, effect, control);
62031cb0ef41Sopenharmony_ci      Node* check = graph()->NewNode(
62041cb0ef41Sopenharmony_ci          simplified()->NumberEqual(),
62051cb0ef41Sopenharmony_ci          graph()->NewNode(
62061cb0ef41Sopenharmony_ci              simplified()->NumberBitwiseAnd(), buffer_bit_field,
62071cb0ef41Sopenharmony_ci              jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
62081cb0ef41Sopenharmony_ci          jsgraph()->ZeroConstant());
62091cb0ef41Sopenharmony_ci      effect = graph()->NewNode(
62101cb0ef41Sopenharmony_ci          simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
62111cb0ef41Sopenharmony_ci                                p.feedback()),
62121cb0ef41Sopenharmony_ci          check, effect, control);
62131cb0ef41Sopenharmony_ci    }
62141cb0ef41Sopenharmony_ci  }
62151cb0ef41Sopenharmony_ci
62161cb0ef41Sopenharmony_ci  // Morph the {node} into a JSCreateArrayIterator with the given {kind}.
62171cb0ef41Sopenharmony_ci  RelaxControls(node);
62181cb0ef41Sopenharmony_ci  node->ReplaceInput(0, receiver);
62191cb0ef41Sopenharmony_ci  node->ReplaceInput(1, context);
62201cb0ef41Sopenharmony_ci  node->ReplaceInput(2, effect);
62211cb0ef41Sopenharmony_ci  node->ReplaceInput(3, control);
62221cb0ef41Sopenharmony_ci  node->TrimInputCount(4);
62231cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node,
62241cb0ef41Sopenharmony_ci                           javascript()->CreateArrayIterator(iteration_kind));
62251cb0ef41Sopenharmony_ci  return Changed(node);
62261cb0ef41Sopenharmony_ci}
62271cb0ef41Sopenharmony_ci
62281cb0ef41Sopenharmony_ci// ES #sec-%arrayiteratorprototype%.next
62291cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
62301cb0ef41Sopenharmony_ci  JSCallNode n(node);
62311cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
62321cb0ef41Sopenharmony_ci  Node* iterator = n.receiver();
62331cb0ef41Sopenharmony_ci  Node* context = n.context();
62341cb0ef41Sopenharmony_ci  Effect effect = n.effect();
62351cb0ef41Sopenharmony_ci  Control control = n.control();
62361cb0ef41Sopenharmony_ci
62371cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
62381cb0ef41Sopenharmony_ci    return NoChange();
62391cb0ef41Sopenharmony_ci  }
62401cb0ef41Sopenharmony_ci
62411cb0ef41Sopenharmony_ci  if (iterator->opcode() != IrOpcode::kJSCreateArrayIterator) return NoChange();
62421cb0ef41Sopenharmony_ci
62431cb0ef41Sopenharmony_ci  IterationKind const iteration_kind =
62441cb0ef41Sopenharmony_ci      CreateArrayIteratorParametersOf(iterator->op()).kind();
62451cb0ef41Sopenharmony_ci  Node* iterated_object = NodeProperties::GetValueInput(iterator, 0);
62461cb0ef41Sopenharmony_ci  Effect iterator_effect{NodeProperties::GetEffectInput(iterator)};
62471cb0ef41Sopenharmony_ci
62481cb0ef41Sopenharmony_ci  MapInference inference(broker(), iterated_object, iterator_effect);
62491cb0ef41Sopenharmony_ci  if (!inference.HaveMaps()) return NoChange();
62501cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& iterated_object_maps = inference.GetMaps();
62511cb0ef41Sopenharmony_ci
62521cb0ef41Sopenharmony_ci  // Check that various {iterated_object_maps} have compatible elements kinds.
62531cb0ef41Sopenharmony_ci  ElementsKind elements_kind = iterated_object_maps[0].elements_kind();
62541cb0ef41Sopenharmony_ci  if (IsTypedArrayElementsKind(elements_kind)) {
62551cb0ef41Sopenharmony_ci    // TurboFan doesn't support loading from BigInt typed arrays yet.
62561cb0ef41Sopenharmony_ci    if (elements_kind == BIGUINT64_ELEMENTS ||
62571cb0ef41Sopenharmony_ci        elements_kind == BIGINT64_ELEMENTS) {
62581cb0ef41Sopenharmony_ci      return inference.NoChange();
62591cb0ef41Sopenharmony_ci    }
62601cb0ef41Sopenharmony_ci    for (const MapRef& iterated_object_map : iterated_object_maps) {
62611cb0ef41Sopenharmony_ci      if (iterated_object_map.elements_kind() != elements_kind) {
62621cb0ef41Sopenharmony_ci        return inference.NoChange();
62631cb0ef41Sopenharmony_ci      }
62641cb0ef41Sopenharmony_ci    }
62651cb0ef41Sopenharmony_ci  } else {
62661cb0ef41Sopenharmony_ci    if (!CanInlineArrayIteratingBuiltin(broker(), iterated_object_maps,
62671cb0ef41Sopenharmony_ci                                        &elements_kind)) {
62681cb0ef41Sopenharmony_ci      return inference.NoChange();
62691cb0ef41Sopenharmony_ci    }
62701cb0ef41Sopenharmony_ci  }
62711cb0ef41Sopenharmony_ci
62721cb0ef41Sopenharmony_ci  if (IsHoleyElementsKind(elements_kind) &&
62731cb0ef41Sopenharmony_ci      !dependencies()->DependOnNoElementsProtector()) {
62741cb0ef41Sopenharmony_ci    return inference.NoChange();
62751cb0ef41Sopenharmony_ci  }
62761cb0ef41Sopenharmony_ci
62771cb0ef41Sopenharmony_ci  // Since the map inference was done relative to {iterator_effect} rather than
62781cb0ef41Sopenharmony_ci  // {effect}, we need to guard the use of the map(s) even when the inference
62791cb0ef41Sopenharmony_ci  // was reliable.
62801cb0ef41Sopenharmony_ci  inference.InsertMapChecks(jsgraph(), &effect, control, p.feedback());
62811cb0ef41Sopenharmony_ci
62821cb0ef41Sopenharmony_ci  if (IsTypedArrayElementsKind(elements_kind)) {
62831cb0ef41Sopenharmony_ci    // See if we can skip the detaching check.
62841cb0ef41Sopenharmony_ci    if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
62851cb0ef41Sopenharmony_ci      // Bail out if the {iterated_object}s JSArrayBuffer was detached.
62861cb0ef41Sopenharmony_ci      Node* buffer = effect = graph()->NewNode(
62871cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
62881cb0ef41Sopenharmony_ci          iterated_object, effect, control);
62891cb0ef41Sopenharmony_ci      Node* buffer_bit_field = effect = graph()->NewNode(
62901cb0ef41Sopenharmony_ci          simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
62911cb0ef41Sopenharmony_ci          buffer, effect, control);
62921cb0ef41Sopenharmony_ci      Node* check = graph()->NewNode(
62931cb0ef41Sopenharmony_ci          simplified()->NumberEqual(),
62941cb0ef41Sopenharmony_ci          graph()->NewNode(
62951cb0ef41Sopenharmony_ci              simplified()->NumberBitwiseAnd(), buffer_bit_field,
62961cb0ef41Sopenharmony_ci              jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
62971cb0ef41Sopenharmony_ci          jsgraph()->ZeroConstant());
62981cb0ef41Sopenharmony_ci      effect = graph()->NewNode(
62991cb0ef41Sopenharmony_ci          simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
63001cb0ef41Sopenharmony_ci                                p.feedback()),
63011cb0ef41Sopenharmony_ci          check, effect, control);
63021cb0ef41Sopenharmony_ci    }
63031cb0ef41Sopenharmony_ci  }
63041cb0ef41Sopenharmony_ci
63051cb0ef41Sopenharmony_ci  // Load the [[NextIndex]] from the {iterator} and leverage the fact
63061cb0ef41Sopenharmony_ci  // that we definitely know that it's in Unsigned32 range since the
63071cb0ef41Sopenharmony_ci  // {iterated_object} is either a JSArray or a JSTypedArray. For the
63081cb0ef41Sopenharmony_ci  // latter case we even know that it's a Smi in UnsignedSmall range.
63091cb0ef41Sopenharmony_ci  FieldAccess index_access = AccessBuilder::ForJSArrayIteratorNextIndex();
63101cb0ef41Sopenharmony_ci  if (IsTypedArrayElementsKind(elements_kind)) {
63111cb0ef41Sopenharmony_ci    index_access.type = TypeCache::Get()->kJSTypedArrayLengthType;
63121cb0ef41Sopenharmony_ci  } else {
63131cb0ef41Sopenharmony_ci    index_access.type = TypeCache::Get()->kJSArrayLengthType;
63141cb0ef41Sopenharmony_ci  }
63151cb0ef41Sopenharmony_ci  Node* index = effect = graph()->NewNode(simplified()->LoadField(index_access),
63161cb0ef41Sopenharmony_ci                                          iterator, effect, control);
63171cb0ef41Sopenharmony_ci
63181cb0ef41Sopenharmony_ci  // Load the elements of the {iterated_object}. While it feels
63191cb0ef41Sopenharmony_ci  // counter-intuitive to place the elements pointer load before
63201cb0ef41Sopenharmony_ci  // the condition below, as it might not be needed (if the {index}
63211cb0ef41Sopenharmony_ci  // is out of bounds for the {iterated_object}), it's better this
63221cb0ef41Sopenharmony_ci  // way as it allows the LoadElimination to eliminate redundant
63231cb0ef41Sopenharmony_ci  // reloads of the elements pointer.
63241cb0ef41Sopenharmony_ci  Node* elements = effect = graph()->NewNode(
63251cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
63261cb0ef41Sopenharmony_ci      iterated_object, effect, control);
63271cb0ef41Sopenharmony_ci
63281cb0ef41Sopenharmony_ci  // Load the length of the {iterated_object}. Due to the map checks we
63291cb0ef41Sopenharmony_ci  // already know something about the length here, which we can leverage
63301cb0ef41Sopenharmony_ci  // to generate Word32 operations below without additional checking.
63311cb0ef41Sopenharmony_ci  FieldAccess length_access =
63321cb0ef41Sopenharmony_ci      IsTypedArrayElementsKind(elements_kind)
63331cb0ef41Sopenharmony_ci          ? AccessBuilder::ForJSTypedArrayLength()
63341cb0ef41Sopenharmony_ci          : AccessBuilder::ForJSArrayLength(elements_kind);
63351cb0ef41Sopenharmony_ci  Node* length = effect = graph()->NewNode(
63361cb0ef41Sopenharmony_ci      simplified()->LoadField(length_access), iterated_object, effect, control);
63371cb0ef41Sopenharmony_ci
63381cb0ef41Sopenharmony_ci  // Check whether {index} is within the valid range for the {iterated_object}.
63391cb0ef41Sopenharmony_ci  Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, length);
63401cb0ef41Sopenharmony_ci  Node* branch =
63411cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(BranchHint::kNone), check, control);
63421cb0ef41Sopenharmony_ci
63431cb0ef41Sopenharmony_ci  Node* done_true;
63441cb0ef41Sopenharmony_ci  Node* value_true;
63451cb0ef41Sopenharmony_ci  Node* etrue = effect;
63461cb0ef41Sopenharmony_ci  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
63471cb0ef41Sopenharmony_ci  {
63481cb0ef41Sopenharmony_ci    // This extra check exists to refine the type of {index} but also to break
63491cb0ef41Sopenharmony_ci    // an exploitation technique that abuses typer mismatches.
63501cb0ef41Sopenharmony_ci    index = etrue = graph()->NewNode(
63511cb0ef41Sopenharmony_ci        simplified()->CheckBounds(p.feedback(),
63521cb0ef41Sopenharmony_ci                                  CheckBoundsFlag::kAbortOnOutOfBounds),
63531cb0ef41Sopenharmony_ci        index, length, etrue, if_true);
63541cb0ef41Sopenharmony_ci
63551cb0ef41Sopenharmony_ci    done_true = jsgraph()->FalseConstant();
63561cb0ef41Sopenharmony_ci    if (iteration_kind == IterationKind::kKeys) {
63571cb0ef41Sopenharmony_ci      // Just return the {index}.
63581cb0ef41Sopenharmony_ci      value_true = index;
63591cb0ef41Sopenharmony_ci    } else {
63601cb0ef41Sopenharmony_ci      DCHECK(iteration_kind == IterationKind::kEntries ||
63611cb0ef41Sopenharmony_ci             iteration_kind == IterationKind::kValues);
63621cb0ef41Sopenharmony_ci
63631cb0ef41Sopenharmony_ci      if (IsTypedArrayElementsKind(elements_kind)) {
63641cb0ef41Sopenharmony_ci        Node* base_ptr = etrue =
63651cb0ef41Sopenharmony_ci            graph()->NewNode(simplified()->LoadField(
63661cb0ef41Sopenharmony_ci                                 AccessBuilder::ForJSTypedArrayBasePointer()),
63671cb0ef41Sopenharmony_ci                             iterated_object, etrue, if_true);
63681cb0ef41Sopenharmony_ci        Node* external_ptr = etrue = graph()->NewNode(
63691cb0ef41Sopenharmony_ci            simplified()->LoadField(
63701cb0ef41Sopenharmony_ci                AccessBuilder::ForJSTypedArrayExternalPointer()),
63711cb0ef41Sopenharmony_ci            iterated_object, etrue, if_true);
63721cb0ef41Sopenharmony_ci
63731cb0ef41Sopenharmony_ci        ExternalArrayType array_type = kExternalInt8Array;
63741cb0ef41Sopenharmony_ci        switch (elements_kind) {
63751cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
63761cb0ef41Sopenharmony_ci  case TYPE##_ELEMENTS:                           \
63771cb0ef41Sopenharmony_ci    array_type = kExternal##Type##Array;          \
63781cb0ef41Sopenharmony_ci    break;
63791cb0ef41Sopenharmony_ci          TYPED_ARRAYS(TYPED_ARRAY_CASE)
63801cb0ef41Sopenharmony_ci          default:
63811cb0ef41Sopenharmony_ci            UNREACHABLE();
63821cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CASE
63831cb0ef41Sopenharmony_ci        }
63841cb0ef41Sopenharmony_ci
63851cb0ef41Sopenharmony_ci        Node* buffer = etrue =
63861cb0ef41Sopenharmony_ci            graph()->NewNode(simplified()->LoadField(
63871cb0ef41Sopenharmony_ci                                 AccessBuilder::ForJSArrayBufferViewBuffer()),
63881cb0ef41Sopenharmony_ci                             iterated_object, etrue, if_true);
63891cb0ef41Sopenharmony_ci
63901cb0ef41Sopenharmony_ci        value_true = etrue =
63911cb0ef41Sopenharmony_ci            graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
63921cb0ef41Sopenharmony_ci                             base_ptr, external_ptr, index, etrue, if_true);
63931cb0ef41Sopenharmony_ci      } else {
63941cb0ef41Sopenharmony_ci        value_true = etrue = graph()->NewNode(
63951cb0ef41Sopenharmony_ci            simplified()->LoadElement(
63961cb0ef41Sopenharmony_ci                AccessBuilder::ForFixedArrayElement(elements_kind)),
63971cb0ef41Sopenharmony_ci            elements, index, etrue, if_true);
63981cb0ef41Sopenharmony_ci
63991cb0ef41Sopenharmony_ci        // Convert hole to undefined if needed.
64001cb0ef41Sopenharmony_ci        if (elements_kind == HOLEY_ELEMENTS ||
64011cb0ef41Sopenharmony_ci            elements_kind == HOLEY_SMI_ELEMENTS) {
64021cb0ef41Sopenharmony_ci          value_true = graph()->NewNode(
64031cb0ef41Sopenharmony_ci              simplified()->ConvertTaggedHoleToUndefined(), value_true);
64041cb0ef41Sopenharmony_ci        } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
64051cb0ef41Sopenharmony_ci          // TODO(6587): avoid deopt if not all uses of value are truncated.
64061cb0ef41Sopenharmony_ci          CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
64071cb0ef41Sopenharmony_ci          value_true = etrue = graph()->NewNode(
64081cb0ef41Sopenharmony_ci              simplified()->CheckFloat64Hole(mode, p.feedback()), value_true,
64091cb0ef41Sopenharmony_ci              etrue, if_true);
64101cb0ef41Sopenharmony_ci        }
64111cb0ef41Sopenharmony_ci      }
64121cb0ef41Sopenharmony_ci
64131cb0ef41Sopenharmony_ci      if (iteration_kind == IterationKind::kEntries) {
64141cb0ef41Sopenharmony_ci        // Allocate elements for key/value pair
64151cb0ef41Sopenharmony_ci        value_true = etrue =
64161cb0ef41Sopenharmony_ci            graph()->NewNode(javascript()->CreateKeyValueArray(), index,
64171cb0ef41Sopenharmony_ci                             value_true, context, etrue);
64181cb0ef41Sopenharmony_ci      } else {
64191cb0ef41Sopenharmony_ci        DCHECK_EQ(IterationKind::kValues, iteration_kind);
64201cb0ef41Sopenharmony_ci      }
64211cb0ef41Sopenharmony_ci    }
64221cb0ef41Sopenharmony_ci
64231cb0ef41Sopenharmony_ci    // Increment the [[NextIndex]] field in the {iterator}. The TypeGuards
64241cb0ef41Sopenharmony_ci    // above guarantee that the {next_index} is in the UnsignedSmall range.
64251cb0ef41Sopenharmony_ci    Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
64261cb0ef41Sopenharmony_ci                                        jsgraph()->OneConstant());
64271cb0ef41Sopenharmony_ci    etrue = graph()->NewNode(simplified()->StoreField(index_access), iterator,
64281cb0ef41Sopenharmony_ci                             next_index, etrue, if_true);
64291cb0ef41Sopenharmony_ci  }
64301cb0ef41Sopenharmony_ci
64311cb0ef41Sopenharmony_ci  Node* done_false;
64321cb0ef41Sopenharmony_ci  Node* value_false;
64331cb0ef41Sopenharmony_ci  Node* efalse = effect;
64341cb0ef41Sopenharmony_ci  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
64351cb0ef41Sopenharmony_ci  {
64361cb0ef41Sopenharmony_ci    // iterator.[[NextIndex]] >= array.length, stop iterating.
64371cb0ef41Sopenharmony_ci    done_false = jsgraph()->TrueConstant();
64381cb0ef41Sopenharmony_ci    value_false = jsgraph()->UndefinedConstant();
64391cb0ef41Sopenharmony_ci
64401cb0ef41Sopenharmony_ci    if (!IsTypedArrayElementsKind(elements_kind)) {
64411cb0ef41Sopenharmony_ci      // Mark the {iterator} as exhausted by setting the [[NextIndex]] to a
64421cb0ef41Sopenharmony_ci      // value that will never pass the length check again (aka the maximum
64431cb0ef41Sopenharmony_ci      // value possible for the specific iterated object). Note that this is
64441cb0ef41Sopenharmony_ci      // different from what the specification says, which is changing the
64451cb0ef41Sopenharmony_ci      // [[IteratedObject]] field to undefined, but that makes it difficult
64461cb0ef41Sopenharmony_ci      // to eliminate the map checks and "length" accesses in for..of loops.
64471cb0ef41Sopenharmony_ci      //
64481cb0ef41Sopenharmony_ci      // This is not necessary for JSTypedArray's, since the length of those
64491cb0ef41Sopenharmony_ci      // cannot change later and so if we were ever out of bounds for them
64501cb0ef41Sopenharmony_ci      // we will stay out-of-bounds forever.
64511cb0ef41Sopenharmony_ci      Node* end_index = jsgraph()->Constant(index_access.type.Max());
64521cb0ef41Sopenharmony_ci      efalse = graph()->NewNode(simplified()->StoreField(index_access),
64531cb0ef41Sopenharmony_ci                                iterator, end_index, efalse, if_false);
64541cb0ef41Sopenharmony_ci    }
64551cb0ef41Sopenharmony_ci  }
64561cb0ef41Sopenharmony_ci
64571cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
64581cb0ef41Sopenharmony_ci  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
64591cb0ef41Sopenharmony_ci  Node* value =
64601cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
64611cb0ef41Sopenharmony_ci                       value_true, value_false, control);
64621cb0ef41Sopenharmony_ci  Node* done =
64631cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
64641cb0ef41Sopenharmony_ci                       done_true, done_false, control);
64651cb0ef41Sopenharmony_ci
64661cb0ef41Sopenharmony_ci  // Create IteratorResult object.
64671cb0ef41Sopenharmony_ci  value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
64681cb0ef41Sopenharmony_ci                                    value, done, context, effect);
64691cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
64701cb0ef41Sopenharmony_ci  return Replace(value);
64711cb0ef41Sopenharmony_ci}
64721cb0ef41Sopenharmony_ci
64731cb0ef41Sopenharmony_ci// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
64741cb0ef41Sopenharmony_ci// ES6 section 21.1.3.3 String.prototype.codePointAt ( pos )
64751cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeStringAt(
64761cb0ef41Sopenharmony_ci    const Operator* string_access_operator, Node* node) {
64771cb0ef41Sopenharmony_ci  DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
64781cb0ef41Sopenharmony_ci         string_access_operator->opcode() == IrOpcode::kStringCodePointAt);
64791cb0ef41Sopenharmony_ci  JSCallNode n(node);
64801cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
64811cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
64821cb0ef41Sopenharmony_ci    return NoChange();
64831cb0ef41Sopenharmony_ci  }
64841cb0ef41Sopenharmony_ci
64851cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
64861cb0ef41Sopenharmony_ci  Node* index = n.ArgumentOr(0, jsgraph()->ZeroConstant());
64871cb0ef41Sopenharmony_ci  Effect effect = n.effect();
64881cb0ef41Sopenharmony_ci  Control control = n.control();
64891cb0ef41Sopenharmony_ci
64901cb0ef41Sopenharmony_ci  // Ensure that the {receiver} is actually a String.
64911cb0ef41Sopenharmony_ci  receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
64921cb0ef41Sopenharmony_ci                                       receiver, effect, control);
64931cb0ef41Sopenharmony_ci
64941cb0ef41Sopenharmony_ci  // Determine the {receiver} length.
64951cb0ef41Sopenharmony_ci  Node* receiver_length =
64961cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->StringLength(), receiver);
64971cb0ef41Sopenharmony_ci
64981cb0ef41Sopenharmony_ci  // Check that the {index} is within range.
64991cb0ef41Sopenharmony_ci  index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
65001cb0ef41Sopenharmony_ci                                    index, receiver_length, effect, control);
65011cb0ef41Sopenharmony_ci
65021cb0ef41Sopenharmony_ci  // Return the character from the {receiver} as single character string.
65031cb0ef41Sopenharmony_ci  Node* value = effect = graph()->NewNode(string_access_operator, receiver,
65041cb0ef41Sopenharmony_ci                                          index, effect, control);
65051cb0ef41Sopenharmony_ci
65061cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
65071cb0ef41Sopenharmony_ci  return Replace(value);
65081cb0ef41Sopenharmony_ci}
65091cb0ef41Sopenharmony_ci
65101cb0ef41Sopenharmony_ci// ES section 21.1.3.20
65111cb0ef41Sopenharmony_ci// String.prototype.startsWith ( searchString [ , position ] )
65121cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) {
65131cb0ef41Sopenharmony_ci  JSCallNode n(node);
65141cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
65151cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
65161cb0ef41Sopenharmony_ci    return NoChange();
65171cb0ef41Sopenharmony_ci  }
65181cb0ef41Sopenharmony_ci
65191cb0ef41Sopenharmony_ci  TNode<Object> search_element = n.ArgumentOrUndefined(0, jsgraph());
65201cb0ef41Sopenharmony_ci
65211cb0ef41Sopenharmony_ci  // Here are three conditions:
65221cb0ef41Sopenharmony_ci  // First, If search_element is definitely not a string, we make no change.
65231cb0ef41Sopenharmony_ci  // Second, If search_element is definitely a string and its length is less
65241cb0ef41Sopenharmony_ci  // or equal than max inline matching sequence threshold, we could inline
65251cb0ef41Sopenharmony_ci  // the entire matching sequence.
65261cb0ef41Sopenharmony_ci  // Third, we try to inline, and have a runtime deopt if search_element is
65271cb0ef41Sopenharmony_ci  // not a string.
65281cb0ef41Sopenharmony_ci  HeapObjectMatcher search_element_matcher(search_element);
65291cb0ef41Sopenharmony_ci  if (search_element_matcher.HasResolvedValue()) {
65301cb0ef41Sopenharmony_ci    ObjectRef target_ref = search_element_matcher.Ref(broker());
65311cb0ef41Sopenharmony_ci    if (!target_ref.IsString()) return NoChange();
65321cb0ef41Sopenharmony_ci    StringRef search_element_string = target_ref.AsString();
65331cb0ef41Sopenharmony_ci    if (search_element_string.length().has_value()) {
65341cb0ef41Sopenharmony_ci      int length = search_element_string.length().value();
65351cb0ef41Sopenharmony_ci      // If search_element's length is less or equal than
65361cb0ef41Sopenharmony_ci      // kMaxInlineMatchSequence, we inline the entire
65371cb0ef41Sopenharmony_ci      // matching sequence.
65381cb0ef41Sopenharmony_ci      if (length <= kMaxInlineMatchSequence) {
65391cb0ef41Sopenharmony_ci        JSCallReducerAssembler a(this, node);
65401cb0ef41Sopenharmony_ci        Node* subgraph =
65411cb0ef41Sopenharmony_ci            a.ReduceStringPrototypeStartsWith(search_element_string);
65421cb0ef41Sopenharmony_ci        return ReplaceWithSubgraph(&a, subgraph);
65431cb0ef41Sopenharmony_ci      }
65441cb0ef41Sopenharmony_ci    }
65451cb0ef41Sopenharmony_ci  }
65461cb0ef41Sopenharmony_ci
65471cb0ef41Sopenharmony_ci  JSCallReducerAssembler a(this, node);
65481cb0ef41Sopenharmony_ci  Node* subgraph = a.ReduceStringPrototypeStartsWith();
65491cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
65501cb0ef41Sopenharmony_ci}
65511cb0ef41Sopenharmony_ci
65521cb0ef41Sopenharmony_ci// ES section 21.1.3.1 String.prototype.charAt ( pos )
65531cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
65541cb0ef41Sopenharmony_ci  JSCallNode n(node);
65551cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
65561cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
65571cb0ef41Sopenharmony_ci    return NoChange();
65581cb0ef41Sopenharmony_ci  }
65591cb0ef41Sopenharmony_ci
65601cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
65611cb0ef41Sopenharmony_ci  Node* index = n.ArgumentOr(0, jsgraph()->ZeroConstant());
65621cb0ef41Sopenharmony_ci  Effect effect = n.effect();
65631cb0ef41Sopenharmony_ci  Control control = n.control();
65641cb0ef41Sopenharmony_ci
65651cb0ef41Sopenharmony_ci  // Ensure that the {receiver} is actually a String.
65661cb0ef41Sopenharmony_ci  receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
65671cb0ef41Sopenharmony_ci                                       receiver, effect, control);
65681cb0ef41Sopenharmony_ci
65691cb0ef41Sopenharmony_ci  // Determine the {receiver} length.
65701cb0ef41Sopenharmony_ci  Node* receiver_length =
65711cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->StringLength(), receiver);
65721cb0ef41Sopenharmony_ci
65731cb0ef41Sopenharmony_ci  // Check that the {index} is within range.
65741cb0ef41Sopenharmony_ci  index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
65751cb0ef41Sopenharmony_ci                                    index, receiver_length, effect, control);
65761cb0ef41Sopenharmony_ci
65771cb0ef41Sopenharmony_ci  // Return the character from the {receiver} as single character string.
65781cb0ef41Sopenharmony_ci  Node* value = effect = graph()->NewNode(simplified()->StringCharCodeAt(),
65791cb0ef41Sopenharmony_ci                                          receiver, index, effect, control);
65801cb0ef41Sopenharmony_ci  value = graph()->NewNode(simplified()->StringFromSingleCharCode(), value);
65811cb0ef41Sopenharmony_ci
65821cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
65831cb0ef41Sopenharmony_ci  return Replace(value);
65841cb0ef41Sopenharmony_ci}
65851cb0ef41Sopenharmony_ci
65861cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT
65871cb0ef41Sopenharmony_ci
65881cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
65891cb0ef41Sopenharmony_ci  JSCallNode n(node);
65901cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
65911cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
65921cb0ef41Sopenharmony_ci    return NoChange();
65931cb0ef41Sopenharmony_ci  }
65941cb0ef41Sopenharmony_ci  Effect effect = n.effect();
65951cb0ef41Sopenharmony_ci  Control control = n.control();
65961cb0ef41Sopenharmony_ci
65971cb0ef41Sopenharmony_ci  Node* receiver = effect = graph()->NewNode(
65981cb0ef41Sopenharmony_ci      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
65991cb0ef41Sopenharmony_ci
66001cb0ef41Sopenharmony_ci  NodeProperties::ReplaceEffectInput(node, effect);
66011cb0ef41Sopenharmony_ci  RelaxEffectsAndControls(node);
66021cb0ef41Sopenharmony_ci  node->ReplaceInput(0, receiver);
66031cb0ef41Sopenharmony_ci  node->TrimInputCount(1);
66041cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, simplified()->StringToLowerCaseIntl());
66051cb0ef41Sopenharmony_ci  NodeProperties::SetType(node, Type::String());
66061cb0ef41Sopenharmony_ci  return Changed(node);
66071cb0ef41Sopenharmony_ci}
66081cb0ef41Sopenharmony_ci
66091cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) {
66101cb0ef41Sopenharmony_ci  JSCallNode n(node);
66111cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
66121cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
66131cb0ef41Sopenharmony_ci    return NoChange();
66141cb0ef41Sopenharmony_ci  }
66151cb0ef41Sopenharmony_ci  Effect effect = n.effect();
66161cb0ef41Sopenharmony_ci  Control control = n.control();
66171cb0ef41Sopenharmony_ci
66181cb0ef41Sopenharmony_ci  Node* receiver = effect = graph()->NewNode(
66191cb0ef41Sopenharmony_ci      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
66201cb0ef41Sopenharmony_ci
66211cb0ef41Sopenharmony_ci  NodeProperties::ReplaceEffectInput(node, effect);
66221cb0ef41Sopenharmony_ci  RelaxEffectsAndControls(node);
66231cb0ef41Sopenharmony_ci  node->ReplaceInput(0, receiver);
66241cb0ef41Sopenharmony_ci  node->TrimInputCount(1);
66251cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, simplified()->StringToUpperCaseIntl());
66261cb0ef41Sopenharmony_ci  NodeProperties::SetType(node, Type::String());
66271cb0ef41Sopenharmony_ci  return Changed(node);
66281cb0ef41Sopenharmony_ci}
66291cb0ef41Sopenharmony_ci
66301cb0ef41Sopenharmony_ci#endif  // V8_INTL_SUPPORT
66311cb0ef41Sopenharmony_ci
66321cb0ef41Sopenharmony_ci// ES #sec-string.fromcharcode
66331cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringFromCharCode(Node* node) {
66341cb0ef41Sopenharmony_ci  JSCallNode n(node);
66351cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
66361cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
66371cb0ef41Sopenharmony_ci    return NoChange();
66381cb0ef41Sopenharmony_ci  }
66391cb0ef41Sopenharmony_ci  if (n.ArgumentCount() == 1) {
66401cb0ef41Sopenharmony_ci    Effect effect = n.effect();
66411cb0ef41Sopenharmony_ci    Control control = n.control();
66421cb0ef41Sopenharmony_ci    Node* input = n.Argument(0);
66431cb0ef41Sopenharmony_ci
66441cb0ef41Sopenharmony_ci    input = effect = graph()->NewNode(
66451cb0ef41Sopenharmony_ci        simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
66461cb0ef41Sopenharmony_ci                                          p.feedback()),
66471cb0ef41Sopenharmony_ci        input, effect, control);
66481cb0ef41Sopenharmony_ci
66491cb0ef41Sopenharmony_ci    Node* value =
66501cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->StringFromSingleCharCode(), input);
66511cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value, effect);
66521cb0ef41Sopenharmony_ci    return Replace(value);
66531cb0ef41Sopenharmony_ci  }
66541cb0ef41Sopenharmony_ci  return NoChange();
66551cb0ef41Sopenharmony_ci}
66561cb0ef41Sopenharmony_ci
66571cb0ef41Sopenharmony_ci// ES #sec-string.fromcodepoint
66581cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringFromCodePoint(Node* node) {
66591cb0ef41Sopenharmony_ci  JSCallNode n(node);
66601cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
66611cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
66621cb0ef41Sopenharmony_ci    return NoChange();
66631cb0ef41Sopenharmony_ci  }
66641cb0ef41Sopenharmony_ci  if (n.ArgumentCount() != 1) return NoChange();
66651cb0ef41Sopenharmony_ci
66661cb0ef41Sopenharmony_ci  Effect effect = n.effect();
66671cb0ef41Sopenharmony_ci  Control control = n.control();
66681cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
66691cb0ef41Sopenharmony_ci
66701cb0ef41Sopenharmony_ci  input = effect = graph()->NewNode(
66711cb0ef41Sopenharmony_ci      simplified()->CheckBounds(p.feedback(),
66721cb0ef41Sopenharmony_ci                                CheckBoundsFlag::kConvertStringAndMinusZero),
66731cb0ef41Sopenharmony_ci      input, jsgraph()->Constant(0x10FFFF + 1), effect, control);
66741cb0ef41Sopenharmony_ci
66751cb0ef41Sopenharmony_ci  Node* value =
66761cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->StringFromSingleCodePoint(), input);
66771cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect);
66781cb0ef41Sopenharmony_ci  return Replace(value);
66791cb0ef41Sopenharmony_ci}
66801cb0ef41Sopenharmony_ci
66811cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
66821cb0ef41Sopenharmony_ci  JSCallNode n(node);
66831cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
66841cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
66851cb0ef41Sopenharmony_ci    return NoChange();
66861cb0ef41Sopenharmony_ci  }
66871cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
66881cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
66891cb0ef41Sopenharmony_ci  Node* receiver = effect = graph()->NewNode(
66901cb0ef41Sopenharmony_ci      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
66911cb0ef41Sopenharmony_ci  Node* iterator = effect =
66921cb0ef41Sopenharmony_ci      graph()->NewNode(javascript()->CreateStringIterator(), receiver,
66931cb0ef41Sopenharmony_ci                       jsgraph()->NoContextConstant(), effect);
66941cb0ef41Sopenharmony_ci  ReplaceWithValue(node, iterator, effect, control);
66951cb0ef41Sopenharmony_ci  return Replace(iterator);
66961cb0ef41Sopenharmony_ci}
66971cb0ef41Sopenharmony_ci
66981cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeLocaleCompare(Node* node) {
66991cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT
67001cb0ef41Sopenharmony_ci  JSCallNode n(node);
67011cb0ef41Sopenharmony_ci  // Signature: receiver.localeCompare(compareString, locales, options)
67021cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1 || n.ArgumentCount() > 3) {
67031cb0ef41Sopenharmony_ci    return NoChange();
67041cb0ef41Sopenharmony_ci  }
67051cb0ef41Sopenharmony_ci
67061cb0ef41Sopenharmony_ci  {
67071cb0ef41Sopenharmony_ci    Handle<Object> locales;
67081cb0ef41Sopenharmony_ci    {
67091cb0ef41Sopenharmony_ci      HeapObjectMatcher m(n.ArgumentOrUndefined(1, jsgraph()));
67101cb0ef41Sopenharmony_ci      if (!m.HasResolvedValue()) return NoChange();
67111cb0ef41Sopenharmony_ci      if (m.Is(factory()->undefined_value())) {
67121cb0ef41Sopenharmony_ci        locales = factory()->undefined_value();
67131cb0ef41Sopenharmony_ci      } else {
67141cb0ef41Sopenharmony_ci        ObjectRef ref = m.Ref(broker());
67151cb0ef41Sopenharmony_ci        if (!ref.IsString()) return NoChange();
67161cb0ef41Sopenharmony_ci        StringRef sref = ref.AsString();
67171cb0ef41Sopenharmony_ci        if (base::Optional<Handle<String>> maybe_locales =
67181cb0ef41Sopenharmony_ci                sref.ObjectIfContentAccessible()) {
67191cb0ef41Sopenharmony_ci          locales = *maybe_locales;
67201cb0ef41Sopenharmony_ci        } else {
67211cb0ef41Sopenharmony_ci          return NoChange();
67221cb0ef41Sopenharmony_ci        }
67231cb0ef41Sopenharmony_ci      }
67241cb0ef41Sopenharmony_ci    }
67251cb0ef41Sopenharmony_ci
67261cb0ef41Sopenharmony_ci    TNode<Object> options = n.ArgumentOrUndefined(2, jsgraph());
67271cb0ef41Sopenharmony_ci    {
67281cb0ef41Sopenharmony_ci      HeapObjectMatcher m(options);
67291cb0ef41Sopenharmony_ci      if (!m.Is(factory()->undefined_value())) {
67301cb0ef41Sopenharmony_ci        return NoChange();
67311cb0ef41Sopenharmony_ci      }
67321cb0ef41Sopenharmony_ci    }
67331cb0ef41Sopenharmony_ci
67341cb0ef41Sopenharmony_ci    if (Intl::CompareStringsOptionsFor(broker()->local_isolate_or_isolate(),
67351cb0ef41Sopenharmony_ci                                       locales, factory()->undefined_value()) !=
67361cb0ef41Sopenharmony_ci        Intl::CompareStringsOptions::kTryFastPath) {
67371cb0ef41Sopenharmony_ci      return NoChange();
67381cb0ef41Sopenharmony_ci    }
67391cb0ef41Sopenharmony_ci  }
67401cb0ef41Sopenharmony_ci
67411cb0ef41Sopenharmony_ci  Callable callable =
67421cb0ef41Sopenharmony_ci      Builtins::CallableFor(isolate(), Builtin::kStringFastLocaleCompare);
67431cb0ef41Sopenharmony_ci  auto call_descriptor = Linkage::GetStubCallDescriptor(
67441cb0ef41Sopenharmony_ci      graph()->zone(), callable.descriptor(),
67451cb0ef41Sopenharmony_ci      callable.descriptor().GetStackParameterCount(),
67461cb0ef41Sopenharmony_ci      CallDescriptor::kNeedsFrameState);
67471cb0ef41Sopenharmony_ci  node->RemoveInput(n.FeedbackVectorIndex());
67481cb0ef41Sopenharmony_ci  if (n.ArgumentCount() == 3) {
67491cb0ef41Sopenharmony_ci    node->RemoveInput(n.ArgumentIndex(2));
67501cb0ef41Sopenharmony_ci  } else if (n.ArgumentCount() == 1) {
67511cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), n.LastArgumentIndex() + 1,
67521cb0ef41Sopenharmony_ci                      jsgraph()->UndefinedConstant());
67531cb0ef41Sopenharmony_ci  } else {
67541cb0ef41Sopenharmony_ci    DCHECK_EQ(2, n.ArgumentCount());
67551cb0ef41Sopenharmony_ci  }
67561cb0ef41Sopenharmony_ci  node->InsertInput(graph()->zone(), 0,
67571cb0ef41Sopenharmony_ci                    jsgraph()->HeapConstant(callable.code()));
67581cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
67591cb0ef41Sopenharmony_ci  return Changed(node);
67601cb0ef41Sopenharmony_ci#else
67611cb0ef41Sopenharmony_ci  return NoChange();
67621cb0ef41Sopenharmony_ci#endif
67631cb0ef41Sopenharmony_ci}
67641cb0ef41Sopenharmony_ci
67651cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
67661cb0ef41Sopenharmony_ci  JSCallNode n(node);
67671cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
67681cb0ef41Sopenharmony_ci  Effect effect = n.effect();
67691cb0ef41Sopenharmony_ci  Control control = n.control();
67701cb0ef41Sopenharmony_ci  Node* context = n.context();
67711cb0ef41Sopenharmony_ci
67721cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
67731cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() ||
67741cb0ef41Sopenharmony_ci      !inference.AllOfInstanceTypesAre(JS_STRING_ITERATOR_TYPE)) {
67751cb0ef41Sopenharmony_ci    return NoChange();
67761cb0ef41Sopenharmony_ci  }
67771cb0ef41Sopenharmony_ci
67781cb0ef41Sopenharmony_ci  Node* string = effect = graph()->NewNode(
67791cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
67801cb0ef41Sopenharmony_ci      receiver, effect, control);
67811cb0ef41Sopenharmony_ci  Node* index = effect = graph()->NewNode(
67821cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()),
67831cb0ef41Sopenharmony_ci      receiver, effect, control);
67841cb0ef41Sopenharmony_ci  Node* length = graph()->NewNode(simplified()->StringLength(), string);
67851cb0ef41Sopenharmony_ci
67861cb0ef41Sopenharmony_ci  // branch0: if (index < length)
67871cb0ef41Sopenharmony_ci  Node* check0 =
67881cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->NumberLessThan(), index, length);
67891cb0ef41Sopenharmony_ci  Node* branch0 =
67901cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(BranchHint::kNone), check0, control);
67911cb0ef41Sopenharmony_ci
67921cb0ef41Sopenharmony_ci  Node* etrue0 = effect;
67931cb0ef41Sopenharmony_ci  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
67941cb0ef41Sopenharmony_ci  Node* done_true;
67951cb0ef41Sopenharmony_ci  Node* vtrue0;
67961cb0ef41Sopenharmony_ci  {
67971cb0ef41Sopenharmony_ci    done_true = jsgraph()->FalseConstant();
67981cb0ef41Sopenharmony_ci    vtrue0 = etrue0 = graph()->NewNode(simplified()->StringFromCodePointAt(),
67991cb0ef41Sopenharmony_ci                                       string, index, etrue0, if_true0);
68001cb0ef41Sopenharmony_ci
68011cb0ef41Sopenharmony_ci    // Update iterator.[[NextIndex]]
68021cb0ef41Sopenharmony_ci    Node* char_length = graph()->NewNode(simplified()->StringLength(), vtrue0);
68031cb0ef41Sopenharmony_ci    index = graph()->NewNode(simplified()->NumberAdd(), index, char_length);
68041cb0ef41Sopenharmony_ci    etrue0 = graph()->NewNode(
68051cb0ef41Sopenharmony_ci        simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
68061cb0ef41Sopenharmony_ci        receiver, index, etrue0, if_true0);
68071cb0ef41Sopenharmony_ci  }
68081cb0ef41Sopenharmony_ci
68091cb0ef41Sopenharmony_ci  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
68101cb0ef41Sopenharmony_ci  Node* done_false;
68111cb0ef41Sopenharmony_ci  Node* vfalse0;
68121cb0ef41Sopenharmony_ci  {
68131cb0ef41Sopenharmony_ci    vfalse0 = jsgraph()->UndefinedConstant();
68141cb0ef41Sopenharmony_ci    done_false = jsgraph()->TrueConstant();
68151cb0ef41Sopenharmony_ci  }
68161cb0ef41Sopenharmony_ci
68171cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
68181cb0ef41Sopenharmony_ci  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control);
68191cb0ef41Sopenharmony_ci  Node* value =
68201cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), vtrue0,
68211cb0ef41Sopenharmony_ci                       vfalse0, control);
68221cb0ef41Sopenharmony_ci  Node* done =
68231cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
68241cb0ef41Sopenharmony_ci                       done_true, done_false, control);
68251cb0ef41Sopenharmony_ci
68261cb0ef41Sopenharmony_ci  value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
68271cb0ef41Sopenharmony_ci                                    value, done, context, effect);
68281cb0ef41Sopenharmony_ci
68291cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
68301cb0ef41Sopenharmony_ci  return Replace(value);
68311cb0ef41Sopenharmony_ci}
68321cb0ef41Sopenharmony_ci
68331cb0ef41Sopenharmony_ci// ES #sec-string.prototype.concat
68341cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) {
68351cb0ef41Sopenharmony_ci  JSCallNode n(node);
68361cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
68371cb0ef41Sopenharmony_ci  const int parameter_count = n.ArgumentCount();
68381cb0ef41Sopenharmony_ci  if (parameter_count > 1) return NoChange();
68391cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
68401cb0ef41Sopenharmony_ci    return NoChange();
68411cb0ef41Sopenharmony_ci  }
68421cb0ef41Sopenharmony_ci
68431cb0ef41Sopenharmony_ci  Effect effect = n.effect();
68441cb0ef41Sopenharmony_ci  Control control = n.control();
68451cb0ef41Sopenharmony_ci  Node* receiver = effect = graph()->NewNode(
68461cb0ef41Sopenharmony_ci      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
68471cb0ef41Sopenharmony_ci
68481cb0ef41Sopenharmony_ci  if (parameter_count == 0) {
68491cb0ef41Sopenharmony_ci    ReplaceWithValue(node, receiver, effect, control);
68501cb0ef41Sopenharmony_ci    return Replace(receiver);
68511cb0ef41Sopenharmony_ci  }
68521cb0ef41Sopenharmony_ci
68531cb0ef41Sopenharmony_ci  Node* argument = effect = graph()->NewNode(
68541cb0ef41Sopenharmony_ci      simplified()->CheckString(p.feedback()), n.Argument(0), effect, control);
68551cb0ef41Sopenharmony_ci  Node* receiver_length =
68561cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->StringLength(), receiver);
68571cb0ef41Sopenharmony_ci  Node* argument_length =
68581cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->StringLength(), argument);
68591cb0ef41Sopenharmony_ci  Node* length = graph()->NewNode(simplified()->NumberAdd(), receiver_length,
68601cb0ef41Sopenharmony_ci                                  argument_length);
68611cb0ef41Sopenharmony_ci  length = effect = graph()->NewNode(
68621cb0ef41Sopenharmony_ci      simplified()->CheckBounds(p.feedback()), length,
68631cb0ef41Sopenharmony_ci      jsgraph()->Constant(String::kMaxLength + 1), effect, control);
68641cb0ef41Sopenharmony_ci
68651cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->StringConcat(), length, receiver,
68661cb0ef41Sopenharmony_ci                                 argument);
68671cb0ef41Sopenharmony_ci
68681cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
68691cb0ef41Sopenharmony_ci  return Replace(value);
68701cb0ef41Sopenharmony_ci}
68711cb0ef41Sopenharmony_ci
68721cb0ef41Sopenharmony_ciReduction JSCallReducer::ReducePromiseConstructor(Node* node) {
68731cb0ef41Sopenharmony_ci  PromiseBuiltinReducerAssembler a(this, node, broker());
68741cb0ef41Sopenharmony_ci
68751cb0ef41Sopenharmony_ci  // We only inline when we have the executor.
68761cb0ef41Sopenharmony_ci  if (a.ConstructArity() < 1) return NoChange();
68771cb0ef41Sopenharmony_ci  // Only handle builtins Promises, not subclasses.
68781cb0ef41Sopenharmony_ci  if (a.TargetInput() != a.NewTargetInput()) return NoChange();
68791cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseHookProtector()) return NoChange();
68801cb0ef41Sopenharmony_ci
68811cb0ef41Sopenharmony_ci  TNode<Object> subgraph = a.ReducePromiseConstructor(native_context());
68821cb0ef41Sopenharmony_ci  return ReplaceWithSubgraph(&a, subgraph);
68831cb0ef41Sopenharmony_ci}
68841cb0ef41Sopenharmony_ci
68851cb0ef41Sopenharmony_cibool JSCallReducer::DoPromiseChecks(MapInference* inference) {
68861cb0ef41Sopenharmony_ci  if (!inference->HaveMaps()) return false;
68871cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference->GetMaps();
68881cb0ef41Sopenharmony_ci
68891cb0ef41Sopenharmony_ci  // Check whether all {receiver_maps} are JSPromise maps and
68901cb0ef41Sopenharmony_ci  // have the initial Promise.prototype as their [[Prototype]].
68911cb0ef41Sopenharmony_ci  for (const MapRef& receiver_map : receiver_maps) {
68921cb0ef41Sopenharmony_ci    if (!receiver_map.IsJSPromiseMap()) return false;
68931cb0ef41Sopenharmony_ci    HeapObjectRef prototype = receiver_map.prototype();
68941cb0ef41Sopenharmony_ci    if (!prototype.equals(native_context().promise_prototype())) {
68951cb0ef41Sopenharmony_ci      return false;
68961cb0ef41Sopenharmony_ci    }
68971cb0ef41Sopenharmony_ci  }
68981cb0ef41Sopenharmony_ci
68991cb0ef41Sopenharmony_ci  return true;
69001cb0ef41Sopenharmony_ci}
69011cb0ef41Sopenharmony_ci
69021cb0ef41Sopenharmony_ci// ES section #sec-promise.prototype.catch
69031cb0ef41Sopenharmony_ciReduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
69041cb0ef41Sopenharmony_ci  JSCallNode n(node);
69051cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
69061cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
69071cb0ef41Sopenharmony_ci    return NoChange();
69081cb0ef41Sopenharmony_ci  }
69091cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
69101cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
69111cb0ef41Sopenharmony_ci  Effect effect = n.effect();
69121cb0ef41Sopenharmony_ci  Control control = n.control();
69131cb0ef41Sopenharmony_ci
69141cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
69151cb0ef41Sopenharmony_ci  if (!DoPromiseChecks(&inference)) return inference.NoChange();
69161cb0ef41Sopenharmony_ci
69171cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseThenProtector()) {
69181cb0ef41Sopenharmony_ci    return inference.NoChange();
69191cb0ef41Sopenharmony_ci  }
69201cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
69211cb0ef41Sopenharmony_ci                                      control, p.feedback());
69221cb0ef41Sopenharmony_ci
69231cb0ef41Sopenharmony_ci  // Massage the {node} to call "then" instead by first removing all inputs
69241cb0ef41Sopenharmony_ci  // following the onRejected parameter, and then filling up the parameters
69251cb0ef41Sopenharmony_ci  // to two inputs from the left with undefined.
69261cb0ef41Sopenharmony_ci  Node* target = jsgraph()->Constant(native_context().promise_then());
69271cb0ef41Sopenharmony_ci  NodeProperties::ReplaceValueInput(node, target, 0);
69281cb0ef41Sopenharmony_ci  NodeProperties::ReplaceEffectInput(node, effect);
69291cb0ef41Sopenharmony_ci  for (; arity > 1; --arity) node->RemoveInput(3);
69301cb0ef41Sopenharmony_ci  for (; arity < 2; ++arity) {
69311cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
69321cb0ef41Sopenharmony_ci  }
69331cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
69341cb0ef41Sopenharmony_ci      node, javascript()->Call(
69351cb0ef41Sopenharmony_ci                JSCallNode::ArityForArgc(arity), p.frequency(), p.feedback(),
69361cb0ef41Sopenharmony_ci                ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(),
69371cb0ef41Sopenharmony_ci                CallFeedbackRelation::kUnrelated));
69381cb0ef41Sopenharmony_ci  return Changed(node).FollowedBy(ReducePromisePrototypeThen(node));
69391cb0ef41Sopenharmony_ci}
69401cb0ef41Sopenharmony_ci
69411cb0ef41Sopenharmony_ciNode* JSCallReducer::CreateClosureFromBuiltinSharedFunctionInfo(
69421cb0ef41Sopenharmony_ci    SharedFunctionInfoRef shared, Node* context, Node* effect, Node* control) {
69431cb0ef41Sopenharmony_ci  DCHECK(shared.HasBuiltinId());
69441cb0ef41Sopenharmony_ci  Handle<FeedbackCell> feedback_cell =
69451cb0ef41Sopenharmony_ci      isolate()->factory()->many_closures_cell();
69461cb0ef41Sopenharmony_ci  Callable const callable =
69471cb0ef41Sopenharmony_ci      Builtins::CallableFor(isolate(), shared.builtin_id());
69481cb0ef41Sopenharmony_ci  CodeTRef code = MakeRef(broker(), *callable.code());
69491cb0ef41Sopenharmony_ci  return graph()->NewNode(javascript()->CreateClosure(shared, code),
69501cb0ef41Sopenharmony_ci                          jsgraph()->HeapConstant(feedback_cell), context,
69511cb0ef41Sopenharmony_ci                          effect, control);
69521cb0ef41Sopenharmony_ci}
69531cb0ef41Sopenharmony_ci
69541cb0ef41Sopenharmony_ci// ES section #sec-promise.prototype.finally
69551cb0ef41Sopenharmony_ciReduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
69561cb0ef41Sopenharmony_ci  JSCallNode n(node);
69571cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
69581cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
69591cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
69601cb0ef41Sopenharmony_ci  Node* on_finally = n.ArgumentOrUndefined(0, jsgraph());
69611cb0ef41Sopenharmony_ci  Effect effect = n.effect();
69621cb0ef41Sopenharmony_ci  Control control = n.control();
69631cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
69641cb0ef41Sopenharmony_ci    return NoChange();
69651cb0ef41Sopenharmony_ci  }
69661cb0ef41Sopenharmony_ci
69671cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
69681cb0ef41Sopenharmony_ci  if (!DoPromiseChecks(&inference)) return inference.NoChange();
69691cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
69701cb0ef41Sopenharmony_ci
69711cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseHookProtector()) {
69721cb0ef41Sopenharmony_ci    return inference.NoChange();
69731cb0ef41Sopenharmony_ci  }
69741cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseThenProtector()) {
69751cb0ef41Sopenharmony_ci    return inference.NoChange();
69761cb0ef41Sopenharmony_ci  }
69771cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseSpeciesProtector()) {
69781cb0ef41Sopenharmony_ci    return inference.NoChange();
69791cb0ef41Sopenharmony_ci  }
69801cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
69811cb0ef41Sopenharmony_ci                                      control, p.feedback());
69821cb0ef41Sopenharmony_ci
69831cb0ef41Sopenharmony_ci  // Check if {on_finally} is callable, and if so wrap it into appropriate
69841cb0ef41Sopenharmony_ci  // closures that perform the finalization.
69851cb0ef41Sopenharmony_ci  Node* check = graph()->NewNode(simplified()->ObjectIsCallable(), on_finally);
69861cb0ef41Sopenharmony_ci  Node* branch =
69871cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
69881cb0ef41Sopenharmony_ci
69891cb0ef41Sopenharmony_ci  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
69901cb0ef41Sopenharmony_ci  Node* etrue = effect;
69911cb0ef41Sopenharmony_ci  Node* catch_true;
69921cb0ef41Sopenharmony_ci  Node* then_true;
69931cb0ef41Sopenharmony_ci  {
69941cb0ef41Sopenharmony_ci    Node* context = jsgraph()->Constant(native_context());
69951cb0ef41Sopenharmony_ci    Node* constructor =
69961cb0ef41Sopenharmony_ci        jsgraph()->Constant(native_context().promise_function());
69971cb0ef41Sopenharmony_ci
69981cb0ef41Sopenharmony_ci    // Allocate shared context for the closures below.
69991cb0ef41Sopenharmony_ci    context = etrue =
70001cb0ef41Sopenharmony_ci        graph()->NewNode(javascript()->CreateFunctionContext(
70011cb0ef41Sopenharmony_ci                             native_context().scope_info(),
70021cb0ef41Sopenharmony_ci                             PromiseBuiltins::kPromiseFinallyContextLength -
70031cb0ef41Sopenharmony_ci                                 Context::MIN_CONTEXT_SLOTS,
70041cb0ef41Sopenharmony_ci                             FUNCTION_SCOPE),
70051cb0ef41Sopenharmony_ci                         context, etrue, if_true);
70061cb0ef41Sopenharmony_ci    etrue = graph()->NewNode(
70071cb0ef41Sopenharmony_ci        simplified()->StoreField(
70081cb0ef41Sopenharmony_ci            AccessBuilder::ForContextSlot(PromiseBuiltins::kOnFinallySlot)),
70091cb0ef41Sopenharmony_ci        context, on_finally, etrue, if_true);
70101cb0ef41Sopenharmony_ci    etrue = graph()->NewNode(
70111cb0ef41Sopenharmony_ci        simplified()->StoreField(
70121cb0ef41Sopenharmony_ci            AccessBuilder::ForContextSlot(PromiseBuiltins::kConstructorSlot)),
70131cb0ef41Sopenharmony_ci        context, constructor, etrue, if_true);
70141cb0ef41Sopenharmony_ci
70151cb0ef41Sopenharmony_ci    // Allocate the closure for the reject case.
70161cb0ef41Sopenharmony_ci    SharedFunctionInfoRef promise_catch_finally =
70171cb0ef41Sopenharmony_ci        MakeRef(broker(), factory()->promise_catch_finally_shared_fun());
70181cb0ef41Sopenharmony_ci    catch_true = etrue = CreateClosureFromBuiltinSharedFunctionInfo(
70191cb0ef41Sopenharmony_ci        promise_catch_finally, context, etrue, if_true);
70201cb0ef41Sopenharmony_ci
70211cb0ef41Sopenharmony_ci    // Allocate the closure for the fulfill case.
70221cb0ef41Sopenharmony_ci    SharedFunctionInfoRef promise_then_finally =
70231cb0ef41Sopenharmony_ci        MakeRef(broker(), factory()->promise_then_finally_shared_fun());
70241cb0ef41Sopenharmony_ci    then_true = etrue = CreateClosureFromBuiltinSharedFunctionInfo(
70251cb0ef41Sopenharmony_ci        promise_then_finally, context, etrue, if_true);
70261cb0ef41Sopenharmony_ci  }
70271cb0ef41Sopenharmony_ci
70281cb0ef41Sopenharmony_ci  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
70291cb0ef41Sopenharmony_ci  Node* efalse = effect;
70301cb0ef41Sopenharmony_ci  Node* catch_false = on_finally;
70311cb0ef41Sopenharmony_ci  Node* then_false = on_finally;
70321cb0ef41Sopenharmony_ci
70331cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
70341cb0ef41Sopenharmony_ci  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
70351cb0ef41Sopenharmony_ci  Node* catch_finally =
70361cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
70371cb0ef41Sopenharmony_ci                       catch_true, catch_false, control);
70381cb0ef41Sopenharmony_ci  Node* then_finally =
70391cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
70401cb0ef41Sopenharmony_ci                       then_true, then_false, control);
70411cb0ef41Sopenharmony_ci
70421cb0ef41Sopenharmony_ci  // At this point we definitely know that {receiver} has one of the
70431cb0ef41Sopenharmony_ci  // {receiver_maps}, so insert a MapGuard as a hint for the lowering
70441cb0ef41Sopenharmony_ci  // of the call to "then" below.
70451cb0ef41Sopenharmony_ci  {
70461cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> maps;
70471cb0ef41Sopenharmony_ci    for (const MapRef& map : receiver_maps) {
70481cb0ef41Sopenharmony_ci      maps.insert(map.object(), graph()->zone());
70491cb0ef41Sopenharmony_ci    }
70501cb0ef41Sopenharmony_ci    effect = graph()->NewNode(simplified()->MapGuard(maps), receiver, effect,
70511cb0ef41Sopenharmony_ci                              control);
70521cb0ef41Sopenharmony_ci  }
70531cb0ef41Sopenharmony_ci
70541cb0ef41Sopenharmony_ci  // Massage the {node} to call "then" instead by first removing all inputs
70551cb0ef41Sopenharmony_ci  // following the onFinally parameter, and then replacing the only parameter
70561cb0ef41Sopenharmony_ci  // input with the {on_finally} value.
70571cb0ef41Sopenharmony_ci  Node* target = jsgraph()->Constant(native_context().promise_then());
70581cb0ef41Sopenharmony_ci  NodeProperties::ReplaceValueInput(node, target, n.TargetIndex());
70591cb0ef41Sopenharmony_ci  NodeProperties::ReplaceEffectInput(node, effect);
70601cb0ef41Sopenharmony_ci  NodeProperties::ReplaceControlInput(node, control);
70611cb0ef41Sopenharmony_ci  for (; arity > 2; --arity) node->RemoveInput(2);
70621cb0ef41Sopenharmony_ci  for (; arity < 2; ++arity) {
70631cb0ef41Sopenharmony_ci    node->InsertInput(graph()->zone(), 2, then_finally);
70641cb0ef41Sopenharmony_ci  }
70651cb0ef41Sopenharmony_ci  node->ReplaceInput(2, then_finally);
70661cb0ef41Sopenharmony_ci  node->ReplaceInput(3, catch_finally);
70671cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
70681cb0ef41Sopenharmony_ci      node, javascript()->Call(
70691cb0ef41Sopenharmony_ci                JSCallNode::ArityForArgc(arity), p.frequency(), p.feedback(),
70701cb0ef41Sopenharmony_ci                ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(),
70711cb0ef41Sopenharmony_ci                CallFeedbackRelation::kUnrelated));
70721cb0ef41Sopenharmony_ci  return Changed(node).FollowedBy(ReducePromisePrototypeThen(node));
70731cb0ef41Sopenharmony_ci}
70741cb0ef41Sopenharmony_ci
70751cb0ef41Sopenharmony_ciReduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
70761cb0ef41Sopenharmony_ci  JSCallNode n(node);
70771cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
70781cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
70791cb0ef41Sopenharmony_ci    return NoChange();
70801cb0ef41Sopenharmony_ci  }
70811cb0ef41Sopenharmony_ci
70821cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
70831cb0ef41Sopenharmony_ci  Node* on_fulfilled = n.ArgumentOrUndefined(0, jsgraph());
70841cb0ef41Sopenharmony_ci  Node* on_rejected = n.ArgumentOrUndefined(1, jsgraph());
70851cb0ef41Sopenharmony_ci  Node* context = n.context();
70861cb0ef41Sopenharmony_ci  Effect effect = n.effect();
70871cb0ef41Sopenharmony_ci  Control control = n.control();
70881cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
70891cb0ef41Sopenharmony_ci
70901cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
70911cb0ef41Sopenharmony_ci  if (!DoPromiseChecks(&inference)) return inference.NoChange();
70921cb0ef41Sopenharmony_ci
70931cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseHookProtector()) {
70941cb0ef41Sopenharmony_ci    return inference.NoChange();
70951cb0ef41Sopenharmony_ci  }
70961cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnPromiseSpeciesProtector()) {
70971cb0ef41Sopenharmony_ci    return inference.NoChange();
70981cb0ef41Sopenharmony_ci  }
70991cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
71001cb0ef41Sopenharmony_ci                                      control, p.feedback());
71011cb0ef41Sopenharmony_ci
71021cb0ef41Sopenharmony_ci  // Check that {on_fulfilled} is callable.
71031cb0ef41Sopenharmony_ci  on_fulfilled = graph()->NewNode(
71041cb0ef41Sopenharmony_ci      common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
71051cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->ObjectIsCallable(), on_fulfilled),
71061cb0ef41Sopenharmony_ci      on_fulfilled, jsgraph()->UndefinedConstant());
71071cb0ef41Sopenharmony_ci
71081cb0ef41Sopenharmony_ci  // Check that {on_rejected} is callable.
71091cb0ef41Sopenharmony_ci  on_rejected = graph()->NewNode(
71101cb0ef41Sopenharmony_ci      common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
71111cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->ObjectIsCallable(), on_rejected),
71121cb0ef41Sopenharmony_ci      on_rejected, jsgraph()->UndefinedConstant());
71131cb0ef41Sopenharmony_ci
71141cb0ef41Sopenharmony_ci  // Create the resulting JSPromise.
71151cb0ef41Sopenharmony_ci  Node* promise = effect =
71161cb0ef41Sopenharmony_ci      graph()->NewNode(javascript()->CreatePromise(), context, effect);
71171cb0ef41Sopenharmony_ci
71181cb0ef41Sopenharmony_ci  // Chain {result} onto {receiver}.
71191cb0ef41Sopenharmony_ci  promise = effect = graph()->NewNode(
71201cb0ef41Sopenharmony_ci      javascript()->PerformPromiseThen(), receiver, on_fulfilled, on_rejected,
71211cb0ef41Sopenharmony_ci      promise, context, frame_state, effect, control);
71221cb0ef41Sopenharmony_ci
71231cb0ef41Sopenharmony_ci  // At this point we know that {promise} is going to have the
71241cb0ef41Sopenharmony_ci  // initial Promise map, since even if {PerformPromiseThen}
71251cb0ef41Sopenharmony_ci  // above called into the host rejection tracker, the {promise}
71261cb0ef41Sopenharmony_ci  // doesn't escape to user JavaScript. So bake this information
71271cb0ef41Sopenharmony_ci  // into the graph such that subsequent passes can use the
71281cb0ef41Sopenharmony_ci  // information for further optimizations.
71291cb0ef41Sopenharmony_ci  MapRef promise_map =
71301cb0ef41Sopenharmony_ci      native_context().promise_function().initial_map(dependencies());
71311cb0ef41Sopenharmony_ci  effect = graph()->NewNode(
71321cb0ef41Sopenharmony_ci      simplified()->MapGuard(ZoneHandleSet<Map>(promise_map.object())), promise,
71331cb0ef41Sopenharmony_ci      effect, control);
71341cb0ef41Sopenharmony_ci
71351cb0ef41Sopenharmony_ci  ReplaceWithValue(node, promise, effect, control);
71361cb0ef41Sopenharmony_ci  return Replace(promise);
71371cb0ef41Sopenharmony_ci}
71381cb0ef41Sopenharmony_ci
71391cb0ef41Sopenharmony_ci// ES section #sec-promise.resolve
71401cb0ef41Sopenharmony_ciReduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) {
71411cb0ef41Sopenharmony_ci  JSCallNode n(node);
71421cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
71431cb0ef41Sopenharmony_ci  Node* value = n.ArgumentOrUndefined(0, jsgraph());
71441cb0ef41Sopenharmony_ci  Node* context = n.context();
71451cb0ef41Sopenharmony_ci  Effect effect = n.effect();
71461cb0ef41Sopenharmony_ci  Control control = n.control();
71471cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
71481cb0ef41Sopenharmony_ci
71491cb0ef41Sopenharmony_ci  // Only reduce when the receiver is guaranteed to be a JSReceiver.
71501cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
71511cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAreJSReceiver()) {
71521cb0ef41Sopenharmony_ci    return NoChange();
71531cb0ef41Sopenharmony_ci  }
71541cb0ef41Sopenharmony_ci
71551cb0ef41Sopenharmony_ci  // Morph the {node} into a JSPromiseResolve operation.
71561cb0ef41Sopenharmony_ci  node->ReplaceInput(0, receiver);
71571cb0ef41Sopenharmony_ci  node->ReplaceInput(1, value);
71581cb0ef41Sopenharmony_ci  node->ReplaceInput(2, context);
71591cb0ef41Sopenharmony_ci  node->ReplaceInput(3, frame_state);
71601cb0ef41Sopenharmony_ci  node->ReplaceInput(4, effect);
71611cb0ef41Sopenharmony_ci  node->ReplaceInput(5, control);
71621cb0ef41Sopenharmony_ci  node->TrimInputCount(6);
71631cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->PromiseResolve());
71641cb0ef41Sopenharmony_ci  return Changed(node);
71651cb0ef41Sopenharmony_ci}
71661cb0ef41Sopenharmony_ci
71671cb0ef41Sopenharmony_ci// ES #sec-typedarray-constructors
71681cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceTypedArrayConstructor(
71691cb0ef41Sopenharmony_ci    Node* node, const SharedFunctionInfoRef& shared) {
71701cb0ef41Sopenharmony_ci  JSConstructNode n(node);
71711cb0ef41Sopenharmony_ci  ConstructParameters const& p = n.Parameters();
71721cb0ef41Sopenharmony_ci  int arity = p.arity_without_implicit_args();
71731cb0ef41Sopenharmony_ci  Node* target = n.target();
71741cb0ef41Sopenharmony_ci  Node* arg0 = n.ArgumentOrUndefined(0, jsgraph());
71751cb0ef41Sopenharmony_ci  Node* arg1 = n.ArgumentOrUndefined(1, jsgraph());
71761cb0ef41Sopenharmony_ci  Node* arg2 = n.ArgumentOrUndefined(2, jsgraph());
71771cb0ef41Sopenharmony_ci  Node* new_target = n.new_target();
71781cb0ef41Sopenharmony_ci  Node* context = n.context();
71791cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
71801cb0ef41Sopenharmony_ci  Effect effect = n.effect();
71811cb0ef41Sopenharmony_ci  Control control = n.control();
71821cb0ef41Sopenharmony_ci
71831cb0ef41Sopenharmony_ci  // Insert a construct stub frame into the chain of frame states. This will
71841cb0ef41Sopenharmony_ci  // reconstruct the proper frame when deoptimizing within the constructor.
71851cb0ef41Sopenharmony_ci  frame_state = CreateArtificialFrameState(
71861cb0ef41Sopenharmony_ci      node, frame_state, arity, BytecodeOffset::ConstructStubInvoke(),
71871cb0ef41Sopenharmony_ci      FrameStateType::kConstructStub, shared, context, common(), graph());
71881cb0ef41Sopenharmony_ci
71891cb0ef41Sopenharmony_ci  // This continuation just returns the newly created JSTypedArray. We
71901cb0ef41Sopenharmony_ci  // pass the_hole as the receiver, just like the builtin construct stub
71911cb0ef41Sopenharmony_ci  // does in this case.
71921cb0ef41Sopenharmony_ci  Node* const parameters[] = {jsgraph()->TheHoleConstant()};
71931cb0ef41Sopenharmony_ci  int const num_parameters = static_cast<int>(arraysize(parameters));
71941cb0ef41Sopenharmony_ci  frame_state = CreateJavaScriptBuiltinContinuationFrameState(
71951cb0ef41Sopenharmony_ci      jsgraph(), shared, Builtin::kGenericLazyDeoptContinuation, target,
71961cb0ef41Sopenharmony_ci      context, parameters, num_parameters, frame_state,
71971cb0ef41Sopenharmony_ci      ContinuationFrameStateMode::LAZY);
71981cb0ef41Sopenharmony_ci
71991cb0ef41Sopenharmony_ci  Node* result =
72001cb0ef41Sopenharmony_ci      graph()->NewNode(javascript()->CreateTypedArray(), target, new_target,
72011cb0ef41Sopenharmony_ci                       arg0, arg1, arg2, context, frame_state, effect, control);
72021cb0ef41Sopenharmony_ci  return Replace(result);
72031cb0ef41Sopenharmony_ci}
72041cb0ef41Sopenharmony_ci
72051cb0ef41Sopenharmony_ci// ES #sec-get-%typedarray%.prototype-@@tostringtag
72061cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) {
72071cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
72081cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
72091cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
72101cb0ef41Sopenharmony_ci
72111cb0ef41Sopenharmony_ci  NodeVector values(graph()->zone());
72121cb0ef41Sopenharmony_ci  NodeVector effects(graph()->zone());
72131cb0ef41Sopenharmony_ci  NodeVector controls(graph()->zone());
72141cb0ef41Sopenharmony_ci
72151cb0ef41Sopenharmony_ci  Node* smi_check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
72161cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Branch(BranchHint::kFalse), smi_check,
72171cb0ef41Sopenharmony_ci                             control);
72181cb0ef41Sopenharmony_ci
72191cb0ef41Sopenharmony_ci  values.push_back(jsgraph()->UndefinedConstant());
72201cb0ef41Sopenharmony_ci  effects.push_back(effect);
72211cb0ef41Sopenharmony_ci  controls.push_back(graph()->NewNode(common()->IfTrue(), control));
72221cb0ef41Sopenharmony_ci
72231cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->IfFalse(), control);
72241cb0ef41Sopenharmony_ci  Node* receiver_map = effect =
72251cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
72261cb0ef41Sopenharmony_ci                       receiver, effect, control);
72271cb0ef41Sopenharmony_ci  Node* receiver_bit_field2 = effect = graph()->NewNode(
72281cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
72291cb0ef41Sopenharmony_ci      effect, control);
72301cb0ef41Sopenharmony_ci  Node* receiver_elements_kind = graph()->NewNode(
72311cb0ef41Sopenharmony_ci      simplified()->NumberShiftRightLogical(),
72321cb0ef41Sopenharmony_ci      graph()->NewNode(
72331cb0ef41Sopenharmony_ci          simplified()->NumberBitwiseAnd(), receiver_bit_field2,
72341cb0ef41Sopenharmony_ci          jsgraph()->Constant(Map::Bits2::ElementsKindBits::kMask)),
72351cb0ef41Sopenharmony_ci      jsgraph()->Constant(Map::Bits2::ElementsKindBits::kShift));
72361cb0ef41Sopenharmony_ci
72371cb0ef41Sopenharmony_ci  // Offset the elements kind by FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
72381cb0ef41Sopenharmony_ci  // so that the branch cascade below is turned into a simple table
72391cb0ef41Sopenharmony_ci  // switch by the ControlFlowOptimizer later.
72401cb0ef41Sopenharmony_ci  receiver_elements_kind = graph()->NewNode(
72411cb0ef41Sopenharmony_ci      simplified()->NumberSubtract(), receiver_elements_kind,
72421cb0ef41Sopenharmony_ci      jsgraph()->Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));
72431cb0ef41Sopenharmony_ci
72441cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                      \
72451cb0ef41Sopenharmony_ci  do {                                                                 \
72461cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(                                    \
72471cb0ef41Sopenharmony_ci        simplified()->NumberEqual(), receiver_elements_kind,           \
72481cb0ef41Sopenharmony_ci        jsgraph()->Constant(TYPE##_ELEMENTS -                          \
72491cb0ef41Sopenharmony_ci                            FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));   \
72501cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->Branch(), check, control);    \
72511cb0ef41Sopenharmony_ci    values.push_back(jsgraph()->Constant(                              \
72521cb0ef41Sopenharmony_ci        broker()->GetTypedArrayStringTag(TYPE##_ELEMENTS)));           \
72531cb0ef41Sopenharmony_ci    effects.push_back(effect);                                         \
72541cb0ef41Sopenharmony_ci    controls.push_back(graph()->NewNode(common()->IfTrue(), control)); \
72551cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->IfFalse(), control);          \
72561cb0ef41Sopenharmony_ci  } while (false);
72571cb0ef41Sopenharmony_ci  TYPED_ARRAYS(TYPED_ARRAY_CASE)
72581cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CASE
72591cb0ef41Sopenharmony_ci
72601cb0ef41Sopenharmony_ci  values.push_back(jsgraph()->UndefinedConstant());
72611cb0ef41Sopenharmony_ci  effects.push_back(effect);
72621cb0ef41Sopenharmony_ci  controls.push_back(control);
72631cb0ef41Sopenharmony_ci
72641cb0ef41Sopenharmony_ci  int const count = static_cast<int>(controls.size());
72651cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Merge(count), count, &controls.front());
72661cb0ef41Sopenharmony_ci  effects.push_back(control);
72671cb0ef41Sopenharmony_ci  effect =
72681cb0ef41Sopenharmony_ci      graph()->NewNode(common()->EffectPhi(count), count + 1, &effects.front());
72691cb0ef41Sopenharmony_ci  values.push_back(control);
72701cb0ef41Sopenharmony_ci  Node* value =
72711cb0ef41Sopenharmony_ci      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
72721cb0ef41Sopenharmony_ci                       count + 1, &values.front());
72731cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
72741cb0ef41Sopenharmony_ci  return Replace(value);
72751cb0ef41Sopenharmony_ci}
72761cb0ef41Sopenharmony_ci
72771cb0ef41Sopenharmony_ci// ES #sec-number.isfinite
72781cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceNumberIsFinite(Node* node) {
72791cb0ef41Sopenharmony_ci  JSCallNode n(node);
72801cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
72811cb0ef41Sopenharmony_ci    Node* value = jsgraph()->FalseConstant();
72821cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
72831cb0ef41Sopenharmony_ci    return Replace(value);
72841cb0ef41Sopenharmony_ci  }
72851cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
72861cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->ObjectIsFiniteNumber(), input);
72871cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
72881cb0ef41Sopenharmony_ci  return Replace(value);
72891cb0ef41Sopenharmony_ci}
72901cb0ef41Sopenharmony_ci
72911cb0ef41Sopenharmony_ci// ES #sec-number.isfinite
72921cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceNumberIsInteger(Node* node) {
72931cb0ef41Sopenharmony_ci  JSCallNode n(node);
72941cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
72951cb0ef41Sopenharmony_ci    Node* value = jsgraph()->FalseConstant();
72961cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
72971cb0ef41Sopenharmony_ci    return Replace(value);
72981cb0ef41Sopenharmony_ci  }
72991cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
73001cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->ObjectIsInteger(), input);
73011cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
73021cb0ef41Sopenharmony_ci  return Replace(value);
73031cb0ef41Sopenharmony_ci}
73041cb0ef41Sopenharmony_ci
73051cb0ef41Sopenharmony_ci// ES #sec-number.issafeinteger
73061cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) {
73071cb0ef41Sopenharmony_ci  JSCallNode n(node);
73081cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
73091cb0ef41Sopenharmony_ci    Node* value = jsgraph()->FalseConstant();
73101cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
73111cb0ef41Sopenharmony_ci    return Replace(value);
73121cb0ef41Sopenharmony_ci  }
73131cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
73141cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->ObjectIsSafeInteger(), input);
73151cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
73161cb0ef41Sopenharmony_ci  return Replace(value);
73171cb0ef41Sopenharmony_ci}
73181cb0ef41Sopenharmony_ci
73191cb0ef41Sopenharmony_ci// ES #sec-number.isnan
73201cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceNumberIsNaN(Node* node) {
73211cb0ef41Sopenharmony_ci  JSCallNode n(node);
73221cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
73231cb0ef41Sopenharmony_ci    Node* value = jsgraph()->FalseConstant();
73241cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
73251cb0ef41Sopenharmony_ci    return Replace(value);
73261cb0ef41Sopenharmony_ci  }
73271cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
73281cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
73291cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value);
73301cb0ef41Sopenharmony_ci  return Replace(value);
73311cb0ef41Sopenharmony_ci}
73321cb0ef41Sopenharmony_ci
73331cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
73341cb0ef41Sopenharmony_ci  // We only optimize if we have target, receiver and key parameters.
73351cb0ef41Sopenharmony_ci  JSCallNode n(node);
73361cb0ef41Sopenharmony_ci  if (n.ArgumentCount() != 1) return NoChange();
73371cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
73381cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
73391cb0ef41Sopenharmony_ci  Control control{NodeProperties::GetControlInput(node)};
73401cb0ef41Sopenharmony_ci  Node* key = NodeProperties::GetValueInput(node, 2);
73411cb0ef41Sopenharmony_ci
73421cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
73431cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(JS_MAP_TYPE)) {
73441cb0ef41Sopenharmony_ci    return NoChange();
73451cb0ef41Sopenharmony_ci  }
73461cb0ef41Sopenharmony_ci
73471cb0ef41Sopenharmony_ci  Node* table = effect = graph()->NewNode(
73481cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
73491cb0ef41Sopenharmony_ci      effect, control);
73501cb0ef41Sopenharmony_ci
73511cb0ef41Sopenharmony_ci  Node* entry = effect = graph()->NewNode(
73521cb0ef41Sopenharmony_ci      simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
73531cb0ef41Sopenharmony_ci
73541cb0ef41Sopenharmony_ci  Node* check = graph()->NewNode(simplified()->NumberEqual(), entry,
73551cb0ef41Sopenharmony_ci                                 jsgraph()->MinusOneConstant());
73561cb0ef41Sopenharmony_ci
73571cb0ef41Sopenharmony_ci  Node* branch = graph()->NewNode(common()->Branch(), check, control);
73581cb0ef41Sopenharmony_ci
73591cb0ef41Sopenharmony_ci  // Key not found.
73601cb0ef41Sopenharmony_ci  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
73611cb0ef41Sopenharmony_ci  Node* etrue = effect;
73621cb0ef41Sopenharmony_ci  Node* vtrue = jsgraph()->UndefinedConstant();
73631cb0ef41Sopenharmony_ci
73641cb0ef41Sopenharmony_ci  // Key found.
73651cb0ef41Sopenharmony_ci  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
73661cb0ef41Sopenharmony_ci  Node* efalse = effect;
73671cb0ef41Sopenharmony_ci  Node* vfalse = efalse = graph()->NewNode(
73681cb0ef41Sopenharmony_ci      simplified()->LoadElement(AccessBuilder::ForOrderedHashMapEntryValue()),
73691cb0ef41Sopenharmony_ci      table, entry, efalse, if_false);
73701cb0ef41Sopenharmony_ci
73711cb0ef41Sopenharmony_ci  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
73721cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(
73731cb0ef41Sopenharmony_ci      common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
73741cb0ef41Sopenharmony_ci  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
73751cb0ef41Sopenharmony_ci
73761cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
73771cb0ef41Sopenharmony_ci  return Replace(value);
73781cb0ef41Sopenharmony_ci}
73791cb0ef41Sopenharmony_ci
73801cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceMapPrototypeHas(Node* node) {
73811cb0ef41Sopenharmony_ci  // We only optimize if we have target, receiver and key parameters.
73821cb0ef41Sopenharmony_ci  JSCallNode n(node);
73831cb0ef41Sopenharmony_ci  if (n.ArgumentCount() != 1) return NoChange();
73841cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
73851cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
73861cb0ef41Sopenharmony_ci  Control control{NodeProperties::GetControlInput(node)};
73871cb0ef41Sopenharmony_ci  Node* key = NodeProperties::GetValueInput(node, 2);
73881cb0ef41Sopenharmony_ci
73891cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
73901cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(JS_MAP_TYPE)) {
73911cb0ef41Sopenharmony_ci    return NoChange();
73921cb0ef41Sopenharmony_ci  }
73931cb0ef41Sopenharmony_ci
73941cb0ef41Sopenharmony_ci  Node* table = effect = graph()->NewNode(
73951cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
73961cb0ef41Sopenharmony_ci      effect, control);
73971cb0ef41Sopenharmony_ci
73981cb0ef41Sopenharmony_ci  Node* index = effect = graph()->NewNode(
73991cb0ef41Sopenharmony_ci      simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
74001cb0ef41Sopenharmony_ci
74011cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->NumberEqual(), index,
74021cb0ef41Sopenharmony_ci                                 jsgraph()->MinusOneConstant());
74031cb0ef41Sopenharmony_ci  value = graph()->NewNode(simplified()->BooleanNot(), value);
74041cb0ef41Sopenharmony_ci
74051cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
74061cb0ef41Sopenharmony_ci  return Replace(value);
74071cb0ef41Sopenharmony_ci}
74081cb0ef41Sopenharmony_ci
74091cb0ef41Sopenharmony_cinamespace {
74101cb0ef41Sopenharmony_ci
74111cb0ef41Sopenharmony_ciInstanceType InstanceTypeForCollectionKind(CollectionKind kind) {
74121cb0ef41Sopenharmony_ci  switch (kind) {
74131cb0ef41Sopenharmony_ci    case CollectionKind::kMap:
74141cb0ef41Sopenharmony_ci      return JS_MAP_TYPE;
74151cb0ef41Sopenharmony_ci    case CollectionKind::kSet:
74161cb0ef41Sopenharmony_ci      return JS_SET_TYPE;
74171cb0ef41Sopenharmony_ci  }
74181cb0ef41Sopenharmony_ci  UNREACHABLE();
74191cb0ef41Sopenharmony_ci}
74201cb0ef41Sopenharmony_ci
74211cb0ef41Sopenharmony_ci}  // namespace
74221cb0ef41Sopenharmony_ci
74231cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceCollectionIteration(
74241cb0ef41Sopenharmony_ci    Node* node, CollectionKind collection_kind, IterationKind iteration_kind) {
74251cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
74261cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
74271cb0ef41Sopenharmony_ci  Node* context = NodeProperties::GetContextInput(node);
74281cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
74291cb0ef41Sopenharmony_ci  Control control{NodeProperties::GetControlInput(node)};
74301cb0ef41Sopenharmony_ci
74311cb0ef41Sopenharmony_ci  InstanceType type = InstanceTypeForCollectionKind(collection_kind);
74321cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
74331cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(type)) {
74341cb0ef41Sopenharmony_ci    return NoChange();
74351cb0ef41Sopenharmony_ci  }
74361cb0ef41Sopenharmony_ci
74371cb0ef41Sopenharmony_ci  Node* js_create_iterator = effect = graph()->NewNode(
74381cb0ef41Sopenharmony_ci      javascript()->CreateCollectionIterator(collection_kind, iteration_kind),
74391cb0ef41Sopenharmony_ci      receiver, context, effect, control);
74401cb0ef41Sopenharmony_ci  ReplaceWithValue(node, js_create_iterator, effect);
74411cb0ef41Sopenharmony_ci  return Replace(js_create_iterator);
74421cb0ef41Sopenharmony_ci}
74431cb0ef41Sopenharmony_ci
74441cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceCollectionPrototypeSize(
74451cb0ef41Sopenharmony_ci    Node* node, CollectionKind collection_kind) {
74461cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
74471cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
74481cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
74491cb0ef41Sopenharmony_ci  Control control{NodeProperties::GetControlInput(node)};
74501cb0ef41Sopenharmony_ci
74511cb0ef41Sopenharmony_ci  InstanceType type = InstanceTypeForCollectionKind(collection_kind);
74521cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
74531cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(type)) {
74541cb0ef41Sopenharmony_ci    return NoChange();
74551cb0ef41Sopenharmony_ci  }
74561cb0ef41Sopenharmony_ci
74571cb0ef41Sopenharmony_ci  Node* table = effect = graph()->NewNode(
74581cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
74591cb0ef41Sopenharmony_ci      effect, control);
74601cb0ef41Sopenharmony_ci  Node* value = effect = graph()->NewNode(
74611cb0ef41Sopenharmony_ci      simplified()->LoadField(
74621cb0ef41Sopenharmony_ci          AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
74631cb0ef41Sopenharmony_ci      table, effect, control);
74641cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
74651cb0ef41Sopenharmony_ci  return Replace(value);
74661cb0ef41Sopenharmony_ci}
74671cb0ef41Sopenharmony_ci
74681cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
74691cb0ef41Sopenharmony_ci    Node* node, int entry_size, Handle<HeapObject> empty_collection,
74701cb0ef41Sopenharmony_ci    InstanceType collection_iterator_instance_type_first,
74711cb0ef41Sopenharmony_ci    InstanceType collection_iterator_instance_type_last) {
74721cb0ef41Sopenharmony_ci  JSCallNode n(node);
74731cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
74741cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
74751cb0ef41Sopenharmony_ci    return NoChange();
74761cb0ef41Sopenharmony_ci  }
74771cb0ef41Sopenharmony_ci
74781cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
74791cb0ef41Sopenharmony_ci  Node* context = n.context();
74801cb0ef41Sopenharmony_ci  Effect effect = n.effect();
74811cb0ef41Sopenharmony_ci  Control control = n.control();
74821cb0ef41Sopenharmony_ci
74831cb0ef41Sopenharmony_ci  // A word of warning to begin with: This whole method might look a bit
74841cb0ef41Sopenharmony_ci  // strange at times, but that's mostly because it was carefully handcrafted
74851cb0ef41Sopenharmony_ci  // to allow for full escape analysis and scalar replacement of both the
74861cb0ef41Sopenharmony_ci  // collection iterator object and the iterator results, including the
74871cb0ef41Sopenharmony_ci  // key-value arrays in case of Set/Map entry iteration.
74881cb0ef41Sopenharmony_ci  //
74891cb0ef41Sopenharmony_ci  // TODO(turbofan): Currently the escape analysis (and the store-load
74901cb0ef41Sopenharmony_ci  // forwarding) is unable to eliminate the allocations for the key-value
74911cb0ef41Sopenharmony_ci  // arrays in case of Set/Map entry iteration, and we should investigate
74921cb0ef41Sopenharmony_ci  // how to update the escape analysis / arrange the graph in a way that
74931cb0ef41Sopenharmony_ci  // this becomes possible.
74941cb0ef41Sopenharmony_ci
74951cb0ef41Sopenharmony_ci  InstanceType receiver_instance_type;
74961cb0ef41Sopenharmony_ci  {
74971cb0ef41Sopenharmony_ci    MapInference inference(broker(), receiver, effect);
74981cb0ef41Sopenharmony_ci    if (!inference.HaveMaps()) return NoChange();
74991cb0ef41Sopenharmony_ci    ZoneVector<MapRef> const& receiver_maps = inference.GetMaps();
75001cb0ef41Sopenharmony_ci    receiver_instance_type = receiver_maps[0].instance_type();
75011cb0ef41Sopenharmony_ci    for (size_t i = 1; i < receiver_maps.size(); ++i) {
75021cb0ef41Sopenharmony_ci      if (receiver_maps[i].instance_type() != receiver_instance_type) {
75031cb0ef41Sopenharmony_ci        return inference.NoChange();
75041cb0ef41Sopenharmony_ci      }
75051cb0ef41Sopenharmony_ci    }
75061cb0ef41Sopenharmony_ci    if (receiver_instance_type < collection_iterator_instance_type_first ||
75071cb0ef41Sopenharmony_ci        receiver_instance_type > collection_iterator_instance_type_last) {
75081cb0ef41Sopenharmony_ci      return inference.NoChange();
75091cb0ef41Sopenharmony_ci    }
75101cb0ef41Sopenharmony_ci    inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
75111cb0ef41Sopenharmony_ci                                        control, p.feedback());
75121cb0ef41Sopenharmony_ci  }
75131cb0ef41Sopenharmony_ci
75141cb0ef41Sopenharmony_ci  // Transition the JSCollectionIterator {receiver} if necessary
75151cb0ef41Sopenharmony_ci  // (i.e. there were certain mutations while we're iterating).
75161cb0ef41Sopenharmony_ci  {
75171cb0ef41Sopenharmony_ci    Node* done_loop;
75181cb0ef41Sopenharmony_ci    Node* done_eloop;
75191cb0ef41Sopenharmony_ci    Node* loop = control =
75201cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Loop(2), control, control);
75211cb0ef41Sopenharmony_ci    Node* eloop = effect =
75221cb0ef41Sopenharmony_ci        graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
75231cb0ef41Sopenharmony_ci    Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
75241cb0ef41Sopenharmony_ci    NodeProperties::MergeControlToEnd(graph(), common(), terminate);
75251cb0ef41Sopenharmony_ci
75261cb0ef41Sopenharmony_ci    // Check if reached the final table of the {receiver}.
75271cb0ef41Sopenharmony_ci    Node* table = effect = graph()->NewNode(
75281cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
75291cb0ef41Sopenharmony_ci        receiver, effect, control);
75301cb0ef41Sopenharmony_ci    Node* next_table = effect =
75311cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->LoadField(
75321cb0ef41Sopenharmony_ci                             AccessBuilder::ForOrderedHashMapOrSetNextTable()),
75331cb0ef41Sopenharmony_ci                         table, effect, control);
75341cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), next_table);
75351cb0ef41Sopenharmony_ci    control =
75361cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
75371cb0ef41Sopenharmony_ci
75381cb0ef41Sopenharmony_ci    // Abort the {loop} when we reach the final table.
75391cb0ef41Sopenharmony_ci    done_loop = graph()->NewNode(common()->IfTrue(), control);
75401cb0ef41Sopenharmony_ci    done_eloop = effect;
75411cb0ef41Sopenharmony_ci
75421cb0ef41Sopenharmony_ci    // Migrate to the {next_table} otherwise.
75431cb0ef41Sopenharmony_ci    control = graph()->NewNode(common()->IfFalse(), control);
75441cb0ef41Sopenharmony_ci
75451cb0ef41Sopenharmony_ci    // Self-heal the {receiver}s index.
75461cb0ef41Sopenharmony_ci    Node* index = effect = graph()->NewNode(
75471cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
75481cb0ef41Sopenharmony_ci        receiver, effect, control);
75491cb0ef41Sopenharmony_ci    Callable const callable =
75501cb0ef41Sopenharmony_ci        Builtins::CallableFor(isolate(), Builtin::kOrderedHashTableHealIndex);
75511cb0ef41Sopenharmony_ci    auto call_descriptor = Linkage::GetStubCallDescriptor(
75521cb0ef41Sopenharmony_ci        graph()->zone(), callable.descriptor(),
75531cb0ef41Sopenharmony_ci        callable.descriptor().GetStackParameterCount(),
75541cb0ef41Sopenharmony_ci        CallDescriptor::kNoFlags, Operator::kEliminatable);
75551cb0ef41Sopenharmony_ci    index = effect =
75561cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Call(call_descriptor),
75571cb0ef41Sopenharmony_ci                         jsgraph()->HeapConstant(callable.code()), table, index,
75581cb0ef41Sopenharmony_ci                         jsgraph()->NoContextConstant(), effect);
75591cb0ef41Sopenharmony_ci
75601cb0ef41Sopenharmony_ci    index = effect = graph()->NewNode(
75611cb0ef41Sopenharmony_ci        common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), index,
75621cb0ef41Sopenharmony_ci        effect, control);
75631cb0ef41Sopenharmony_ci
75641cb0ef41Sopenharmony_ci    // Update the {index} and {table} on the {receiver}.
75651cb0ef41Sopenharmony_ci    effect = graph()->NewNode(
75661cb0ef41Sopenharmony_ci        simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorIndex()),
75671cb0ef41Sopenharmony_ci        receiver, index, effect, control);
75681cb0ef41Sopenharmony_ci    effect = graph()->NewNode(
75691cb0ef41Sopenharmony_ci        simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorTable()),
75701cb0ef41Sopenharmony_ci        receiver, next_table, effect, control);
75711cb0ef41Sopenharmony_ci
75721cb0ef41Sopenharmony_ci    // Tie the knot.
75731cb0ef41Sopenharmony_ci    loop->ReplaceInput(1, control);
75741cb0ef41Sopenharmony_ci    eloop->ReplaceInput(1, effect);
75751cb0ef41Sopenharmony_ci
75761cb0ef41Sopenharmony_ci    control = done_loop;
75771cb0ef41Sopenharmony_ci    effect = done_eloop;
75781cb0ef41Sopenharmony_ci  }
75791cb0ef41Sopenharmony_ci
75801cb0ef41Sopenharmony_ci  // Get current index and table from the JSCollectionIterator {receiver}.
75811cb0ef41Sopenharmony_ci  Node* index = effect = graph()->NewNode(
75821cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
75831cb0ef41Sopenharmony_ci      receiver, effect, control);
75841cb0ef41Sopenharmony_ci  Node* table = effect = graph()->NewNode(
75851cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
75861cb0ef41Sopenharmony_ci      receiver, effect, control);
75871cb0ef41Sopenharmony_ci
75881cb0ef41Sopenharmony_ci  // Create the {JSIteratorResult} first to ensure that we always have
75891cb0ef41Sopenharmony_ci  // a dominating Allocate node for the allocation folding phase.
75901cb0ef41Sopenharmony_ci  Node* iterator_result = effect = graph()->NewNode(
75911cb0ef41Sopenharmony_ci      javascript()->CreateIterResultObject(), jsgraph()->UndefinedConstant(),
75921cb0ef41Sopenharmony_ci      jsgraph()->TrueConstant(), context, effect);
75931cb0ef41Sopenharmony_ci
75941cb0ef41Sopenharmony_ci  // Look for the next non-holey key, starting from {index} in the {table}.
75951cb0ef41Sopenharmony_ci  Node* controls[2];
75961cb0ef41Sopenharmony_ci  Node* effects[3];
75971cb0ef41Sopenharmony_ci  {
75981cb0ef41Sopenharmony_ci    // Compute the currently used capacity.
75991cb0ef41Sopenharmony_ci    Node* number_of_buckets = effect = graph()->NewNode(
76001cb0ef41Sopenharmony_ci        simplified()->LoadField(
76011cb0ef41Sopenharmony_ci            AccessBuilder::ForOrderedHashMapOrSetNumberOfBuckets()),
76021cb0ef41Sopenharmony_ci        table, effect, control);
76031cb0ef41Sopenharmony_ci    Node* number_of_elements = effect = graph()->NewNode(
76041cb0ef41Sopenharmony_ci        simplified()->LoadField(
76051cb0ef41Sopenharmony_ci            AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
76061cb0ef41Sopenharmony_ci        table, effect, control);
76071cb0ef41Sopenharmony_ci    Node* number_of_deleted_elements = effect = graph()->NewNode(
76081cb0ef41Sopenharmony_ci        simplified()->LoadField(
76091cb0ef41Sopenharmony_ci            AccessBuilder::ForOrderedHashMapOrSetNumberOfDeletedElements()),
76101cb0ef41Sopenharmony_ci        table, effect, control);
76111cb0ef41Sopenharmony_ci    Node* used_capacity =
76121cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->NumberAdd(), number_of_elements,
76131cb0ef41Sopenharmony_ci                         number_of_deleted_elements);
76141cb0ef41Sopenharmony_ci
76151cb0ef41Sopenharmony_ci    // Skip holes and update the {index}.
76161cb0ef41Sopenharmony_ci    Node* loop = graph()->NewNode(common()->Loop(2), control, control);
76171cb0ef41Sopenharmony_ci    Node* eloop =
76181cb0ef41Sopenharmony_ci        graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
76191cb0ef41Sopenharmony_ci    Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
76201cb0ef41Sopenharmony_ci    NodeProperties::MergeControlToEnd(graph(), common(), terminate);
76211cb0ef41Sopenharmony_ci    Node* iloop = graph()->NewNode(
76221cb0ef41Sopenharmony_ci        common()->Phi(MachineRepresentation::kTagged, 2), index, index, loop);
76231cb0ef41Sopenharmony_ci
76241cb0ef41Sopenharmony_ci    index = effect = graph()->NewNode(
76251cb0ef41Sopenharmony_ci        common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), iloop,
76261cb0ef41Sopenharmony_ci        eloop, control);
76271cb0ef41Sopenharmony_ci    {
76281cb0ef41Sopenharmony_ci      Node* check0 = graph()->NewNode(simplified()->NumberLessThan(), index,
76291cb0ef41Sopenharmony_ci                                      used_capacity);
76301cb0ef41Sopenharmony_ci      Node* branch0 =
76311cb0ef41Sopenharmony_ci          graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, loop);
76321cb0ef41Sopenharmony_ci
76331cb0ef41Sopenharmony_ci      Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
76341cb0ef41Sopenharmony_ci      Node* efalse0 = effect;
76351cb0ef41Sopenharmony_ci      {
76361cb0ef41Sopenharmony_ci        // Mark the {receiver} as exhausted.
76371cb0ef41Sopenharmony_ci        efalse0 = graph()->NewNode(
76381cb0ef41Sopenharmony_ci            simplified()->StoreField(
76391cb0ef41Sopenharmony_ci                AccessBuilder::ForJSCollectionIteratorTable()),
76401cb0ef41Sopenharmony_ci            receiver, jsgraph()->HeapConstant(empty_collection), efalse0,
76411cb0ef41Sopenharmony_ci            if_false0);
76421cb0ef41Sopenharmony_ci
76431cb0ef41Sopenharmony_ci        controls[0] = if_false0;
76441cb0ef41Sopenharmony_ci        effects[0] = efalse0;
76451cb0ef41Sopenharmony_ci      }
76461cb0ef41Sopenharmony_ci
76471cb0ef41Sopenharmony_ci      Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
76481cb0ef41Sopenharmony_ci      Node* etrue0 = effect;
76491cb0ef41Sopenharmony_ci      {
76501cb0ef41Sopenharmony_ci        // Load the key of the entry.
76511cb0ef41Sopenharmony_ci        STATIC_ASSERT(OrderedHashMap::HashTableStartIndex() ==
76521cb0ef41Sopenharmony_ci                      OrderedHashSet::HashTableStartIndex());
76531cb0ef41Sopenharmony_ci        Node* entry_start_position = graph()->NewNode(
76541cb0ef41Sopenharmony_ci            simplified()->NumberAdd(),
76551cb0ef41Sopenharmony_ci            graph()->NewNode(
76561cb0ef41Sopenharmony_ci                simplified()->NumberAdd(),
76571cb0ef41Sopenharmony_ci                graph()->NewNode(simplified()->NumberMultiply(), index,
76581cb0ef41Sopenharmony_ci                                 jsgraph()->Constant(entry_size)),
76591cb0ef41Sopenharmony_ci                number_of_buckets),
76601cb0ef41Sopenharmony_ci            jsgraph()->Constant(OrderedHashMap::HashTableStartIndex()));
76611cb0ef41Sopenharmony_ci        Node* entry_key = etrue0 = graph()->NewNode(
76621cb0ef41Sopenharmony_ci            simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
76631cb0ef41Sopenharmony_ci            table, entry_start_position, etrue0, if_true0);
76641cb0ef41Sopenharmony_ci
76651cb0ef41Sopenharmony_ci        // Advance the index.
76661cb0ef41Sopenharmony_ci        index = graph()->NewNode(simplified()->NumberAdd(), index,
76671cb0ef41Sopenharmony_ci                                 jsgraph()->OneConstant());
76681cb0ef41Sopenharmony_ci
76691cb0ef41Sopenharmony_ci        Node* check1 =
76701cb0ef41Sopenharmony_ci            graph()->NewNode(simplified()->ReferenceEqual(), entry_key,
76711cb0ef41Sopenharmony_ci                             jsgraph()->TheHoleConstant());
76721cb0ef41Sopenharmony_ci        Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
76731cb0ef41Sopenharmony_ci                                         check1, if_true0);
76741cb0ef41Sopenharmony_ci
76751cb0ef41Sopenharmony_ci        {
76761cb0ef41Sopenharmony_ci          // Abort loop with resulting value.
76771cb0ef41Sopenharmony_ci          control = graph()->NewNode(common()->IfFalse(), branch1);
76781cb0ef41Sopenharmony_ci          effect = etrue0;
76791cb0ef41Sopenharmony_ci          Node* value = effect =
76801cb0ef41Sopenharmony_ci              graph()->NewNode(common()->TypeGuard(Type::NonInternal()),
76811cb0ef41Sopenharmony_ci                               entry_key, effect, control);
76821cb0ef41Sopenharmony_ci          Node* done = jsgraph()->FalseConstant();
76831cb0ef41Sopenharmony_ci
76841cb0ef41Sopenharmony_ci          // Advance the index on the {receiver}.
76851cb0ef41Sopenharmony_ci          effect = graph()->NewNode(
76861cb0ef41Sopenharmony_ci              simplified()->StoreField(
76871cb0ef41Sopenharmony_ci                  AccessBuilder::ForJSCollectionIteratorIndex()),
76881cb0ef41Sopenharmony_ci              receiver, index, effect, control);
76891cb0ef41Sopenharmony_ci
76901cb0ef41Sopenharmony_ci          // The actual {value} depends on the {receiver} iteration type.
76911cb0ef41Sopenharmony_ci          switch (receiver_instance_type) {
76921cb0ef41Sopenharmony_ci            case JS_MAP_KEY_ITERATOR_TYPE:
76931cb0ef41Sopenharmony_ci            case JS_SET_VALUE_ITERATOR_TYPE:
76941cb0ef41Sopenharmony_ci              break;
76951cb0ef41Sopenharmony_ci
76961cb0ef41Sopenharmony_ci            case JS_SET_KEY_VALUE_ITERATOR_TYPE:
76971cb0ef41Sopenharmony_ci              value = effect =
76981cb0ef41Sopenharmony_ci                  graph()->NewNode(javascript()->CreateKeyValueArray(), value,
76991cb0ef41Sopenharmony_ci                                   value, context, effect);
77001cb0ef41Sopenharmony_ci              break;
77011cb0ef41Sopenharmony_ci
77021cb0ef41Sopenharmony_ci            case JS_MAP_VALUE_ITERATOR_TYPE:
77031cb0ef41Sopenharmony_ci              value = effect = graph()->NewNode(
77041cb0ef41Sopenharmony_ci                  simplified()->LoadElement(
77051cb0ef41Sopenharmony_ci                      AccessBuilder::ForFixedArrayElement()),
77061cb0ef41Sopenharmony_ci                  table,
77071cb0ef41Sopenharmony_ci                  graph()->NewNode(
77081cb0ef41Sopenharmony_ci                      simplified()->NumberAdd(), entry_start_position,
77091cb0ef41Sopenharmony_ci                      jsgraph()->Constant(OrderedHashMap::kValueOffset)),
77101cb0ef41Sopenharmony_ci                  effect, control);
77111cb0ef41Sopenharmony_ci              break;
77121cb0ef41Sopenharmony_ci
77131cb0ef41Sopenharmony_ci            case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
77141cb0ef41Sopenharmony_ci              value = effect = graph()->NewNode(
77151cb0ef41Sopenharmony_ci                  simplified()->LoadElement(
77161cb0ef41Sopenharmony_ci                      AccessBuilder::ForFixedArrayElement()),
77171cb0ef41Sopenharmony_ci                  table,
77181cb0ef41Sopenharmony_ci                  graph()->NewNode(
77191cb0ef41Sopenharmony_ci                      simplified()->NumberAdd(), entry_start_position,
77201cb0ef41Sopenharmony_ci                      jsgraph()->Constant(OrderedHashMap::kValueOffset)),
77211cb0ef41Sopenharmony_ci                  effect, control);
77221cb0ef41Sopenharmony_ci              value = effect =
77231cb0ef41Sopenharmony_ci                  graph()->NewNode(javascript()->CreateKeyValueArray(),
77241cb0ef41Sopenharmony_ci                                   entry_key, value, context, effect);
77251cb0ef41Sopenharmony_ci              break;
77261cb0ef41Sopenharmony_ci
77271cb0ef41Sopenharmony_ci            default:
77281cb0ef41Sopenharmony_ci              UNREACHABLE();
77291cb0ef41Sopenharmony_ci          }
77301cb0ef41Sopenharmony_ci
77311cb0ef41Sopenharmony_ci          // Store final {value} and {done} into the {iterator_result}.
77321cb0ef41Sopenharmony_ci          effect =
77331cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->StoreField(
77341cb0ef41Sopenharmony_ci                                   AccessBuilder::ForJSIteratorResultValue()),
77351cb0ef41Sopenharmony_ci                               iterator_result, value, effect, control);
77361cb0ef41Sopenharmony_ci          effect =
77371cb0ef41Sopenharmony_ci              graph()->NewNode(simplified()->StoreField(
77381cb0ef41Sopenharmony_ci                                   AccessBuilder::ForJSIteratorResultDone()),
77391cb0ef41Sopenharmony_ci                               iterator_result, done, effect, control);
77401cb0ef41Sopenharmony_ci
77411cb0ef41Sopenharmony_ci          controls[1] = control;
77421cb0ef41Sopenharmony_ci          effects[1] = effect;
77431cb0ef41Sopenharmony_ci        }
77441cb0ef41Sopenharmony_ci
77451cb0ef41Sopenharmony_ci        // Continue with next loop index.
77461cb0ef41Sopenharmony_ci        loop->ReplaceInput(1, graph()->NewNode(common()->IfTrue(), branch1));
77471cb0ef41Sopenharmony_ci        eloop->ReplaceInput(1, etrue0);
77481cb0ef41Sopenharmony_ci        iloop->ReplaceInput(1, index);
77491cb0ef41Sopenharmony_ci      }
77501cb0ef41Sopenharmony_ci    }
77511cb0ef41Sopenharmony_ci
77521cb0ef41Sopenharmony_ci    control = effects[2] = graph()->NewNode(common()->Merge(2), 2, controls);
77531cb0ef41Sopenharmony_ci    effect = graph()->NewNode(common()->EffectPhi(2), 3, effects);
77541cb0ef41Sopenharmony_ci  }
77551cb0ef41Sopenharmony_ci
77561cb0ef41Sopenharmony_ci  // Yield the final {iterator_result}.
77571cb0ef41Sopenharmony_ci  ReplaceWithValue(node, iterator_result, effect, control);
77581cb0ef41Sopenharmony_ci  return Replace(iterator_result);
77591cb0ef41Sopenharmony_ci}
77601cb0ef41Sopenharmony_ci
77611cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayBufferIsView(Node* node) {
77621cb0ef41Sopenharmony_ci  JSCallNode n(node);
77631cb0ef41Sopenharmony_ci  Node* value = n.ArgumentOrUndefined(0, jsgraph());
77641cb0ef41Sopenharmony_ci  RelaxEffectsAndControls(node);
77651cb0ef41Sopenharmony_ci  node->ReplaceInput(0, value);
77661cb0ef41Sopenharmony_ci  node->TrimInputCount(1);
77671cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, simplified()->ObjectIsArrayBufferView());
77681cb0ef41Sopenharmony_ci  return Changed(node);
77691cb0ef41Sopenharmony_ci}
77701cb0ef41Sopenharmony_ci
77711cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceArrayBufferViewAccessor(
77721cb0ef41Sopenharmony_ci    Node* node, InstanceType instance_type, FieldAccess const& access) {
77731cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
77741cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
77751cb0ef41Sopenharmony_ci  Control control{NodeProperties::GetControlInput(node)};
77761cb0ef41Sopenharmony_ci
77771cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
77781cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() ||
77791cb0ef41Sopenharmony_ci      !inference.AllOfInstanceTypesAre(instance_type)) {
77801cb0ef41Sopenharmony_ci    return NoChange();
77811cb0ef41Sopenharmony_ci  }
77821cb0ef41Sopenharmony_ci
77831cb0ef41Sopenharmony_ci  // Load the {receiver}s field.
77841cb0ef41Sopenharmony_ci  Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
77851cb0ef41Sopenharmony_ci                                          receiver, effect, control);
77861cb0ef41Sopenharmony_ci
77871cb0ef41Sopenharmony_ci  // See if we can skip the detaching check.
77881cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
77891cb0ef41Sopenharmony_ci    // Check whether {receiver}s JSArrayBuffer was detached.
77901cb0ef41Sopenharmony_ci    Node* buffer = effect = graph()->NewNode(
77911cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
77921cb0ef41Sopenharmony_ci        receiver, effect, control);
77931cb0ef41Sopenharmony_ci    Node* buffer_bit_field = effect = graph()->NewNode(
77941cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
77951cb0ef41Sopenharmony_ci        buffer, effect, control);
77961cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(
77971cb0ef41Sopenharmony_ci        simplified()->NumberEqual(),
77981cb0ef41Sopenharmony_ci        graph()->NewNode(
77991cb0ef41Sopenharmony_ci            simplified()->NumberBitwiseAnd(), buffer_bit_field,
78001cb0ef41Sopenharmony_ci            jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
78011cb0ef41Sopenharmony_ci        jsgraph()->ZeroConstant());
78021cb0ef41Sopenharmony_ci
78031cb0ef41Sopenharmony_ci    // TODO(turbofan): Ideally we would bail out here if the {receiver}s
78041cb0ef41Sopenharmony_ci    // JSArrayBuffer was detached, but there's no way to guard against
78051cb0ef41Sopenharmony_ci    // deoptimization loops right now, since the JSCall {node} is usually
78061cb0ef41Sopenharmony_ci    // created from a LOAD_IC inlining, and so there's no CALL_IC slot
78071cb0ef41Sopenharmony_ci    // from which we could use the speculation bit.
78081cb0ef41Sopenharmony_ci    value = graph()->NewNode(
78091cb0ef41Sopenharmony_ci        common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
78101cb0ef41Sopenharmony_ci        check, value, jsgraph()->ZeroConstant());
78111cb0ef41Sopenharmony_ci  }
78121cb0ef41Sopenharmony_ci
78131cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
78141cb0ef41Sopenharmony_ci  return Replace(value);
78151cb0ef41Sopenharmony_ci}
78161cb0ef41Sopenharmony_ci
78171cb0ef41Sopenharmony_cinamespace {
78181cb0ef41Sopenharmony_ciuint32_t ExternalArrayElementSize(const ExternalArrayType element_type) {
78191cb0ef41Sopenharmony_ci  switch (element_type) {
78201cb0ef41Sopenharmony_ci#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
78211cb0ef41Sopenharmony_ci  case kExternal##Type##Array:                    \
78221cb0ef41Sopenharmony_ci    DCHECK_LE(sizeof(ctype), 8);                  \
78231cb0ef41Sopenharmony_ci    return sizeof(ctype);
78241cb0ef41Sopenharmony_ci    TYPED_ARRAYS(TYPED_ARRAY_CASE)
78251cb0ef41Sopenharmony_ci    default:
78261cb0ef41Sopenharmony_ci      UNREACHABLE();
78271cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_CASE
78281cb0ef41Sopenharmony_ci  }
78291cb0ef41Sopenharmony_ci}
78301cb0ef41Sopenharmony_ci}  // namespace
78311cb0ef41Sopenharmony_ci
78321cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
78331cb0ef41Sopenharmony_ci                                              ExternalArrayType element_type) {
78341cb0ef41Sopenharmony_ci  JSCallNode n(node);
78351cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
78361cb0ef41Sopenharmony_ci  size_t const element_size = ExternalArrayElementSize(element_type);
78371cb0ef41Sopenharmony_ci  Effect effect = n.effect();
78381cb0ef41Sopenharmony_ci  Control control = n.control();
78391cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
78401cb0ef41Sopenharmony_ci  Node* offset = n.ArgumentOr(0, jsgraph()->ZeroConstant());
78411cb0ef41Sopenharmony_ci  Node* value = nullptr;
78421cb0ef41Sopenharmony_ci  if (access == DataViewAccess::kSet) {
78431cb0ef41Sopenharmony_ci    value = n.ArgumentOrUndefined(1, jsgraph());
78441cb0ef41Sopenharmony_ci  }
78451cb0ef41Sopenharmony_ci  const int endian_index = (access == DataViewAccess::kGet ? 1 : 2);
78461cb0ef41Sopenharmony_ci  Node* is_little_endian =
78471cb0ef41Sopenharmony_ci      n.ArgumentOr(endian_index, jsgraph()->FalseConstant());
78481cb0ef41Sopenharmony_ci
78491cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
78501cb0ef41Sopenharmony_ci    return NoChange();
78511cb0ef41Sopenharmony_ci  }
78521cb0ef41Sopenharmony_ci
78531cb0ef41Sopenharmony_ci  // Only do stuff if the {receiver} is really a DataView.
78541cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
78551cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() ||
78561cb0ef41Sopenharmony_ci      !inference.AllOfInstanceTypesAre(JS_DATA_VIEW_TYPE)) {
78571cb0ef41Sopenharmony_ci    return NoChange();
78581cb0ef41Sopenharmony_ci  }
78591cb0ef41Sopenharmony_ci
78601cb0ef41Sopenharmony_ci  // Check that the {offset} is within range for the {receiver}.
78611cb0ef41Sopenharmony_ci  HeapObjectMatcher m(receiver);
78621cb0ef41Sopenharmony_ci  if (m.HasResolvedValue() && m.Ref(broker()).IsJSDataView()) {
78631cb0ef41Sopenharmony_ci    // We only deal with DataViews here whose [[ByteLength]] is at least
78641cb0ef41Sopenharmony_ci    // {element_size}, as for all other DataViews it'll be out-of-bounds.
78651cb0ef41Sopenharmony_ci    JSDataViewRef dataview = m.Ref(broker()).AsJSDataView();
78661cb0ef41Sopenharmony_ci    size_t length = dataview.byte_length();
78671cb0ef41Sopenharmony_ci    if (length < element_size) return NoChange();
78681cb0ef41Sopenharmony_ci
78691cb0ef41Sopenharmony_ci    // Check that the {offset} is within range of the {length}.
78701cb0ef41Sopenharmony_ci    Node* byte_length = jsgraph()->Constant(length - (element_size - 1));
78711cb0ef41Sopenharmony_ci    offset = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
78721cb0ef41Sopenharmony_ci                                       offset, byte_length, effect, control);
78731cb0ef41Sopenharmony_ci  } else {
78741cb0ef41Sopenharmony_ci    // We only deal with DataViews here that have Smi [[ByteLength]]s.
78751cb0ef41Sopenharmony_ci    Node* byte_length = effect =
78761cb0ef41Sopenharmony_ci        graph()->NewNode(simplified()->LoadField(
78771cb0ef41Sopenharmony_ci                             AccessBuilder::ForJSArrayBufferViewByteLength()),
78781cb0ef41Sopenharmony_ci                         receiver, effect, control);
78791cb0ef41Sopenharmony_ci
78801cb0ef41Sopenharmony_ci    if (element_size > 1) {
78811cb0ef41Sopenharmony_ci      // For non-byte accesses we also need to check that the {offset}
78821cb0ef41Sopenharmony_ci      // plus the {element_size}-1 fits within the given {byte_length}.
78831cb0ef41Sopenharmony_ci      // So to keep this as a single check on the {offset}, we subtract
78841cb0ef41Sopenharmony_ci      // the {element_size}-1 from the {byte_length} here (clamped to
78851cb0ef41Sopenharmony_ci      // positive safe integer range), and perform a check against that
78861cb0ef41Sopenharmony_ci      // with the {offset} below.
78871cb0ef41Sopenharmony_ci      byte_length = graph()->NewNode(
78881cb0ef41Sopenharmony_ci          simplified()->NumberMax(), jsgraph()->ZeroConstant(),
78891cb0ef41Sopenharmony_ci          graph()->NewNode(simplified()->NumberSubtract(), byte_length,
78901cb0ef41Sopenharmony_ci                           jsgraph()->Constant(element_size - 1)));
78911cb0ef41Sopenharmony_ci    }
78921cb0ef41Sopenharmony_ci
78931cb0ef41Sopenharmony_ci    // Check that the {offset} is within range of the {byte_length}.
78941cb0ef41Sopenharmony_ci    offset = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
78951cb0ef41Sopenharmony_ci                                       offset, byte_length, effect, control);
78961cb0ef41Sopenharmony_ci  }
78971cb0ef41Sopenharmony_ci
78981cb0ef41Sopenharmony_ci  // Coerce {is_little_endian} to boolean.
78991cb0ef41Sopenharmony_ci  is_little_endian =
79001cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->ToBoolean(), is_little_endian);
79011cb0ef41Sopenharmony_ci
79021cb0ef41Sopenharmony_ci  // Coerce {value} to Number.
79031cb0ef41Sopenharmony_ci  if (access == DataViewAccess::kSet) {
79041cb0ef41Sopenharmony_ci    value = effect = graph()->NewNode(
79051cb0ef41Sopenharmony_ci        simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
79061cb0ef41Sopenharmony_ci                                          p.feedback()),
79071cb0ef41Sopenharmony_ci        value, effect, control);
79081cb0ef41Sopenharmony_ci  }
79091cb0ef41Sopenharmony_ci
79101cb0ef41Sopenharmony_ci  // We need to retain either the {receiver} itself or it's backing
79111cb0ef41Sopenharmony_ci  // JSArrayBuffer to make sure that the GC doesn't collect the raw
79121cb0ef41Sopenharmony_ci  // memory. We default to {receiver} here, and only use the buffer
79131cb0ef41Sopenharmony_ci  // if we anyways have to load it (to reduce register pressure).
79141cb0ef41Sopenharmony_ci  Node* buffer_or_receiver = receiver;
79151cb0ef41Sopenharmony_ci
79161cb0ef41Sopenharmony_ci  if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
79171cb0ef41Sopenharmony_ci    // Get the underlying buffer and check that it has not been detached.
79181cb0ef41Sopenharmony_ci    Node* buffer = effect = graph()->NewNode(
79191cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
79201cb0ef41Sopenharmony_ci        receiver, effect, control);
79211cb0ef41Sopenharmony_ci
79221cb0ef41Sopenharmony_ci    // Bail out if the {buffer} was detached.
79231cb0ef41Sopenharmony_ci    Node* buffer_bit_field = effect = graph()->NewNode(
79241cb0ef41Sopenharmony_ci        simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
79251cb0ef41Sopenharmony_ci        buffer, effect, control);
79261cb0ef41Sopenharmony_ci    Node* check = graph()->NewNode(
79271cb0ef41Sopenharmony_ci        simplified()->NumberEqual(),
79281cb0ef41Sopenharmony_ci        graph()->NewNode(
79291cb0ef41Sopenharmony_ci            simplified()->NumberBitwiseAnd(), buffer_bit_field,
79301cb0ef41Sopenharmony_ci            jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
79311cb0ef41Sopenharmony_ci        jsgraph()->ZeroConstant());
79321cb0ef41Sopenharmony_ci    effect = graph()->NewNode(
79331cb0ef41Sopenharmony_ci        simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
79341cb0ef41Sopenharmony_ci                              p.feedback()),
79351cb0ef41Sopenharmony_ci        check, effect, control);
79361cb0ef41Sopenharmony_ci
79371cb0ef41Sopenharmony_ci    // We can reduce register pressure by holding on to the {buffer}
79381cb0ef41Sopenharmony_ci    // now to retain the backing store memory.
79391cb0ef41Sopenharmony_ci    buffer_or_receiver = buffer;
79401cb0ef41Sopenharmony_ci  }
79411cb0ef41Sopenharmony_ci
79421cb0ef41Sopenharmony_ci  // Load the {receiver}s data pointer.
79431cb0ef41Sopenharmony_ci  Node* data_pointer = effect = graph()->NewNode(
79441cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSDataViewDataPointer()),
79451cb0ef41Sopenharmony_ci      receiver, effect, control);
79461cb0ef41Sopenharmony_ci
79471cb0ef41Sopenharmony_ci  switch (access) {
79481cb0ef41Sopenharmony_ci    case DataViewAccess::kGet:
79491cb0ef41Sopenharmony_ci      // Perform the load.
79501cb0ef41Sopenharmony_ci      value = effect = graph()->NewNode(
79511cb0ef41Sopenharmony_ci          simplified()->LoadDataViewElement(element_type), buffer_or_receiver,
79521cb0ef41Sopenharmony_ci          data_pointer, offset, is_little_endian, effect, control);
79531cb0ef41Sopenharmony_ci      break;
79541cb0ef41Sopenharmony_ci    case DataViewAccess::kSet:
79551cb0ef41Sopenharmony_ci      // Perform the store.
79561cb0ef41Sopenharmony_ci      effect = graph()->NewNode(
79571cb0ef41Sopenharmony_ci          simplified()->StoreDataViewElement(element_type), buffer_or_receiver,
79581cb0ef41Sopenharmony_ci          data_pointer, offset, value, is_little_endian, effect, control);
79591cb0ef41Sopenharmony_ci      value = jsgraph()->UndefinedConstant();
79601cb0ef41Sopenharmony_ci      break;
79611cb0ef41Sopenharmony_ci  }
79621cb0ef41Sopenharmony_ci
79631cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
79641cb0ef41Sopenharmony_ci  return Changed(value);
79651cb0ef41Sopenharmony_ci}
79661cb0ef41Sopenharmony_ci
79671cb0ef41Sopenharmony_ci// ES6 section 18.2.2 isFinite ( number )
79681cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceGlobalIsFinite(Node* node) {
79691cb0ef41Sopenharmony_ci  JSCallNode n(node);
79701cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
79711cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
79721cb0ef41Sopenharmony_ci    return NoChange();
79731cb0ef41Sopenharmony_ci  }
79741cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
79751cb0ef41Sopenharmony_ci    Node* value = jsgraph()->FalseConstant();
79761cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
79771cb0ef41Sopenharmony_ci    return Replace(value);
79781cb0ef41Sopenharmony_ci  }
79791cb0ef41Sopenharmony_ci
79801cb0ef41Sopenharmony_ci  Effect effect = n.effect();
79811cb0ef41Sopenharmony_ci  Control control = n.control();
79821cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
79831cb0ef41Sopenharmony_ci
79841cb0ef41Sopenharmony_ci  input = effect =
79851cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(
79861cb0ef41Sopenharmony_ci                           NumberOperationHint::kNumberOrOddball, p.feedback()),
79871cb0ef41Sopenharmony_ci                       input, effect, control);
79881cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->NumberIsFinite(), input);
79891cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect);
79901cb0ef41Sopenharmony_ci  return Replace(value);
79911cb0ef41Sopenharmony_ci}
79921cb0ef41Sopenharmony_ci
79931cb0ef41Sopenharmony_ci// ES6 section 18.2.3 isNaN ( number )
79941cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceGlobalIsNaN(Node* node) {
79951cb0ef41Sopenharmony_ci  JSCallNode n(node);
79961cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
79971cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
79981cb0ef41Sopenharmony_ci    return NoChange();
79991cb0ef41Sopenharmony_ci  }
80001cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
80011cb0ef41Sopenharmony_ci    Node* value = jsgraph()->TrueConstant();
80021cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
80031cb0ef41Sopenharmony_ci    return Replace(value);
80041cb0ef41Sopenharmony_ci  }
80051cb0ef41Sopenharmony_ci
80061cb0ef41Sopenharmony_ci  Effect effect = n.effect();
80071cb0ef41Sopenharmony_ci  Control control = n.control();
80081cb0ef41Sopenharmony_ci  Node* input = n.Argument(0);
80091cb0ef41Sopenharmony_ci
80101cb0ef41Sopenharmony_ci  input = effect =
80111cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->SpeculativeToNumber(
80121cb0ef41Sopenharmony_ci                           NumberOperationHint::kNumberOrOddball, p.feedback()),
80131cb0ef41Sopenharmony_ci                       input, effect, control);
80141cb0ef41Sopenharmony_ci  Node* value = graph()->NewNode(simplified()->NumberIsNaN(), input);
80151cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect);
80161cb0ef41Sopenharmony_ci  return Replace(value);
80171cb0ef41Sopenharmony_ci}
80181cb0ef41Sopenharmony_ci
80191cb0ef41Sopenharmony_ci// ES6 section 20.3.4.10 Date.prototype.getTime ( )
80201cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceDatePrototypeGetTime(Node* node) {
80211cb0ef41Sopenharmony_ci  Node* receiver = NodeProperties::GetValueInput(node, 1);
80221cb0ef41Sopenharmony_ci  Effect effect{NodeProperties::GetEffectInput(node)};
80231cb0ef41Sopenharmony_ci  Control control{NodeProperties::GetControlInput(node)};
80241cb0ef41Sopenharmony_ci
80251cb0ef41Sopenharmony_ci  MapInference inference(broker(), receiver, effect);
80261cb0ef41Sopenharmony_ci  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(JS_DATE_TYPE)) {
80271cb0ef41Sopenharmony_ci    return NoChange();
80281cb0ef41Sopenharmony_ci  }
80291cb0ef41Sopenharmony_ci
80301cb0ef41Sopenharmony_ci  Node* value = effect =
80311cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForJSDateValue()),
80321cb0ef41Sopenharmony_ci                       receiver, effect, control);
80331cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
80341cb0ef41Sopenharmony_ci  return Replace(value);
80351cb0ef41Sopenharmony_ci}
80361cb0ef41Sopenharmony_ci
80371cb0ef41Sopenharmony_ci// ES6 section 20.3.3.1 Date.now ( )
80381cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceDateNow(Node* node) {
80391cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
80401cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
80411cb0ef41Sopenharmony_ci  Node* value = effect =
80421cb0ef41Sopenharmony_ci      graph()->NewNode(simplified()->DateNow(), effect, control);
80431cb0ef41Sopenharmony_ci  ReplaceWithValue(node, value, effect, control);
80441cb0ef41Sopenharmony_ci  return Replace(value);
80451cb0ef41Sopenharmony_ci}
80461cb0ef41Sopenharmony_ci
80471cb0ef41Sopenharmony_ci// ES6 section 20.1.2.13 Number.parseInt ( string, radix )
80481cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceNumberParseInt(Node* node) {
80491cb0ef41Sopenharmony_ci  JSCallNode n(node);
80501cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) {
80511cb0ef41Sopenharmony_ci    Node* value = jsgraph()->NaNConstant();
80521cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value);
80531cb0ef41Sopenharmony_ci    return Replace(value);
80541cb0ef41Sopenharmony_ci  }
80551cb0ef41Sopenharmony_ci
80561cb0ef41Sopenharmony_ci  Effect effect = n.effect();
80571cb0ef41Sopenharmony_ci  Control control = n.control();
80581cb0ef41Sopenharmony_ci  Node* context = n.context();
80591cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
80601cb0ef41Sopenharmony_ci  Node* object = n.Argument(0);
80611cb0ef41Sopenharmony_ci  Node* radix = n.ArgumentOrUndefined(1, jsgraph());
80621cb0ef41Sopenharmony_ci  node->ReplaceInput(0, object);
80631cb0ef41Sopenharmony_ci  node->ReplaceInput(1, radix);
80641cb0ef41Sopenharmony_ci  node->ReplaceInput(2, context);
80651cb0ef41Sopenharmony_ci  node->ReplaceInput(3, frame_state);
80661cb0ef41Sopenharmony_ci  node->ReplaceInput(4, effect);
80671cb0ef41Sopenharmony_ci  node->ReplaceInput(5, control);
80681cb0ef41Sopenharmony_ci  node->TrimInputCount(6);
80691cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->ParseInt());
80701cb0ef41Sopenharmony_ci  return Changed(node);
80711cb0ef41Sopenharmony_ci}
80721cb0ef41Sopenharmony_ci
80731cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
80741cb0ef41Sopenharmony_ci  JSCallNode n(node);
80751cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
80761cb0ef41Sopenharmony_ci  if (FLAG_force_slow_path) return NoChange();
80771cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 1) return NoChange();
80781cb0ef41Sopenharmony_ci
80791cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
80801cb0ef41Sopenharmony_ci    return NoChange();
80811cb0ef41Sopenharmony_ci  }
80821cb0ef41Sopenharmony_ci
80831cb0ef41Sopenharmony_ci  Effect effect = n.effect();
80841cb0ef41Sopenharmony_ci  Control control = n.control();
80851cb0ef41Sopenharmony_ci  Node* regexp = n.receiver();
80861cb0ef41Sopenharmony_ci
80871cb0ef41Sopenharmony_ci  // Only the initial JSRegExp map is valid here, since the following lastIndex
80881cb0ef41Sopenharmony_ci  // check as well as the lowered builtin call rely on a known location of the
80891cb0ef41Sopenharmony_ci  // lastIndex field.
80901cb0ef41Sopenharmony_ci  MapRef regexp_initial_map =
80911cb0ef41Sopenharmony_ci      native_context().regexp_function().initial_map(dependencies());
80921cb0ef41Sopenharmony_ci
80931cb0ef41Sopenharmony_ci  MapInference inference(broker(), regexp, effect);
80941cb0ef41Sopenharmony_ci  if (!inference.Is(regexp_initial_map)) return inference.NoChange();
80951cb0ef41Sopenharmony_ci  ZoneVector<MapRef> const& regexp_maps = inference.GetMaps();
80961cb0ef41Sopenharmony_ci
80971cb0ef41Sopenharmony_ci  ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
80981cb0ef41Sopenharmony_ci  AccessInfoFactory access_info_factory(broker(), dependencies(),
80991cb0ef41Sopenharmony_ci                                        graph()->zone());
81001cb0ef41Sopenharmony_ci
81011cb0ef41Sopenharmony_ci  for (const MapRef& map : regexp_maps) {
81021cb0ef41Sopenharmony_ci    access_infos.push_back(broker()->GetPropertyAccessInfo(
81031cb0ef41Sopenharmony_ci        map, MakeRef(broker(), isolate()->factory()->exec_string()),
81041cb0ef41Sopenharmony_ci        AccessMode::kLoad, dependencies()));
81051cb0ef41Sopenharmony_ci  }
81061cb0ef41Sopenharmony_ci
81071cb0ef41Sopenharmony_ci  PropertyAccessInfo ai_exec =
81081cb0ef41Sopenharmony_ci      access_info_factory.FinalizePropertyAccessInfosAsOne(access_infos,
81091cb0ef41Sopenharmony_ci                                                           AccessMode::kLoad);
81101cb0ef41Sopenharmony_ci  if (ai_exec.IsInvalid()) return inference.NoChange();
81111cb0ef41Sopenharmony_ci  if (!ai_exec.IsFastDataConstant()) return inference.NoChange();
81121cb0ef41Sopenharmony_ci
81131cb0ef41Sopenharmony_ci  // Do not reduce if the exec method is not on the prototype chain.
81141cb0ef41Sopenharmony_ci  base::Optional<JSObjectRef> holder = ai_exec.holder();
81151cb0ef41Sopenharmony_ci  if (!holder.has_value()) return inference.NoChange();
81161cb0ef41Sopenharmony_ci
81171cb0ef41Sopenharmony_ci  // Bail out if the exec method is not the original one.
81181cb0ef41Sopenharmony_ci  base::Optional<ObjectRef> constant = holder->GetOwnFastDataProperty(
81191cb0ef41Sopenharmony_ci      ai_exec.field_representation(), ai_exec.field_index(), dependencies());
81201cb0ef41Sopenharmony_ci  if (!constant.has_value() ||
81211cb0ef41Sopenharmony_ci      !constant->equals(native_context().regexp_exec_function())) {
81221cb0ef41Sopenharmony_ci    return inference.NoChange();
81231cb0ef41Sopenharmony_ci  }
81241cb0ef41Sopenharmony_ci
81251cb0ef41Sopenharmony_ci  // Add proper dependencies on the {regexp}s [[Prototype]]s.
81261cb0ef41Sopenharmony_ci  dependencies()->DependOnStablePrototypeChains(
81271cb0ef41Sopenharmony_ci      ai_exec.lookup_start_object_maps(), kStartAtPrototype, holder.value());
81281cb0ef41Sopenharmony_ci
81291cb0ef41Sopenharmony_ci  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
81301cb0ef41Sopenharmony_ci                                      control, p.feedback());
81311cb0ef41Sopenharmony_ci
81321cb0ef41Sopenharmony_ci  Node* context = n.context();
81331cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
81341cb0ef41Sopenharmony_ci  Node* search = n.Argument(0);
81351cb0ef41Sopenharmony_ci  Node* search_string = effect = graph()->NewNode(
81361cb0ef41Sopenharmony_ci      simplified()->CheckString(p.feedback()), search, effect, control);
81371cb0ef41Sopenharmony_ci
81381cb0ef41Sopenharmony_ci  Node* lastIndex = effect = graph()->NewNode(
81391cb0ef41Sopenharmony_ci      simplified()->LoadField(AccessBuilder::ForJSRegExpLastIndex()), regexp,
81401cb0ef41Sopenharmony_ci      effect, control);
81411cb0ef41Sopenharmony_ci
81421cb0ef41Sopenharmony_ci  Node* lastIndexSmi = effect = graph()->NewNode(
81431cb0ef41Sopenharmony_ci      simplified()->CheckSmi(p.feedback()), lastIndex, effect, control);
81441cb0ef41Sopenharmony_ci
81451cb0ef41Sopenharmony_ci  Node* is_positive = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
81461cb0ef41Sopenharmony_ci                                       jsgraph()->ZeroConstant(), lastIndexSmi);
81471cb0ef41Sopenharmony_ci
81481cb0ef41Sopenharmony_ci  effect = graph()->NewNode(
81491cb0ef41Sopenharmony_ci      simplified()->CheckIf(DeoptimizeReason::kNotASmi, p.feedback()),
81501cb0ef41Sopenharmony_ci      is_positive, effect, control);
81511cb0ef41Sopenharmony_ci
81521cb0ef41Sopenharmony_ci  node->ReplaceInput(0, regexp);
81531cb0ef41Sopenharmony_ci  node->ReplaceInput(1, search_string);
81541cb0ef41Sopenharmony_ci  node->ReplaceInput(2, context);
81551cb0ef41Sopenharmony_ci  node->ReplaceInput(3, frame_state);
81561cb0ef41Sopenharmony_ci  node->ReplaceInput(4, effect);
81571cb0ef41Sopenharmony_ci  node->ReplaceInput(5, control);
81581cb0ef41Sopenharmony_ci  node->TrimInputCount(6);
81591cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->RegExpTest());
81601cb0ef41Sopenharmony_ci  return Changed(node);
81611cb0ef41Sopenharmony_ci}
81621cb0ef41Sopenharmony_ci
81631cb0ef41Sopenharmony_ci// ES section #sec-number-constructor
81641cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceNumberConstructor(Node* node) {
81651cb0ef41Sopenharmony_ci  JSCallNode n(node);
81661cb0ef41Sopenharmony_ci  Node* target = n.target();
81671cb0ef41Sopenharmony_ci  Node* receiver = n.receiver();
81681cb0ef41Sopenharmony_ci  Node* value = n.ArgumentOr(0, jsgraph()->ZeroConstant());
81691cb0ef41Sopenharmony_ci  Node* context = n.context();
81701cb0ef41Sopenharmony_ci  FrameState frame_state = n.frame_state();
81711cb0ef41Sopenharmony_ci
81721cb0ef41Sopenharmony_ci  // Create the artificial frame state in the middle of the Number constructor.
81731cb0ef41Sopenharmony_ci  SharedFunctionInfoRef shared_info =
81741cb0ef41Sopenharmony_ci      native_context().number_function().shared();
81751cb0ef41Sopenharmony_ci  Node* stack_parameters[] = {receiver};
81761cb0ef41Sopenharmony_ci  int stack_parameter_count = arraysize(stack_parameters);
81771cb0ef41Sopenharmony_ci  Node* continuation_frame_state =
81781cb0ef41Sopenharmony_ci      CreateJavaScriptBuiltinContinuationFrameState(
81791cb0ef41Sopenharmony_ci          jsgraph(), shared_info, Builtin::kGenericLazyDeoptContinuation,
81801cb0ef41Sopenharmony_ci          target, context, stack_parameters, stack_parameter_count, frame_state,
81811cb0ef41Sopenharmony_ci          ContinuationFrameStateMode::LAZY);
81821cb0ef41Sopenharmony_ci
81831cb0ef41Sopenharmony_ci  // Convert the {value} to a Number.
81841cb0ef41Sopenharmony_ci  NodeProperties::ReplaceValueInputs(node, value);
81851cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, javascript()->ToNumberConvertBigInt());
81861cb0ef41Sopenharmony_ci  NodeProperties::ReplaceFrameStateInput(node, continuation_frame_state);
81871cb0ef41Sopenharmony_ci  return Changed(node);
81881cb0ef41Sopenharmony_ci}
81891cb0ef41Sopenharmony_ci
81901cb0ef41Sopenharmony_ciReduction JSCallReducer::ReduceBigIntAsN(Node* node, Builtin builtin) {
81911cb0ef41Sopenharmony_ci  DCHECK(builtin == Builtin::kBigIntAsIntN ||
81921cb0ef41Sopenharmony_ci         builtin == Builtin::kBigIntAsUintN);
81931cb0ef41Sopenharmony_ci
81941cb0ef41Sopenharmony_ci  if (!jsgraph()->machine()->Is64()) return NoChange();
81951cb0ef41Sopenharmony_ci
81961cb0ef41Sopenharmony_ci  JSCallNode n(node);
81971cb0ef41Sopenharmony_ci  CallParameters const& p = n.Parameters();
81981cb0ef41Sopenharmony_ci  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
81991cb0ef41Sopenharmony_ci    return NoChange();
82001cb0ef41Sopenharmony_ci  }
82011cb0ef41Sopenharmony_ci  if (n.ArgumentCount() < 2) {
82021cb0ef41Sopenharmony_ci    return NoChange();
82031cb0ef41Sopenharmony_ci  }
82041cb0ef41Sopenharmony_ci
82051cb0ef41Sopenharmony_ci  Effect effect = n.effect();
82061cb0ef41Sopenharmony_ci  Control control = n.control();
82071cb0ef41Sopenharmony_ci  Node* bits = n.Argument(0);
82081cb0ef41Sopenharmony_ci  Node* value = n.Argument(1);
82091cb0ef41Sopenharmony_ci
82101cb0ef41Sopenharmony_ci  NumberMatcher matcher(bits);
82111cb0ef41Sopenharmony_ci  if (matcher.IsInteger() && matcher.IsInRange(0, 64)) {
82121cb0ef41Sopenharmony_ci    const int bits_value = static_cast<int>(matcher.ResolvedValue());
82131cb0ef41Sopenharmony_ci    value = effect = graph()->NewNode(
82141cb0ef41Sopenharmony_ci        (builtin == Builtin::kBigIntAsIntN
82151cb0ef41Sopenharmony_ci             ? simplified()->SpeculativeBigIntAsIntN(bits_value, p.feedback())
82161cb0ef41Sopenharmony_ci             : simplified()->SpeculativeBigIntAsUintN(bits_value,
82171cb0ef41Sopenharmony_ci                                                      p.feedback())),
82181cb0ef41Sopenharmony_ci        value, effect, control);
82191cb0ef41Sopenharmony_ci    ReplaceWithValue(node, value, effect);
82201cb0ef41Sopenharmony_ci    return Replace(value);
82211cb0ef41Sopenharmony_ci  }
82221cb0ef41Sopenharmony_ci
82231cb0ef41Sopenharmony_ci  return NoChange();
82241cb0ef41Sopenharmony_ci}
82251cb0ef41Sopenharmony_ci
82261cb0ef41Sopenharmony_ciCompilationDependencies* JSCallReducer::dependencies() const {
82271cb0ef41Sopenharmony_ci  return broker()->dependencies();
82281cb0ef41Sopenharmony_ci}
82291cb0ef41Sopenharmony_ci
82301cb0ef41Sopenharmony_ciGraph* JSCallReducer::graph() const { return jsgraph()->graph(); }
82311cb0ef41Sopenharmony_ci
82321cb0ef41Sopenharmony_ciIsolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
82331cb0ef41Sopenharmony_ci
82341cb0ef41Sopenharmony_ciFactory* JSCallReducer::factory() const { return isolate()->factory(); }
82351cb0ef41Sopenharmony_ci
82361cb0ef41Sopenharmony_ciNativeContextRef JSCallReducer::native_context() const {
82371cb0ef41Sopenharmony_ci  return broker()->target_native_context();
82381cb0ef41Sopenharmony_ci}
82391cb0ef41Sopenharmony_ci
82401cb0ef41Sopenharmony_ciCommonOperatorBuilder* JSCallReducer::common() const {
82411cb0ef41Sopenharmony_ci  return jsgraph()->common();
82421cb0ef41Sopenharmony_ci}
82431cb0ef41Sopenharmony_ci
82441cb0ef41Sopenharmony_ciJSOperatorBuilder* JSCallReducer::javascript() const {
82451cb0ef41Sopenharmony_ci  return jsgraph()->javascript();
82461cb0ef41Sopenharmony_ci}
82471cb0ef41Sopenharmony_ci
82481cb0ef41Sopenharmony_ciSimplifiedOperatorBuilder* JSCallReducer::simplified() const {
82491cb0ef41Sopenharmony_ci  return jsgraph()->simplified();
82501cb0ef41Sopenharmony_ci}
82511cb0ef41Sopenharmony_ci
82521cb0ef41Sopenharmony_ci}  // namespace compiler
82531cb0ef41Sopenharmony_ci}  // namespace internal
82541cb0ef41Sopenharmony_ci}  // namespace v8
8255