// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/js-call-reducer.h"

#include <functional>

#include "include/v8-fast-api-calls.h"
#include "src/api/api-inl.h"
#include "src/base/small-vector.h"
#include "src/builtins/builtins-promise.h"
#include "src/builtins/builtins-utils.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/tnode.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/allocation-builder.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/feedback-source.h"
#include "src/compiler/graph-assembler.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/map-inference.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/property-access-builder.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/type-cache.h"
#include "src/ic/call-optimization.h"
#include "src/logging/counters.h"
#include "src/objects/arguments-inl.h"
#include "src/objects/feedback-vector-inl.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-objects.h"
#include "src/objects/objects-inl.h"
#include "src/objects/ordered-hash-table.h"

namespace v8 {
namespace internal {
namespace compiler {

// Shorter lambda declarations with less visual clutter.
#define _ [&]()  // NOLINT(whitespace/braces)

class JSCallReducerAssembler : public JSGraphAssembler {
 protected:
  class CatchScope;

 private:
  static constexpr bool kMarkLoopExits = true;

 public:
  JSCallReducerAssembler(JSCallReducer* reducer, Node* node)
      : JSGraphAssembler(
            reducer->JSGraphForGraphAssembler(),
            reducer->ZoneForGraphAssembler(),
            [reducer](Node* n) { reducer->RevisitForGraphAssembler(n); },
            nullptr, kMarkLoopExits),
        node_(node),
        outermost_catch_scope_(
            CatchScope::Outermost(reducer->ZoneForGraphAssembler())),
        catch_scope_(&outermost_catch_scope_) {
    InitializeEffectControl(NodeProperties::GetEffectInput(node),
                            NodeProperties::GetControlInput(node));

    // Finish initializing the outermost catch scope.
    bool has_handler =
        NodeProperties::IsExceptionalCall(node, &outermost_handler_);
    outermost_catch_scope_.set_has_handler(has_handler);
    outermost_catch_scope_.set_gasm(this);
  }

  TNode<Object> ReduceMathUnary(const Operator* op);
  TNode<Object> ReduceMathBinary(const Operator* op);
  TNode<String> ReduceStringPrototypeSubstring();
  TNode<String> ReduceStringPrototypeSlice();

  TNode<Object> TargetInput() const { return JSCallNode{node_ptr()}.target(); }

  template <typename T>
  TNode<T> ReceiverInputAs() const {
    return TNode<T>::UncheckedCast(JSCallNode{node_ptr()}.receiver());
  }

  TNode<Object> ReceiverInput() const { return ReceiverInputAs<Object>(); }

  CatchScope* catch_scope() const { return catch_scope_; }
  Node* outermost_handler() const { return outermost_handler_; }

  Node* node_ptr() const { return node_; }

 protected:
  using NodeGenerator0 = std::function<TNode<Object>()>;
  using VoidGenerator0 = std::function<void()>;

  // TODO(jgruber): Currently IfBuilder0 and IfBuilder1 are implemented as
  // separate classes. If, in the future, we encounter additional use cases that
  // return more than 1 value, we should merge these back into a single variadic
  // implementation.
  class IfBuilder0 final {
   public:
    IfBuilder0(JSGraphAssembler* gasm, TNode<Boolean> cond, bool negate_cond)
        : gasm_(gasm),
          cond_(cond),
          negate_cond_(negate_cond),
          initial_effect_(gasm->effect()),
          initial_control_(gasm->control()) {}

    IfBuilder0& ExpectTrue() {
      DCHECK_EQ(hint_, BranchHint::kNone);
      hint_ = BranchHint::kTrue;
      return *this;
    }
    IfBuilder0& ExpectFalse() {
      DCHECK_EQ(hint_, BranchHint::kNone);
      hint_ = BranchHint::kFalse;
      return *this;
    }

    IfBuilder0& Then(const VoidGenerator0& body) {
      then_body_ = body;
      return *this;
    }
    IfBuilder0& Else(const VoidGenerator0& body) {
      else_body_ = body;
      return *this;
    }

    ~IfBuilder0() {
      // Ensure correct usage: effect/control must not have been modified while
      // the IfBuilder0 instance is alive.
      DCHECK_EQ(gasm_->effect(), initial_effect_);
      DCHECK_EQ(gasm_->control(), initial_control_);

      // Unlike IfBuilder1, this supports an empty then or else body. This is
      // possible since the merge does not take any value inputs.
      DCHECK(then_body_ || else_body_);

      if (negate_cond_) std::swap(then_body_, else_body_);

      auto if_true = (hint_ == BranchHint::kFalse) ? gasm_->MakeDeferredLabel()
                                                   : gasm_->MakeLabel();
      auto if_false = (hint_ == BranchHint::kTrue) ? gasm_->MakeDeferredLabel()
                                                   : gasm_->MakeLabel();
      auto merge = gasm_->MakeLabel();
      gasm_->Branch(cond_, &if_true, &if_false);

      gasm_->Bind(&if_true);
      if (then_body_) then_body_();
      if (gasm_->HasActiveBlock()) gasm_->Goto(&merge);

      gasm_->Bind(&if_false);
      if (else_body_) else_body_();
      if (gasm_->HasActiveBlock()) gasm_->Goto(&merge);

      gasm_->Bind(&merge);
    }

    IfBuilder0(const IfBuilder0&) = delete;
    IfBuilder0& operator=(const IfBuilder0&) = delete;

   private:
    JSGraphAssembler* const gasm_;
    const TNode<Boolean> cond_;
    const bool negate_cond_;
    const Effect initial_effect_;
    const Control initial_control_;
    BranchHint hint_ = BranchHint::kNone;
    VoidGenerator0 then_body_;
    VoidGenerator0 else_body_;
  };

  IfBuilder0 If(TNode<Boolean> cond) { return {this, cond, false}; }
  IfBuilder0 IfNot(TNode<Boolean> cond) { return {this, cond, true}; }

  template <typename T>
  class IfBuilder1 {
    using If1BodyFunction = std::function<TNode<T>()>;

   public:
    IfBuilder1(JSGraphAssembler* gasm, TNode<Boolean> cond)
        : gasm_(gasm), cond_(cond) {}

    V8_WARN_UNUSED_RESULT IfBuilder1& ExpectTrue() {
      DCHECK_EQ(hint_, BranchHint::kNone);
      hint_ = BranchHint::kTrue;
      return *this;
    }

    V8_WARN_UNUSED_RESULT IfBuilder1& ExpectFalse() {
      DCHECK_EQ(hint_, BranchHint::kNone);
      hint_ = BranchHint::kFalse;
      return *this;
    }

    V8_WARN_UNUSED_RESULT IfBuilder1& Then(const If1BodyFunction& body) {
      then_body_ = body;
      return *this;
    }
    V8_WARN_UNUSED_RESULT IfBuilder1& Else(const If1BodyFunction& body) {
      else_body_ = body;
      return *this;
    }

    V8_WARN_UNUSED_RESULT TNode<T> Value() {
      DCHECK(then_body_);
      DCHECK(else_body_);
      auto if_true = (hint_ == BranchHint::kFalse) ? gasm_->MakeDeferredLabel()
                                                   : gasm_->MakeLabel();
      auto if_false = (hint_ == BranchHint::kTrue) ? gasm_->MakeDeferredLabel()
                                                   : gasm_->MakeLabel();
      auto merge = gasm_->MakeLabel(kPhiRepresentation);
      gasm_->Branch(cond_, &if_true, &if_false);

      gasm_->Bind(&if_true);
      TNode<T> then_result = then_body_();
      if (gasm_->HasActiveBlock()) gasm_->Goto(&merge, then_result);

      gasm_->Bind(&if_false);
      TNode<T> else_result = else_body_();
      if (gasm_->HasActiveBlock()) {
        gasm_->Goto(&merge, else_result);
      }

      gasm_->Bind(&merge);
      return merge.PhiAt<T>(0);
    }

   private:
    static constexpr MachineRepresentation kPhiRepresentation =
        MachineRepresentation::kTagged;

    JSGraphAssembler* const gasm_;
    const TNode<Boolean> cond_;
    BranchHint hint_ = BranchHint::kNone;
    If1BodyFunction then_body_;
    If1BodyFunction else_body_;
  };

  template <typename T>
  IfBuilder1<T> SelectIf(TNode<Boolean> cond) {
    return {this, cond};
  }

  // Simplified operators.
  TNode<Number> SpeculativeToNumber(
      TNode<Object> value,
      NumberOperationHint hint = NumberOperationHint::kNumberOrOddball);
  TNode<Smi> CheckSmi(TNode<Object> value);
  TNode<String> CheckString(TNode<Object> value);
  TNode<Number> CheckBounds(TNode<Number> value, TNode<Number> limit);

  // Common operators.
  TNode<Smi> TypeGuardUnsignedSmall(TNode<Object> value);
  TNode<Object> TypeGuardNonInternal(TNode<Object> value);
  TNode<Number> TypeGuardFixedArrayLength(TNode<Object> value);
  TNode<Object> Call4(const Callable& callable, TNode<Context> context,
                      TNode<Object> arg0, TNode<Object> arg1,
                      TNode<Object> arg2, TNode<Object> arg3);

  // Javascript operators.
  TNode<Object> JSCall3(TNode<Object> function, TNode<Object> this_arg,
                        TNode<Object> arg0, TNode<Object> arg1,
                        TNode<Object> arg2, FrameState frame_state);
  TNode<Object> JSCall4(TNode<Object> function, TNode<Object> this_arg,
                        TNode<Object> arg0, TNode<Object> arg1,
                        TNode<Object> arg2, TNode<Object> arg3,
                        FrameState frame_state);
  TNode<Object> JSCallRuntime2(Runtime::FunctionId function_id,
                               TNode<Object> arg0, TNode<Object> arg1,
                               FrameState frame_state);
  // Used in special cases in which we are certain CreateArray does not throw.
  TNode<JSArray> CreateArrayNoThrow(TNode<Object> ctor, TNode<Number> size,
                                    FrameState frame_state);

  TNode<JSArray> AllocateEmptyJSArray(ElementsKind kind,
                                      const NativeContextRef& native_context);

  TNode<Number> NumberInc(TNode<Number> value) {
    return NumberAdd(value, OneConstant());
  }

  void MaybeInsertMapChecks(MapInference* inference,
                            bool has_stability_dependency) {
    // TODO(jgruber): Implement MapInference::InsertMapChecks in graph
    // assembler.
    if (!has_stability_dependency) {
      Effect e = effect();
      inference->InsertMapChecks(jsgraph(), &e, Control{control()}, feedback());
      InitializeEffectControl(e, control());
    }
  }

  // TODO(jgruber): Currently, it's the responsibility of the developer to note
  // which operations may throw and appropriately wrap these in a call to
  // MayThrow (see e.g. JSCall3 and CallRuntime2). A more methodical approach
  // would be good.
  TNode<Object> MayThrow(const NodeGenerator0& body) {
    TNode<Object> result = body();

    if (catch_scope()->has_handler()) {
      // The IfException node is later merged into the outer graph.
      // Note: AddNode is intentionally not called since effect and control
      // should not be updated.
      Node* if_exception =
          graph()->NewNode(common()->IfException(), effect(), control());
      catch_scope()->RegisterIfExceptionNode(if_exception);

      // Control resumes here.
      AddNode(graph()->NewNode(common()->IfSuccess(), control()));
    }

    return result;
  }

  // A catch scope represents a single catch handler. The handler can be
  // custom catch logic within the reduction itself; or a catch handler in the
  // outside graph into which the reduction will be integrated (in this case
  // the scope is called 'outermost').
  class CatchScope {
   private:
    // Only used to partially construct the outermost scope.
    explicit CatchScope(Zone* zone) : if_exception_nodes_(zone) {}

    // For all inner scopes.
    CatchScope(Zone* zone, JSCallReducerAssembler* gasm)
        : gasm_(gasm),
          parent_(gasm->catch_scope_),
          has_handler_(true),
          if_exception_nodes_(zone) {
      gasm_->catch_scope_ = this;
    }

   public:
    ~CatchScope() { gasm_->catch_scope_ = parent_; }

    static CatchScope Outermost(Zone* zone) { return CatchScope{zone}; }
    static CatchScope Inner(Zone* zone, JSCallReducerAssembler* gasm) {
      return {zone, gasm};
    }

    bool has_handler() const { return has_handler_; }
    bool is_outermost() const { return parent_ == nullptr; }
    CatchScope* parent() const { return parent_; }

    // Should only be used to initialize the outermost scope (inner scopes
    // always have a handler and are passed the gasm pointer at construction).
    void set_has_handler(bool v) {
      DCHECK(is_outermost());
      has_handler_ = v;
    }
    void set_gasm(JSCallReducerAssembler* v) {
      DCHECK(is_outermost());
      gasm_ = v;
    }

    bool has_exceptional_control_flow() const {
      return !if_exception_nodes_.empty();
    }

    void RegisterIfExceptionNode(Node* if_exception) {
      DCHECK(has_handler());
      if_exception_nodes_.push_back(if_exception);
    }

    void MergeExceptionalPaths(TNode<Object>* exception_out, Effect* effect_out,
                               Control* control_out) {
      DCHECK(has_handler());
      DCHECK(has_exceptional_control_flow());

      const int size = static_cast<int>(if_exception_nodes_.size());

      if (size == 1) {
        // No merge needed.
        Node* e = if_exception_nodes_.at(0);
        *exception_out = TNode<Object>::UncheckedCast(e);
        *effect_out = Effect(e);
        *control_out = Control(e);
      } else {
        DCHECK_GT(size, 1);

        Node* merge = gasm_->graph()->NewNode(gasm_->common()->Merge(size),
                                              size, if_exception_nodes_.data());

        // These phis additionally take {merge} as an input. Temporarily add
        // it to the list.
        if_exception_nodes_.push_back(merge);
        const int size_with_merge =
            static_cast<int>(if_exception_nodes_.size());

        Node* ephi = gasm_->graph()->NewNode(gasm_->common()->EffectPhi(size),
                                             size_with_merge,
                                             if_exception_nodes_.data());
        Node* phi = gasm_->graph()->NewNode(
            gasm_->common()->Phi(MachineRepresentation::kTagged, size),
            size_with_merge, if_exception_nodes_.data());
        if_exception_nodes_.pop_back();

        *exception_out = TNode<Object>::UncheckedCast(phi);
        *effect_out = Effect(ephi);
        *control_out = Control(merge);
      }
    }

   private:
    JSCallReducerAssembler* gasm_ = nullptr;
    CatchScope* const parent_ = nullptr;
    bool has_handler_ = false;
    NodeVector if_exception_nodes_;
  };

  class TryCatchBuilder0 {
   public:
    using TryFunction = VoidGenerator0;
    using CatchFunction = std::function<void(TNode<Object>)>;

    TryCatchBuilder0(JSCallReducerAssembler* gasm, const TryFunction& try_body)
        : gasm_(gasm), try_body_(try_body) {}

    void Catch(const CatchFunction& catch_body) {
      TNode<Object> handler_exception;
      Effect handler_effect{nullptr};
      Control handler_control{nullptr};

      auto continuation = gasm_->MakeLabel();

      // Try.
      {
        CatchScope catch_scope = CatchScope::Inner(gasm_->temp_zone(), gasm_);
        try_body_();
        gasm_->Goto(&continuation);

        catch_scope.MergeExceptionalPaths(&handler_exception, &handler_effect,
                                          &handler_control);
      }

      // Catch.
      {
        gasm_->InitializeEffectControl(handler_effect, handler_control);
        catch_body(handler_exception);
        gasm_->Goto(&continuation);
      }

      gasm_->Bind(&continuation);
    }

   private:
    JSCallReducerAssembler* const gasm_;
    const VoidGenerator0 try_body_;
  };

  TryCatchBuilder0 Try(const VoidGenerator0& try_body) {
    return {this, try_body};
  }

  using ConditionFunction1 = std::function<TNode<Boolean>(TNode<Number>)>;
  using StepFunction1 = std::function<TNode<Number>(TNode<Number>)>;
  class ForBuilder0 {
    using For0BodyFunction = std::function<void(TNode<Number>)>;

   public:
    ForBuilder0(JSGraphAssembler* gasm, TNode<Number> initial_value,
                const ConditionFunction1& cond, const StepFunction1& step)
        : gasm_(gasm),
          initial_value_(initial_value),
          cond_(cond),
          step_(step) {}

    void Do(const For0BodyFunction& body) {
      auto loop_exit = gasm_->MakeLabel();

      {
        GraphAssembler::LoopScope<kPhiRepresentation> loop_scope(gasm_);

        auto loop_header = loop_scope.loop_header_label();
        auto loop_body = gasm_->MakeLabel();

        gasm_->Goto(loop_header, initial_value_);

        gasm_->Bind(loop_header);
        TNode<Number> i = loop_header->PhiAt<Number>(0);

        gasm_->BranchWithHint(cond_(i), &loop_body, &loop_exit,
                              BranchHint::kTrue);

        gasm_->Bind(&loop_body);
        body(i);
        gasm_->Goto(loop_header, step_(i));
      }

      gasm_->Bind(&loop_exit);
    }

   private:
    static constexpr MachineRepresentation kPhiRepresentation =
        MachineRepresentation::kTagged;

    JSGraphAssembler* const gasm_;
    const TNode<Number> initial_value_;
    const ConditionFunction1 cond_;
    const StepFunction1 step_;
  };

  ForBuilder0 ForZeroUntil(TNode<Number> excluded_limit) {
    TNode<Number> initial_value = ZeroConstant();
    auto cond = [=](TNode<Number> i) {
      return NumberLessThan(i, excluded_limit);
    };
    auto step = [=](TNode<Number> i) { return NumberAdd(i, OneConstant()); };
    return {this, initial_value, cond, step};
  }

  ForBuilder0 Forever(TNode<Number> initial_value, const StepFunction1& step) {
    return {this, initial_value, [=](TNode<Number>) { return TrueConstant(); },
            step};
  }

  using For1BodyFunction = std::function<void(TNode<Number>, TNode<Object>*)>;
  class ForBuilder1 {
   public:
    ForBuilder1(JSGraphAssembler* gasm, TNode<Number> initial_value,
                const ConditionFunction1& cond, const StepFunction1& step,
                TNode<Object> initial_arg0)
        : gasm_(gasm),
          initial_value_(initial_value),
          cond_(cond),
          step_(step),
          initial_arg0_(initial_arg0) {}

    V8_WARN_UNUSED_RESULT ForBuilder1& Do(const For1BodyFunction& body) {
      body_ = body;
      return *this;
    }

    V8_WARN_UNUSED_RESULT TNode<Object> Value() {
      DCHECK(body_);
      TNode<Object> arg0 = initial_arg0_;

      auto loop_exit = gasm_->MakeDeferredLabel(kPhiRepresentation);

      {
        GraphAssembler::LoopScope<kPhiRepresentation, kPhiRepresentation>
            loop_scope(gasm_);

        auto loop_header = loop_scope.loop_header_label();
        auto loop_body = gasm_->MakeDeferredLabel(kPhiRepresentation);

        gasm_->Goto(loop_header, initial_value_, initial_arg0_);

        gasm_->Bind(loop_header);
        TNode<Number> i = loop_header->PhiAt<Number>(0);
        arg0 = loop_header->PhiAt<Object>(1);

        gasm_->BranchWithHint(cond_(i), &loop_body, &loop_exit,
                              BranchHint::kTrue, arg0);

        gasm_->Bind(&loop_body);
        body_(i, &arg0);
        gasm_->Goto(loop_header, step_(i), arg0);
      }

      gasm_->Bind(&loop_exit);
      return TNode<Object>::UncheckedCast(loop_exit.PhiAt<Object>(0));
    }

    void ValueIsUnused() { USE(Value()); }

   private:
    static constexpr MachineRepresentation kPhiRepresentation =
        MachineRepresentation::kTagged;

    JSGraphAssembler* const gasm_;
    const TNode<Number> initial_value_;
    const ConditionFunction1 cond_;
    const StepFunction1 step_;
    For1BodyFunction body_;
    const TNode<Object> initial_arg0_;
  };

  ForBuilder1 For1(TNode<Number> initial_value, const ConditionFunction1& cond,
                   const StepFunction1& step, TNode<Object> initial_arg0) {
    return {this, initial_value, cond, step, initial_arg0};
  }

  ForBuilder1 For1ZeroUntil(TNode<Number> excluded_limit,
                            TNode<Object> initial_arg0) {
    TNode<Number> initial_value = ZeroConstant();
    auto cond = [=](TNode<Number> i) {
      return NumberLessThan(i, excluded_limit);
    };
    auto step = [=](TNode<Number> i) { return NumberAdd(i, OneConstant()); };
    return {this, initial_value, cond, step, initial_arg0};
  }

  void ThrowIfNotCallable(TNode<Object> maybe_callable,
                          FrameState frame_state) {
    IfNot(ObjectIsCallable(maybe_callable))
        .Then(_ {
          JSCallRuntime2(Runtime::kThrowTypeError,
                         NumberConstant(static_cast<double>(
                             MessageTemplate::kCalledNonCallable)),
                         maybe_callable, frame_state);
          Unreachable();  // The runtime call throws unconditionally.
        })
        .ExpectTrue();
  }

  const FeedbackSource& feedback() const {
    CallParameters const& p = CallParametersOf(node_ptr()->op());
    return p.feedback();
  }

  int ArgumentCount() const { return JSCallNode{node_ptr()}.ArgumentCount(); }

  TNode<Object> Argument(int index) const {
    return TNode<Object>::UncheckedCast(JSCallNode{node_ptr()}.Argument(index));
  }

  template <typename T>
  TNode<T> ArgumentAs(int index) const {
    return TNode<T>::UncheckedCast(Argument(index));
  }

  TNode<Object> ArgumentOrNaN(int index) {
    return TNode<Object>::UncheckedCast(
        ArgumentCount() > index ? Argument(index) : NaNConstant());
  }

  TNode<Object> ArgumentOrUndefined(int index) {
    return TNode<Object>::UncheckedCast(
        ArgumentCount() > index ? Argument(index) : UndefinedConstant());
  }

  TNode<Number> ArgumentOrZero(int index) {
    return TNode<Number>::UncheckedCast(
        ArgumentCount() > index ? Argument(index) : ZeroConstant());
  }

  TNode<Context> ContextInput() const {
    return TNode<Context>::UncheckedCast(
        NodeProperties::GetContextInput(node_));
  }

  FrameState FrameStateInput() const {
    return FrameState(NodeProperties::GetFrameStateInput(node_));
  }

  JSOperatorBuilder* javascript() const { return jsgraph()->javascript(); }

 private:
  Node* const node_;

  CatchScope outermost_catch_scope_;
  Node* outermost_handler_;
  CatchScope* catch_scope_;
  friend class CatchScope;
};

enum class ArrayReduceDirection { kLeft, kRight };
enum class ArrayFindVariant { kFind, kFindIndex };
enum class ArrayEverySomeVariant { kEvery, kSome };
enum class ArrayIndexOfIncludesVariant { kIncludes, kIndexOf };

// This subclass bundles functionality specific to reducing iterating array
// builtins.
class IteratingArrayBuiltinReducerAssembler : public JSCallReducerAssembler {
 public:
  IteratingArrayBuiltinReducerAssembler(JSCallReducer* reducer, Node* node)
      : JSCallReducerAssembler(reducer, node) {
    DCHECK(FLAG_turbo_inline_array_builtins);
  }

  TNode<Object> ReduceArrayPrototypeForEach(
      MapInference* inference, const bool has_stability_dependency,
      ElementsKind kind, const SharedFunctionInfoRef& shared);
  TNode<Object> ReduceArrayPrototypeReduce(MapInference* inference,
                                           const bool has_stability_dependency,
                                           ElementsKind kind,
                                           ArrayReduceDirection direction,
                                           const SharedFunctionInfoRef& shared);
  TNode<JSArray> ReduceArrayPrototypeMap(
      MapInference* inference, const bool has_stability_dependency,
      ElementsKind kind, const SharedFunctionInfoRef& shared,
      const NativeContextRef& native_context);
  TNode<JSArray> ReduceArrayPrototypeFilter(
      MapInference* inference, const bool has_stability_dependency,
      ElementsKind kind, const SharedFunctionInfoRef& shared,
      const NativeContextRef& native_context);
  TNode<Object> ReduceArrayPrototypeFind(MapInference* inference,
                                         const bool has_stability_dependency,
                                         ElementsKind kind,
                                         const SharedFunctionInfoRef& shared,
                                         const NativeContextRef& native_context,
                                         ArrayFindVariant variant);
  TNode<Boolean> ReduceArrayPrototypeEverySome(
      MapInference* inference, const bool has_stability_dependency,
      ElementsKind kind, const SharedFunctionInfoRef& shared,
      const NativeContextRef& native_context, ArrayEverySomeVariant variant);
  TNode<Object> ReduceArrayPrototypeIndexOfIncludes(
      ElementsKind kind, ArrayIndexOfIncludesVariant variant);

 private:
  // Returns {index,value}. Assumes that the map has not changed, but possibly
  // the length and backing store.
  std::pair<TNode<Number>, TNode<Object>> SafeLoadElement(ElementsKind kind,
                                                          TNode<JSArray> o,
                                                          TNode<Number> index) {
    // Make sure that the access is still in bounds, since the callback could
    // have changed the array's size.
    TNode<Number> length = LoadJSArrayLength(o, kind);
    index = CheckBounds(index, length);

    // Reload the elements pointer before calling the callback, since the
    // previous callback might have resized the array causing the elements
    // buffer to be re-allocated.
    TNode<HeapObject> elements =
        LoadField<HeapObject>(AccessBuilder::ForJSObjectElements(), o);
    TNode<Object> value = LoadElement<Object>(
        AccessBuilder::ForFixedArrayElement(kind, LoadSensitivity::kCritical),
        elements, index);
    return std::make_pair(index, value);
  }

  template <typename... Vars>
  TNode<Object> MaybeSkipHole(
      TNode<Object> o, ElementsKind kind,
      GraphAssemblerLabel<sizeof...(Vars)>* continue_label,
      TNode<Vars>... vars) {
    if (!IsHoleyElementsKind(kind)) return o;

    std::array<MachineRepresentation, sizeof...(Vars)> reps = {
        MachineRepresentationOf<Vars>::value...};
    auto if_not_hole =
        MakeLabel<sizeof...(Vars)>(reps, GraphAssemblerLabelType::kNonDeferred);
    BranchWithHint(HoleCheck(kind, o), continue_label, &if_not_hole,
                   BranchHint::kFalse, vars...);

    // The contract is that we don't leak "the hole" into "user JavaScript",
    // so we must rename the {element} here to explicitly exclude "the hole"
    // from the type of {element}.
    Bind(&if_not_hole);
    return TypeGuardNonInternal(o);
  }

  TNode<Smi> LoadJSArrayLength(TNode<JSArray> array, ElementsKind kind) {
    return LoadField<Smi>(AccessBuilder::ForJSArrayLength(kind), array);
  }
  void StoreJSArrayLength(TNode<JSArray> array, TNode<Number> value,
                          ElementsKind kind) {
    StoreField(AccessBuilder::ForJSArrayLength(kind), array, value);
  }
  void StoreFixedArrayBaseElement(TNode<FixedArrayBase> o, TNode<Number> index,
                                  TNode<Object> v, ElementsKind kind) {
    StoreElement(AccessBuilder::ForFixedArrayElement(kind), o, index, v);
  }

  TNode<FixedArrayBase> LoadElements(TNode<JSObject> o) {
    return LoadField<FixedArrayBase>(AccessBuilder::ForJSObjectElements(), o);
  }
  TNode<Smi> LoadFixedArrayBaseLength(TNode<FixedArrayBase> o) {
    return LoadField<Smi>(AccessBuilder::ForFixedArrayLength(), o);
  }

  TNode<Boolean> HoleCheck(ElementsKind kind, TNode<Object> v) {
    return IsDoubleElementsKind(kind)
               ? NumberIsFloat64Hole(TNode<Number>::UncheckedCast(v))
               : IsTheHole(v);
  }

  TNode<Number> CheckFloat64Hole(TNode<Number> value,
                                 CheckFloat64HoleMode mode) {
    return AddNode<Number>(
        graph()->NewNode(simplified()->CheckFloat64Hole(mode, feedback()),
                         value, effect(), control()));
  }

  // May deopt for holey double elements.
  TNode<Object> TryConvertHoleToUndefined(TNode<Object> value,
                                          ElementsKind kind) {
    DCHECK(IsHoleyElementsKind(kind));
    if (kind == HOLEY_DOUBLE_ELEMENTS) {
      // TODO(7409): avoid deopt if not all uses of value are truncated.
      TNode<Number> number = TNode<Number>::UncheckedCast(value);
      return CheckFloat64Hole(number, CheckFloat64HoleMode::kAllowReturnHole);
    }

    return ConvertTaggedHoleToUndefined(value);
  }
};

class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler {
 public:
  PromiseBuiltinReducerAssembler(JSCallReducer* reducer, Node* node,
                                 JSHeapBroker* broker)
      : JSCallReducerAssembler(reducer, node), broker_(broker) {
    DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
  }

  TNode<Object> ReducePromiseConstructor(
      const NativeContextRef& native_context);

  int ConstructArity() const {
    return JSConstructNode{node_ptr()}.ArgumentCount();
  }

  TNode<Object> TargetInput() const {
    return JSConstructNode{node_ptr()}.target();
  }

  TNode<Object> NewTargetInput() const {
    return JSConstructNode{node_ptr()}.new_target();
  }

 private:
  TNode<JSPromise> CreatePromise(TNode<Context> context) {
    return AddNode<JSPromise>(
        graph()->NewNode(javascript()->CreatePromise(), context, effect()));
  }

  TNode<Context> CreateFunctionContext(const NativeContextRef& native_context,
                                       TNode<Context> outer_context,
                                       int slot_count) {
    return AddNode<Context>(graph()->NewNode(
        javascript()->CreateFunctionContext(
            native_context.scope_info().object(),
            slot_count - Context::MIN_CONTEXT_SLOTS, FUNCTION_SCOPE),
        outer_context, effect(), control()));
  }

  void StoreContextSlot(TNode<Context> context, size_t slot_index,
                        TNode<Object> value) {
    StoreField(AccessBuilder::ForContextSlot(slot_index), context, value);
  }

  TNode<JSFunction> CreateClosureFromBuiltinSharedFunctionInfo(
      SharedFunctionInfoRef shared, TNode<Context> context) {
    DCHECK(shared.HasBuiltinId());
    Handle<FeedbackCell> feedback_cell =
        isolate()->factory()->many_closures_cell();
    Callable const callable = Builtins::CallableFor(
        isolate(), static_cast<Builtins::Name>(shared.builtin_id()));
    return AddNode<JSFunction>(graph()->NewNode(
        javascript()->CreateClosure(shared.object(), callable.code()),
        HeapConstant(feedback_cell), context, effect(), control()));
  }

  void CallPromiseExecutor(TNode<Object> executor, TNode<JSFunction> resolve,
                           TNode<JSFunction> reject, FrameState frame_state) {
    JSConstructNode n(node_ptr());
    const ConstructParameters& p = n.Parameters();
    FeedbackSource no_feedback_source{};
    Node* no_feedback = UndefinedConstant();
    MayThrow(_ {
      return AddNode<Object>(graph()->NewNode(
          javascript()->Call(JSCallNode::ArityForArgc(2), p.frequency(),
                             no_feedback_source,
                             ConvertReceiverMode::kNullOrUndefined),
          executor, UndefinedConstant(), resolve, reject, no_feedback,
          n.context(), frame_state, effect(), control()));
    });
  }

  void CallPromiseReject(TNode<JSFunction> reject, TNode<Object> exception,
                         FrameState frame_state) {
    JSConstructNode n(node_ptr());
    const ConstructParameters& p = n.Parameters();
    FeedbackSource no_feedback_source{};
    Node* no_feedback = UndefinedConstant();
    MayThrow(_ {
      return AddNode<Object>(graph()->NewNode(
          javascript()->Call(JSCallNode::ArityForArgc(1), p.frequency(),
                             no_feedback_source,
                             ConvertReceiverMode::kNullOrUndefined),
          reject, UndefinedConstant(), exception, no_feedback, n.context(),
          frame_state, effect(), control()));
    });
  }

  JSHeapBroker* const broker_;
};

class FastApiCallReducerAssembler : public JSCallReducerAssembler {
 public:
  FastApiCallReducerAssembler(
      JSCallReducer* reducer, Node* node,
      const FunctionTemplateInfoRef function_template_info, Node* receiver,
      Node* holder, const SharedFunctionInfoRef shared, Node* target,
      const int arity, Node* effect)
      : JSCallReducerAssembler(reducer, node),
        c_function_(function_template_info.c_function()),
        c_signature_(function_template_info.c_signature()),
        function_template_info_(function_template_info),
        receiver_(receiver),
        holder_(holder),
        shared_(shared),
        target_(target),
        arity_(arity) {
    DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    DCHECK_NE(c_function_, kNullAddress);
    CHECK_NOT_NULL(c_signature_);
    InitializeEffectControl(effect, NodeProperties::GetControlInput(node));
  }

  TNode<Object> ReduceFastApiCall() {
    JSCallNode n(node_ptr());
    // C arguments include the receiver at index 0. Thus C index 1 corresponds
    // to the JS argument 0, etc.
    const int c_argument_count =
        static_cast<int>(c_signature_->ArgumentCount());
    CHECK_GE(c_argument_count, kReceiver);

    int cursor = 0;
    base::SmallVector<Node*, kInlineSize> inputs(c_argument_count + arity_ +
                                                 kExtraInputsCount);
    inputs[cursor++] = ExternalConstant(ExternalReference::Create(c_function_));

    inputs[cursor++] = n.receiver();

    // TODO(turbofan): Consider refactoring CFunctionInfo to distinguish
    // between receiver and arguments, simplifying this (and related) spots.
    int js_args_count = c_argument_count - kReceiver;
    for (int i = 0; i < js_args_count; ++i) {
      if (i < n.ArgumentCount()) {
        inputs[cursor++] = n.Argument(i);
      } else {
        inputs[cursor++] = UndefinedConstant();
      }
    }

    // Here we add the arguments for the slow call, which will be
    // reconstructed at a later phase. Those are effectively the same
    // arguments as for the fast call, but we want to have them as
    // separate inputs, so that SimplifiedLowering can provide the best
    // possible UseInfos for each of them. The inputs to FastApiCall
    // look like:
    // [fast callee, receiver, ... C arguments,
    // call code, external constant for function, argc, call handler info data,
    // holder, receiver, ... JS arguments, context, new frame state]
    CallHandlerInfoRef call_handler_info = *function_template_info_.call_code();
    Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
    CallInterfaceDescriptor cid = call_api_callback.descriptor();
    CallDescriptor* call_descriptor =
        Linkage::GetStubCallDescriptor(graph()->zone(), cid, arity_ + kReceiver,
                                       CallDescriptor::kNeedsFrameState);
    ApiFunction api_function(call_handler_info.callback());
    ExternalReference function_reference = ExternalReference::Create(
        &api_function, ExternalReference::DIRECT_API_CALL);

    Node* continuation_frame_state =
        CreateGenericLazyDeoptContinuationFrameState(
            jsgraph(), shared_, target_, ContextInput(), receiver_,
            FrameStateInput());

    inputs[cursor++] = HeapConstant(call_api_callback.code());
    inputs[cursor++] = ExternalConstant(function_reference);
    inputs[cursor++] = NumberConstant(arity_);
    inputs[cursor++] = Constant(call_handler_info.data());
    inputs[cursor++] = holder_;
    inputs[cursor++] = receiver_;
    for (int i = 0; i < arity_; ++i) {
      inputs[cursor++] = Argument(i);
    }
    inputs[cursor++] = ContextInput();
    inputs[cursor++] = continuation_frame_state;
    inputs[cursor++] = effect();
    inputs[cursor++] = control();

    DCHECK_EQ(cursor, c_argument_count + arity_ + kExtraInputsCount);

    return FastApiCall(call_descriptor, inputs.begin(), inputs.size());
  }

 private:
  static constexpr int kTarget = 1;
  static constexpr int kEffectAndControl = 2;
  static constexpr int kContextAndFrameState = 2;
  static constexpr int kCallCodeDataAndArgc = 3;
  static constexpr int kHolder = 1, kReceiver = 1;
  static constexpr int kExtraInputsCount =
      kTarget * 2 + kEffectAndControl + kContextAndFrameState +
      kCallCodeDataAndArgc + kHolder + kReceiver;
  static constexpr int kInlineSize = 12;

  TNode<Object> FastApiCall(CallDescriptor* descriptor, Node** inputs,
                            size_t inputs_size) {
    return AddNode<Object>(graph()->NewNode(
        simplified()->FastApiCall(c_signature_, feedback(), descriptor),
        static_cast<int>(inputs_size), inputs));
  }

  const Address c_function_;
  const CFunctionInfo* const c_signature_;
  const FunctionTemplateInfoRef function_template_info_;
  Node* const receiver_;
  Node* const holder_;
  const SharedFunctionInfoRef shared_;
  Node* const target_;
  const int arity_;
};

TNode<Number> JSCallReducerAssembler::SpeculativeToNumber(
    TNode<Object> value, NumberOperationHint hint) {
  return AddNode<Number>(
      graph()->NewNode(simplified()->SpeculativeToNumber(hint, feedback()),
                       value, effect(), control()));
}

TNode<Smi> JSCallReducerAssembler::CheckSmi(TNode<Object> value) {
  return AddNode<Smi>(graph()->NewNode(simplified()->CheckSmi(feedback()),
                                       value, effect(), control()));
}

TNode<String> JSCallReducerAssembler::CheckString(TNode<Object> value) {
  return AddNode<String>(graph()->NewNode(simplified()->CheckString(feedback()),
                                          value, effect(), control()));
}

TNode<Number> JSCallReducerAssembler::CheckBounds(TNode<Number> value,
                                                  TNode<Number> limit) {
  return AddNode<Number>(graph()->NewNode(simplified()->CheckBounds(feedback()),
                                          value, limit, effect(), control()));
}

TNode<Smi> JSCallReducerAssembler::TypeGuardUnsignedSmall(TNode<Object> value) {
  return TNode<Smi>::UncheckedCast(TypeGuard(Type::UnsignedSmall(), value));
}

TNode<Object> JSCallReducerAssembler::TypeGuardNonInternal(
    TNode<Object> value) {
  return TNode<Object>::UncheckedCast(TypeGuard(Type::NonInternal(), value));
}

TNode<Number> JSCallReducerAssembler::TypeGuardFixedArrayLength(
    TNode<Object> value) {
  DCHECK(TypeCache::Get()->kFixedDoubleArrayLengthType.Is(
      TypeCache::Get()->kFixedArrayLengthType));
  return TNode<Number>::UncheckedCast(
      TypeGuard(TypeCache::Get()->kFixedArrayLengthType, value));
}

TNode<Object> JSCallReducerAssembler::Call4(
    const Callable& callable, TNode<Context> context, TNode<Object> arg0,
    TNode<Object> arg1, TNode<Object> arg2, TNode<Object> arg3) {
  // TODO(jgruber): Make this more generic. Currently it's fitted to its single
  // callsite.
  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
      graph()->zone(), callable.descriptor(),
      callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
      Operator::kEliminatable);

  return TNode<Object>::UncheckedCast(Call(desc, HeapConstant(callable.code()),
                                           arg0, arg1, arg2, arg3, context));
}

TNode<Object> JSCallReducerAssembler::JSCall3(
    TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0,
    TNode<Object> arg1, TNode<Object> arg2, FrameState frame_state) {
  JSCallNode n(node_ptr());
  CallParameters const& p = n.Parameters();
  return MayThrow(_ {
    return AddNode<Object>(graph()->NewNode(
        javascript()->Call(JSCallNode::ArityForArgc(3), p.frequency(),
                           p.feedback(), ConvertReceiverMode::kAny,
                           p.speculation_mode(),
                           CallFeedbackRelation::kUnrelated),
        function, this_arg, arg0, arg1, arg2, n.feedback_vector(),
        ContextInput(), frame_state, effect(), control()));
  });
}

TNode<Object> JSCallReducerAssembler::JSCall4(
    TNode<Object> function, TNode<Object> this_arg, TNode<Object> arg0,
    TNode<Object> arg1, TNode<Object> arg2, TNode<Object> arg3,
    FrameState frame_state) {
  JSCallNode n(node_ptr());
  CallParameters const& p = n.Parameters();
  return MayThrow(_ {
    return AddNode<Object>(graph()->NewNode(
        javascript()->Call(JSCallNode::ArityForArgc(4), p.frequency(),
                           p.feedback(), ConvertReceiverMode::kAny,
                           p.speculation_mode(),
                           CallFeedbackRelation::kUnrelated),
        function, this_arg, arg0, arg1, arg2, arg3, n.feedback_vector(),
        ContextInput(), frame_state, effect(), control()));
  });
}

TNode<Object> JSCallReducerAssembler::JSCallRuntime2(
    Runtime::FunctionId function_id, TNode<Object> arg0, TNode<Object> arg1,
    FrameState frame_state) {
  return MayThrow(_ {
    return AddNode<Object>(
        graph()->NewNode(javascript()->CallRuntime(function_id, 2), arg0, arg1,
                         ContextInput(), frame_state, effect(), control()));
  });
}

TNode<JSArray> JSCallReducerAssembler::CreateArrayNoThrow(
    TNode<Object> ctor, TNode<Number> size, FrameState frame_state) {
  return AddNode<JSArray>(graph()->NewNode(
      javascript()->CreateArray(1, MaybeHandle<AllocationSite>()), ctor, ctor,
      size, ContextInput(), frame_state, effect(), control()));
}
TNode<JSArray> JSCallReducerAssembler::AllocateEmptyJSArray(
    ElementsKind kind, const NativeContextRef& native_context) {
  // TODO(jgruber): Port AllocationBuilder to JSGraphAssembler.
  MapRef map = native_context.GetInitialJSArrayMap(kind);

  AllocationBuilder ab(jsgraph(), effect(), control());
  ab.Allocate(map.instance_size(), AllocationType::kYoung, Type::Array());
  ab.Store(AccessBuilder::ForMap(), map);
  Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
  ab.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
           empty_fixed_array);
  ab.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
  ab.Store(AccessBuilder::ForJSArrayLength(kind), jsgraph()->ZeroConstant());
  for (int i = 0; i < map.GetInObjectProperties(); ++i) {
    ab.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
             jsgraph()->UndefinedConstant());
  }
  Node* result = ab.Finish();
  InitializeEffectControl(result, control());
  return TNode<JSArray>::UncheckedCast(result);
}

TNode<Object> JSCallReducerAssembler::ReduceMathUnary(const Operator* op) {
  TNode<Object> input = Argument(0);
  TNode<Number> input_as_number = SpeculativeToNumber(input);
  return TNode<Object>::UncheckedCast(graph()->NewNode(op, input_as_number));
}

TNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) {
  TNode<Object> left = Argument(0);
  TNode<Object> right = ArgumentOrNaN(1);
  TNode<Number> left_number = SpeculativeToNumber(left);
  TNode<Number> right_number = SpeculativeToNumber(right);
  return TNode<Object>::UncheckedCast(
      graph()->NewNode(op, left_number, right_number));
}

TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() {
  TNode<Object> receiver = ReceiverInput();
  TNode<Object> start = Argument(0);
  TNode<Object> end = ArgumentOrUndefined(1);

  TNode<String> receiver_string = CheckString(receiver);
  TNode<Number> start_smi = CheckSmi(start);

  TNode<Number> length = StringLength(receiver_string);

  TNode<Number> end_smi = SelectIf<Number>(IsUndefined(end))
                              .Then(_ { return length; })
                              .Else(_ { return CheckSmi(end); })
                              .ExpectFalse()
                              .Value();

  TNode<Number> zero = TNode<Number>::UncheckedCast(ZeroConstant());
  TNode<Number> finalStart = NumberMin(NumberMax(start_smi, zero), length);
  TNode<Number> finalEnd = NumberMin(NumberMax(end_smi, zero), length);
  TNode<Number> from = NumberMin(finalStart, finalEnd);
  TNode<Number> to = NumberMax(finalStart, finalEnd);

  return StringSubstring(receiver_string, from, to);
}

TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() {
  TNode<Object> receiver = ReceiverInput();
  TNode<Object> start = Argument(0);
  TNode<Object> end = ArgumentOrUndefined(1);

  TNode<String> receiver_string = CheckString(receiver);
  TNode<Number> start_smi = CheckSmi(start);

  TNode<Number> length = StringLength(receiver_string);

  TNode<Number> end_smi = SelectIf<Number>(IsUndefined(end))
                              .Then(_ { return length; })
                              .Else(_ { return CheckSmi(end); })
                              .ExpectFalse()
                              .Value();

  TNode<Number> zero = TNode<Number>::UncheckedCast(ZeroConstant());
  TNode<Number> from_untyped =
      SelectIf<Number>(NumberLessThan(start_smi, zero))
          .Then(_ { return NumberMax(NumberAdd(length, start_smi), zero); })
          .Else(_ { return NumberMin(start_smi, length); })
          .ExpectFalse()
          .Value();
  // {from} is always in non-negative Smi range, but our typer cannot figure
  // that out yet.
  TNode<Smi> from = TypeGuardUnsignedSmall(from_untyped);

  TNode<Number> to_untyped =
      SelectIf<Number>(NumberLessThan(end_smi, zero))
          .Then(_ { return NumberMax(NumberAdd(length, end_smi), zero); })
          .Else(_ { return NumberMin(end_smi, length); })
          .ExpectFalse()
          .Value();
  // {to} is always in non-negative Smi range, but our typer cannot figure that
  // out yet.
  TNode<Smi> to = TypeGuardUnsignedSmall(to_untyped);

  return SelectIf<String>(NumberLessThan(from, to))
      .Then(_ { return StringSubstring(receiver_string, from, to); })
      .Else(_ { return EmptyStringConstant(); })
      .ExpectTrue()
      .Value();
}

namespace {

struct ForEachFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
  TNode<Object> receiver;
  TNode<Object> callback;
  TNode<Object> this_arg;
  TNode<Object> original_length;
};

FrameState ForEachLoopLazyFrameState(const ForEachFrameStateParams& params,
                                     TNode<Object> k) {
  Builtins::Name builtin = Builtins::kArrayForEachLoopLazyDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, k, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::LAZY);
}

FrameState ForEachLoopEagerFrameState(const ForEachFrameStateParams& params,
                                      TNode<Object> k) {
  Builtins::Name builtin = Builtins::kArrayForEachLoopEagerDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, k, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::EAGER);
}

}  // namespace

TNode<Object>
IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeForEach(
    MapInference* inference, const bool has_stability_dependency,
    ElementsKind kind, const SharedFunctionInfoRef& shared) {
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> fncallback = ArgumentOrUndefined(0);
  TNode<Object> this_arg = ArgumentOrUndefined(1);

  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);

  ForEachFrameStateParams frame_state_params{
      jsgraph(), shared,     context,  target,         outer_frame_state,
      receiver,  fncallback, this_arg, original_length};

  ThrowIfNotCallable(fncallback, ForEachLoopLazyFrameState(frame_state_params,
                                                           ZeroConstant()));

  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
    Checkpoint(ForEachLoopEagerFrameState(frame_state_params, k));

    // Deopt if the map has changed during the iteration.
    MaybeInsertMapChecks(inference, has_stability_dependency);

    TNode<Object> element;
    std::tie(k, element) = SafeLoadElement(kind, receiver, k);

    auto continue_label = MakeLabel();
    element = MaybeSkipHole(element, kind, &continue_label);

    TNode<Number> next_k = NumberAdd(k, OneConstant());
    JSCall3(fncallback, this_arg, element, k, receiver,
            ForEachLoopLazyFrameState(frame_state_params, next_k));

    Goto(&continue_label);
    Bind(&continue_label);
  });

  return UndefinedConstant();
}

namespace {

struct ReduceFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  ArrayReduceDirection direction;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
};

FrameState ReducePreLoopLazyFrameState(const ReduceFrameStateParams& params,
                                       TNode<Object> receiver,
                                       TNode<Object> callback, TNode<Object> k,
                                       TNode<Number> original_length) {
  Builtins::Name builtin =
      (params.direction == ArrayReduceDirection::kLeft)
          ? Builtins::kArrayReduceLoopLazyDeoptContinuation
          : Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
  Node* checkpoint_params[] = {receiver, callback, k, original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::LAZY);
}

FrameState ReducePreLoopEagerFrameState(const ReduceFrameStateParams& params,
                                        TNode<Object> receiver,
                                        TNode<Object> callback,
                                        TNode<Number> original_length) {
  Builtins::Name builtin =
      (params.direction == ArrayReduceDirection::kLeft)
          ? Builtins::kArrayReducePreLoopEagerDeoptContinuation
          : Builtins::kArrayReduceRightPreLoopEagerDeoptContinuation;
  Node* checkpoint_params[] = {receiver, callback, original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::EAGER);
}

FrameState ReduceLoopLazyFrameState(const ReduceFrameStateParams& params,
                                    TNode<Object> receiver,
                                    TNode<Object> callback, TNode<Object> k,
                                    TNode<Number> original_length) {
  Builtins::Name builtin =
      (params.direction == ArrayReduceDirection::kLeft)
          ? Builtins::kArrayReduceLoopLazyDeoptContinuation
          : Builtins::kArrayReduceRightLoopLazyDeoptContinuation;
  Node* checkpoint_params[] = {receiver, callback, k, original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::LAZY);
}

FrameState ReduceLoopEagerFrameState(const ReduceFrameStateParams& params,
                                     TNode<Object> receiver,
                                     TNode<Object> callback, TNode<Object> k,
                                     TNode<Number> original_length,
                                     TNode<Object> accumulator) {
  Builtins::Name builtin =
      (params.direction == ArrayReduceDirection::kLeft)
          ? Builtins::kArrayReduceLoopEagerDeoptContinuation
          : Builtins::kArrayReduceRightLoopEagerDeoptContinuation;
  Node* checkpoint_params[] = {receiver, callback, k, original_length,
                               accumulator};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::EAGER);
}

}  // namespace

TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeReduce(
    MapInference* inference, const bool has_stability_dependency,
    ElementsKind kind, ArrayReduceDirection direction,
    const SharedFunctionInfoRef& shared) {
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> fncallback = ArgumentOrUndefined(0);

  ReduceFrameStateParams frame_state_params{
      jsgraph(), shared, direction, context, target, outer_frame_state};

  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);

  // Set up variable behavior depending on the reduction kind (left/right).
  TNode<Number> k;
  StepFunction1 step;
  ConditionFunction1 cond;
  TNode<Number> zero = ZeroConstant();
  TNode<Number> one = OneConstant();
  if (direction == ArrayReduceDirection::kLeft) {
    k = zero;
    step = [&](TNode<Number> i) { return NumberAdd(i, one); };
    cond = [&](TNode<Number> i) { return NumberLessThan(i, original_length); };
  } else {
    k = NumberSubtract(original_length, one);
    step = [&](TNode<Number> i) { return NumberSubtract(i, one); };
    cond = [&](TNode<Number> i) { return NumberLessThanOrEqual(zero, i); };
  }

  ThrowIfNotCallable(
      fncallback, ReducePreLoopLazyFrameState(frame_state_params, receiver,
                                              fncallback, k, original_length));

  // Set initial accumulator value.
  TNode<Object> accumulator;
  if (ArgumentCount() > 1) {
    accumulator = Argument(1);  // Initial value specified by the user.
  } else {
    // The initial value was not specified by the user. In this case, the first
    // (or last in the case of reduceRight) non-holey value of the array is
    // used. Loop until we find it. If not found, trigger a deopt.
    // TODO(jgruber): The deopt does not seem necessary. Instead we could simply
    // throw the TypeError here from optimized code.
    auto found_initial_element = MakeLabel(MachineRepresentation::kTagged,
                                           MachineRepresentation::kTagged);
    Forever(k, step).Do([&](TNode<Number> k) {
      Checkpoint(ReducePreLoopEagerFrameState(frame_state_params, receiver,
                                              fncallback, original_length));
      CheckIf(cond(k), DeoptimizeReason::kNoInitialElement);

      TNode<Object> element;
      std::tie(k, element) = SafeLoadElement(kind, receiver, k);

      auto continue_label = MakeLabel();
      GotoIf(HoleCheck(kind, element), &continue_label);
      Goto(&found_initial_element, k, TypeGuardNonInternal(element));

      Bind(&continue_label);
    });
    Unreachable();  // The loop is exited either by deopt or a jump to below.

    // TODO(jgruber): This manual fiddling with blocks could be avoided by
    // implementing a `break` mechanic for loop builders.
    Bind(&found_initial_element);
    k = step(found_initial_element.PhiAt<Number>(0));
    accumulator = found_initial_element.PhiAt<Object>(1);
  }

  TNode<Object> result =
      For1(k, cond, step, accumulator)
          .Do([&](TNode<Number> k, TNode<Object>* accumulator) {
            Checkpoint(ReduceLoopEagerFrameState(frame_state_params, receiver,
                                                 fncallback, k, original_length,
                                                 *accumulator));

            // Deopt if the map has changed during the iteration.
            MaybeInsertMapChecks(inference, has_stability_dependency);

            TNode<Object> element;
            std::tie(k, element) = SafeLoadElement(kind, receiver, k);

            auto continue_label = MakeLabel(MachineRepresentation::kTagged);
            element =
                MaybeSkipHole(element, kind, &continue_label, *accumulator);

            TNode<Number> next_k = step(k);
            TNode<Object> next_accumulator = JSCall4(
                fncallback, UndefinedConstant(), *accumulator, element, k,
                receiver,
                ReduceLoopLazyFrameState(frame_state_params, receiver,
                                         fncallback, next_k, original_length));
            Goto(&continue_label, next_accumulator);

            Bind(&continue_label);
            *accumulator = continue_label.PhiAt<Object>(0);
          })
          .Value();

  return result;
}

namespace {

struct MapFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
  TNode<Object> receiver;
  TNode<Object> callback;
  TNode<Object> this_arg;
  TNode<JSArray> a;
  TNode<Object> original_length;
};

FrameState MapPreLoopLazyFrameState(const MapFrameStateParams& params) {
  DCHECK(params.a.is_null());
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kArrayMapPreLoopLazyDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      params.outer_frame_state, ContinuationFrameStateMode::LAZY);
}

FrameState MapLoopLazyFrameState(const MapFrameStateParams& params,
                                 TNode<Number> k) {
  Node* checkpoint_params[] = {
      params.receiver,       params.callback, params.this_arg, params.a, k,
      params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kArrayMapLoopLazyDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      params.outer_frame_state, ContinuationFrameStateMode::LAZY);
}

FrameState MapLoopEagerFrameState(const MapFrameStateParams& params,
                                  TNode<Number> k) {
  Node* checkpoint_params[] = {
      params.receiver,       params.callback, params.this_arg, params.a, k,
      params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kArrayMapLoopEagerDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      params.outer_frame_state, ContinuationFrameStateMode::EAGER);
}

}  // namespace

TNode<JSArray> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeMap(
    MapInference* inference, const bool has_stability_dependency,
    ElementsKind kind, const SharedFunctionInfoRef& shared,
    const NativeContextRef& native_context) {
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> fncallback = ArgumentOrUndefined(0);
  TNode<Object> this_arg = ArgumentOrUndefined(1);

  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);

  // If the array length >= kMaxFastArrayLength, then CreateArray
  // will create a dictionary. We should deopt in this case, and make sure
  // not to attempt inlining again.
  original_length = CheckBounds(original_length,
                                NumberConstant(JSArray::kMaxFastArrayLength));

  // Even though {JSCreateArray} is not marked as {kNoThrow}, we can elide the
  // exceptional projections because it cannot throw with the given
  // parameters.
  TNode<Object> array_ctor =
      Constant(native_context.GetInitialJSArrayMap(kind).GetConstructor());

  MapFrameStateParams frame_state_params{
      jsgraph(), shared,     context,  target,       outer_frame_state,
      receiver,  fncallback, this_arg, {} /* TBD */, original_length};

  TNode<JSArray> a =
      CreateArrayNoThrow(array_ctor, original_length,
                         MapPreLoopLazyFrameState(frame_state_params));
  frame_state_params.a = a;

  ThrowIfNotCallable(fncallback,
                     MapLoopLazyFrameState(frame_state_params, ZeroConstant()));

  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
    Checkpoint(MapLoopEagerFrameState(frame_state_params, k));
    MaybeInsertMapChecks(inference, has_stability_dependency);

    TNode<Object> element;
    std::tie(k, element) = SafeLoadElement(kind, receiver, k);

    auto continue_label = MakeLabel();
    element = MaybeSkipHole(element, kind, &continue_label);

    TNode<Object> v = JSCall3(fncallback, this_arg, element, k, receiver,
                              MapLoopLazyFrameState(frame_state_params, k));

    // The array {a} should be HOLEY_SMI_ELEMENTS because we'd only come into
    // this loop if the input array length is non-zero, and "new Array({x > 0})"
    // always produces a HOLEY array.
    MapRef holey_double_map =
        native_context.GetInitialJSArrayMap(HOLEY_DOUBLE_ELEMENTS);
    MapRef holey_map = native_context.GetInitialJSArrayMap(HOLEY_ELEMENTS);
    TransitionAndStoreElement(holey_double_map, holey_map, a, k, v);

    Goto(&continue_label);
    Bind(&continue_label);
  });

  return a;
}

namespace {

struct FilterFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
  TNode<Object> receiver;
  TNode<Object> callback;
  TNode<Object> this_arg;
  TNode<JSArray> a;
  TNode<Object> original_length;
};

FrameState FilterLoopLazyFrameState(const FilterFrameStateParams& params,
                                    TNode<Number> k, TNode<Number> to,
                                    TNode<Object> element) {
  Node* checkpoint_params[] = {params.receiver,
                               params.callback,
                               params.this_arg,
                               params.a,
                               k,
                               params.original_length,
                               element,
                               to};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kArrayFilterLoopLazyDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      params.outer_frame_state, ContinuationFrameStateMode::LAZY);
}

FrameState FilterLoopEagerPostCallbackFrameState(
    const FilterFrameStateParams& params, TNode<Number> k, TNode<Number> to,
    TNode<Object> element, TNode<Object> callback_value) {
  // Note that we are intentionally reusing the
  // Builtins::kArrayFilterLoopLazyDeoptContinuation as an *eager* entry point
  // in this case. This is safe, because re-evaluating a [ToBoolean] coercion is
  // safe.
  Node* checkpoint_params[] = {params.receiver,
                               params.callback,
                               params.this_arg,
                               params.a,
                               k,
                               params.original_length,
                               element,
                               to,
                               callback_value};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kArrayFilterLoopLazyDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      params.outer_frame_state, ContinuationFrameStateMode::EAGER);
}

FrameState FilterLoopEagerFrameState(const FilterFrameStateParams& params,
                                     TNode<Number> k, TNode<Number> to) {
  Node* checkpoint_params[] = {params.receiver,
                               params.callback,
                               params.this_arg,
                               params.a,
                               k,
                               params.original_length,
                               to};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kArrayFilterLoopEagerDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      params.outer_frame_state, ContinuationFrameStateMode::EAGER);
}

}  // namespace

TNode<JSArray>
IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFilter(
    MapInference* inference, const bool has_stability_dependency,
    ElementsKind kind, const SharedFunctionInfoRef& shared,
    const NativeContextRef& native_context) {
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> fncallback = ArgumentOrUndefined(0);
  TNode<Object> this_arg = ArgumentOrUndefined(1);

  // The output array is packed (filter doesn't visit holes).
  const ElementsKind packed_kind = GetPackedElementsKind(kind);
  TNode<JSArray> a = AllocateEmptyJSArray(packed_kind, native_context);

  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);

  FilterFrameStateParams frame_state_params{
      jsgraph(), shared,     context,  target, outer_frame_state,
      receiver,  fncallback, this_arg, a,      original_length};

  // This frame state doesn't ever call the deopt continuation, it's only
  // necessary to specify a continuation in order to handle the exceptional
  // case. We don't have all the values available to completely fill out
  // the checkpoint parameters yet, but that's okay because it'll never be
  // called.
  TNode<Number> zero = ZeroConstant();
  ThrowIfNotCallable(fncallback, FilterLoopLazyFrameState(frame_state_params,
                                                          zero, zero, zero));

  TNode<Number> initial_a_length = zero;
  For1ZeroUntil(original_length, initial_a_length)
      .Do([&](TNode<Number> k, TNode<Object>* a_length_object) {
        TNode<Number> a_length = TNode<Number>::UncheckedCast(*a_length_object);
        Checkpoint(FilterLoopEagerFrameState(frame_state_params, k, a_length));
        MaybeInsertMapChecks(inference, has_stability_dependency);

        TNode<Object> element;
        std::tie(k, element) = SafeLoadElement(kind, receiver, k);

        auto continue_label = MakeLabel(MachineRepresentation::kTaggedSigned);
        element = MaybeSkipHole(element, kind, &continue_label, a_length);

        TNode<Object> v = JSCall3(
            fncallback, this_arg, element, k, receiver,
            FilterLoopLazyFrameState(frame_state_params, k, a_length, element));

        // We need an eager frame state for right after the callback function
        // returned, just in case an attempt to grow the output array fails.
        Checkpoint(FilterLoopEagerPostCallbackFrameState(frame_state_params, k,
                                                         a_length, element, v));

        GotoIfNot(ToBoolean(v), &continue_label, a_length);

        // Since the callback returned a trueish value, store the element in a.
        {
          TNode<Number> a_length1 = TypeGuardFixedArrayLength(a_length);
          TNode<FixedArrayBase> elements = LoadElements(a);
          elements = MaybeGrowFastElements(kind, FeedbackSource{}, a, elements,
                                           a_length1,
                                           LoadFixedArrayBaseLength(elements));

          TNode<Number> new_a_length = NumberInc(a_length1);
          StoreJSArrayLength(a, new_a_length, kind);
          StoreFixedArrayBaseElement(elements, a_length1, element, kind);

          Goto(&continue_label, new_a_length);
        }

        Bind(&continue_label);
        *a_length_object =
            TNode<Object>::UncheckedCast(continue_label.PhiAt(0));
      })
      .ValueIsUnused();

  return a;
}

namespace {

struct FindFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
  TNode<Object> receiver;
  TNode<Object> callback;
  TNode<Object> this_arg;
  TNode<Object> original_length;
};

FrameState FindLoopLazyFrameState(const FindFrameStateParams& params,
                                  TNode<Number> k, ArrayFindVariant variant) {
  Builtins::Name builtin =
      (variant == ArrayFindVariant::kFind)
          ? Builtins::kArrayFindLoopLazyDeoptContinuation
          : Builtins::kArrayFindIndexLoopLazyDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, k, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::LAZY);
}

FrameState FindLoopEagerFrameState(const FindFrameStateParams& params,
                                   TNode<Number> k, ArrayFindVariant variant) {
  Builtins::Name builtin =
      (variant == ArrayFindVariant::kFind)
          ? Builtins::kArrayFindLoopEagerDeoptContinuation
          : Builtins::kArrayFindIndexLoopEagerDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, k, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::EAGER);
}

FrameState FindLoopAfterCallbackLazyFrameState(
    const FindFrameStateParams& params, TNode<Number> next_k,
    TNode<Object> if_found_value, ArrayFindVariant variant) {
  Builtins::Name builtin =
      (variant == ArrayFindVariant::kFind)
          ? Builtins::kArrayFindLoopAfterCallbackLazyDeoptContinuation
          : Builtins::kArrayFindIndexLoopAfterCallbackLazyDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver,        params.callback,
                               params.this_arg,        next_k,
                               params.original_length, if_found_value};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::LAZY);
}

}  // namespace

TNode<Object> IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeFind(
    MapInference* inference, const bool has_stability_dependency,
    ElementsKind kind, const SharedFunctionInfoRef& shared,
    const NativeContextRef& native_context, ArrayFindVariant variant) {
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> fncallback = ArgumentOrUndefined(0);
  TNode<Object> this_arg = ArgumentOrUndefined(1);

  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);

  FindFrameStateParams frame_state_params{
      jsgraph(), shared,     context,  target,         outer_frame_state,
      receiver,  fncallback, this_arg, original_length};

  ThrowIfNotCallable(
      fncallback,
      FindLoopLazyFrameState(frame_state_params, ZeroConstant(), variant));

  const bool is_find_variant = (variant == ArrayFindVariant::kFind);
  auto out = MakeLabel(MachineRepresentation::kTagged);

  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
    Checkpoint(FindLoopEagerFrameState(frame_state_params, k, variant));
    MaybeInsertMapChecks(inference, has_stability_dependency);

    TNode<Object> element;
    std::tie(k, element) = SafeLoadElement(kind, receiver, k);

    if (IsHoleyElementsKind(kind)) {
      element = TryConvertHoleToUndefined(element, kind);
    }

    TNode<Object> if_found_value = is_find_variant ? element : k;
    TNode<Number> next_k = NumberInc(k);

    // The callback result states whether the desired element was found.
    TNode<Object> v =
        JSCall3(fncallback, this_arg, element, k, receiver,
                FindLoopAfterCallbackLazyFrameState(frame_state_params, next_k,
                                                    if_found_value, variant));

    GotoIf(ToBoolean(v), &out, if_found_value);
  });

  // If the loop completed, the element was not found.
  TNode<Object> if_not_found_value =
      is_find_variant ? TNode<Object>::UncheckedCast(UndefinedConstant())
                      : TNode<Object>::UncheckedCast(MinusOneConstant());
  Goto(&out, if_not_found_value);

  Bind(&out);
  return out.PhiAt<Object>(0);
}

namespace {

struct EverySomeFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
  TNode<Object> receiver;
  TNode<Object> callback;
  TNode<Object> this_arg;
  TNode<Object> original_length;
};

FrameState EverySomeLoopLazyFrameState(const EverySomeFrameStateParams& params,
                                       TNode<Number> k,
                                       ArrayEverySomeVariant variant) {
  Builtins::Name builtin = (variant == ArrayEverySomeVariant::kEvery)
                               ? Builtins::kArrayEveryLoopLazyDeoptContinuation
                               : Builtins::kArraySomeLoopLazyDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, k, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::LAZY);
}

FrameState EverySomeLoopEagerFrameState(const EverySomeFrameStateParams& params,
                                        TNode<Number> k,
                                        ArrayEverySomeVariant variant) {
  Builtins::Name builtin = (variant == ArrayEverySomeVariant::kEvery)
                               ? Builtins::kArrayEveryLoopEagerDeoptContinuation
                               : Builtins::kArraySomeLoopEagerDeoptContinuation;
  Node* checkpoint_params[] = {params.receiver, params.callback,
                               params.this_arg, k, params.original_length};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared, builtin, params.target, params.context,
      checkpoint_params, arraysize(checkpoint_params), params.outer_frame_state,
      ContinuationFrameStateMode::EAGER);
}

}  // namespace

TNode<Boolean>
IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeEverySome(
    MapInference* inference, const bool has_stability_dependency,
    ElementsKind kind, const SharedFunctionInfoRef& shared,
    const NativeContextRef& native_context, ArrayEverySomeVariant variant) {
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> fncallback = ArgumentOrUndefined(0);
  TNode<Object> this_arg = ArgumentOrUndefined(1);

  TNode<Number> original_length = LoadJSArrayLength(receiver, kind);

  EverySomeFrameStateParams frame_state_params{
      jsgraph(), shared,     context,  target,         outer_frame_state,
      receiver,  fncallback, this_arg, original_length};

  ThrowIfNotCallable(
      fncallback,
      EverySomeLoopLazyFrameState(frame_state_params, ZeroConstant(), variant));

  auto out = MakeLabel(MachineRepresentation::kTagged);

  ForZeroUntil(original_length).Do([&](TNode<Number> k) {
    Checkpoint(EverySomeLoopEagerFrameState(frame_state_params, k, variant));
    MaybeInsertMapChecks(inference, has_stability_dependency);

    TNode<Object> element;
    std::tie(k, element) = SafeLoadElement(kind, receiver, k);

    auto continue_label = MakeLabel();
    element = MaybeSkipHole(element, kind, &continue_label);

    TNode<Object> v =
        JSCall3(fncallback, this_arg, element, k, receiver,
                EverySomeLoopLazyFrameState(frame_state_params, k, variant));

    if (variant == ArrayEverySomeVariant::kEvery) {
      GotoIfNot(ToBoolean(v), &out, FalseConstant());
    } else {
      DCHECK_EQ(variant, ArrayEverySomeVariant::kSome);
      GotoIf(ToBoolean(v), &out, TrueConstant());
    }
    Goto(&continue_label);
    Bind(&continue_label);
  });

  Goto(&out, (variant == ArrayEverySomeVariant::kEvery) ? TrueConstant()
                                                        : FalseConstant());

  Bind(&out);
  return out.PhiAt<Boolean>(0);
}

namespace {

Callable GetCallableForArrayIndexOfIncludes(ArrayIndexOfIncludesVariant variant,
                                            ElementsKind elements_kind,
                                            Isolate* isolate) {
  if (variant == ArrayIndexOfIncludesVariant::kIndexOf) {
    switch (elements_kind) {
      case PACKED_SMI_ELEMENTS:
      case HOLEY_SMI_ELEMENTS:
      case PACKED_ELEMENTS:
      case HOLEY_ELEMENTS:
        return Builtins::CallableFor(isolate,
                                     Builtins::kArrayIndexOfSmiOrObject);
      case PACKED_DOUBLE_ELEMENTS:
        return Builtins::CallableFor(isolate,
                                     Builtins::kArrayIndexOfPackedDoubles);
      default:
        DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
        return Builtins::CallableFor(isolate,
                                     Builtins::kArrayIndexOfHoleyDoubles);
    }
  } else {
    DCHECK_EQ(variant, ArrayIndexOfIncludesVariant::kIncludes);
    switch (elements_kind) {
      case PACKED_SMI_ELEMENTS:
      case HOLEY_SMI_ELEMENTS:
      case PACKED_ELEMENTS:
      case HOLEY_ELEMENTS:
        return Builtins::CallableFor(isolate,
                                     Builtins::kArrayIncludesSmiOrObject);
      case PACKED_DOUBLE_ELEMENTS:
        return Builtins::CallableFor(isolate,
                                     Builtins::kArrayIncludesPackedDoubles);
      default:
        DCHECK_EQ(HOLEY_DOUBLE_ELEMENTS, elements_kind);
        return Builtins::CallableFor(isolate,
                                     Builtins::kArrayIncludesHoleyDoubles);
    }
  }
  UNREACHABLE();
}

}  // namespace

TNode<Object>
IteratingArrayBuiltinReducerAssembler::ReduceArrayPrototypeIndexOfIncludes(
    ElementsKind kind, ArrayIndexOfIncludesVariant variant) {
  TNode<Context> context = ContextInput();
  TNode<JSArray> receiver = ReceiverInputAs<JSArray>();
  TNode<Object> search_element = ArgumentOrUndefined(0);
  TNode<Object> from_index = ArgumentOrZero(1);

  // TODO(jgruber): This currently only reduces to a stub call. Create a full
  // reduction (similar to other higher-order array builtins) instead of
  // lowering to a builtin call. E.g. Array.p.every and Array.p.some have almost
  // identical functionality.

  TNode<Number> length = LoadJSArrayLength(receiver, kind);
  TNode<FixedArrayBase> elements = LoadElements(receiver);

  const bool have_from_index = ArgumentCount() > 1;
  if (have_from_index) {
    TNode<Smi> from_index_smi = CheckSmi(from_index);

    // If the index is negative, it means the offset from the end and
    // therefore needs to be added to the length. If the result is still
    // negative, it needs to be clamped to 0.
    TNode<Boolean> cond = NumberLessThan(from_index_smi, ZeroConstant());
    from_index = SelectIf<Number>(cond)
                     .Then(_ {
                       return NumberMax(NumberAdd(length, from_index_smi),
                                        ZeroConstant());
                     })
                     .Else(_ { return from_index_smi; })
                     .ExpectFalse()
                     .Value();
  }

  return Call4(GetCallableForArrayIndexOfIncludes(variant, kind, isolate()),
               context, elements, search_element, length, from_index);
}

namespace {

struct PromiseCtorFrameStateParams {
  JSGraph* jsgraph;
  SharedFunctionInfoRef shared;
  Node* node_ptr;
  TNode<Context> context;
  TNode<Object> target;
  FrameState outer_frame_state;
};

// Remnant of old-style JSCallReducer code. Could be ported to graph assembler,
// but probably not worth the effort.
FrameState CreateArtificialFrameState(Node* node, Node* outer_frame_state,
                                      int parameter_count, BailoutId bailout_id,
                                      FrameStateType frame_state_type,
                                      const SharedFunctionInfoRef& shared,
                                      Node* context,
                                      CommonOperatorBuilder* common,
                                      Graph* graph) {
  const FrameStateFunctionInfo* state_info =
      common->CreateFrameStateFunctionInfo(
          frame_state_type, parameter_count + 1, 0, shared.object());

  const Operator* op = common->FrameState(
      bailout_id, OutputFrameStateCombine::Ignore(), state_info);
  const Operator* op0 = common->StateValues(0, SparseInputMask::Dense());
  Node* node0 = graph->NewNode(op0);

  static constexpr int kTargetInputIndex = 0;
  static constexpr int kReceiverInputIndex = 1;
  const int parameter_count_with_receiver = parameter_count + 1;
  std::vector<Node*> params;
  params.reserve(parameter_count_with_receiver);
  for (int i = 0; i < parameter_count_with_receiver; i++) {
    params.push_back(node->InputAt(kReceiverInputIndex + i));
  }
  const Operator* op_param = common->StateValues(
      static_cast<int>(params.size()), SparseInputMask::Dense());
  Node* params_node = graph->NewNode(op_param, static_cast<int>(params.size()),
                                     &params.front());
  DCHECK(context);
  return FrameState(graph->NewNode(op, params_node, node0, node0, context,
                                   node->InputAt(kTargetInputIndex),
                                   outer_frame_state));
}

FrameState PromiseConstructorFrameState(
    const PromiseCtorFrameStateParams& params, CommonOperatorBuilder* common,
    Graph* graph) {
  DCHECK_EQ(1, params.shared.internal_formal_parameter_count());
  return CreateArtificialFrameState(
      params.node_ptr, params.outer_frame_state, 1,
      BailoutId::ConstructStubInvoke(), FrameStateType::kConstructStub,
      params.shared, params.context, common, graph);
}

FrameState PromiseConstructorLazyFrameState(
    const PromiseCtorFrameStateParams& params,
    FrameState constructor_frame_state) {
  // The deopt continuation of this frame state is never called; the frame state
  // is only necessary to obtain the right stack trace.
  JSGraph* jsgraph = params.jsgraph;
  Node* checkpoint_params[] = {
      jsgraph->UndefinedConstant(), /* receiver */
      jsgraph->UndefinedConstant(), /* promise */
      jsgraph->UndefinedConstant(), /* reject function */
      jsgraph->TheHoleConstant()    /* exception */
  };
  return CreateJavaScriptBuiltinContinuationFrameState(
      jsgraph, params.shared,
      Builtins::kPromiseConstructorLazyDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      constructor_frame_state, ContinuationFrameStateMode::LAZY);
}

FrameState PromiseConstructorLazyWithCatchFrameState(
    const PromiseCtorFrameStateParams& params,
    FrameState constructor_frame_state, TNode<JSPromise> promise,
    TNode<JSFunction> reject) {
  // This continuation just returns the created promise and takes care of
  // exceptions thrown by the executor.
  Node* checkpoint_params[] = {
      params.jsgraph->UndefinedConstant(), /* receiver */
      promise, reject};
  return CreateJavaScriptBuiltinContinuationFrameState(
      params.jsgraph, params.shared,
      Builtins::kPromiseConstructorLazyDeoptContinuation, params.target,
      params.context, checkpoint_params, arraysize(checkpoint_params),
      constructor_frame_state, ContinuationFrameStateMode::LAZY_WITH_CATCH);
}

}  // namespace

TNode<Object> PromiseBuiltinReducerAssembler::ReducePromiseConstructor(
    const NativeContextRef& native_context) {
  DCHECK_GE(ConstructArity(), 1);

  JSConstructNode n(node_ptr());
  FrameState outer_frame_state = FrameStateInput();
  TNode<Context> context = ContextInput();
  TNode<Object> target = TargetInput();
  TNode<Object> executor = n.Argument(0);
  DCHECK_EQ(target, NewTargetInput());

  SharedFunctionInfoRef promise_shared =
      native_context.promise_function().shared();

  PromiseCtorFrameStateParams frame_state_params{jsgraph(),  promise_shared,
                                                 node_ptr(), context,
                                                 target,     outer_frame_state};

  // Insert a construct stub frame into the chain of frame states. This will
  // reconstruct the proper frame when deoptimizing within the constructor.
  // For the frame state, we only provide the executor parameter, even if more
  // arguments were passed. This is not observable from JS.
  FrameState constructor_frame_state =
      PromiseConstructorFrameState(frame_state_params, common(), graph());

  ThrowIfNotCallable(executor,
                     PromiseConstructorLazyFrameState(frame_state_params,
                                                      constructor_frame_state));

  TNode<JSPromise> promise = CreatePromise(context);

  // 8. CreatePromiseResolvingFunctions
  // Allocate a promise context for the closures below.
  TNode<Context> promise_context = CreateFunctionContext(
      native_context, context, PromiseBuiltins::kPromiseContextLength);
  StoreContextSlot(promise_context, PromiseBuiltins::kPromiseSlot, promise);
  StoreContextSlot(promise_context, PromiseBuiltins::kAlreadyResolvedSlot,
                   FalseConstant());
  StoreContextSlot(promise_context, PromiseBuiltins::kDebugEventSlot,
                   TrueConstant());

  // Allocate closures for the resolve and reject cases.
  SharedFunctionInfoRef resolve_sfi(
      broker_, broker_->isolate()
                   ->factory()
                   ->promise_capability_default_resolve_shared_fun());
  TNode<JSFunction> resolve =
      CreateClosureFromBuiltinSharedFunctionInfo(resolve_sfi, promise_context);

  SharedFunctionInfoRef reject_sfi(
      broker_, broker_->isolate()
                   ->factory()
                   ->promise_capability_default_reject_shared_fun());
  TNode<JSFunction> reject =
      CreateClosureFromBuiltinSharedFunctionInfo(reject_sfi, promise_context);

  FrameState lazy_with_catch_frame_state =
      PromiseConstructorLazyWithCatchFrameState(
          frame_state_params, constructor_frame_state, promise, reject);

  // 9. Call executor with both resolving functions.
  // 10a. Call reject if the call to executor threw.
  Try(_ {
    CallPromiseExecutor(executor, resolve, reject, lazy_with_catch_frame_state);
  }).Catch([&](TNode<Object> exception) {
    CallPromiseReject(reject, exception, lazy_with_catch_frame_state);
  });

  return promise;
}

#undef _

bool JSCallReducer::should_disallow_heap_access() const {
  return broker_->is_concurrent_inlining();
}

Reduction JSCallReducer::ReplaceWithSubgraph(JSCallReducerAssembler* gasm,
                                             Node* subgraph) {
  // TODO(jgruber): Consider a less fiddly way of integrating the new subgraph
  // into the outer graph. For instance, the subgraph could be created in
  // complete isolation, and then plugged into the outer graph in one go.
  // Instead of manually tracking IfException nodes, we could iterate the
  // subgraph.

  // Replace the Call node with the newly-produced subgraph.
  ReplaceWithValue(gasm->node_ptr(), subgraph, gasm->effect(), gasm->control());

  // Wire exception edges contained in the newly-produced subgraph into the
  // outer graph.
  auto catch_scope = gasm->catch_scope();
  DCHECK(catch_scope->is_outermost());

  if (catch_scope->has_handler() &&
      catch_scope->has_exceptional_control_flow()) {
    TNode<Object> handler_exception;
    Effect handler_effect{nullptr};
    Control handler_control{nullptr};
    gasm->catch_scope()->MergeExceptionalPaths(
        &handler_exception, &handler_effect, &handler_control);

    ReplaceWithValue(gasm->outermost_handler(), handler_exception,
                     handler_effect, handler_control);
  }

  return Replace(subgraph);
}

Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->NaNConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }

  JSCallReducerAssembler a(this, node);
  Node* subgraph = a.ReduceMathUnary(op);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->NaNConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }

  JSCallReducerAssembler a(this, node);
  Node* subgraph = a.ReduceMathBinary(op);
  return ReplaceWithSubgraph(&a, subgraph);
}

// ES6 section 20.2.2.19 Math.imul ( x, y )
Reduction JSCallReducer::ReduceMathImul(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->ZeroConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  Node* left = n.Argument(0);
  Node* right = n.ArgumentOr(1, jsgraph()->ZeroConstant());
  Effect effect = n.effect();
  Control control = n.control();

  left = effect =
      graph()->NewNode(simplified()->SpeculativeToNumber(
                           NumberOperationHint::kNumberOrOddball, p.feedback()),
                       left, effect, control);
  right = effect =
      graph()->NewNode(simplified()->SpeculativeToNumber(
                           NumberOperationHint::kNumberOrOddball, p.feedback()),
                       right, effect, control);
  left = graph()->NewNode(simplified()->NumberToUint32(), left);
  right = graph()->NewNode(simplified()->NumberToUint32(), right);
  Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
  ReplaceWithValue(node, value, effect);
  return Replace(value);
}

// ES6 section 20.2.2.11 Math.clz32 ( x )
Reduction JSCallReducer::ReduceMathClz32(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->Constant(32);
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  Node* input = n.Argument(0);
  Effect effect = n.effect();
  Control control = n.control();

  input = effect =
      graph()->NewNode(simplified()->SpeculativeToNumber(
                           NumberOperationHint::kNumberOrOddball, p.feedback()),
                       input, effect, control);
  input = graph()->NewNode(simplified()->NumberToUint32(), input);
  Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
  ReplaceWithValue(node, value, effect);
  return Replace(value);
}

// ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
// ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op,
                                          Node* empty_value) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    ReplaceWithValue(node, empty_value);
    return Replace(empty_value);
  }
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  Node* value = effect =
      graph()->NewNode(simplified()->SpeculativeToNumber(
                           NumberOperationHint::kNumberOrOddball, p.feedback()),
                       n.Argument(0), effect, control);
  for (int i = 1; i < n.ArgumentCount(); i++) {
    Node* input = effect = graph()->NewNode(
        simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
                                          p.feedback()),
        n.Argument(i), effect, control);
    value = graph()->NewNode(op, value, input);
  }

  ReplaceWithValue(node, value, effect);
  return Replace(value);
}

Reduction JSCallReducer::Reduce(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  switch (node->opcode()) {
    case IrOpcode::kJSConstruct:
      return ReduceJSConstruct(node);
    case IrOpcode::kJSConstructWithArrayLike:
      return ReduceJSConstructWithArrayLike(node);
    case IrOpcode::kJSConstructWithSpread:
      return ReduceJSConstructWithSpread(node);
    case IrOpcode::kJSCall:
      return ReduceJSCall(node);
    case IrOpcode::kJSCallWithArrayLike:
      return ReduceJSCallWithArrayLike(node);
    case IrOpcode::kJSCallWithSpread:
      return ReduceJSCallWithSpread(node);
    default:
      break;
  }
  return NoChange();
}

void JSCallReducer::Finalize() {
  // TODO(turbofan): This is not the best solution; ideally we would be able
  // to teach the GraphReducer about arbitrary dependencies between different
  // nodes, even if they don't show up in the use list of the other node.
  std::set<Node*> const waitlist = std::move(waitlist_);
  for (Node* node : waitlist) {
    if (!node->IsDead()) {
      Reduction const reduction = Reduce(node);
      if (reduction.Changed()) {
        Node* replacement = reduction.replacement();
        if (replacement != node) {
          Replace(node, replacement);
        }
      }
    }
  }
}

// ES6 section 22.1.1 The Array Constructor
Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  Node* target = n.target();
  CallParameters const& p = n.Parameters();

  // Turn the {node} into a {JSCreateArray} call.
  size_t const arity = p.arity_without_implicit_args();
  node->RemoveInput(n.FeedbackVectorIndex());
  NodeProperties::ReplaceValueInput(node, target, 0);
  NodeProperties::ReplaceValueInput(node, target, 1);
  NodeProperties::ChangeOp(
      node, javascript()->CreateArray(arity, MaybeHandle<AllocationSite>()));
  return Changed(node);
}

// ES6 section 19.3.1.1 Boolean ( value )
Reduction JSCallReducer::ReduceBooleanConstructor(Node* node) {
  // Replace the {node} with a proper {ToBoolean} operator.
  JSCallNode n(node);
  Node* value = n.ArgumentOrUndefined(0, jsgraph());
  value = graph()->NewNode(simplified()->ToBoolean(), value);
  ReplaceWithValue(node, value);
  return Replace(value);
}

// ES section #sec-object-constructor
Reduction JSCallReducer::ReduceObjectConstructor(Node* node) {
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) return NoChange();
  Node* value = n.Argument(0);
  Effect effect = n.effect();

  // We can fold away the Object(x) call if |x| is definitely not a primitive.
  if (NodeProperties::CanBePrimitive(broker(), value, effect)) {
    if (!NodeProperties::CanBeNullOrUndefined(broker(), value, effect)) {
      // Turn the {node} into a {JSToObject} call if we know that
      // the {value} cannot be null or undefined.
      NodeProperties::ReplaceValueInputs(node, value);
      NodeProperties::ChangeOp(node, javascript()->ToObject());
      return Changed(node);
    }
  } else {
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  return NoChange();
}

// ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny;
  if (arity == 0) {
    // Neither thisArg nor argArray was provided.
    convert_mode = ConvertReceiverMode::kNullOrUndefined;
    node->ReplaceInput(n.TargetIndex(), n.receiver());
    node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
  } else if (arity == 1) {
    // The argArray was not provided, just remove the {target}.
    node->RemoveInput(n.TargetIndex());
    --arity;
  } else {
    Node* target = n.receiver();
    Node* this_argument = n.Argument(0);
    Node* arguments_list = n.Argument(1);
    Node* context = n.context();
    FrameState frame_state = n.frame_state();
    Effect effect = n.effect();
    Control control = n.control();

    // If {arguments_list} cannot be null or undefined, we don't need
    // to expand this {node} to control-flow.
    if (!NodeProperties::CanBeNullOrUndefined(broker(), arguments_list,
                                              effect)) {
      // Massage the value inputs appropriately.
      node->ReplaceInput(n.TargetIndex(), target);
      node->ReplaceInput(n.ReceiverIndex(), this_argument);
      node->ReplaceInput(n.ArgumentIndex(0), arguments_list);
      while (arity-- > 1) node->RemoveInput(n.ArgumentIndex(1));

      // Morph the {node} to a {JSCallWithArrayLike}.
      NodeProperties::ChangeOp(
          node, javascript()->CallWithArrayLike(
                    p.frequency(), p.feedback(), p.speculation_mode(),
                    CallFeedbackRelation::kUnrelated));
      return Changed(node).FollowedBy(ReduceJSCallWithArrayLike(node));
    } else {
      // Check whether {arguments_list} is null.
      Node* check_null =
          graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
                           jsgraph()->NullConstant());
      control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
                                 check_null, control);
      Node* if_null = graph()->NewNode(common()->IfTrue(), control);
      control = graph()->NewNode(common()->IfFalse(), control);

      // Check whether {arguments_list} is undefined.
      Node* check_undefined =
          graph()->NewNode(simplified()->ReferenceEqual(), arguments_list,
                           jsgraph()->UndefinedConstant());
      control = graph()->NewNode(common()->Branch(BranchHint::kFalse),
                                 check_undefined, control);
      Node* if_undefined = graph()->NewNode(common()->IfTrue(), control);
      control = graph()->NewNode(common()->IfFalse(), control);

      // Lower to {JSCallWithArrayLike} if {arguments_list} is neither null
      // nor undefined.
      Node* effect0 = effect;
      Node* control0 = control;
      Node* value0 = effect0 = control0 = graph()->NewNode(
          javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
                                          p.speculation_mode(),
                                          CallFeedbackRelation::kUnrelated),
          target, this_argument, arguments_list, n.feedback_vector(), context,
          frame_state, effect0, control0);

      // Lower to {JSCall} if {arguments_list} is either null or undefined.
      Node* effect1 = effect;
      Node* control1 =
          graph()->NewNode(common()->Merge(2), if_null, if_undefined);
      Node* value1 = effect1 = control1 =
          graph()->NewNode(javascript()->Call(JSCallNode::ArityForArgc(0)),
                           target, this_argument, n.feedback_vector(), context,
                           frame_state, effect1, control1);

      // Rewire potential exception edges.
      Node* if_exception = nullptr;
      if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
        // Create appropriate {IfException} and {IfSuccess} nodes.
        Node* if_exception0 =
            graph()->NewNode(common()->IfException(), control0, effect0);
        control0 = graph()->NewNode(common()->IfSuccess(), control0);
        Node* if_exception1 =
            graph()->NewNode(common()->IfException(), control1, effect1);
        control1 = graph()->NewNode(common()->IfSuccess(), control1);

        // Join the exception edges.
        Node* merge =
            graph()->NewNode(common()->Merge(2), if_exception0, if_exception1);
        Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception0,
                                      if_exception1, merge);
        Node* phi =
            graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                             if_exception0, if_exception1, merge);
        ReplaceWithValue(if_exception, phi, ephi, merge);
      }

      // Join control paths.
      control = graph()->NewNode(common()->Merge(2), control0, control1);
      effect =
          graph()->NewNode(common()->EffectPhi(2), effect0, effect1, control);
      Node* value =
          graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                           value0, value1, control);
      ReplaceWithValue(node, value, effect, control);
      return Replace(value);
    }
  }
  // Change {node} to the new {JSCall} operator.
  NodeProperties::ChangeOp(
      node, javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
                               p.feedback(), convert_mode, p.speculation_mode(),
                               CallFeedbackRelation::kUnrelated));
  // Try to further reduce the JSCall {node}.
  return Changed(node).FollowedBy(ReduceJSCall(node));
}

// ES section #sec-function.prototype.bind
Reduction JSCallReducer::ReduceFunctionPrototypeBind(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  // Value inputs to the {node} are as follows:
  //
  //  - target, which is Function.prototype.bind JSFunction
  //  - receiver, which is the [[BoundTargetFunction]]
  //  - bound_this (optional), which is the [[BoundThis]]
  //  - and all the remaining value inputs are [[BoundArguments]]
  Node* receiver = n.receiver();
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();

  // Ensure that the {receiver} is known to be a JSBoundFunction or
  // a JSFunction with the same [[Prototype]], and all maps we've
  // seen for the {receiver} so far indicate that {receiver} is
  // definitely a constructor or not a constructor.
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& receiver_maps = inference.GetMaps();

  MapRef first_receiver_map(broker(), receiver_maps[0]);
  bool const is_constructor = first_receiver_map.is_constructor();

  if (should_disallow_heap_access() &&
      !first_receiver_map.serialized_prototype()) {
    TRACE_BROKER_MISSING(broker(),
                         "serialized prototype on map " << first_receiver_map);
    return inference.NoChange();
  }
  ObjectRef const prototype = first_receiver_map.prototype();
  for (Handle<Map> const map : receiver_maps) {
    MapRef receiver_map(broker(), map);

    if (should_disallow_heap_access() && !receiver_map.serialized_prototype()) {
      TRACE_BROKER_MISSING(broker(),
                           "serialized prototype on map " << receiver_map);
      return inference.NoChange();
    }

    // Check for consistency among the {receiver_maps}.
    STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE);
    if (!receiver_map.prototype().equals(prototype) ||
        receiver_map.is_constructor() != is_constructor ||
        receiver_map.instance_type() < FIRST_FUNCTION_TYPE) {
      return inference.NoChange();
    }

    // Disallow binding of slow-mode functions. We need to figure out
    // whether the length and name property are in the original state.
    if (receiver_map.is_dictionary_map()) return inference.NoChange();

    // Check whether the length and name properties are still present
    // as AccessorInfo objects. In that case, their values can be
    // recomputed even if the actual value of the object changes.
    // This mirrors the checks done in builtins-function-gen.cc at
    // runtime otherwise.
    int minimum_nof_descriptors = std::max({JSFunction::kLengthDescriptorIndex,
                                            JSFunction::kNameDescriptorIndex}) +
                                  1;
    if (receiver_map.NumberOfOwnDescriptors() < minimum_nof_descriptors) {
      return inference.NoChange();
    }
    const InternalIndex kLengthIndex(JSFunction::kLengthDescriptorIndex);
    const InternalIndex kNameIndex(JSFunction::kNameDescriptorIndex);
    if (!receiver_map.serialized_own_descriptor(kLengthIndex) ||
        !receiver_map.serialized_own_descriptor(kNameIndex)) {
      TRACE_BROKER_MISSING(broker(),
                           "serialized descriptors on map " << receiver_map);
      return inference.NoChange();
    }
    ReadOnlyRoots roots(isolate());
    StringRef length_string(broker(), roots.length_string_handle());
    StringRef name_string(broker(), roots.name_string_handle());

    base::Optional<ObjectRef> length_value(
        receiver_map.GetStrongValue(kLengthIndex));
    base::Optional<ObjectRef> name_value(
        receiver_map.GetStrongValue(kNameIndex));
    if (!length_value || !name_value) {
      TRACE_BROKER_MISSING(
          broker(), "name or length descriptors on map " << receiver_map);
      return inference.NoChange();
    }
    if (!receiver_map.GetPropertyKey(kLengthIndex).equals(length_string) ||
        !length_value->IsAccessorInfo() ||
        !receiver_map.GetPropertyKey(kNameIndex).equals(name_string) ||
        !name_value->IsAccessorInfo()) {
      return inference.NoChange();
    }
  }

  // Choose the map for the resulting JSBoundFunction (but bail out in case of a
  // custom prototype).
  MapRef map = is_constructor
                   ? native_context().bound_function_with_constructor_map()
                   : native_context().bound_function_without_constructor_map();
  if (!map.prototype().equals(prototype)) return inference.NoChange();

  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  // Replace the {node} with a JSCreateBoundFunction.
  static constexpr int kBoundThis = 1;
  static constexpr int kReceiverContextEffectAndControl = 4;
  int const arity = n.ArgumentCount();
  int const arity_with_bound_this = std::max(arity, kBoundThis);
  int const input_count =
      arity_with_bound_this + kReceiverContextEffectAndControl;
  Node** inputs = graph()->zone()->NewArray<Node*>(input_count);
  int cursor = 0;
  inputs[cursor++] = receiver;
  inputs[cursor++] = n.ArgumentOrUndefined(0, jsgraph());  // bound_this.
  for (int i = 1; i < arity; ++i) {
    inputs[cursor++] = n.Argument(i);
  }
  inputs[cursor++] = context;
  inputs[cursor++] = effect;
  inputs[cursor++] = control;
  DCHECK_EQ(cursor, input_count);
  Node* value = effect =
      graph()->NewNode(javascript()->CreateBoundFunction(
                           arity_with_bound_this - kBoundThis, map.object()),
                       input_count, inputs);
  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES6 section 19.2.3.3 Function.prototype.call (thisArg, ...args)
Reduction JSCallReducer::ReduceFunctionPrototypeCall(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  Node* target = n.target();
  Effect effect = n.effect();
  Control control = n.control();

  // Change context of {node} to the Function.prototype.call context,
  // to ensure any exception is thrown in the correct context.
  Node* context;
  HeapObjectMatcher m(target);
  if (m.HasResolvedValue() && m.Ref(broker()).IsJSFunction()) {
    JSFunctionRef function = m.Ref(broker()).AsJSFunction();
    if (should_disallow_heap_access() && !function.serialized()) {
      TRACE_BROKER_MISSING(broker(), "Serialize call on function " << function);
      return NoChange();
    }
    context = jsgraph()->Constant(function.context());
  } else {
    context = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
        effect, control);
  }
  NodeProperties::ReplaceContextInput(node, context);
  NodeProperties::ReplaceEffectInput(node, effect);

  // Remove the target from {node} and use the receiver as target instead, and
  // the thisArg becomes the new target.  If thisArg was not provided, insert
  // undefined instead.
  int arity = p.arity_without_implicit_args();
  ConvertReceiverMode convert_mode;
  if (arity == 0) {
    // The thisArg was not provided, use undefined as receiver.
    convert_mode = ConvertReceiverMode::kNullOrUndefined;
    node->ReplaceInput(n.TargetIndex(), n.receiver());
    node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
  } else {
    // Just remove the target, which is the first value input.
    convert_mode = ConvertReceiverMode::kAny;
    node->RemoveInput(n.TargetIndex());
    --arity;
  }
  NodeProperties::ChangeOp(
      node, javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
                               p.feedback(), convert_mode, p.speculation_mode(),
                               CallFeedbackRelation::kUnrelated));
  // Try to further reduce the JSCall {node}.
  return Changed(node).FollowedBy(ReduceJSCall(node));
}

// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] (V)
Reduction JSCallReducer::ReduceFunctionPrototypeHasInstance(Node* node) {
  JSCallNode n(node);
  Node* receiver = n.receiver();
  Node* object = n.ArgumentOrUndefined(0, jsgraph());
  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Effect effect = n.effect();
  Control control = n.control();

  // TODO(turbofan): If JSOrdinaryToInstance raises an exception, the
  // stack trace doesn't contain the @@hasInstance call; we have the
  // corresponding bug in the baseline case. Some massaging of the frame
  // state would be necessary here.

  // Morph this {node} into a JSOrdinaryHasInstance node.
  node->ReplaceInput(0, receiver);
  node->ReplaceInput(1, object);
  node->ReplaceInput(2, context);
  node->ReplaceInput(3, frame_state);
  node->ReplaceInput(4, effect);
  node->ReplaceInput(5, control);
  node->TrimInputCount(6);
  NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
  return Changed(node);
}

Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
  Node* effect = NodeProperties::GetEffectInput(node);

  // Try to determine the {object} map.
  MapInference inference(broker(), object, effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& object_maps = inference.GetMaps();

  MapRef candidate_map(broker(), object_maps[0]);
  if (should_disallow_heap_access() && !candidate_map.serialized_prototype()) {
    TRACE_BROKER_MISSING(broker(), "prototype for map " << candidate_map);
    return inference.NoChange();
  }
  ObjectRef candidate_prototype = candidate_map.prototype();

  // Check if we can constant-fold the {candidate_prototype}.
  for (size_t i = 0; i < object_maps.size(); ++i) {
    MapRef object_map(broker(), object_maps[i]);
    if (should_disallow_heap_access() && !object_map.serialized_prototype()) {
      TRACE_BROKER_MISSING(broker(), "prototype for map " << object_map);
      return inference.NoChange();
    }
    if (IsSpecialReceiverInstanceType(object_map.instance_type()) ||
        !object_map.prototype().equals(candidate_prototype)) {
      // We exclude special receivers, like JSProxy or API objects that
      // might require access checks here; we also don't want to deal
      // with hidden prototypes at this point.
      return inference.NoChange();
    }
    // The above check also excludes maps for primitive values, which is
    // important because we are not applying [[ToObject]] here as expected.
    DCHECK(!object_map.IsPrimitiveMap() && object_map.IsJSReceiverMap());
  }
  if (!inference.RelyOnMapsViaStability(dependencies())) {
    return inference.NoChange();
  }
  Node* value = jsgraph()->Constant(candidate_prototype);
  ReplaceWithValue(node, value);
  return Replace(value);
}

// ES6 section 19.1.2.11 Object.getPrototypeOf ( O )
Reduction JSCallReducer::ReduceObjectGetPrototypeOf(Node* node) {
  JSCallNode n(node);
  Node* object = n.ArgumentOrUndefined(0, jsgraph());
  return ReduceObjectGetPrototype(node, object);
}

// ES section #sec-object.is
Reduction JSCallReducer::ReduceObjectIs(Node* node) {
  JSCallNode n(node);
  Node* lhs = n.ArgumentOrUndefined(0, jsgraph());
  Node* rhs = n.ArgumentOrUndefined(1, jsgraph());
  Node* value = graph()->NewNode(simplified()->SameValue(), lhs, rhs);
  ReplaceWithValue(node, value);
  return Replace(value);
}

// ES6 section B.2.2.1.1 get Object.prototype.__proto__
Reduction JSCallReducer::ReduceObjectPrototypeGetProto(Node* node) {
  JSCallNode n(node);
  return ReduceObjectGetPrototype(node, n.receiver());
}

// ES #sec-object.prototype.hasownproperty
Reduction JSCallReducer::ReduceObjectPrototypeHasOwnProperty(Node* node) {
  JSCallNode n(node);
  Node* receiver = n.receiver();
  Node* name = n.ArgumentOrUndefined(0, jsgraph());
  Effect effect = n.effect();
  Control control = n.control();

  // We can optimize a call to Object.prototype.hasOwnProperty if it's being
  // used inside a fast-mode for..in, so for code like this:
  //
  //   for (name in receiver) {
  //     if (receiver.hasOwnProperty(name)) {
  //        ...
  //     }
  //   }
  //
  // If the for..in is in fast-mode, we know that the {receiver} has {name}
  // as own property, otherwise the enumeration wouldn't include it. The graph
  // constructed by the BytecodeGraphBuilder in this case looks like this:

  // receiver
  //  ^    ^
  //  |    |
  //  |    +-+
  //  |      |
  //  |   JSToObject
  //  |      ^
  //  |      |
  //  |   JSForInNext
  //  |      ^
  //  +----+ |
  //       | |
  //  JSCall[hasOwnProperty]

  // We can constant-fold the {node} to True in this case, and insert
  // a (potentially redundant) map check to guard the fact that the
  // {receiver} map didn't change since the dominating JSForInNext. This
  // map check is only necessary when TurboFan cannot prove that there
  // is no observable side effect between the {JSForInNext} and the
  // {JSCall} to Object.prototype.hasOwnProperty.
  //
  // Also note that it's safe to look through the {JSToObject}, since the
  // Object.prototype.hasOwnProperty does an implicit ToObject anyway, and
  // these operations are not observable.
  if (name->opcode() == IrOpcode::kJSForInNext) {
    JSForInNextNode n(name);
    if (n.Parameters().mode() != ForInMode::kGeneric) {
      Node* object = n.receiver();
      Node* cache_type = n.cache_type();
      if (object->opcode() == IrOpcode::kJSToObject) {
        object = NodeProperties::GetValueInput(object, 0);
      }
      if (object == receiver) {
        // No need to repeat the map check if we can prove that there's no
        // observable side effect between {effect} and {name].
        if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
          Node* receiver_map = effect =
              graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
                               receiver, effect, control);
          Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
                                         receiver_map, cache_type);
          effect = graph()->NewNode(
              simplified()->CheckIf(DeoptimizeReason::kWrongMap), check, effect,
              control);
        }
        Node* value = jsgraph()->TrueConstant();
        ReplaceWithValue(node, value, effect, control);
        return Replace(value);
      }
    }
  }

  return NoChange();
}

// ES #sec-object.prototype.isprototypeof
Reduction JSCallReducer::ReduceObjectPrototypeIsPrototypeOf(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  Node* receiver = n.receiver();
  Node* value = n.ArgumentOrUndefined(0, jsgraph());
  Effect effect = n.effect();

  // Ensure that the {receiver} is known to be a JSReceiver (so that
  // the ToObject step of Object.prototype.isPrototypeOf is a no-op).
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAreJSReceiver()) {
    return NoChange();
  }

  // We don't check whether {value} is a proper JSReceiver here explicitly,
  // and don't explicitly rule out Primitive {value}s, since all of them
  // have null as their prototype, so the prototype chain walk inside the
  // JSHasInPrototypeChain operator immediately aborts and yields false.
  NodeProperties::ReplaceValueInput(node, value, n.TargetIndex());
  for (int i = node->op()->ValueInputCount(); i > 2; i--) {
    node->RemoveInput(2);
  }
  NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
  return Changed(node);
}

// ES6 section 26.1.1 Reflect.apply ( target, thisArgument, argumentsList )
Reduction JSCallReducer::ReduceReflectApply(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  // Massage value inputs appropriately.
  STATIC_ASSERT(n.ReceiverIndex() > n.TargetIndex());
  node->RemoveInput(n.ReceiverIndex());
  node->RemoveInput(n.TargetIndex());
  while (arity < 3) {
    node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
  }
  while (arity-- > 3) {
    node->RemoveInput(arity);
  }
  NodeProperties::ChangeOp(
      node, javascript()->CallWithArrayLike(p.frequency(), p.feedback(),
                                            p.speculation_mode(),
                                            CallFeedbackRelation::kUnrelated));
  return Changed(node).FollowedBy(ReduceJSCallWithArrayLike(node));
}

// ES6 section 26.1.2 Reflect.construct ( target, argumentsList [, newTarget] )
Reduction JSCallReducer::ReduceReflectConstruct(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  // Massage value inputs appropriately.
  Node* arg_target = n.ArgumentOrUndefined(0, jsgraph());
  Node* arg_argument_list = n.ArgumentOrUndefined(1, jsgraph());
  Node* arg_new_target = n.ArgumentOr(2, arg_target);

  STATIC_ASSERT(n.ReceiverIndex() > n.TargetIndex());
  node->RemoveInput(n.ReceiverIndex());
  node->RemoveInput(n.TargetIndex());

  // TODO(jgruber): This pattern essentially ensures that we have the correct
  // number of inputs for a given argument count. Wrap it in a helper function.
  STATIC_ASSERT(JSConstructNode::FirstArgumentIndex() == 2);
  while (arity < 3) {
    node->InsertInput(graph()->zone(), arity++, jsgraph()->UndefinedConstant());
  }
  while (arity-- > 3) {
    node->RemoveInput(arity);
  }

  STATIC_ASSERT(JSConstructNode::TargetIndex() == 0);
  STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
  STATIC_ASSERT(JSConstructNode::kFeedbackVectorIsLastInput);
  node->ReplaceInput(JSConstructNode::TargetIndex(), arg_target);
  node->ReplaceInput(JSConstructNode::NewTargetIndex(), arg_new_target);
  node->ReplaceInput(JSConstructNode::ArgumentIndex(0), arg_argument_list);

  NodeProperties::ChangeOp(
      node, javascript()->ConstructWithArrayLike(p.frequency(), p.feedback()));
  return Changed(node).FollowedBy(ReduceJSConstructWithArrayLike(node));
}

// ES6 section 26.1.7 Reflect.getPrototypeOf ( target )
Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
  JSCallNode n(node);
  Node* target = n.ArgumentOrUndefined(0, jsgraph());
  return ReduceObjectGetPrototype(node, target);
}

// ES6 section #sec-object.create Object.create(proto, properties)
Reduction JSCallReducer::ReduceObjectCreate(Node* node) {
  JSCallNode n(node);
  Node* properties = n.ArgumentOrUndefined(1, jsgraph());
  if (properties != jsgraph()->UndefinedConstant()) return NoChange();

  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Effect effect = n.effect();
  Control control = n.control();
  Node* prototype = n.ArgumentOrUndefined(0, jsgraph());
  node->ReplaceInput(0, prototype);
  node->ReplaceInput(1, context);
  node->ReplaceInput(2, frame_state);
  node->ReplaceInput(3, effect);
  node->ReplaceInput(4, control);
  node->TrimInputCount(5);
  NodeProperties::ChangeOp(node, javascript()->CreateObject());
  return Changed(node);
}

// ES section #sec-reflect.get
Reduction JSCallReducer::ReduceReflectGet(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  if (arity != 2) return NoChange();
  Node* target = n.Argument(0);
  Node* key = n.Argument(1);
  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Effect effect = n.effect();
  Control control = n.control();

  // Check whether {target} is a JSReceiver.
  Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
  Node* branch =
      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);

  // Throw an appropriate TypeError if the {target} is not a JSReceiver.
  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
  Node* efalse = effect;
  {
    if_false = efalse = graph()->NewNode(
        javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
        jsgraph()->Constant(
            static_cast<int>(MessageTemplate::kCalledOnNonObject)),
        jsgraph()->HeapConstant(factory()->ReflectGet_string()), context,
        frame_state, efalse, if_false);
  }

  // Otherwise just use the existing GetPropertyStub.
  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
  Node* etrue = effect;
  Node* vtrue;
  {
    Callable callable =
        Builtins::CallableFor(isolate(), Builtins::kGetProperty);
    auto call_descriptor = Linkage::GetStubCallDescriptor(
        graph()->zone(), callable.descriptor(),
        callable.descriptor().GetStackParameterCount(),
        CallDescriptor::kNeedsFrameState, Operator::kNoProperties);
    Node* stub_code = jsgraph()->HeapConstant(callable.code());
    vtrue = etrue = if_true =
        graph()->NewNode(common()->Call(call_descriptor), stub_code, target,
                         key, context, frame_state, etrue, if_true);
  }

  // Rewire potential exception edges.
  Node* on_exception = nullptr;
  if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    // Create appropriate {IfException} and {IfSuccess} nodes.
    Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
    if_true = graph()->NewNode(common()->IfSuccess(), if_true);
    Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
    if_false = graph()->NewNode(common()->IfSuccess(), if_false);

    // Join the exception edges.
    Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
    Node* ephi =
        graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
    Node* phi =
        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                         extrue, exfalse, merge);
    ReplaceWithValue(on_exception, phi, ephi, merge);
  }

  // Connect the throwing path to end.
  if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
  NodeProperties::MergeControlToEnd(graph(), common(), if_false);

  // Continue on the regular path.
  ReplaceWithValue(node, vtrue, etrue, if_true);
  return Changed(vtrue);
}

// ES section #sec-reflect.has
Reduction JSCallReducer::ReduceReflectHas(Node* node) {
  JSCallNode n(node);
  Node* target = n.ArgumentOrUndefined(0, jsgraph());
  Node* key = n.ArgumentOrUndefined(1, jsgraph());
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();
  FrameState frame_state = n.frame_state();

  // Check whether {target} is a JSReceiver.
  Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), target);
  Node* branch =
      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);

  // Throw an appropriate TypeError if the {target} is not a JSReceiver.
  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
  Node* efalse = effect;
  {
    if_false = efalse = graph()->NewNode(
        javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
        jsgraph()->Constant(
            static_cast<int>(MessageTemplate::kCalledOnNonObject)),
        jsgraph()->HeapConstant(factory()->ReflectHas_string()), context,
        frame_state, efalse, if_false);
  }

  // Otherwise just use the existing {JSHasProperty} logic.
  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
  Node* etrue = effect;
  Node* vtrue;
  {
    // TODO(magardn): collect feedback so this can be optimized
    vtrue = etrue = if_true = graph()->NewNode(
        javascript()->HasProperty(FeedbackSource()), target, key,
        jsgraph()->UndefinedConstant(), context, frame_state, etrue, if_true);
  }

  // Rewire potential exception edges.
  Node* on_exception = nullptr;
  if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    // Create appropriate {IfException} and {IfSuccess} nodes.
    Node* extrue = graph()->NewNode(common()->IfException(), etrue, if_true);
    if_true = graph()->NewNode(common()->IfSuccess(), if_true);
    Node* exfalse = graph()->NewNode(common()->IfException(), efalse, if_false);
    if_false = graph()->NewNode(common()->IfSuccess(), if_false);

    // Join the exception edges.
    Node* merge = graph()->NewNode(common()->Merge(2), extrue, exfalse);
    Node* ephi =
        graph()->NewNode(common()->EffectPhi(2), extrue, exfalse, merge);
    Node* phi =
        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                         extrue, exfalse, merge);
    ReplaceWithValue(on_exception, phi, ephi, merge);
  }

  // Connect the throwing path to end.
  if_false = graph()->NewNode(common()->Throw(), efalse, if_false);
  NodeProperties::MergeControlToEnd(graph(), common(), if_false);

  // Continue on the regular path.
  ReplaceWithValue(node, vtrue, etrue, if_true);
  return Changed(vtrue);
}

namespace {
bool CanInlineArrayIteratingBuiltin(JSHeapBroker* broker,
                                    MapHandles const& receiver_maps,
                                    ElementsKind* kind_return) {
  DCHECK_NE(0, receiver_maps.size());
  *kind_return = MapRef(broker, receiver_maps[0]).elements_kind();
  for (auto receiver_map : receiver_maps) {
    MapRef map(broker, receiver_map);
    if (!map.supports_fast_array_iteration() ||
        !UnionElementsKindUptoSize(kind_return, map.elements_kind())) {
      return false;
    }
  }
  return true;
}

bool CanInlineArrayResizingBuiltin(JSHeapBroker* broker,
                                   MapHandles const& receiver_maps,
                                   std::vector<ElementsKind>* kinds,
                                   bool builtin_is_push = false) {
  DCHECK_NE(0, receiver_maps.size());
  for (auto receiver_map : receiver_maps) {
    MapRef map(broker, receiver_map);
    if (!map.supports_fast_array_resize()) return false;
    // TODO(turbofan): We should also handle fast holey double elements once
    // we got the hole NaN mess sorted out in TurboFan/V8.
    if (map.elements_kind() == HOLEY_DOUBLE_ELEMENTS && !builtin_is_push) {
      return false;
    }
    ElementsKind current_kind = map.elements_kind();
    auto kind_ptr = kinds->data();
    size_t i;
    for (i = 0; i < kinds->size(); i++, kind_ptr++) {
      if (UnionElementsKindUptoPackedness(kind_ptr, current_kind)) {
        break;
      }
    }
    if (i == kinds->size()) kinds->push_back(current_kind);
  }
  return true;
}

// Wraps common setup code for iterating array builtins.
class IteratingArrayBuiltinHelper {
 public:
  IteratingArrayBuiltinHelper(Node* node, JSHeapBroker* broker,
                              JSGraph* jsgraph,
                              CompilationDependencies* dependencies)
      : receiver_(NodeProperties::GetValueInput(node, 1)),
        effect_(NodeProperties::GetEffectInput(node)),
        control_(NodeProperties::GetControlInput(node)),
        inference_(broker, receiver_, effect_) {
    if (!FLAG_turbo_inline_array_builtins) return;

    DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
    const CallParameters& p = CallParametersOf(node->op());
    if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
      return;
    }

    // Try to determine the {receiver} map.
    if (!inference_.HaveMaps()) return;
    MapHandles const& receiver_maps = inference_.GetMaps();

    if (!CanInlineArrayIteratingBuiltin(broker, receiver_maps,
                                        &elements_kind_)) {
      return;
    }

    // TODO(jgruber): May only be needed for holey elements kinds.
    if (!dependencies->DependOnNoElementsProtector()) UNREACHABLE();
    has_stability_dependency_ = inference_.RelyOnMapsPreferStability(
        dependencies, jsgraph, &effect_, control_, p.feedback());

    can_reduce_ = true;
  }

  bool can_reduce() const { return can_reduce_; }
  bool has_stability_dependency() const { return has_stability_dependency_; }
  Effect effect() const { return effect_; }
  Control control() const { return control_; }
  MapInference* inference() { return &inference_; }
  ElementsKind elements_kind() const { return elements_kind_; }

 private:
  bool can_reduce_ = false;
  bool has_stability_dependency_ = false;
  Node* receiver_;
  Effect effect_;
  Control control_;
  MapInference inference_;
  ElementsKind elements_kind_;
};

}  // namespace

Reduction JSCallReducer::ReduceArrayForEach(
    Node* node, const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());
  TNode<Object> subgraph = a.ReduceArrayPrototypeForEach(
      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayReduce(
    Node* node, const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());
  TNode<Object> subgraph = a.ReduceArrayPrototypeReduce(
      h.inference(), h.has_stability_dependency(), h.elements_kind(),
      ArrayReduceDirection::kLeft, shared);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayReduceRight(
    Node* node, const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());
  TNode<Object> subgraph = a.ReduceArrayPrototypeReduce(
      h.inference(), h.has_stability_dependency(), h.elements_kind(),
      ArrayReduceDirection::kRight, shared);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayMap(Node* node,
                                        const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  // Calls CreateArray and thus requires this additional protector dependency.
  if (!dependencies()->DependOnArraySpeciesProtector()) {
    return h.inference()->NoChange();
  }

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph =
      a.ReduceArrayPrototypeMap(h.inference(), h.has_stability_dependency(),
                                h.elements_kind(), shared, native_context());
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayFilter(
    Node* node, const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  // Calls CreateArray and thus requires this additional protector dependency.
  if (!dependencies()->DependOnArraySpeciesProtector()) {
    return h.inference()->NoChange();
  }

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph =
      a.ReduceArrayPrototypeFilter(h.inference(), h.has_stability_dependency(),
                                   h.elements_kind(), shared, native_context());
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayFind(Node* node,
                                         const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph = a.ReduceArrayPrototypeFind(
      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
      native_context(), ArrayFindVariant::kFind);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayFindIndex(
    Node* node, const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph = a.ReduceArrayPrototypeFind(
      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
      native_context(), ArrayFindVariant::kFindIndex);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArrayEvery(Node* node,
                                          const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph = a.ReduceArrayPrototypeEverySome(
      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
      native_context(), ArrayEverySomeVariant::kEvery);
  return ReplaceWithSubgraph(&a, subgraph);
}

// ES7 Array.prototype.inludes(searchElement[, fromIndex])
// #sec-array.prototype.includes
Reduction JSCallReducer::ReduceArrayIncludes(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph = a.ReduceArrayPrototypeIndexOfIncludes(
      h.elements_kind(), ArrayIndexOfIncludesVariant::kIncludes);
  return ReplaceWithSubgraph(&a, subgraph);
}

// ES6 Array.prototype.indexOf(searchElement[, fromIndex])
// #sec-array.prototype.indexof
Reduction JSCallReducer::ReduceArrayIndexOf(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph = a.ReduceArrayPrototypeIndexOfIncludes(
      h.elements_kind(), ArrayIndexOfIncludesVariant::kIndexOf);
  return ReplaceWithSubgraph(&a, subgraph);
}

Reduction JSCallReducer::ReduceArraySome(Node* node,
                                         const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());
  IteratingArrayBuiltinHelper h(node, broker(), jsgraph(), dependencies());
  if (!h.can_reduce()) return h.inference()->NoChange();

  IteratingArrayBuiltinReducerAssembler a(this, node);
  a.InitializeEffectControl(h.effect(), h.control());

  TNode<Object> subgraph = a.ReduceArrayPrototypeEverySome(
      h.inference(), h.has_stability_dependency(), h.elements_kind(), shared,
      native_context(), ArrayEverySomeVariant::kSome);
  return ReplaceWithSubgraph(&a, subgraph);
}

#ifndef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
namespace {
bool HasFPParamsInSignature(const CFunctionInfo* c_signature) {
  for (unsigned int i = 0; i < c_signature->ArgumentCount(); ++i) {
    if (c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kFloat32 ||
        c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kFloat64) {
      return true;
    }
  }
  return false;
}
}  // namespace
#endif

#ifndef V8_TARGET_ARCH_64_BIT
namespace {
bool Has64BitIntegerParamsInSignature(const CFunctionInfo* c_signature) {
  for (unsigned int i = 0; i < c_signature->ArgumentCount(); ++i) {
    if (c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kInt64 ||
        c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kUint64) {
      return true;
    }
  }
  return false;
}
}  // namespace
#endif

bool CanOptimizeFastCall(
    const FunctionTemplateInfoRef& function_template_info) {
  const CFunctionInfo* c_signature = function_template_info.c_signature();

  bool optimize_to_fast_call =
      FLAG_turbo_fast_api_calls &&
      function_template_info.c_function() != kNullAddress;
#ifndef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
  optimize_to_fast_call =
      optimize_to_fast_call && !HasFPParamsInSignature(c_signature);
#else
  USE(c_signature);
#endif
#ifndef V8_TARGET_ARCH_64_BIT
  optimize_to_fast_call =
      optimize_to_fast_call && !Has64BitIntegerParamsInSignature(c_signature);
#endif
  return optimize_to_fast_call;
}

Reduction JSCallReducer::ReduceCallApiFunction(
    Node* node, const SharedFunctionInfoRef& shared) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  int const argc = p.arity_without_implicit_args();
  Node* target = n.target();
  Node* global_proxy =
      jsgraph()->Constant(native_context().global_proxy_object());
  Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
                       ? global_proxy
                       : n.receiver();
  Node* holder;
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();
  FrameState frame_state = n.frame_state();

  if (!shared.function_template_info().has_value()) {
    TRACE_BROKER_MISSING(
        broker(), "FunctionTemplateInfo for function with SFI " << shared);
    return NoChange();
  }

  // See if we can optimize this API call to {shared}.
  FunctionTemplateInfoRef function_template_info(
      shared.function_template_info().value());

  if (!function_template_info.has_call_code()) return NoChange();

  if (function_template_info.accept_any_receiver() &&
      function_template_info.is_signature_undefined()) {
    // We might be able to
    // optimize the API call depending on the {function_template_info}.
    // If the API function accepts any kind of {receiver}, we only need to
    // ensure that the {receiver} is actually a JSReceiver at this point,
    // and also pass that as the {holder}. There are two independent bits
    // here:
    //
    //  a. When the "accept any receiver" bit is set, it means we don't
    //     need to perform access checks, even if the {receiver}'s map
    //     has the "needs access check" bit set.
    //  b. When the {function_template_info} has no signature, we don't
    //     need to do the compatible receiver check, since all receivers
    //     are considered compatible at that point, and the {receiver}
    //     will be pass as the {holder}.
    //
    receiver = holder = effect =
        graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()),
                         receiver, global_proxy, effect, control);
  } else {
    // Try to infer the {receiver} maps from the graph.
    MapInference inference(broker(), receiver, effect);
    if (inference.HaveMaps()) {
      MapHandles const& receiver_maps = inference.GetMaps();
      MapRef first_receiver_map(broker(), receiver_maps[0]);

      // See if we can constant-fold the compatible receiver checks.
      HolderLookupResult api_holder =
          function_template_info.LookupHolderOfExpectedType(first_receiver_map);
      if (api_holder.lookup == CallOptimization::kHolderNotFound) {
        return inference.NoChange();
      }

      // Check that all {receiver_maps} are actually JSReceiver maps and
      // that the {function_template_info} accepts them without access
      // checks (even if "access check needed" is set for {receiver}).
      //
      // Note that we don't need to know the concrete {receiver} maps here,
      // meaning it's fine if the {receiver_maps} are unreliable, and we also
      // don't need to install any stability dependencies, since the only
      // relevant information regarding the {receiver} is the Map::constructor
      // field on the root map (which is different from the JavaScript exposed
      // "constructor" property) and that field cannot change.
      //
      // So if we know that {receiver} had a certain constructor at some point
      // in the past (i.e. it had a certain map), then this constructor is going
      // to be the same later, since this information cannot change with map
      // transitions.
      //
      // The same is true for the instance type, e.g. we still know that the
      // instance type is JSObject even if that information is unreliable, and
      // the "access check needed" bit, which also cannot change later.
      CHECK(first_receiver_map.IsJSReceiverMap());
      CHECK(!first_receiver_map.is_access_check_needed() ||
            function_template_info.accept_any_receiver());

      for (size_t i = 1; i < receiver_maps.size(); ++i) {
        MapRef receiver_map(broker(), receiver_maps[i]);
        HolderLookupResult holder_i =
            function_template_info.LookupHolderOfExpectedType(receiver_map);

        if (api_holder.lookup != holder_i.lookup) return inference.NoChange();
        DCHECK(holder_i.lookup == CallOptimization::kHolderFound ||
               holder_i.lookup == CallOptimization::kHolderIsReceiver);
        if (holder_i.lookup == CallOptimization::kHolderFound) {
          DCHECK(api_holder.holder.has_value() && holder_i.holder.has_value());
          if (!api_holder.holder->equals(*holder_i.holder)) {
            return inference.NoChange();
          }
        }

        CHECK(receiver_map.IsJSReceiverMap());
        CHECK(!receiver_map.is_access_check_needed() ||
              function_template_info.accept_any_receiver());
      }

      if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation &&
          !inference.RelyOnMapsViaStability(dependencies())) {
        // We were not able to make the receiver maps reliable without map
        // checks but doing map checks would lead to deopt loops, so give up.
        return inference.NoChange();
      }

      // TODO(neis): The maps were used in a way that does not actually require
      // map checks or stability dependencies.
      inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                          control, p.feedback());

      // Determine the appropriate holder for the {lookup}.
      holder = api_holder.lookup == CallOptimization::kHolderFound
                   ? jsgraph()->Constant(*api_holder.holder)
                   : receiver;
    } else {
      // We don't have enough information to eliminate the access check
      // and/or the compatible receiver check, so use the generic builtin
      // that does those checks dynamically. This is still significantly
      // faster than the generic call sequence.
      Builtins::Name builtin_name;
      if (function_template_info.accept_any_receiver()) {
        builtin_name = Builtins::kCallFunctionTemplate_CheckCompatibleReceiver;
      } else if (function_template_info.is_signature_undefined()) {
        builtin_name = Builtins::kCallFunctionTemplate_CheckAccess;
      } else {
        builtin_name =
            Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver;
      }

      // The CallFunctionTemplate builtin requires the {receiver} to be
      // an actual JSReceiver, so make sure we do the proper conversion
      // first if necessary.
      receiver = holder = effect =
          graph()->NewNode(simplified()->ConvertReceiver(p.convert_mode()),
                           receiver, global_proxy, effect, control);

      Callable callable = Builtins::CallableFor(isolate(), builtin_name);
      auto call_descriptor = Linkage::GetStubCallDescriptor(
          graph()->zone(), callable.descriptor(),
          argc + 1 /* implicit receiver */, CallDescriptor::kNeedsFrameState);
      node->RemoveInput(n.FeedbackVectorIndex());
      node->InsertInput(graph()->zone(), 0,
                        jsgraph()->HeapConstant(callable.code()));
      node->ReplaceInput(1, jsgraph()->Constant(function_template_info));
      node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(argc));
      node->ReplaceInput(3, receiver);       // Update receiver input.
      node->ReplaceInput(6 + argc, effect);  // Update effect input.
      NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
      return Changed(node);
    }
  }

  // TODO(turbofan): Consider introducing a JSCallApiCallback operator for
  // this and lower it during JSGenericLowering, and unify this with the
  // JSNativeContextSpecialization::InlineApiCall method a bit.
  if (!function_template_info.call_code().has_value()) {
    TRACE_BROKER_MISSING(broker(), "call code for function template info "
                                       << function_template_info);
    return NoChange();
  }

  if (CanOptimizeFastCall(function_template_info)) {
    FastApiCallReducerAssembler a(this, node, function_template_info, receiver,
                                  holder, shared, target, argc, effect);
    Node* fast_call_subgraph = a.ReduceFastApiCall();
    ReplaceWithSubgraph(&a, fast_call_subgraph);

    return Replace(fast_call_subgraph);
  }

  CallHandlerInfoRef call_handler_info = *function_template_info.call_code();
  Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
  CallInterfaceDescriptor cid = call_api_callback.descriptor();
  auto call_descriptor =
      Linkage::GetStubCallDescriptor(graph()->zone(), cid, argc + 1 /*
     implicit receiver */, CallDescriptor::kNeedsFrameState);
  ApiFunction api_function(call_handler_info.callback());
  ExternalReference function_reference = ExternalReference::Create(
      &api_function, ExternalReference::DIRECT_API_CALL);

  Node* continuation_frame_state = CreateGenericLazyDeoptContinuationFrameState(
      jsgraph(), shared, target, context, receiver, frame_state);

  node->RemoveInput(n.FeedbackVectorIndex());
  node->InsertInput(graph()->zone(), 0,
                    jsgraph()->HeapConstant(call_api_callback.code()));
  node->ReplaceInput(1, jsgraph()->ExternalConstant(function_reference));
  node->InsertInput(graph()->zone(), 2, jsgraph()->Constant(argc));
  node->InsertInput(graph()->zone(), 3,
                    jsgraph()->Constant(call_handler_info.data()));
  node->InsertInput(graph()->zone(), 4, holder);
  node->ReplaceInput(5, receiver);  // Update receiver input.
  // 6 + argc is context input.
  node->ReplaceInput(6 + argc + 1, continuation_frame_state);
  node->ReplaceInput(6 + argc + 2, effect);
  NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
  return Changed(node);
}

namespace {

// Check whether elements aren't mutated; we play it extremely safe here by
// explicitly checking that {node} is only used by {LoadField} or
// {LoadElement}.
bool IsSafeArgumentsElements(Node* node) {
  for (Edge const edge : node->use_edges()) {
    if (!NodeProperties::IsValueEdge(edge)) continue;
    if (edge.from()->opcode() != IrOpcode::kLoadField &&
        edge.from()->opcode() != IrOpcode::kLoadElement) {
      return false;
    }
  }
  return true;
}

#ifdef DEBUG
bool IsCallOrConstructWithArrayLike(Node* node) {
  return node->opcode() == IrOpcode::kJSCallWithArrayLike ||
         node->opcode() == IrOpcode::kJSConstructWithArrayLike;
}
#endif

bool IsCallOrConstructWithSpread(Node* node) {
  return node->opcode() == IrOpcode::kJSCallWithSpread ||
         node->opcode() == IrOpcode::kJSConstructWithSpread;
}

bool IsCallWithArrayLikeOrSpread(Node* node) {
  return node->opcode() == IrOpcode::kJSCallWithArrayLike ||
         node->opcode() == IrOpcode::kJSCallWithSpread;
}

}  // namespace

Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
    Node* node, int arraylike_or_spread_index, CallFrequency const& frequency,
    FeedbackSource const& feedback, SpeculationMode speculation_mode,
    CallFeedbackRelation feedback_relation) {
  DCHECK(IsCallOrConstructWithArrayLike(node) ||
         IsCallOrConstructWithSpread(node));
  DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
                 feedback.IsValid());

  Node* arguments_list =
      NodeProperties::GetValueInput(node, arraylike_or_spread_index);
  if (arguments_list->opcode() != IrOpcode::kJSCreateArguments) {
    return NoChange();
  }

  // Check if {node} is the only value user of {arguments_list} (except for
  // value uses in frame states). If not, we give up for now.
  for (Edge edge : arguments_list->use_edges()) {
    if (!NodeProperties::IsValueEdge(edge)) continue;
    Node* const user = edge.from();
    switch (user->opcode()) {
      case IrOpcode::kCheckMaps:
      case IrOpcode::kFrameState:
      case IrOpcode::kStateValues:
      case IrOpcode::kReferenceEqual:
      case IrOpcode::kReturn:
        // Ignore safe uses that definitely don't mess with the arguments.
        continue;
      case IrOpcode::kLoadField: {
        DCHECK_EQ(arguments_list, user->InputAt(0));
        FieldAccess const& access = FieldAccessOf(user->op());
        if (access.offset == JSArray::kLengthOffset) {
          // Ignore uses for arguments#length.
          STATIC_ASSERT(
              static_cast<int>(JSArray::kLengthOffset) ==
              static_cast<int>(JSStrictArgumentsObject::kLengthOffset));
          STATIC_ASSERT(
              static_cast<int>(JSArray::kLengthOffset) ==
              static_cast<int>(JSSloppyArgumentsObject::kLengthOffset));
          continue;
        } else if (access.offset == JSObject::kElementsOffset) {
          // Ignore safe uses for arguments#elements.
          if (IsSafeArgumentsElements(user)) continue;
        }
        break;
      }
      case IrOpcode::kJSCallWithArrayLike: {
        // Ignore uses as argumentsList input to calls with array like.
        JSCallWithArrayLikeNode n(user);
        if (n.Argument(0) == arguments_list) continue;
        break;
      }
      case IrOpcode::kJSConstructWithArrayLike: {
        // Ignore uses as argumentsList input to calls with array like.
        JSConstructWithArrayLikeNode n(user);
        if (n.Argument(0) == arguments_list) continue;
        break;
      }
      case IrOpcode::kJSCallWithSpread: {
        // Ignore uses as spread input to calls with spread.
        JSCallWithSpreadNode n(user);
        if (n.LastArgument() == arguments_list) continue;
        break;
      }
      case IrOpcode::kJSConstructWithSpread: {
        // Ignore uses as spread input to construct with spread.
        JSConstructWithSpreadNode n(user);
        if (n.LastArgument() == arguments_list) continue;
        break;
      }
      default:
        break;
    }
    // We cannot currently reduce the {node} to something better than what
    // it already is, but we might be able to do something about the {node}
    // later, so put it on the waitlist and try again during finalization.
    waitlist_.insert(node);
    return NoChange();
  }

  // Get to the actual frame state from which to extract the arguments;
  // we can only optimize this in case the {node} was already inlined into
  // some other function (and same for the {arguments_list}).
  CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op());
  Node* frame_state = NodeProperties::GetFrameStateInput(arguments_list);
  FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
  int start_index = 0;

  int formal_parameter_count;
  {
    Handle<SharedFunctionInfo> shared;
    if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
    formal_parameter_count = SharedFunctionInfoRef(broker(), shared)
                                 .internal_formal_parameter_count();
  }

  if (type == CreateArgumentsType::kMappedArguments) {
    // Mapped arguments (sloppy mode) that are aliased can only be handled
    // here if there's no side-effect between the {node} and the {arg_array}.
    // TODO(turbofan): Further relax this constraint.
    if (formal_parameter_count != 0) {
      Node* effect = NodeProperties::GetEffectInput(node);
      if (!NodeProperties::NoObservableSideEffectBetween(effect,
                                                         arguments_list)) {
        return NoChange();
      }
    }
  } else if (type == CreateArgumentsType::kRestParameter) {
    start_index = formal_parameter_count;
  }

  // TODO(jgruber,v8:8888): Attempt to remove this restriction. The reason it
  // currently exists is because we cannot create code dependencies in NCI code.
  if (broker()->is_native_context_independent()) return NoChange();

  // For call/construct with spread, we need to also install a code
  // dependency on the array iterator lookup protector cell to ensure
  // that no one messed with the %ArrayIteratorPrototype%.next method.
  if (IsCallOrConstructWithSpread(node)) {
    if (!dependencies()->DependOnArrayIteratorProtector()) return NoChange();
  }

  // Remove the {arguments_list} input from the {node}.
  node->RemoveInput(arraylike_or_spread_index);

  // After removing the arraylike or spread object, the argument count is:
  int argc =
      arraylike_or_spread_index - JSCallOrConstructNode::FirstArgumentIndex();
  // Check if are spreading to inlined arguments or to the arguments of
  // the outermost function.
  Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
  if (outer_state->opcode() != IrOpcode::kFrameState) {
    Operator const* op;
    if (IsCallWithArrayLikeOrSpread(node)) {
      static constexpr int kTargetAndReceiver = 2;
      op = javascript()->CallForwardVarargs(argc + kTargetAndReceiver,
                                            start_index);
    } else {
      static constexpr int kTargetAndNewTarget = 2;
      op = javascript()->ConstructForwardVarargs(argc + kTargetAndNewTarget,
                                                 start_index);
    }
    node->RemoveInput(JSCallOrConstructNode::FeedbackVectorIndexForArgc(argc));
    NodeProperties::ChangeOp(node, op);
    return Changed(node);
  }
  // Get to the actual frame state from which to extract the arguments;
  // we can only optimize this in case the {node} was already inlined into
  // some other function (and same for the {arg_array}).
  FrameStateInfo outer_info = FrameStateInfoOf(outer_state->op());
  if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
    // Need to take the parameters from the arguments adaptor.
    frame_state = outer_state;
  }
  // Add the actual parameters to the {node}, skipping the receiver.
  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
  for (int i = start_index + 1; i < parameters->InputCount(); ++i) {
    node->InsertInput(graph()->zone(),
                      JSCallOrConstructNode::ArgumentIndex(argc++),
                      parameters->InputAt(i));
  }

  if (IsCallWithArrayLikeOrSpread(node)) {
    NodeProperties::ChangeOp(
        node,
        javascript()->Call(JSCallNode::ArityForArgc(argc), frequency, feedback,
                           ConvertReceiverMode::kAny, speculation_mode,
                           CallFeedbackRelation::kUnrelated));
    return Changed(node).FollowedBy(ReduceJSCall(node));
  } else {
    NodeProperties::ChangeOp(
        node, javascript()->Construct(JSConstructNode::ArityForArgc(argc),
                                      frequency, feedback));

    JSConstructNode n(node);
    Node* new_target = n.new_target();
    FrameState frame_state = n.frame_state();
    Node* context = n.context();
    Effect effect = n.effect();
    Control control = n.control();

    // Check whether the given new target value is a constructor function. The
    // replacement {JSConstruct} operator only checks the passed target value
    // but relies on the new target value to be implicitly valid.
    Node* check =
        graph()->NewNode(simplified()->ObjectIsConstructor(), new_target);
    Node* check_branch =
        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
    Node* check_fail = graph()->NewNode(common()->IfFalse(), check_branch);
    Node* check_throw = check_fail = graph()->NewNode(
        javascript()->CallRuntime(Runtime::kThrowTypeError, 2),
        jsgraph()->Constant(static_cast<int>(MessageTemplate::kNotConstructor)),
        new_target, context, frame_state, effect, check_fail);
    control = graph()->NewNode(common()->IfTrue(), check_branch);
    NodeProperties::ReplaceControlInput(node, control);

    // Rewire potential exception edges.
    Node* on_exception = nullptr;
    if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
      // Create appropriate {IfException}  and {IfSuccess} nodes.
      Node* if_exception =
          graph()->NewNode(common()->IfException(), check_throw, check_fail);
      check_fail = graph()->NewNode(common()->IfSuccess(), check_fail);

      // Join the exception edges.
      Node* merge =
          graph()->NewNode(common()->Merge(2), if_exception, on_exception);
      Node* ephi = graph()->NewNode(common()->EffectPhi(2), if_exception,
                                    on_exception, merge);
      Node* phi =
          graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                           if_exception, on_exception, merge);
      ReplaceWithValue(on_exception, phi, ephi, merge);
      merge->ReplaceInput(1, on_exception);
      ephi->ReplaceInput(1, on_exception);
      phi->ReplaceInput(1, on_exception);
    }

    // The above %ThrowTypeError runtime call is an unconditional throw,
    // making it impossible to return a successful completion in this case. We
    // simply connect the successful completion to the graph end.
    Node* throw_node =
        graph()->NewNode(common()->Throw(), check_throw, check_fail);
    NodeProperties::MergeControlToEnd(graph(), common(), throw_node);

    return Changed(node).FollowedBy(ReduceJSConstruct(node));
  }
}

namespace {

bool ShouldUseCallICFeedback(Node* node) {
  HeapObjectMatcher m(node);
  if (m.HasResolvedValue() || m.IsCheckClosure() || m.IsJSCreateClosure()) {
    // Don't use CallIC feedback when we know the function
    // being called, i.e. either know the closure itself or
    // at least the SharedFunctionInfo.
    return false;
  } else if (m.IsPhi()) {
    // Protect against endless loops here.
    Node* control = NodeProperties::GetControlInput(node);
    if (control->opcode() == IrOpcode::kLoop) return false;
    // Check if {node} is a Phi of nodes which shouldn't
    // use CallIC feedback (not looking through loops).
    int const value_input_count = m.node()->op()->ValueInputCount();
    for (int n = 0; n < value_input_count; ++n) {
      if (ShouldUseCallICFeedback(node->InputAt(n))) return true;
    }
    return false;
  }
  return true;
}

}  // namespace

bool JSCallReducer::IsBuiltinOrApiFunction(JSFunctionRef function) const {
  if (should_disallow_heap_access() && !function.serialized()) {
    TRACE_BROKER_MISSING(broker(), "data for function " << function);
    return false;
  }

  // TODO(neis): Add a way to check if function template info isn't serialized
  // and add a warning in such cases. Currently we can't tell if function
  // template info doesn't exist or wasn't serialized.
  return function.shared().HasBuiltinId() ||
         function.shared().function_template_info().has_value();
}

Reduction JSCallReducer::ReduceJSCall(Node* node) {
  if (broker()->StackHasOverflowed()) return NoChange();

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  Node* target = n.target();
  Effect effect = n.effect();
  Control control = n.control();
  int arity = p.arity_without_implicit_args();

  // Try to specialize JSCall {node}s with constant {target}s.
  HeapObjectMatcher m(target);
  if (m.HasResolvedValue()) {
    ObjectRef target_ref = m.Ref(broker());
    if (target_ref.IsJSFunction()) {
      JSFunctionRef function = target_ref.AsJSFunction();
      if (should_disallow_heap_access() && !function.serialized()) {
        TRACE_BROKER_MISSING(broker(), "data for function " << function);
        return NoChange();
      }

      // Don't inline cross native context.
      if (!function.native_context().equals(native_context())) {
        return NoChange();
      }

      return ReduceJSCall(node, function.shared());
    } else if (target_ref.IsJSBoundFunction()) {
      JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
      if (should_disallow_heap_access() && !function.serialized()) {
        TRACE_BROKER_MISSING(broker(), "data for function " << function);
        return NoChange();
      }

      ObjectRef bound_this = function.bound_this();
      ConvertReceiverMode const convert_mode =
          bound_this.IsNullOrUndefined()
              ? ConvertReceiverMode::kNullOrUndefined
              : ConvertReceiverMode::kNotNullOrUndefined;

      // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
      NodeProperties::ReplaceValueInput(
          node, jsgraph()->Constant(function.bound_target_function()),
          JSCallNode::TargetIndex());
      NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
                                        JSCallNode::ReceiverIndex());

      // Insert the [[BoundArguments]] for {node}.
      FixedArrayRef bound_arguments = function.bound_arguments();
      for (int i = 0; i < bound_arguments.length(); ++i) {
        node->InsertInput(graph()->zone(), i + 2,
                          jsgraph()->Constant(bound_arguments.get(i)));
        arity++;
      }

      NodeProperties::ChangeOp(
          node,
          javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
                             p.feedback(), convert_mode, p.speculation_mode(),
                             CallFeedbackRelation::kUnrelated));

      // Try to further reduce the JSCall {node}.
      return Changed(node).FollowedBy(ReduceJSCall(node));
    }

    // Don't mess with other {node}s that have a constant {target}.
    // TODO(bmeurer): Also support proxies here.
    return NoChange();
  }

  // If {target} is the result of a JSCreateClosure operation, we can
  // just immediately try to inline based on the SharedFunctionInfo,
  // since TurboFan generally doesn't inline cross-context, and hence
  // the {target} must have the same native context as the call site.
  // Same if the {target} is the result of a CheckClosure operation.
  if (target->opcode() == IrOpcode::kJSCreateClosure) {
    CreateClosureParameters const& p = JSCreateClosureNode{target}.Parameters();
    return ReduceJSCall(node, SharedFunctionInfoRef(broker(), p.shared_info()));
  } else if (target->opcode() == IrOpcode::kCheckClosure) {
    FeedbackCellRef cell(broker(), FeedbackCellOf(target->op()));
    return ReduceJSCall(node,
                        cell.value().AsFeedbackVector().shared_function_info());
  }

  // If {target} is the result of a JSCreateBoundFunction operation,
  // we can just fold the construction and call the bound target
  // function directly instead.
  if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
    Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
    Node* bound_this = NodeProperties::GetValueInput(target, 1);
    int const bound_arguments_length =
        static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());

    // Patch the {node} to use [[BoundTargetFunction]] and [[BoundThis]].
    NodeProperties::ReplaceValueInput(node, bound_target_function,
                                      n.TargetIndex());
    NodeProperties::ReplaceValueInput(node, bound_this, n.ReceiverIndex());

    // Insert the [[BoundArguments]] for {node}.
    for (int i = 0; i < bound_arguments_length; ++i) {
      Node* value = NodeProperties::GetValueInput(target, 2 + i);
      node->InsertInput(graph()->zone(), n.ArgumentIndex(i), value);
      arity++;
    }

    // Update the JSCall operator on {node}.
    ConvertReceiverMode const convert_mode =
        NodeProperties::CanBeNullOrUndefined(broker(), bound_this, effect)
            ? ConvertReceiverMode::kAny
            : ConvertReceiverMode::kNotNullOrUndefined;
    NodeProperties::ChangeOp(
        node,
        javascript()->Call(JSCallNode::ArityForArgc(arity), p.frequency(),
                           p.feedback(), convert_mode, p.speculation_mode(),
                           CallFeedbackRelation::kUnrelated));

    // Try to further reduce the JSCall {node}.
    return Changed(node).FollowedBy(ReduceJSCall(node));
  }

  if (!ShouldUseCallICFeedback(target) ||
      p.feedback_relation() != CallFeedbackRelation::kRelated ||
      !p.feedback().IsValid()) {
    return NoChange();
  }

  ProcessedFeedback const& feedback =
      broker()->GetFeedbackForCall(p.feedback());
  if (feedback.IsInsufficient()) {
    return ReduceForInsufficientFeedback(
        node, DeoptimizeReason::kInsufficientTypeFeedbackForCall);
  }

  base::Optional<HeapObjectRef> feedback_target = feedback.AsCall().target();
  if (feedback_target.has_value() && feedback_target->map().is_callable()) {
    Node* target_function = jsgraph()->Constant(*feedback_target);

    if (broker()->is_turboprop()) {
      if (!feedback_target->IsJSFunction()) return NoChange();
      if (!IsBuiltinOrApiFunction(feedback_target->AsJSFunction())) {
        return NoChange();
      }
    }

    // Check that the {target} is still the {target_function}.
    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
                                   target_function);
    effect = graph()->NewNode(
        simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
        effect, control);

    // Specialize the JSCall node to the {target_function}.
    NodeProperties::ReplaceValueInput(node, target_function, n.TargetIndex());
    NodeProperties::ReplaceEffectInput(node, effect);

    // Try to further reduce the JSCall {node}.
    return Changed(node).FollowedBy(ReduceJSCall(node));
  } else if (feedback_target.has_value() && feedback_target->IsFeedbackCell()) {
    FeedbackCellRef feedback_cell(
        broker(), feedback_target.value().AsFeedbackCell().object());
    if (feedback_cell.value().IsFeedbackVector()) {
      // Check that {target} is a closure with given {feedback_cell},
      // which uniquely identifies a given function inside a native context.
      FeedbackVectorRef feedback_vector =
          feedback_cell.value().AsFeedbackVector();
      if (!feedback_vector.serialized()) {
        TRACE_BROKER_MISSING(
            broker(), "feedback vector, not serialized: " << feedback_vector);
        return NoChange();
      }

      if (broker()->is_turboprop() &&
          !feedback_vector.shared_function_info().HasBuiltinId()) {
        return NoChange();
      }

      Node* target_closure = effect =
          graph()->NewNode(simplified()->CheckClosure(feedback_cell.object()),
                           target, effect, control);

      // Specialize the JSCall node to the {target_closure}.
      NodeProperties::ReplaceValueInput(node, target_closure, n.TargetIndex());
      NodeProperties::ReplaceEffectInput(node, effect);

      // Try to further reduce the JSCall {node}.
      return Changed(node).FollowedBy(ReduceJSCall(node));
    }
  }
  return NoChange();
}

Reduction JSCallReducer::ReduceJSCall(Node* node,
                                      const SharedFunctionInfoRef& shared) {
  JSCallNode n(node);
  Node* target = n.target();

  // Do not reduce calls to functions with break points.
  if (shared.HasBreakInfo()) return NoChange();

  // Raise a TypeError if the {target} is a "classConstructor".
  if (IsClassConstructor(shared.kind())) {
    NodeProperties::ReplaceValueInputs(node, target);
    NodeProperties::ChangeOp(
        node, javascript()->CallRuntime(
                  Runtime::kThrowConstructorNonCallableError, 1));
    return Changed(node);
  }

  // Check for known builtin functions.

  int builtin_id =
      shared.HasBuiltinId() ? shared.builtin_id() : Builtins::kNoBuiltinId;
  switch (builtin_id) {
    case Builtins::kArrayConstructor:
      return ReduceArrayConstructor(node);
    case Builtins::kBooleanConstructor:
      return ReduceBooleanConstructor(node);
    case Builtins::kFunctionPrototypeApply:
      return ReduceFunctionPrototypeApply(node);
    case Builtins::kFastFunctionPrototypeBind:
      return ReduceFunctionPrototypeBind(node);
    case Builtins::kFunctionPrototypeCall:
      return ReduceFunctionPrototypeCall(node);
    case Builtins::kFunctionPrototypeHasInstance:
      return ReduceFunctionPrototypeHasInstance(node);
    case Builtins::kObjectConstructor:
      return ReduceObjectConstructor(node);
    case Builtins::kObjectCreate:
      return ReduceObjectCreate(node);
    case Builtins::kObjectGetPrototypeOf:
      return ReduceObjectGetPrototypeOf(node);
    case Builtins::kObjectIs:
      return ReduceObjectIs(node);
    case Builtins::kObjectPrototypeGetProto:
      return ReduceObjectPrototypeGetProto(node);
    case Builtins::kObjectPrototypeHasOwnProperty:
      return ReduceObjectPrototypeHasOwnProperty(node);
    case Builtins::kObjectPrototypeIsPrototypeOf:
      return ReduceObjectPrototypeIsPrototypeOf(node);
    case Builtins::kReflectApply:
      return ReduceReflectApply(node);
    case Builtins::kReflectConstruct:
      return ReduceReflectConstruct(node);
    case Builtins::kReflectGet:
      return ReduceReflectGet(node);
    case Builtins::kReflectGetPrototypeOf:
      return ReduceReflectGetPrototypeOf(node);
    case Builtins::kReflectHas:
      return ReduceReflectHas(node);
    case Builtins::kArrayForEach:
      return ReduceArrayForEach(node, shared);
    case Builtins::kArrayMap:
      return ReduceArrayMap(node, shared);
    case Builtins::kArrayFilter:
      return ReduceArrayFilter(node, shared);
    case Builtins::kArrayReduce:
      return ReduceArrayReduce(node, shared);
    case Builtins::kArrayReduceRight:
      return ReduceArrayReduceRight(node, shared);
    case Builtins::kArrayPrototypeFind:
      return ReduceArrayFind(node, shared);
    case Builtins::kArrayPrototypeFindIndex:
      return ReduceArrayFindIndex(node, shared);
    case Builtins::kArrayEvery:
      return ReduceArrayEvery(node, shared);
    case Builtins::kArrayIndexOf:
      return ReduceArrayIndexOf(node);
    case Builtins::kArrayIncludes:
      return ReduceArrayIncludes(node);
    case Builtins::kArraySome:
      return ReduceArraySome(node, shared);
    case Builtins::kArrayPrototypePush:
      return ReduceArrayPrototypePush(node);
    case Builtins::kArrayPrototypePop:
      return ReduceArrayPrototypePop(node);
    case Builtins::kArrayPrototypeShift:
      return ReduceArrayPrototypeShift(node);
    case Builtins::kArrayPrototypeSlice:
      return ReduceArrayPrototypeSlice(node);
    case Builtins::kArrayPrototypeEntries:
      return ReduceArrayIterator(node, ArrayIteratorKind::kArrayLike,
                                 IterationKind::kEntries);
    case Builtins::kArrayPrototypeKeys:
      return ReduceArrayIterator(node, ArrayIteratorKind::kArrayLike,
                                 IterationKind::kKeys);
    case Builtins::kArrayPrototypeValues:
      return ReduceArrayIterator(node, ArrayIteratorKind::kArrayLike,
                                 IterationKind::kValues);
    case Builtins::kArrayIteratorPrototypeNext:
      return ReduceArrayIteratorPrototypeNext(node);
    case Builtins::kArrayIsArray:
      return ReduceArrayIsArray(node);
    case Builtins::kArrayBufferIsView:
      return ReduceArrayBufferIsView(node);
    case Builtins::kDataViewPrototypeGetByteLength:
      return ReduceArrayBufferViewAccessor(
          node, JS_DATA_VIEW_TYPE,
          AccessBuilder::ForJSArrayBufferViewByteLength());
    case Builtins::kDataViewPrototypeGetByteOffset:
      return ReduceArrayBufferViewAccessor(
          node, JS_DATA_VIEW_TYPE,
          AccessBuilder::ForJSArrayBufferViewByteOffset());
    case Builtins::kDataViewPrototypeGetUint8:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalUint8Array);
    case Builtins::kDataViewPrototypeGetInt8:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalInt8Array);
    case Builtins::kDataViewPrototypeGetUint16:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalUint16Array);
    case Builtins::kDataViewPrototypeGetInt16:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalInt16Array);
    case Builtins::kDataViewPrototypeGetUint32:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalUint32Array);
    case Builtins::kDataViewPrototypeGetInt32:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalInt32Array);
    case Builtins::kDataViewPrototypeGetFloat32:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalFloat32Array);
    case Builtins::kDataViewPrototypeGetFloat64:
      return ReduceDataViewAccess(node, DataViewAccess::kGet,
                                  ExternalArrayType::kExternalFloat64Array);
    case Builtins::kDataViewPrototypeSetUint8:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalUint8Array);
    case Builtins::kDataViewPrototypeSetInt8:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalInt8Array);
    case Builtins::kDataViewPrototypeSetUint16:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalUint16Array);
    case Builtins::kDataViewPrototypeSetInt16:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalInt16Array);
    case Builtins::kDataViewPrototypeSetUint32:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalUint32Array);
    case Builtins::kDataViewPrototypeSetInt32:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalInt32Array);
    case Builtins::kDataViewPrototypeSetFloat32:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalFloat32Array);
    case Builtins::kDataViewPrototypeSetFloat64:
      return ReduceDataViewAccess(node, DataViewAccess::kSet,
                                  ExternalArrayType::kExternalFloat64Array);
    case Builtins::kTypedArrayPrototypeByteLength:
      return ReduceArrayBufferViewAccessor(
          node, JS_TYPED_ARRAY_TYPE,
          AccessBuilder::ForJSArrayBufferViewByteLength());
    case Builtins::kTypedArrayPrototypeByteOffset:
      return ReduceArrayBufferViewAccessor(
          node, JS_TYPED_ARRAY_TYPE,
          AccessBuilder::ForJSArrayBufferViewByteOffset());
    case Builtins::kTypedArrayPrototypeLength:
      return ReduceArrayBufferViewAccessor(
          node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
    case Builtins::kTypedArrayPrototypeToStringTag:
      return ReduceTypedArrayPrototypeToStringTag(node);
    case Builtins::kMathAbs:
      return ReduceMathUnary(node, simplified()->NumberAbs());
    case Builtins::kMathAcos:
      return ReduceMathUnary(node, simplified()->NumberAcos());
    case Builtins::kMathAcosh:
      return ReduceMathUnary(node, simplified()->NumberAcosh());
    case Builtins::kMathAsin:
      return ReduceMathUnary(node, simplified()->NumberAsin());
    case Builtins::kMathAsinh:
      return ReduceMathUnary(node, simplified()->NumberAsinh());
    case Builtins::kMathAtan:
      return ReduceMathUnary(node, simplified()->NumberAtan());
    case Builtins::kMathAtanh:
      return ReduceMathUnary(node, simplified()->NumberAtanh());
    case Builtins::kMathCbrt:
      return ReduceMathUnary(node, simplified()->NumberCbrt());
    case Builtins::kMathCeil:
      return ReduceMathUnary(node, simplified()->NumberCeil());
    case Builtins::kMathCos:
      return ReduceMathUnary(node, simplified()->NumberCos());
    case Builtins::kMathCosh:
      return ReduceMathUnary(node, simplified()->NumberCosh());
    case Builtins::kMathExp:
      return ReduceMathUnary(node, simplified()->NumberExp());
    case Builtins::kMathExpm1:
      return ReduceMathUnary(node, simplified()->NumberExpm1());
    case Builtins::kMathFloor:
      return ReduceMathUnary(node, simplified()->NumberFloor());
    case Builtins::kMathFround:
      return ReduceMathUnary(node, simplified()->NumberFround());
    case Builtins::kMathLog:
      return ReduceMathUnary(node, simplified()->NumberLog());
    case Builtins::kMathLog1p:
      return ReduceMathUnary(node, simplified()->NumberLog1p());
    case Builtins::kMathLog10:
      return ReduceMathUnary(node, simplified()->NumberLog10());
    case Builtins::kMathLog2:
      return ReduceMathUnary(node, simplified()->NumberLog2());
    case Builtins::kMathRound:
      return ReduceMathUnary(node, simplified()->NumberRound());
    case Builtins::kMathSign:
      return ReduceMathUnary(node, simplified()->NumberSign());
    case Builtins::kMathSin:
      return ReduceMathUnary(node, simplified()->NumberSin());
    case Builtins::kMathSinh:
      return ReduceMathUnary(node, simplified()->NumberSinh());
    case Builtins::kMathSqrt:
      return ReduceMathUnary(node, simplified()->NumberSqrt());
    case Builtins::kMathTan:
      return ReduceMathUnary(node, simplified()->NumberTan());
    case Builtins::kMathTanh:
      return ReduceMathUnary(node, simplified()->NumberTanh());
    case Builtins::kMathTrunc:
      return ReduceMathUnary(node, simplified()->NumberTrunc());
    case Builtins::kMathAtan2:
      return ReduceMathBinary(node, simplified()->NumberAtan2());
    case Builtins::kMathPow:
      return ReduceMathBinary(node, simplified()->NumberPow());
    case Builtins::kMathClz32:
      return ReduceMathClz32(node);
    case Builtins::kMathImul:
      return ReduceMathImul(node);
    case Builtins::kMathMax:
      return ReduceMathMinMax(node, simplified()->NumberMax(),
                              jsgraph()->Constant(-V8_INFINITY));
    case Builtins::kMathMin:
      return ReduceMathMinMax(node, simplified()->NumberMin(),
                              jsgraph()->Constant(V8_INFINITY));
    case Builtins::kNumberIsFinite:
      return ReduceNumberIsFinite(node);
    case Builtins::kNumberIsInteger:
      return ReduceNumberIsInteger(node);
    case Builtins::kNumberIsSafeInteger:
      return ReduceNumberIsSafeInteger(node);
    case Builtins::kNumberIsNaN:
      return ReduceNumberIsNaN(node);
    case Builtins::kNumberParseInt:
      return ReduceNumberParseInt(node);
    case Builtins::kGlobalIsFinite:
      return ReduceGlobalIsFinite(node);
    case Builtins::kGlobalIsNaN:
      return ReduceGlobalIsNaN(node);
    case Builtins::kMapPrototypeGet:
      return ReduceMapPrototypeGet(node);
    case Builtins::kMapPrototypeHas:
      return ReduceMapPrototypeHas(node);
    case Builtins::kRegExpPrototypeTest:
      return ReduceRegExpPrototypeTest(node);
    case Builtins::kReturnReceiver:
      return ReduceReturnReceiver(node);
    case Builtins::kStringPrototypeIndexOf:
      return ReduceStringPrototypeIndexOf(node);
    case Builtins::kStringPrototypeCharAt:
      return ReduceStringPrototypeCharAt(node);
    case Builtins::kStringPrototypeCharCodeAt:
      return ReduceStringPrototypeStringAt(simplified()->StringCharCodeAt(),
                                           node);
    case Builtins::kStringPrototypeCodePointAt:
      return ReduceStringPrototypeStringAt(simplified()->StringCodePointAt(),
                                           node);
    case Builtins::kStringPrototypeSubstring:
      return ReduceStringPrototypeSubstring(node);
    case Builtins::kStringPrototypeSlice:
      return ReduceStringPrototypeSlice(node);
    case Builtins::kStringPrototypeSubstr:
      return ReduceStringPrototypeSubstr(node);
    case Builtins::kStringPrototypeStartsWith:
      return ReduceStringPrototypeStartsWith(node);
#ifdef V8_INTL_SUPPORT
    case Builtins::kStringPrototypeToLowerCaseIntl:
      return ReduceStringPrototypeToLowerCaseIntl(node);
    case Builtins::kStringPrototypeToUpperCaseIntl:
      return ReduceStringPrototypeToUpperCaseIntl(node);
#endif  // V8_INTL_SUPPORT
    case Builtins::kStringFromCharCode:
      return ReduceStringFromCharCode(node);
    case Builtins::kStringFromCodePoint:
      return ReduceStringFromCodePoint(node);
    case Builtins::kStringPrototypeIterator:
      return ReduceStringPrototypeIterator(node);
    case Builtins::kStringIteratorPrototypeNext:
      return ReduceStringIteratorPrototypeNext(node);
    case Builtins::kStringPrototypeConcat:
      return ReduceStringPrototypeConcat(node);
    case Builtins::kTypedArrayPrototypeEntries:
      return ReduceArrayIterator(node, ArrayIteratorKind::kTypedArray,
                                 IterationKind::kEntries);
    case Builtins::kTypedArrayPrototypeKeys:
      return ReduceArrayIterator(node, ArrayIteratorKind::kTypedArray,
                                 IterationKind::kKeys);
    case Builtins::kTypedArrayPrototypeValues:
      return ReduceArrayIterator(node, ArrayIteratorKind::kTypedArray,
                                 IterationKind::kValues);
    case Builtins::kPromisePrototypeCatch:
      return ReducePromisePrototypeCatch(node);
    case Builtins::kPromisePrototypeFinally:
      return ReducePromisePrototypeFinally(node);
    case Builtins::kPromisePrototypeThen:
      return ReducePromisePrototypeThen(node);
    case Builtins::kPromiseResolveTrampoline:
      return ReducePromiseResolveTrampoline(node);
    case Builtins::kMapPrototypeEntries:
      return ReduceCollectionIteration(node, CollectionKind::kMap,
                                       IterationKind::kEntries);
    case Builtins::kMapPrototypeKeys:
      return ReduceCollectionIteration(node, CollectionKind::kMap,
                                       IterationKind::kKeys);
    case Builtins::kMapPrototypeGetSize:
      return ReduceCollectionPrototypeSize(node, CollectionKind::kMap);
    case Builtins::kMapPrototypeValues:
      return ReduceCollectionIteration(node, CollectionKind::kMap,
                                       IterationKind::kValues);
    case Builtins::kMapIteratorPrototypeNext:
      return ReduceCollectionIteratorPrototypeNext(
          node, OrderedHashMap::kEntrySize, factory()->empty_ordered_hash_map(),
          FIRST_JS_MAP_ITERATOR_TYPE, LAST_JS_MAP_ITERATOR_TYPE);
    case Builtins::kSetPrototypeEntries:
      return ReduceCollectionIteration(node, CollectionKind::kSet,
                                       IterationKind::kEntries);
    case Builtins::kSetPrototypeGetSize:
      return ReduceCollectionPrototypeSize(node, CollectionKind::kSet);
    case Builtins::kSetPrototypeValues:
      return ReduceCollectionIteration(node, CollectionKind::kSet,
                                       IterationKind::kValues);
    case Builtins::kSetIteratorPrototypeNext:
      return ReduceCollectionIteratorPrototypeNext(
          node, OrderedHashSet::kEntrySize, factory()->empty_ordered_hash_set(),
          FIRST_JS_SET_ITERATOR_TYPE, LAST_JS_SET_ITERATOR_TYPE);
    case Builtins::kDatePrototypeGetTime:
      return ReduceDatePrototypeGetTime(node);
    case Builtins::kDateNow:
      return ReduceDateNow(node);
    case Builtins::kNumberConstructor:
      return ReduceNumberConstructor(node);
    case Builtins::kBigIntAsUintN:
      return ReduceBigIntAsUintN(node);
    default:
      break;
  }

  if (shared.function_template_info().has_value()) {
    return ReduceCallApiFunction(node, shared);
  }
  return NoChange();
}

Reduction JSCallReducer::ReduceJSCallWithArrayLike(Node* node) {
  JSCallWithArrayLikeNode n(node);
  CallParameters const& p = n.Parameters();
  DCHECK_EQ(p.arity_without_implicit_args(), 1);  // The arraylike object.
  return ReduceCallOrConstructWithArrayLikeOrSpread(
      node, n.LastArgumentIndex(), p.frequency(), p.feedback(),
      p.speculation_mode(), p.feedback_relation());
}

Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
  JSCallWithSpreadNode n(node);
  CallParameters const& p = n.Parameters();
  DCHECK_GE(p.arity_without_implicit_args(), 1);  // At least the spread.
  return ReduceCallOrConstructWithArrayLikeOrSpread(
      node, n.LastArgumentIndex(), p.frequency(), p.feedback(),
      p.speculation_mode(), p.feedback_relation());
}

Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
  JSConstructNode n(node);
  ConstructParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  Node* target = n.target();
  Node* new_target = n.new_target();
  Effect effect = n.effect();
  Control control = n.control();

  if (p.feedback().IsValid()) {
    ProcessedFeedback const& feedback =
        broker()->GetFeedbackForCall(p.feedback());
    if (feedback.IsInsufficient()) {
      return ReduceForInsufficientFeedback(
          node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
    }

    base::Optional<HeapObjectRef> feedback_target = feedback.AsCall().target();
    if (feedback_target.has_value() && feedback_target->IsAllocationSite()) {
      // The feedback is an AllocationSite, which means we have called the
      // Array function and collected transition (and pretenuring) feedback
      // for the resulting arrays.  This has to be kept in sync with the
      // implementation in Ignition.

      Node* array_function =
          jsgraph()->Constant(native_context().array_function());

      // Check that the {target} is still the {array_function}.
      Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
                                     array_function);
      effect = graph()->NewNode(
          simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
          effect, control);

      // Turn the {node} into a {JSCreateArray} call.
      NodeProperties::ReplaceEffectInput(node, effect);
      STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
      node->ReplaceInput(n.NewTargetIndex(), array_function);
      node->RemoveInput(n.FeedbackVectorIndex());
      NodeProperties::ChangeOp(
          node, javascript()->CreateArray(
                    arity, feedback_target->AsAllocationSite().object()));
      return Changed(node);
    } else if (feedback_target.has_value() &&
               !HeapObjectMatcher(new_target).HasResolvedValue() &&
               feedback_target->map().is_constructor()) {
      Node* new_target_feedback = jsgraph()->Constant(*feedback_target);

      // Check that the {new_target} is still the {new_target_feedback}.
      Node* check = graph()->NewNode(simplified()->ReferenceEqual(), new_target,
                                     new_target_feedback);
      effect = graph()->NewNode(
          simplified()->CheckIf(DeoptimizeReason::kWrongCallTarget), check,
          effect, control);

      // Specialize the JSConstruct node to the {new_target_feedback}.
      node->ReplaceInput(n.NewTargetIndex(), new_target_feedback);
      NodeProperties::ReplaceEffectInput(node, effect);
      if (target == new_target) {
        node->ReplaceInput(n.TargetIndex(), new_target_feedback);
      }

      // Try to further reduce the JSConstruct {node}.
      return Changed(node).FollowedBy(ReduceJSConstruct(node));
    }
  }

  // Try to specialize JSConstruct {node}s with constant {target}s.
  HeapObjectMatcher m(target);
  if (m.HasResolvedValue()) {
    HeapObjectRef target_ref = m.Ref(broker());

    // Raise a TypeError if the {target} is not a constructor.
    if (!target_ref.map().is_constructor()) {
      NodeProperties::ReplaceValueInputs(node, target);
      NodeProperties::ChangeOp(node,
                               javascript()->CallRuntime(
                                   Runtime::kThrowConstructedNonConstructable));
      return Changed(node);
    }

    if (target_ref.IsJSFunction()) {
      JSFunctionRef function = target_ref.AsJSFunction();
      if (should_disallow_heap_access() && !function.serialized()) {
        TRACE_BROKER_MISSING(broker(),
                             "function, not serialized: " << function);
        return NoChange();
      }

      // Do not reduce constructors with break points.
      if (function.shared().HasBreakInfo()) return NoChange();

      // Don't inline cross native context.
      if (!function.native_context().equals(native_context())) {
        return NoChange();
      }

      // Check for known builtin functions.
      int builtin_id = function.shared().HasBuiltinId()
                           ? function.shared().builtin_id()
                           : Builtins::kNoBuiltinId;
      switch (builtin_id) {
        case Builtins::kArrayConstructor: {
          // TODO(bmeurer): Deal with Array subclasses here.
          // Turn the {node} into a {JSCreateArray} call.
          STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1);
          node->ReplaceInput(n.NewTargetIndex(), new_target);
          node->RemoveInput(n.FeedbackVectorIndex());
          NodeProperties::ChangeOp(
              node, javascript()->CreateArray(arity, Handle<AllocationSite>()));
          return Changed(node);
        }
        case Builtins::kObjectConstructor: {
          // If no value is passed, we can immediately lower to a simple
          // JSCreate and don't need to do any massaging of the {node}.
          if (arity == 0) {
            node->RemoveInput(n.FeedbackVectorIndex());
            NodeProperties::ChangeOp(node, javascript()->Create());
            return Changed(node);
          }

          // If {target} is not the same as {new_target} (i.e. the Object
          // constructor), {value} will be ignored and therefore we can lower
          // to {JSCreate}. See https://tc39.es/ecma262/#sec-object-value.
          HeapObjectMatcher mnew_target(new_target);
          if (mnew_target.HasResolvedValue() &&
              !mnew_target.Ref(broker()).equals(function)) {
            // Drop the value inputs.
            node->RemoveInput(n.FeedbackVectorIndex());
            for (int i = n.ArgumentCount() - 1; i >= 0; i--) {
              node->RemoveInput(n.ArgumentIndex(i));
            }
            NodeProperties::ChangeOp(node, javascript()->Create());
            return Changed(node);
          }
          break;
        }
        case Builtins::kPromiseConstructor:
          return ReducePromiseConstructor(node);
        case Builtins::kTypedArrayConstructor:
          return ReduceTypedArrayConstructor(node, function.shared());
        default:
          break;
      }
    } else if (target_ref.IsJSBoundFunction()) {
      JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
      if (should_disallow_heap_access() && !function.serialized()) {
        TRACE_BROKER_MISSING(broker(),
                             "function, not serialized: " << function);
        return NoChange();
      }

      ObjectRef bound_target_function = function.bound_target_function();
      FixedArrayRef bound_arguments = function.bound_arguments();

      // Patch {node} to use [[BoundTargetFunction]].
      node->ReplaceInput(n.TargetIndex(),
                         jsgraph()->Constant(bound_target_function));

      // Patch {node} to use [[BoundTargetFunction]]
      // as new.target if {new_target} equals {target}.
      node->ReplaceInput(
          n.NewTargetIndex(),
          graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
                           graph()->NewNode(simplified()->ReferenceEqual(),
                                            target, new_target),
                           jsgraph()->Constant(bound_target_function),
                           new_target));

      // Insert the [[BoundArguments]] for {node}.
      for (int i = 0; i < bound_arguments.length(); ++i) {
        node->InsertInput(graph()->zone(), n.ArgumentIndex(i),
                          jsgraph()->Constant(bound_arguments.get(i)));
        arity++;
      }

      // Update the JSConstruct operator on {node}.
      NodeProperties::ChangeOp(
          node, javascript()->Construct(JSConstructNode::ArityForArgc(arity),
                                        p.frequency(), FeedbackSource()));

      // Try to further reduce the JSConstruct {node}.
      return Changed(node).FollowedBy(ReduceJSConstruct(node));
    }

    // TODO(bmeurer): Also support optimizing proxies here.
  }

  // If {target} is the result of a JSCreateBoundFunction operation,
  // we can just fold the construction and construct the bound target
  // function directly instead.
  if (target->opcode() == IrOpcode::kJSCreateBoundFunction) {
    Node* bound_target_function = NodeProperties::GetValueInput(target, 0);
    int const bound_arguments_length =
        static_cast<int>(CreateBoundFunctionParametersOf(target->op()).arity());

    // Patch the {node} to use [[BoundTargetFunction]].
    node->ReplaceInput(n.TargetIndex(), bound_target_function);

    // Patch {node} to use [[BoundTargetFunction]]
    // as new.target if {new_target} equals {target}.
    node->ReplaceInput(
        n.NewTargetIndex(),
        graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
                         graph()->NewNode(simplified()->ReferenceEqual(),
                                          target, new_target),
                         bound_target_function, new_target));

    // Insert the [[BoundArguments]] for {node}.
    for (int i = 0; i < bound_arguments_length; ++i) {
      Node* value = NodeProperties::GetValueInput(target, 2 + i);
      node->InsertInput(graph()->zone(), n.ArgumentIndex(i), value);
      arity++;
    }

    // Update the JSConstruct operator on {node}.
    NodeProperties::ChangeOp(
        node, javascript()->Construct(JSConstructNode::ArityForArgc(arity),
                                      p.frequency(), FeedbackSource()));

    // Try to further reduce the JSConstruct {node}.
    return Changed(node).FollowedBy(ReduceJSConstruct(node));
  }

  return NoChange();
}

// ES #sec-string.prototype.indexof
Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Effect effect = n.effect();
  Control control = n.control();
  if (n.ArgumentCount() > 0) {
    Node* receiver = n.receiver();
    Node* new_receiver = effect = graph()->NewNode(
        simplified()->CheckString(p.feedback()), receiver, effect, control);

    Node* search_string = n.Argument(0);
    Node* new_search_string = effect =
        graph()->NewNode(simplified()->CheckString(p.feedback()), search_string,
                         effect, control);

    Node* new_position = jsgraph()->ZeroConstant();
    if (n.ArgumentCount() > 1) {
      Node* position = n.Argument(1);
      new_position = effect = graph()->NewNode(
          simplified()->CheckSmi(p.feedback()), position, effect, control);
    }

    NodeProperties::ReplaceEffectInput(node, effect);
    RelaxEffectsAndControls(node);
    node->ReplaceInput(0, new_receiver);
    node->ReplaceInput(1, new_search_string);
    node->ReplaceInput(2, new_position);
    node->TrimInputCount(3);
    NodeProperties::ChangeOp(node, simplified()->StringIndexOf());
    return Changed(node);
  }
  return NoChange();
}

// ES #sec-string.prototype.substring
Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (n.ArgumentCount() < 1) return NoChange();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  JSCallReducerAssembler a(this, node);
  Node* subgraph = a.ReduceStringPrototypeSubstring();
  return ReplaceWithSubgraph(&a, subgraph);
}

// ES #sec-string.prototype.slice
Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (n.ArgumentCount() < 1) return NoChange();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  JSCallReducerAssembler a(this, node);
  Node* subgraph = a.ReduceStringPrototypeSlice();
  return ReplaceWithSubgraph(&a, subgraph);
}

// ES #sec-string.prototype.substr
Reduction JSCallReducer::ReduceStringPrototypeSubstr(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (n.ArgumentCount() < 1) return NoChange();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* receiver = n.receiver();
  Node* start = n.Argument(0);
  Node* end = n.ArgumentOrUndefined(1, jsgraph());

  receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
                                       receiver, effect, control);

  start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
                                    effect, control);

  Node* length = graph()->NewNode(simplified()->StringLength(), receiver);

  // Replace {end} argument with {length} if it is undefined.
  {
    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
                                   jsgraph()->UndefinedConstant());
    Node* branch =
        graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);

    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    Node* etrue = effect;
    Node* vtrue = length;

    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    Node* efalse = effect;
    Node* vfalse = efalse = graph()->NewNode(
        simplified()->CheckSmi(p.feedback()), end, efalse, if_false);

    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                           vtrue, vfalse, control);
  }

  Node* initStart = graph()->NewNode(
      common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
      graph()->NewNode(simplified()->NumberLessThan(), start,
                       jsgraph()->ZeroConstant()),
      graph()->NewNode(
          simplified()->NumberMax(),
          graph()->NewNode(simplified()->NumberAdd(), length, start),
          jsgraph()->ZeroConstant()),
      start);
  // The select above guarantees that initStart is non-negative, but
  // our typer can't figure that out yet.
  initStart = effect = graph()->NewNode(
      common()->TypeGuard(Type::UnsignedSmall()), initStart, effect, control);

  Node* resultLength = graph()->NewNode(
      simplified()->NumberMin(),
      graph()->NewNode(simplified()->NumberMax(), end,
                       jsgraph()->ZeroConstant()),
      graph()->NewNode(simplified()->NumberSubtract(), length, initStart));

  // The the select below uses {resultLength} only if {resultLength > 0},
  // but our typer can't figure that out yet.
  Node* to = effect = graph()->NewNode(
      common()->TypeGuard(Type::UnsignedSmall()),
      graph()->NewNode(simplified()->NumberAdd(), initStart, resultLength),
      effect, control);

  Node* result_string = nullptr;
  // Return empty string if {from} is smaller than {to}.
  {
    Node* check = graph()->NewNode(simplified()->NumberLessThan(),
                                   jsgraph()->ZeroConstant(), resultLength);

    Node* branch =
        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);

    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    Node* etrue = effect;
    Node* vtrue = etrue =
        graph()->NewNode(simplified()->StringSubstring(), receiver, initStart,
                         to, etrue, if_true);

    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    Node* efalse = effect;
    Node* vfalse = jsgraph()->EmptyStringConstant();

    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    result_string =
        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                         vtrue, vfalse, control);
  }

  ReplaceWithValue(node, result_string, effect, control);
  return Replace(result_string);
}

Reduction JSCallReducer::ReduceJSConstructWithArrayLike(Node* node) {
  JSConstructWithArrayLikeNode n(node);
  ConstructParameters const& p = n.Parameters();
  const int arraylike_index = n.LastArgumentIndex();
  DCHECK_EQ(n.ArgumentCount(), 1);  // The arraylike object.
  return ReduceCallOrConstructWithArrayLikeOrSpread(
      node, arraylike_index, p.frequency(), p.feedback(),
      SpeculationMode::kDisallowSpeculation, CallFeedbackRelation::kRelated);
}

Reduction JSCallReducer::ReduceJSConstructWithSpread(Node* node) {
  JSConstructWithSpreadNode n(node);
  ConstructParameters const& p = n.Parameters();
  const int spread_index = n.LastArgumentIndex();
  DCHECK_GE(n.ArgumentCount(), 1);  // At least the spread.
  return ReduceCallOrConstructWithArrayLikeOrSpread(
      node, spread_index, p.frequency(), p.feedback(),
      SpeculationMode::kDisallowSpeculation, CallFeedbackRelation::kRelated);
}

Reduction JSCallReducer::ReduceReturnReceiver(Node* node) {
  JSCallNode n(node);
  Node* receiver = n.receiver();
  ReplaceWithValue(node, receiver);
  return Replace(receiver);
}

Reduction JSCallReducer::ReduceForInsufficientFeedback(
    Node* node, DeoptimizeReason reason) {
  DCHECK(node->opcode() == IrOpcode::kJSCall ||
         node->opcode() == IrOpcode::kJSConstruct);
  if (!(flags() & kBailoutOnUninitialized)) return NoChange();
  // TODO(mythria): May be add additional flags to specify if we need to deopt
  // on calls / construct rather than checking for TurboProp here. We may need
  // it for NativeContextIndependent code too.
  if (broker()->is_turboprop()) return NoChange();

  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* frame_state =
      NodeProperties::FindFrameStateBefore(node, jsgraph()->Dead());
  Node* deoptimize = graph()->NewNode(
      common()->Deoptimize(DeoptimizeKind::kSoft, reason, FeedbackSource()),
      frame_state, effect, control);
  // TODO(bmeurer): This should be on the AdvancedReducer somehow.
  NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
  Revisit(graph()->end());
  node->TrimInputCount(0);
  NodeProperties::ChangeOp(node, common()->Dead());
  return Changed(node);
}

Node* JSCallReducer::LoadReceiverElementsKind(Node* receiver, Effect* effect,
                                              Control control) {
  Node* effect_node = *effect;
  Node* receiver_map = effect_node =
      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
                       receiver, effect_node, control);
  Node* receiver_bit_field2 = effect_node = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
      effect_node, control);
  Node* receiver_elements_kind = graph()->NewNode(
      simplified()->NumberShiftRightLogical(),
      graph()->NewNode(
          simplified()->NumberBitwiseAnd(), receiver_bit_field2,
          jsgraph()->Constant(Map::Bits2::ElementsKindBits::kMask)),
      jsgraph()->Constant(Map::Bits2::ElementsKindBits::kShift));
  *effect = effect_node;
  return receiver_elements_kind;
}

void JSCallReducer::CheckIfElementsKind(Node* receiver_elements_kind,
                                        ElementsKind kind, Node* control,
                                        Node** if_true, Node** if_false) {
  Node* is_packed_kind =
      graph()->NewNode(simplified()->NumberEqual(), receiver_elements_kind,
                       jsgraph()->Constant(GetPackedElementsKind(kind)));
  Node* packed_branch =
      graph()->NewNode(common()->Branch(), is_packed_kind, control);
  Node* if_packed = graph()->NewNode(common()->IfTrue(), packed_branch);

  if (IsHoleyElementsKind(kind)) {
    Node* if_not_packed = graph()->NewNode(common()->IfFalse(), packed_branch);
    Node* is_holey_kind =
        graph()->NewNode(simplified()->NumberEqual(), receiver_elements_kind,
                         jsgraph()->Constant(GetHoleyElementsKind(kind)));
    Node* holey_branch =
        graph()->NewNode(common()->Branch(), is_holey_kind, if_not_packed);
    Node* if_holey = graph()->NewNode(common()->IfTrue(), holey_branch);

    Node* if_not_packed_not_holey =
        graph()->NewNode(common()->IfFalse(), holey_branch);

    *if_true = graph()->NewNode(common()->Merge(2), if_packed, if_holey);
    *if_false = if_not_packed_not_holey;
  } else {
    *if_true = if_packed;
    *if_false = graph()->NewNode(common()->IfFalse(), packed_branch);
  }
}

// ES6 section 22.1.3.18 Array.prototype.push ( )
Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  int const num_values = n.ArgumentCount();
  Node* receiver = n.receiver();
  Effect effect = n.effect();
  Control control = n.control();

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& receiver_maps = inference.GetMaps();

  std::vector<ElementsKind> kinds;
  if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kinds, true)) {
    return inference.NoChange();
  }
  if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  std::vector<Node*> controls_to_merge;
  std::vector<Node*> effects_to_merge;
  std::vector<Node*> values_to_merge;
  Node* return_value = jsgraph()->UndefinedConstant();

  Node* receiver_elements_kind =
      LoadReceiverElementsKind(receiver, &effect, control);
  Node* next_control = control;
  Node* next_effect = effect;
  for (size_t i = 0; i < kinds.size(); i++) {
    ElementsKind kind = kinds[i];
    control = next_control;
    effect = next_effect;
    // We do not need branch for the last elements kind.
    if (i != kinds.size() - 1) {
      Node* control_node = control;
      CheckIfElementsKind(receiver_elements_kind, kind, control_node,
                          &control_node, &next_control);
      control = control_node;
    }

    // Collect the value inputs to push.
    std::vector<Node*> values(num_values);
    for (int i = 0; i < num_values; ++i) {
      values[i] = n.Argument(i);
    }

    for (auto& value : values) {
      if (IsSmiElementsKind(kind)) {
        value = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
                                          value, effect, control);
      } else if (IsDoubleElementsKind(kind)) {
        value = effect = graph()->NewNode(
            simplified()->CheckNumber(p.feedback()), value, effect, control);
        // Make sure we do not store signaling NaNs into double arrays.
        value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
      }
    }

    // Load the "length" property of the {receiver}.
    Node* length = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)),
        receiver, effect, control);
    return_value = length;

    // Check if we have any {values} to push.
    if (num_values > 0) {
      // Compute the resulting "length" of the {receiver}.
      Node* new_length = return_value = graph()->NewNode(
          simplified()->NumberAdd(), length, jsgraph()->Constant(num_values));

      // Load the elements backing store of the {receiver}.
      Node* elements = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
          receiver, effect, control);
      Node* elements_length = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
          elements, effect, control);

      GrowFastElementsMode mode =
          IsDoubleElementsKind(kind)
              ? GrowFastElementsMode::kDoubleElements
              : GrowFastElementsMode::kSmiOrObjectElements;
      elements = effect = graph()->NewNode(
          simplified()->MaybeGrowFastElements(mode, p.feedback()), receiver,
          elements,
          graph()->NewNode(simplified()->NumberAdd(), length,
                           jsgraph()->Constant(num_values - 1)),
          elements_length, effect, control);

      // Update the JSArray::length field. Since this is observable,
      // there must be no other check after this.
      effect = graph()->NewNode(
          simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
          receiver, new_length, effect, control);

      // Append the {values} to the {elements}.
      for (int i = 0; i < num_values; ++i) {
        Node* value = values[i];
        Node* index = graph()->NewNode(simplified()->NumberAdd(), length,
                                       jsgraph()->Constant(i));
        effect =
            graph()->NewNode(simplified()->StoreElement(
                                 AccessBuilder::ForFixedArrayElement(kind)),
                             elements, index, value, effect, control);
      }
    }

    controls_to_merge.push_back(control);
    effects_to_merge.push_back(effect);
    values_to_merge.push_back(return_value);
  }

  if (controls_to_merge.size() > 1) {
    int const count = static_cast<int>(controls_to_merge.size());

    control = graph()->NewNode(common()->Merge(count), count,
                               &controls_to_merge.front());
    effects_to_merge.push_back(control);
    effect = graph()->NewNode(common()->EffectPhi(count), count + 1,
                              &effects_to_merge.front());
    values_to_merge.push_back(control);
    return_value =
        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
                         count + 1, &values_to_merge.front());
  }

  ReplaceWithValue(node, return_value, effect, control);
  return Replace(return_value);
}

// ES6 section 22.1.3.17 Array.prototype.pop ( )
Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* receiver = n.receiver();

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& receiver_maps = inference.GetMaps();

  std::vector<ElementsKind> kinds;
  if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kinds)) {
    return inference.NoChange();
  }
  if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  std::vector<Node*> controls_to_merge;
  std::vector<Node*> effects_to_merge;
  std::vector<Node*> values_to_merge;
  Node* value = jsgraph()->UndefinedConstant();

  Node* receiver_elements_kind =
      LoadReceiverElementsKind(receiver, &effect, control);
  Node* next_control = control;
  Node* next_effect = effect;
  for (size_t i = 0; i < kinds.size(); i++) {
    ElementsKind kind = kinds[i];
    control = next_control;
    effect = next_effect;
    // We do not need branch for the last elements kind.
    if (i != kinds.size() - 1) {
      Node* control_node = control;
      CheckIfElementsKind(receiver_elements_kind, kind, control_node,
                          &control_node, &next_control);
      control = control_node;
    }

    // Load the "length" property of the {receiver}.
    Node* length = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)),
        receiver, effect, control);

    // Check if the {receiver} has any elements.
    Node* check = graph()->NewNode(simplified()->NumberEqual(), length,
                                   jsgraph()->ZeroConstant());
    Node* branch =
        graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);

    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    Node* etrue = effect;
    Node* vtrue = jsgraph()->UndefinedConstant();

    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    Node* efalse = effect;
    Node* vfalse;
    {
      // TODO(tebbi): We should trim the backing store if the capacity is too
      // big, as implemented in elements.cc:ElementsAccessorBase::SetLengthImpl.

      // Load the elements backing store from the {receiver}.
      Node* elements = efalse = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
          receiver, efalse, if_false);

      // Ensure that we aren't popping from a copy-on-write backing store.
      if (IsSmiOrObjectElementsKind(kind)) {
        elements = efalse =
            graph()->NewNode(simplified()->EnsureWritableFastElements(),
                             receiver, elements, efalse, if_false);
      }

      // Compute the new {length}.
      length = graph()->NewNode(simplified()->NumberSubtract(), length,
                                jsgraph()->OneConstant());

      // Store the new {length} to the {receiver}.
      efalse = graph()->NewNode(
          simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
          receiver, length, efalse, if_false);

      // Load the last entry from the {elements}.
      vfalse = efalse = graph()->NewNode(
          simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(kind)),
          elements, length, efalse, if_false);

      // Store a hole to the element we just removed from the {receiver}.
      efalse = graph()->NewNode(
          simplified()->StoreElement(
              AccessBuilder::ForFixedArrayElement(GetHoleyElementsKind(kind))),
          elements, length, jsgraph()->TheHoleConstant(), efalse, if_false);
    }

    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                             vtrue, vfalse, control);

    // Convert the hole to undefined. Do this last, so that we can optimize
    // conversion operator via some smart strength reduction in many cases.
    if (IsHoleyElementsKind(kind)) {
      value =
          graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
    }

    controls_to_merge.push_back(control);
    effects_to_merge.push_back(effect);
    values_to_merge.push_back(value);
  }

  if (controls_to_merge.size() > 1) {
    int const count = static_cast<int>(controls_to_merge.size());

    control = graph()->NewNode(common()->Merge(count), count,
                               &controls_to_merge.front());
    effects_to_merge.push_back(control);
    effect = graph()->NewNode(common()->EffectPhi(count), count + 1,
                              &effects_to_merge.front());
    values_to_merge.push_back(control);
    value =
        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
                         count + 1, &values_to_merge.front());
  }

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES6 section 22.1.3.22 Array.prototype.shift ( )
Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* target = n.target();
  Node* receiver = n.receiver();
  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Effect effect = n.effect();
  Control control = n.control();

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& receiver_maps = inference.GetMaps();

  std::vector<ElementsKind> kinds;
  if (!CanInlineArrayResizingBuiltin(broker(), receiver_maps, &kinds)) {
    return inference.NoChange();
  }
  if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  std::vector<Node*> controls_to_merge;
  std::vector<Node*> effects_to_merge;
  std::vector<Node*> values_to_merge;
  Node* value = jsgraph()->UndefinedConstant();

  Node* receiver_elements_kind =
      LoadReceiverElementsKind(receiver, &effect, control);
  Node* next_control = control;
  Node* next_effect = effect;
  for (size_t i = 0; i < kinds.size(); i++) {
    ElementsKind kind = kinds[i];
    control = next_control;
    effect = next_effect;
    // We do not need branch for the last elements kind.
    if (i != kinds.size() - 1) {
      Node* control_node = control;
      CheckIfElementsKind(receiver_elements_kind, kind, control_node,
                          &control_node, &next_control);
      control = control_node;
    }

    // Load length of the {receiver}.
    Node* length = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayLength(kind)),
        receiver, effect, control);

    // Return undefined if {receiver} has no elements.
    Node* check0 = graph()->NewNode(simplified()->NumberEqual(), length,
                                    jsgraph()->ZeroConstant());
    Node* branch0 =
        graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);

    Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    Node* etrue0 = effect;
    Node* vtrue0 = jsgraph()->UndefinedConstant();

    Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    Node* efalse0 = effect;
    Node* vfalse0;
    {
      // Check if we should take the fast-path.
      Node* check1 =
          graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
                           jsgraph()->Constant(JSArray::kMaxCopyElements));
      Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
                                       check1, if_false0);

      Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
      Node* etrue1 = efalse0;
      Node* vtrue1;
      {
        Node* elements = etrue1 = graph()->NewNode(
            simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
            receiver, etrue1, if_true1);

        // Load the first element here, which we return below.
        vtrue1 = etrue1 = graph()->NewNode(
            simplified()->LoadElement(
                AccessBuilder::ForFixedArrayElement(kind)),
            elements, jsgraph()->ZeroConstant(), etrue1, if_true1);

        // Ensure that we aren't shifting a copy-on-write backing store.
        if (IsSmiOrObjectElementsKind(kind)) {
          elements = etrue1 =
              graph()->NewNode(simplified()->EnsureWritableFastElements(),
                               receiver, elements, etrue1, if_true1);
        }

        // Shift the remaining {elements} by one towards the start.
        Node* loop = graph()->NewNode(common()->Loop(2), if_true1, if_true1);
        Node* eloop =
            graph()->NewNode(common()->EffectPhi(2), etrue1, etrue1, loop);
        Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
        NodeProperties::MergeControlToEnd(graph(), common(), terminate);
        Node* index = graph()->NewNode(
            common()->Phi(MachineRepresentation::kTagged, 2),
            jsgraph()->OneConstant(),
            jsgraph()->Constant(JSArray::kMaxCopyElements - 1), loop);

        {
          Node* check2 =
              graph()->NewNode(simplified()->NumberLessThan(), index, length);
          Node* branch2 = graph()->NewNode(common()->Branch(), check2, loop);

          if_true1 = graph()->NewNode(common()->IfFalse(), branch2);
          etrue1 = eloop;

          Node* control = graph()->NewNode(common()->IfTrue(), branch2);
          Node* effect = etrue1;

          ElementAccess const access =
              AccessBuilder::ForFixedArrayElement(kind);
          Node* value = effect =
              graph()->NewNode(simplified()->LoadElement(access), elements,
                               index, effect, control);
          effect = graph()->NewNode(
              simplified()->StoreElement(access), elements,
              graph()->NewNode(simplified()->NumberSubtract(), index,
                               jsgraph()->OneConstant()),
              value, effect, control);

          loop->ReplaceInput(1, control);
          eloop->ReplaceInput(1, effect);
          index->ReplaceInput(1,
                              graph()->NewNode(simplified()->NumberAdd(), index,
                                               jsgraph()->OneConstant()));
        }

        // Compute the new {length}.
        length = graph()->NewNode(simplified()->NumberSubtract(), length,
                                  jsgraph()->OneConstant());

        // Store the new {length} to the {receiver}.
        etrue1 = graph()->NewNode(
            simplified()->StoreField(AccessBuilder::ForJSArrayLength(kind)),
            receiver, length, etrue1, if_true1);

        // Store a hole to the element we just removed from the {receiver}.
        etrue1 = graph()->NewNode(
            simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
                GetHoleyElementsKind(kind))),
            elements, length, jsgraph()->TheHoleConstant(), etrue1, if_true1);
      }

      Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
      Node* efalse1 = efalse0;
      Node* vfalse1;
      {
        // Call the generic C++ implementation.
        const int builtin_index = Builtins::kArrayShift;
        auto call_descriptor = Linkage::GetCEntryStubCallDescriptor(
            graph()->zone(), 1, BuiltinArguments::kNumExtraArgsWithReceiver,
            Builtins::name(builtin_index), node->op()->properties(),
            CallDescriptor::kNeedsFrameState);
        Node* stub_code = jsgraph()->CEntryStubConstant(1, kDontSaveFPRegs,
                                                        kArgvOnStack, true);
        Address builtin_entry = Builtins::CppEntryOf(builtin_index);
        Node* entry = jsgraph()->ExternalConstant(
            ExternalReference::Create(builtin_entry));
        Node* argc =
            jsgraph()->Constant(BuiltinArguments::kNumExtraArgsWithReceiver);
        if_false1 = efalse1 = vfalse1 =
            graph()->NewNode(common()->Call(call_descriptor), stub_code,
                             receiver, jsgraph()->PaddingConstant(), argc,
                             target, jsgraph()->UndefinedConstant(), entry,
                             argc, context, frame_state, efalse1, if_false1);
      }

      if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
      efalse0 =
          graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
      vfalse0 =
          graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                           vtrue1, vfalse1, if_false0);
    }

    control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
    value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                             vtrue0, vfalse0, control);

    // Convert the hole to undefined. Do this last, so that we can optimize
    // conversion operator via some smart strength reduction in many cases.
    if (IsHoleyElementsKind(kind)) {
      value =
          graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
    }

    controls_to_merge.push_back(control);
    effects_to_merge.push_back(effect);
    values_to_merge.push_back(value);
  }

  if (controls_to_merge.size() > 1) {
    int const count = static_cast<int>(controls_to_merge.size());

    control = graph()->NewNode(common()->Merge(count), count,
                               &controls_to_merge.front());
    effects_to_merge.push_back(control);
    effect = graph()->NewNode(common()->EffectPhi(count), count + 1,
                              &effects_to_merge.front());
    values_to_merge.push_back(control);
    value =
        graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
                         count + 1, &values_to_merge.front());
  }

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES6 section 22.1.3.23 Array.prototype.slice ( )
Reduction JSCallReducer::ReduceArrayPrototypeSlice(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  if (!FLAG_turbo_inline_array_builtins) return NoChange();
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* receiver = n.receiver();
  Node* start = n.ArgumentOr(0, jsgraph()->ZeroConstant());
  Node* end = n.ArgumentOrUndefined(1, jsgraph());
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();

  // Optimize for the case where we simply clone the {receiver},
  // i.e. when the {start} is zero and the {end} is undefined
  // (meaning it will be set to {receiver}s "length" property).
  if (!NumberMatcher(start).Is(0) ||
      !HeapObjectMatcher(end).Is(factory()->undefined_value())) {
    return NoChange();
  }

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& receiver_maps = inference.GetMaps();

  // Check that the maps are of JSArray (and more).
  // TODO(turbofan): Consider adding special case for the common pattern
  // `slice.call(arguments)`, for example jQuery makes heavy use of that.
  bool can_be_holey = false;
  for (Handle<Map> map : receiver_maps) {
    MapRef receiver_map(broker(), map);
    if (!receiver_map.supports_fast_array_iteration())
      return inference.NoChange();
    if (IsHoleyElementsKind(receiver_map.elements_kind())) {
      can_be_holey = true;
    }
  }

  if (!dependencies()->DependOnArraySpeciesProtector())
    return inference.NoChange();
  if (can_be_holey) {
    if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
  }
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  // TODO(turbofan): We can do even better here, either adding a CloneArray
  // simplified operator, whose output type indicates that it's an Array,
  // saving subsequent checks, or yet better, by introducing new operators
  // CopySmiOrObjectElements / CopyDoubleElements and inlining the JSArray
  // allocation in here. That way we'd even get escape analysis and scalar
  // replacement to help in some cases.
  Callable callable =
      Builtins::CallableFor(isolate(), Builtins::kCloneFastJSArray);
  auto call_descriptor = Linkage::GetStubCallDescriptor(
      graph()->zone(), callable.descriptor(),
      callable.descriptor().GetStackParameterCount(), CallDescriptor::kNoFlags,
      Operator::kNoThrow | Operator::kNoDeopt);

  // Calls to Builtins::kCloneFastJSArray produce COW arrays
  // if the original array is COW
  Node* clone = effect = graph()->NewNode(
      common()->Call(call_descriptor), jsgraph()->HeapConstant(callable.code()),
      receiver, context, effect, control);

  ReplaceWithValue(node, clone, effect, control);
  return Replace(clone);
}

// ES6 section 22.1.2.2 Array.isArray ( arg )
Reduction JSCallReducer::ReduceArrayIsArray(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  // We certainly know that undefined is not an array.
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Node* object = n.Argument(0);
  node->ReplaceInput(0, object);
  node->ReplaceInput(1, context);
  node->ReplaceInput(2, frame_state);
  node->ReplaceInput(3, effect);
  node->ReplaceInput(4, control);
  node->TrimInputCount(5);
  NodeProperties::ChangeOp(node, javascript()->ObjectIsArray());
  return Changed(node);
}

Reduction JSCallReducer::ReduceArrayIterator(Node* node,
                                             ArrayIteratorKind array_kind,
                                             IterationKind iteration_kind) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  Node* receiver = n.receiver();
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();

  // Check if we know that {receiver} is a valid JSReceiver.
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAreJSReceiver()) {
    return NoChange();
  }

  // TypedArray iteration is stricter: it throws if the receiver is not a typed
  // array. So don't bother optimizing in that case.
  if (array_kind == ArrayIteratorKind::kTypedArray &&
      !inference.AllOfInstanceTypesAre(InstanceType::JS_TYPED_ARRAY_TYPE)) {
    return NoChange();
  }

  if (array_kind == ArrayIteratorKind::kTypedArray) {
    // Make sure we deopt when the JSArrayBuffer is detached.
    if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
      CallParameters const& p = CallParametersOf(node->op());
      if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
        return NoChange();
      }
      Node* buffer = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
          receiver, effect, control);
      Node* buffer_bit_field = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
          buffer, effect, control);
      Node* check = graph()->NewNode(
          simplified()->NumberEqual(),
          graph()->NewNode(
              simplified()->NumberBitwiseAnd(), buffer_bit_field,
              jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
          jsgraph()->ZeroConstant());
      effect = graph()->NewNode(
          simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
                                p.feedback()),
          check, effect, control);
    }
  }

  // Morph the {node} into a JSCreateArrayIterator with the given {kind}.
  RelaxControls(node);
  node->ReplaceInput(0, receiver);
  node->ReplaceInput(1, context);
  node->ReplaceInput(2, effect);
  node->ReplaceInput(3, control);
  node->TrimInputCount(4);
  NodeProperties::ChangeOp(node,
                           javascript()->CreateArrayIterator(iteration_kind));
  return Changed(node);
}

// ES #sec-%arrayiteratorprototype%.next
Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  Node* iterator = n.receiver();
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();

  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  if (iterator->opcode() != IrOpcode::kJSCreateArrayIterator) return NoChange();

  IterationKind const iteration_kind =
      CreateArrayIteratorParametersOf(iterator->op()).kind();
  Node* iterated_object = NodeProperties::GetValueInput(iterator, 0);
  Node* iterator_effect = NodeProperties::GetEffectInput(iterator);

  MapInference inference(broker(), iterated_object, iterator_effect);
  if (!inference.HaveMaps()) return NoChange();
  MapHandles const& iterated_object_maps = inference.GetMaps();

  // Check that various {iterated_object_maps} have compatible elements kinds.
  ElementsKind elements_kind =
      MapRef(broker(), iterated_object_maps[0]).elements_kind();
  if (IsTypedArrayElementsKind(elements_kind)) {
    // TurboFan doesn't support loading from BigInt typed arrays yet.
    if (elements_kind == BIGUINT64_ELEMENTS ||
        elements_kind == BIGINT64_ELEMENTS) {
      return inference.NoChange();
    }
    for (Handle<Map> map : iterated_object_maps) {
      MapRef iterated_object_map(broker(), map);
      if (iterated_object_map.elements_kind() != elements_kind) {
        return inference.NoChange();
      }
    }
  } else {
    if (!CanInlineArrayIteratingBuiltin(broker(), iterated_object_maps,
                                        &elements_kind)) {
      return inference.NoChange();
    }
  }

  if (IsHoleyElementsKind(elements_kind)) {
    if (!dependencies()->DependOnNoElementsProtector()) UNREACHABLE();
  }
  // Since the map inference was done relative to {iterator_effect} rather than
  // {effect}, we need to guard the use of the map(s) even when the inference
  // was reliable.
  inference.InsertMapChecks(jsgraph(), &effect, control, p.feedback());

  if (IsTypedArrayElementsKind(elements_kind)) {
    // See if we can skip the detaching check.
    if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
      // Bail out if the {iterated_object}s JSArrayBuffer was detached.
      Node* buffer = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
          iterated_object, effect, control);
      Node* buffer_bit_field = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
          buffer, effect, control);
      Node* check = graph()->NewNode(
          simplified()->NumberEqual(),
          graph()->NewNode(
              simplified()->NumberBitwiseAnd(), buffer_bit_field,
              jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
          jsgraph()->ZeroConstant());
      effect = graph()->NewNode(
          simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
                                p.feedback()),
          check, effect, control);
    }
  }

  // Load the [[NextIndex]] from the {iterator} and leverage the fact
  // that we definitely know that it's in Unsigned32 range since the
  // {iterated_object} is either a JSArray or a JSTypedArray. For the
  // latter case we even know that it's a Smi in UnsignedSmall range.
  FieldAccess index_access = AccessBuilder::ForJSArrayIteratorNextIndex();
  if (IsTypedArrayElementsKind(elements_kind)) {
    index_access.type = TypeCache::Get()->kJSTypedArrayLengthType;
  } else {
    index_access.type = TypeCache::Get()->kJSArrayLengthType;
  }
  Node* index = effect = graph()->NewNode(simplified()->LoadField(index_access),
                                          iterator, effect, control);

  // Load the elements of the {iterated_object}. While it feels
  // counter-intuitive to place the elements pointer load before
  // the condition below, as it might not be needed (if the {index}
  // is out of bounds for the {iterated_object}), it's better this
  // way as it allows the LoadElimination to eliminate redundant
  // reloads of the elements pointer.
  Node* elements = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
      iterated_object, effect, control);

  // Load the length of the {iterated_object}. Due to the map checks we
  // already know something about the length here, which we can leverage
  // to generate Word32 operations below without additional checking.
  FieldAccess length_access =
      IsTypedArrayElementsKind(elements_kind)
          ? AccessBuilder::ForJSTypedArrayLength()
          : AccessBuilder::ForJSArrayLength(elements_kind);
  Node* length = effect = graph()->NewNode(
      simplified()->LoadField(length_access), iterated_object, effect, control);

  // Check whether {index} is within the valid range for the {iterated_object}.
  Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, length);
  Node* branch =
      graph()->NewNode(common()->Branch(BranchHint::kNone), check, control);

  Node* done_true;
  Node* value_true;
  Node* etrue = effect;
  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
  {
    // We know that the {index} is range of the {length} now.
    index = etrue = graph()->NewNode(
        common()->TypeGuard(
            Type::Range(0.0, length_access.type.Max() - 1.0, graph()->zone())),
        index, etrue, if_true);

    done_true = jsgraph()->FalseConstant();
    if (iteration_kind == IterationKind::kKeys) {
      // Just return the {index}.
      value_true = index;
    } else {
      DCHECK(iteration_kind == IterationKind::kEntries ||
             iteration_kind == IterationKind::kValues);

      if (IsTypedArrayElementsKind(elements_kind)) {
        Node* base_ptr = etrue =
            graph()->NewNode(simplified()->LoadField(
                                 AccessBuilder::ForJSTypedArrayBasePointer()),
                             iterated_object, etrue, if_true);
        Node* external_ptr = etrue = graph()->NewNode(
            simplified()->LoadField(
                AccessBuilder::ForJSTypedArrayExternalPointer()),
            iterated_object, etrue, if_true);

        ExternalArrayType array_type = kExternalInt8Array;
        switch (elements_kind) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
  case TYPE##_ELEMENTS:                           \
    array_type = kExternal##Type##Array;          \
    break;
          TYPED_ARRAYS(TYPED_ARRAY_CASE)
          default:
            UNREACHABLE();
#undef TYPED_ARRAY_CASE
        }

        Node* buffer = etrue =
            graph()->NewNode(simplified()->LoadField(
                                 AccessBuilder::ForJSArrayBufferViewBuffer()),
                             iterated_object, etrue, if_true);

        value_true = etrue =
            graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
                             base_ptr, external_ptr, index, etrue, if_true);
      } else {
        value_true = etrue = graph()->NewNode(
            simplified()->LoadElement(
                AccessBuilder::ForFixedArrayElement(elements_kind)),
            elements, index, etrue, if_true);

        // Convert hole to undefined if needed.
        if (elements_kind == HOLEY_ELEMENTS ||
            elements_kind == HOLEY_SMI_ELEMENTS) {
          value_true = graph()->NewNode(
              simplified()->ConvertTaggedHoleToUndefined(), value_true);
        } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
          // TODO(6587): avoid deopt if not all uses of value are truncated.
          CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
          value_true = etrue = graph()->NewNode(
              simplified()->CheckFloat64Hole(mode, p.feedback()), value_true,
              etrue, if_true);
        }
      }

      if (iteration_kind == IterationKind::kEntries) {
        // Allocate elements for key/value pair
        value_true = etrue =
            graph()->NewNode(javascript()->CreateKeyValueArray(), index,
                             value_true, context, etrue);
      } else {
        DCHECK_EQ(IterationKind::kValues, iteration_kind);
      }
    }

    // Increment the [[NextIndex]] field in the {iterator}. The TypeGuards
    // above guarantee that the {next_index} is in the UnsignedSmall range.
    Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
                                        jsgraph()->OneConstant());
    etrue = graph()->NewNode(simplified()->StoreField(index_access), iterator,
                             next_index, etrue, if_true);
  }

  Node* done_false;
  Node* value_false;
  Node* efalse = effect;
  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
  {
    // iterator.[[NextIndex]] >= array.length, stop iterating.
    done_false = jsgraph()->TrueConstant();
    value_false = jsgraph()->UndefinedConstant();

    if (!IsTypedArrayElementsKind(elements_kind)) {
      // Mark the {iterator} as exhausted by setting the [[NextIndex]] to a
      // value that will never pass the length check again (aka the maximum
      // value possible for the specific iterated object). Note that this is
      // different from what the specification says, which is changing the
      // [[IteratedObject]] field to undefined, but that makes it difficult
      // to eliminate the map checks and "length" accesses in for..of loops.
      //
      // This is not necessary for JSTypedArray's, since the length of those
      // cannot change later and so if we were ever out of bounds for them
      // we will stay out-of-bounds forever.
      Node* end_index = jsgraph()->Constant(index_access.type.Max());
      efalse = graph()->NewNode(simplified()->StoreField(index_access),
                                iterator, end_index, efalse, if_false);
    }
  }

  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
  Node* value =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                       value_true, value_false, control);
  Node* done =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                       done_true, done_false, control);

  // Create IteratorResult object.
  value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
                                    value, done, context, effect);
  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
// ES6 section 21.1.3.3 String.prototype.codePointAt ( pos )
Reduction JSCallReducer::ReduceStringPrototypeStringAt(
    const Operator* string_access_operator, Node* node) {
  DCHECK(string_access_operator->opcode() == IrOpcode::kStringCharCodeAt ||
         string_access_operator->opcode() == IrOpcode::kStringCodePointAt);
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* receiver = n.receiver();
  Node* index = n.ArgumentOr(0, jsgraph()->ZeroConstant());
  Effect effect = n.effect();
  Control control = n.control();

  // Ensure that the {receiver} is actually a String.
  receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
                                       receiver, effect, control);

  // Determine the {receiver} length.
  Node* receiver_length =
      graph()->NewNode(simplified()->StringLength(), receiver);

  // Check that the {index} is within range.
  index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
                                    index, receiver_length, effect, control);

  // Return the character from the {receiver} as single character string.
  Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
  Node* value = effect = graph()->NewNode(string_access_operator, receiver,
                                          masked_index, effect, control);

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES section 21.1.3.20
// String.prototype.startsWith ( searchString [ , position ] )
Reduction JSCallReducer::ReduceStringPrototypeStartsWith(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* receiver = n.receiver();
  Effect effect = n.effect();
  Control control = n.control();

  if (n.ArgumentCount() < 1) {
    effect = graph()->NewNode(simplified()->CheckString(p.feedback()), receiver,
                              effect, control);

    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value, effect, control);
    return Replace(value);
  }

  Node* search_string = n.Argument(0);
  Node* position = n.ArgumentOr(1, jsgraph()->ZeroConstant());

  HeapObjectMatcher m(search_string);
  if (m.HasResolvedValue()) {
    ObjectRef target_ref = m.Ref(broker());
    if (target_ref.IsString()) {
      StringRef str = target_ref.AsString();
      if (str.length() == 1) {
        receiver = effect = graph()->NewNode(
            simplified()->CheckString(p.feedback()), receiver, effect, control);

        position = effect = graph()->NewNode(
            simplified()->CheckSmi(p.feedback()), position, effect, control);

        Node* string_length =
            graph()->NewNode(simplified()->StringLength(), receiver);
        Node* unsigned_position = graph()->NewNode(
            simplified()->NumberMax(), position, jsgraph()->ZeroConstant());

        Node* check = graph()->NewNode(simplified()->NumberLessThan(),
                                       unsigned_position, string_length);
        Node* branch = graph()->NewNode(common()->Branch(BranchHint::kNone),
                                        check, control);

        Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
        Node* efalse = effect;
        Node* vfalse = jsgraph()->FalseConstant();

        Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
        Node* etrue = effect;
        Node* vtrue;
        {
          Node* masked_position =
              graph()->NewNode(simplified()->PoisonIndex(), unsigned_position);
          Node* string_first = etrue =
              graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
                               masked_position, etrue, if_true);

          Node* search_first = jsgraph()->Constant(str.GetFirstChar());
          vtrue = graph()->NewNode(simplified()->NumberEqual(), string_first,
                                   search_first);
        }

        control = graph()->NewNode(common()->Merge(2), if_true, if_false);
        Node* value =
            graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                             vtrue, vfalse, control);
        effect =
            graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);

        ReplaceWithValue(node, value, effect, control);
        return Replace(value);
      }
    }
  }

  return NoChange();
}

// ES section 21.1.3.1 String.prototype.charAt ( pos )
Reduction JSCallReducer::ReduceStringPrototypeCharAt(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* receiver = n.receiver();
  Node* index = n.ArgumentOr(0, jsgraph()->ZeroConstant());
  Effect effect = n.effect();
  Control control = n.control();

  // Ensure that the {receiver} is actually a String.
  receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
                                       receiver, effect, control);

  // Determine the {receiver} length.
  Node* receiver_length =
      graph()->NewNode(simplified()->StringLength(), receiver);

  // Check that the {index} is within range.
  index = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
                                    index, receiver_length, effect, control);

  // Return the character from the {receiver} as single character string.
  Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
  Node* value = effect =
      graph()->NewNode(simplified()->StringCharCodeAt(), receiver, masked_index,
                       effect, control);
  value = graph()->NewNode(simplified()->StringFromSingleCharCode(), value);

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

#ifdef V8_INTL_SUPPORT

Reduction JSCallReducer::ReduceStringPrototypeToLowerCaseIntl(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  Effect effect = n.effect();
  Control control = n.control();

  Node* receiver = effect = graph()->NewNode(
      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);

  NodeProperties::ReplaceEffectInput(node, effect);
  RelaxEffectsAndControls(node);
  node->ReplaceInput(0, receiver);
  node->TrimInputCount(1);
  NodeProperties::ChangeOp(node, simplified()->StringToLowerCaseIntl());
  NodeProperties::SetType(node, Type::String());
  return Changed(node);
}

Reduction JSCallReducer::ReduceStringPrototypeToUpperCaseIntl(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  Effect effect = n.effect();
  Control control = n.control();

  Node* receiver = effect = graph()->NewNode(
      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);

  NodeProperties::ReplaceEffectInput(node, effect);
  RelaxEffectsAndControls(node);
  node->ReplaceInput(0, receiver);
  node->TrimInputCount(1);
  NodeProperties::ChangeOp(node, simplified()->StringToUpperCaseIntl());
  NodeProperties::SetType(node, Type::String());
  return Changed(node);
}

#endif  // V8_INTL_SUPPORT

// ES #sec-string.fromcharcode
Reduction JSCallReducer::ReduceStringFromCharCode(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() == 1) {
    Effect effect = n.effect();
    Control control = n.control();
    Node* input = n.Argument(0);

    input = effect = graph()->NewNode(
        simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
                                          p.feedback()),
        input, effect, control);

    Node* value =
        graph()->NewNode(simplified()->StringFromSingleCharCode(), input);
    ReplaceWithValue(node, value, effect);
    return Replace(value);
  }
  return NoChange();
}

// ES #sec-string.fromcodepoint
Reduction JSCallReducer::ReduceStringFromCodePoint(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() != 1) return NoChange();

  Effect effect = n.effect();
  Control control = n.control();
  Node* input = n.Argument(0);

  input = effect = graph()->NewNode(
      simplified()->CheckBounds(p.feedback(),
                                CheckBoundsFlag::kConvertStringAndMinusZero),
      input, jsgraph()->Constant(0x10FFFF + 1), effect, control);

  Node* value =
      graph()->NewNode(simplified()->StringFromSingleCodePoint(), input);
  ReplaceWithValue(node, value, effect);
  return Replace(value);
}

Reduction JSCallReducer::ReduceStringPrototypeIterator(Node* node) {
  // TODO(jgruber): We could reduce here when generating native context
  // independent code, if LowerJSCreateStringIterator were implemented in
  // generic lowering.
  if (broker()->is_native_context_independent()) return NoChange();
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* receiver = effect = graph()->NewNode(
      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);
  Node* iterator = effect =
      graph()->NewNode(javascript()->CreateStringIterator(), receiver,
                       jsgraph()->NoContextConstant(), effect);
  ReplaceWithValue(node, iterator, effect, control);
  return Replace(iterator);
}

Reduction JSCallReducer::ReduceStringIteratorPrototypeNext(Node* node) {
  JSCallNode n(node);
  Node* receiver = n.receiver();
  Effect effect = n.effect();
  Control control = n.control();
  Node* context = n.context();

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() ||
      !inference.AllOfInstanceTypesAre(JS_STRING_ITERATOR_TYPE)) {
    return NoChange();
  }

  Node* string = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()),
      receiver, effect, control);
  Node* index = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()),
      receiver, effect, control);
  Node* length = graph()->NewNode(simplified()->StringLength(), string);

  // branch0: if (index < length)
  Node* check0 =
      graph()->NewNode(simplified()->NumberLessThan(), index, length);
  Node* branch0 =
      graph()->NewNode(common()->Branch(BranchHint::kNone), check0, control);

  Node* etrue0 = effect;
  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
  Node* done_true;
  Node* vtrue0;
  {
    done_true = jsgraph()->FalseConstant();
    vtrue0 = etrue0 = graph()->NewNode(simplified()->StringFromCodePointAt(),
                                       string, index, etrue0, if_true0);

    // Update iterator.[[NextIndex]]
    Node* char_length = graph()->NewNode(simplified()->StringLength(), vtrue0);
    index = graph()->NewNode(simplified()->NumberAdd(), index, char_length);
    etrue0 = graph()->NewNode(
        simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()),
        receiver, index, etrue0, if_true0);
  }

  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
  Node* done_false;
  Node* vfalse0;
  {
    vfalse0 = jsgraph()->UndefinedConstant();
    done_false = jsgraph()->TrueConstant();
  }

  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control);
  Node* value =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), vtrue0,
                       vfalse0, control);
  Node* done =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                       done_true, done_false, control);

  value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
                                    value, done, context, effect);

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES #sec-string.prototype.concat
Reduction JSCallReducer::ReduceStringPrototypeConcat(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  const int parameter_count = n.ArgumentCount();
  if (parameter_count > 1) return NoChange();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* receiver = effect = graph()->NewNode(
      simplified()->CheckString(p.feedback()), n.receiver(), effect, control);

  if (parameter_count == 0) {
    ReplaceWithValue(node, receiver, effect, control);
    return Replace(receiver);
  }

  Node* argument = effect = graph()->NewNode(
      simplified()->CheckString(p.feedback()), n.Argument(0), effect, control);
  Node* receiver_length =
      graph()->NewNode(simplified()->StringLength(), receiver);
  Node* argument_length =
      graph()->NewNode(simplified()->StringLength(), argument);
  Node* length = graph()->NewNode(simplified()->NumberAdd(), receiver_length,
                                  argument_length);
  length = effect = graph()->NewNode(
      simplified()->CheckBounds(p.feedback()), length,
      jsgraph()->Constant(String::kMaxLength + 1), effect, control);

  Node* value = graph()->NewNode(simplified()->StringConcat(), length, receiver,
                                 argument);

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
  // TODO(jgruber): We could reduce here when generating native context
  // independent code, if LowerJSCreatePromise were implemented in generic
  // lowering.
  if (broker()->is_native_context_independent()) return NoChange();

  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());
  PromiseBuiltinReducerAssembler a(this, node, broker());

  // We only inline when we have the executor.
  if (a.ConstructArity() < 1) return NoChange();
  // Only handle builtins Promises, not subclasses.
  if (a.TargetInput() != a.NewTargetInput()) return NoChange();
  if (!dependencies()->DependOnPromiseHookProtector()) return NoChange();

  TNode<Object> subgraph = a.ReducePromiseConstructor(native_context());
  return ReplaceWithSubgraph(&a, subgraph);
}

bool JSCallReducer::DoPromiseChecks(MapInference* inference) {
  if (!inference->HaveMaps()) return false;
  MapHandles const& receiver_maps = inference->GetMaps();

  // Check whether all {receiver_maps} are JSPromise maps and
  // have the initial Promise.prototype as their [[Prototype]].
  for (Handle<Map> map : receiver_maps) {
    MapRef receiver_map(broker(), map);
    if (!receiver_map.IsJSPromiseMap()) return false;
    if (should_disallow_heap_access() && !receiver_map.serialized_prototype()) {
      TRACE_BROKER_MISSING(broker(), "prototype for map " << receiver_map);
      return false;
    }
    if (!receiver_map.prototype().equals(
            native_context().promise_prototype())) {
      return false;
    }
  }

  return true;
}

// ES section #sec-promise.prototype.catch
Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  int arity = p.arity_without_implicit_args();
  Node* receiver = n.receiver();
  Effect effect = n.effect();
  Control control = n.control();

  MapInference inference(broker(), receiver, effect);
  if (!DoPromiseChecks(&inference)) return inference.NoChange();

  if (!dependencies()->DependOnPromiseThenProtector()) {
    return inference.NoChange();
  }
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  // Massage the {node} to call "then" instead by first removing all inputs
  // following the onRejected parameter, and then filling up the parameters
  // to two inputs from the left with undefined.
  Node* target = jsgraph()->Constant(native_context().promise_then());
  NodeProperties::ReplaceValueInput(node, target, 0);
  NodeProperties::ReplaceEffectInput(node, effect);
  for (; arity > 1; --arity) node->RemoveInput(3);
  for (; arity < 2; ++arity) {
    node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
  }
  NodeProperties::ChangeOp(
      node, javascript()->Call(
                JSCallNode::ArityForArgc(arity), p.frequency(), p.feedback(),
                ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(),
                CallFeedbackRelation::kUnrelated));
  return Changed(node).FollowedBy(ReducePromisePrototypeThen(node));
}

Node* JSCallReducer::CreateClosureFromBuiltinSharedFunctionInfo(
    SharedFunctionInfoRef shared, Node* context, Node* effect, Node* control) {
  DCHECK(shared.HasBuiltinId());
  Handle<FeedbackCell> feedback_cell =
      isolate()->factory()->many_closures_cell();
  Callable const callable = Builtins::CallableFor(
      isolate(), static_cast<Builtins::Name>(shared.builtin_id()));
  return graph()->NewNode(
      javascript()->CreateClosure(shared.object(), callable.code()),
      jsgraph()->HeapConstant(feedback_cell), context, effect, control);
}

// ES section #sec-promise.prototype.finally
Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  Node* receiver = n.receiver();
  Node* on_finally = n.ArgumentOrUndefined(0, jsgraph());
  Effect effect = n.effect();
  Control control = n.control();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  MapInference inference(broker(), receiver, effect);
  if (!DoPromiseChecks(&inference)) return inference.NoChange();
  MapHandles const& receiver_maps = inference.GetMaps();

  if (!dependencies()->DependOnPromiseHookProtector()) {
    return inference.NoChange();
  }
  if (!dependencies()->DependOnPromiseThenProtector()) {
    return inference.NoChange();
  }
  if (!dependencies()->DependOnPromiseSpeciesProtector()) {
    return inference.NoChange();
  }
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  // Check if {on_finally} is callable, and if so wrap it into appropriate
  // closures that perform the finalization.
  Node* check = graph()->NewNode(simplified()->ObjectIsCallable(), on_finally);
  Node* branch =
      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);

  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
  Node* etrue = effect;
  Node* catch_true;
  Node* then_true;
  {
    Node* context = jsgraph()->Constant(native_context());
    Node* constructor =
        jsgraph()->Constant(native_context().promise_function());

    // Allocate shared context for the closures below.
    context = etrue =
        graph()->NewNode(javascript()->CreateFunctionContext(
                             native_context().scope_info().object(),
                             PromiseBuiltins::kPromiseFinallyContextLength -
                                 Context::MIN_CONTEXT_SLOTS,
                             FUNCTION_SCOPE),
                         context, etrue, if_true);
    etrue = graph()->NewNode(
        simplified()->StoreField(
            AccessBuilder::ForContextSlot(PromiseBuiltins::kOnFinallySlot)),
        context, on_finally, etrue, if_true);
    etrue = graph()->NewNode(
        simplified()->StoreField(
            AccessBuilder::ForContextSlot(PromiseBuiltins::kConstructorSlot)),
        context, constructor, etrue, if_true);

    // Allocate the closure for the reject case.
    SharedFunctionInfoRef promise_catch_finally(
        broker(), factory()->promise_catch_finally_shared_fun());
    catch_true = etrue = CreateClosureFromBuiltinSharedFunctionInfo(
        promise_catch_finally, context, etrue, if_true);

    // Allocate the closure for the fulfill case.
    SharedFunctionInfoRef promise_then_finally(
        broker(), factory()->promise_then_finally_shared_fun());
    then_true = etrue = CreateClosureFromBuiltinSharedFunctionInfo(
        promise_then_finally, context, etrue, if_true);
  }

  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
  Node* efalse = effect;
  Node* catch_false = on_finally;
  Node* then_false = on_finally;

  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
  Node* catch_finally =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                       catch_true, catch_false, control);
  Node* then_finally =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                       then_true, then_false, control);

  // At this point we definitely know that {receiver} has one of the
  // {receiver_maps}, so insert a MapGuard as a hint for the lowering
  // of the call to "then" below.
  {
    ZoneHandleSet<Map> maps;
    for (Handle<Map> map : receiver_maps) maps.insert(map, graph()->zone());
    effect = graph()->NewNode(simplified()->MapGuard(maps), receiver, effect,
                              control);
  }

  // Massage the {node} to call "then" instead by first removing all inputs
  // following the onFinally parameter, and then replacing the only parameter
  // input with the {on_finally} value.
  Node* target = jsgraph()->Constant(native_context().promise_then());
  NodeProperties::ReplaceValueInput(node, target, n.TargetIndex());
  NodeProperties::ReplaceEffectInput(node, effect);
  NodeProperties::ReplaceControlInput(node, control);
  for (; arity > 2; --arity) node->RemoveInput(2);
  for (; arity < 2; ++arity) {
    node->InsertInput(graph()->zone(), 2, then_finally);
  }
  node->ReplaceInput(2, then_finally);
  node->ReplaceInput(3, catch_finally);
  NodeProperties::ChangeOp(
      node, javascript()->Call(
                JSCallNode::ArityForArgc(arity), p.frequency(), p.feedback(),
                ConvertReceiverMode::kNotNullOrUndefined, p.speculation_mode(),
                CallFeedbackRelation::kUnrelated));
  return Changed(node).FollowedBy(ReducePromisePrototypeThen(node));
}

Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* receiver = n.receiver();
  Node* on_fulfilled = n.ArgumentOrUndefined(0, jsgraph());
  Node* on_rejected = n.ArgumentOrUndefined(1, jsgraph());
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();
  FrameState frame_state = n.frame_state();

  MapInference inference(broker(), receiver, effect);
  if (!DoPromiseChecks(&inference)) return inference.NoChange();

  if (!dependencies()->DependOnPromiseHookProtector()) {
    return inference.NoChange();
  }
  if (!dependencies()->DependOnPromiseSpeciesProtector()) {
    return inference.NoChange();
  }
  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  // Check that {on_fulfilled} is callable.
  on_fulfilled = graph()->NewNode(
      common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
      graph()->NewNode(simplified()->ObjectIsCallable(), on_fulfilled),
      on_fulfilled, jsgraph()->UndefinedConstant());

  // Check that {on_rejected} is callable.
  on_rejected = graph()->NewNode(
      common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
      graph()->NewNode(simplified()->ObjectIsCallable(), on_rejected),
      on_rejected, jsgraph()->UndefinedConstant());

  // Create the resulting JSPromise.
  Node* promise = effect =
      graph()->NewNode(javascript()->CreatePromise(), context, effect);

  // Chain {result} onto {receiver}.
  promise = effect = graph()->NewNode(
      javascript()->PerformPromiseThen(), receiver, on_fulfilled, on_rejected,
      promise, context, frame_state, effect, control);

  // At this point we know that {promise} is going to have the
  // initial Promise map, since even if {PerformPromiseThen}
  // above called into the host rejection tracker, the {promise}
  // doesn't escape to user JavaScript. So bake this information
  // into the graph such that subsequent passes can use the
  // information for further optimizations.
  MapRef promise_map = native_context().promise_function().initial_map();
  effect = graph()->NewNode(
      simplified()->MapGuard(ZoneHandleSet<Map>(promise_map.object())), promise,
      effect, control);

  ReplaceWithValue(node, promise, effect, control);
  return Replace(promise);
}

// ES section #sec-promise.resolve
Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) {
  DisallowHeapAccessIf no_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  Node* receiver = n.receiver();
  Node* value = n.ArgumentOrUndefined(0, jsgraph());
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();
  FrameState frame_state = n.frame_state();

  // Only reduce when the receiver is guaranteed to be a JSReceiver.
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAreJSReceiver()) {
    return NoChange();
  }

  // Morph the {node} into a JSPromiseResolve operation.
  node->ReplaceInput(0, receiver);
  node->ReplaceInput(1, value);
  node->ReplaceInput(2, context);
  node->ReplaceInput(3, frame_state);
  node->ReplaceInput(4, effect);
  node->ReplaceInput(5, control);
  node->TrimInputCount(6);
  NodeProperties::ChangeOp(node, javascript()->PromiseResolve());
  return Changed(node);
}

// ES #sec-typedarray-constructors
Reduction JSCallReducer::ReduceTypedArrayConstructor(
    Node* node, const SharedFunctionInfoRef& shared) {
  JSConstructNode n(node);
  ConstructParameters const& p = n.Parameters();
  int arity = p.arity_without_implicit_args();
  Node* target = n.target();
  Node* arg0 = n.ArgumentOrUndefined(0, jsgraph());
  Node* arg1 = n.ArgumentOrUndefined(1, jsgraph());
  Node* arg2 = n.ArgumentOrUndefined(2, jsgraph());
  Node* new_target = n.new_target();
  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Effect effect = n.effect();
  Control control = n.control();

  // Insert a construct stub frame into the chain of frame states. This will
  // reconstruct the proper frame when deoptimizing within the constructor.
  frame_state = CreateArtificialFrameState(
      node, frame_state, arity, BailoutId::ConstructStubInvoke(),
      FrameStateType::kConstructStub, shared, context, common(), graph());

  // This continuation just returns the newly created JSTypedArray. We
  // pass the_hole as the receiver, just like the builtin construct stub
  // does in this case.
  Node* const parameters[] = {jsgraph()->TheHoleConstant()};
  int const num_parameters = static_cast<int>(arraysize(parameters));
  frame_state = CreateJavaScriptBuiltinContinuationFrameState(
      jsgraph(), shared, Builtins::kGenericLazyDeoptContinuation, target,
      context, parameters, num_parameters, frame_state,
      ContinuationFrameStateMode::LAZY);

  Node* result =
      graph()->NewNode(javascript()->CreateTypedArray(), target, new_target,
                       arg0, arg1, arg2, context, frame_state, effect, control);
  return Replace(result);
}

// ES #sec-get-%typedarray%.prototype-@@tostringtag
Reduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) {
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  NodeVector values(graph()->zone());
  NodeVector effects(graph()->zone());
  NodeVector controls(graph()->zone());

  Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
  control =
      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);

  values.push_back(jsgraph()->UndefinedConstant());
  effects.push_back(effect);
  controls.push_back(graph()->NewNode(common()->IfTrue(), control));

  control = graph()->NewNode(common()->IfFalse(), control);
  Node* receiver_map = effect =
      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
                       receiver, effect, control);
  Node* receiver_bit_field2 = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForMapBitField2()), receiver_map,
      effect, control);
  Node* receiver_elements_kind = graph()->NewNode(
      simplified()->NumberShiftRightLogical(),
      graph()->NewNode(
          simplified()->NumberBitwiseAnd(), receiver_bit_field2,
          jsgraph()->Constant(Map::Bits2::ElementsKindBits::kMask)),
      jsgraph()->Constant(Map::Bits2::ElementsKindBits::kShift));

  // Offset the elements kind by FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
  // so that the branch cascade below is turned into a simple table
  // switch by the ControlFlowOptimizer later.
  receiver_elements_kind = graph()->NewNode(
      simplified()->NumberSubtract(), receiver_elements_kind,
      jsgraph()->Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));

#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                      \
  do {                                                                 \
    Node* check = graph()->NewNode(                                    \
        simplified()->NumberEqual(), receiver_elements_kind,           \
        jsgraph()->Constant(TYPE##_ELEMENTS -                          \
                            FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND));   \
    control = graph()->NewNode(common()->Branch(), check, control);    \
    values.push_back(jsgraph()->Constant(                              \
        broker()->GetTypedArrayStringTag(TYPE##_ELEMENTS)));           \
    effects.push_back(effect);                                         \
    controls.push_back(graph()->NewNode(common()->IfTrue(), control)); \
    control = graph()->NewNode(common()->IfFalse(), control);          \
  } while (false);
  TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

  values.push_back(jsgraph()->UndefinedConstant());
  effects.push_back(effect);
  controls.push_back(control);

  int const count = static_cast<int>(controls.size());
  control = graph()->NewNode(common()->Merge(count), count, &controls.front());
  effects.push_back(control);
  effect =
      graph()->NewNode(common()->EffectPhi(count), count + 1, &effects.front());
  values.push_back(control);
  Node* value =
      graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count),
                       count + 1, &values.front());
  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES #sec-number.isfinite
Reduction JSCallReducer::ReduceNumberIsFinite(Node* node) {
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  Node* input = n.Argument(0);
  Node* value = graph()->NewNode(simplified()->ObjectIsFiniteNumber(), input);
  ReplaceWithValue(node, value);
  return Replace(value);
}

// ES #sec-number.isfinite
Reduction JSCallReducer::ReduceNumberIsInteger(Node* node) {
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  Node* input = n.Argument(0);
  Node* value = graph()->NewNode(simplified()->ObjectIsInteger(), input);
  ReplaceWithValue(node, value);
  return Replace(value);
}

// ES #sec-number.issafeinteger
Reduction JSCallReducer::ReduceNumberIsSafeInteger(Node* node) {
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  Node* input = n.Argument(0);
  Node* value = graph()->NewNode(simplified()->ObjectIsSafeInteger(), input);
  ReplaceWithValue(node, value);
  return Replace(value);
}

// ES #sec-number.isnan
Reduction JSCallReducer::ReduceNumberIsNaN(Node* node) {
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  Node* input = n.Argument(0);
  Node* value = graph()->NewNode(simplified()->ObjectIsNaN(), input);
  ReplaceWithValue(node, value);
  return Replace(value);
}

Reduction JSCallReducer::ReduceMapPrototypeGet(Node* node) {
  // We only optimize if we have target, receiver and key parameters.
  JSCallNode n(node);
  if (n.ArgumentCount() != 1) return NoChange();
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* key = NodeProperties::GetValueInput(node, 2);

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(JS_MAP_TYPE)) {
    return NoChange();
  }

  Node* table = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
      effect, control);

  Node* entry = effect = graph()->NewNode(
      simplified()->FindOrderedHashMapEntry(), table, key, effect, control);

  Node* check = graph()->NewNode(simplified()->NumberEqual(), entry,
                                 jsgraph()->MinusOneConstant());

  Node* branch = graph()->NewNode(common()->Branch(), check, control);

  // Key not found.
  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
  Node* etrue = effect;
  Node* vtrue = jsgraph()->UndefinedConstant();

  // Key found.
  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
  Node* efalse = effect;
  Node* vfalse = efalse = graph()->NewNode(
      simplified()->LoadElement(AccessBuilder::ForOrderedHashMapEntryValue()),
      table, entry, efalse, if_false);

  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
  Node* value = graph()->NewNode(
      common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control);
  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

Reduction JSCallReducer::ReduceMapPrototypeHas(Node* node) {
  // We only optimize if we have target, receiver and key parameters.
  JSCallNode n(node);
  if (n.ArgumentCount() != 1) return NoChange();
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* key = NodeProperties::GetValueInput(node, 2);

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(JS_MAP_TYPE)) {
    return NoChange();
  }

  Node* table = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
      effect, control);

  Node* index = effect = graph()->NewNode(
      simplified()->FindOrderedHashMapEntry(), table, key, effect, control);

  Node* value = graph()->NewNode(simplified()->NumberEqual(), index,
                                 jsgraph()->MinusOneConstant());
  value = graph()->NewNode(simplified()->BooleanNot(), value);

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

namespace {

InstanceType InstanceTypeForCollectionKind(CollectionKind kind) {
  switch (kind) {
    case CollectionKind::kMap:
      return JS_MAP_TYPE;
    case CollectionKind::kSet:
      return JS_SET_TYPE;
  }
  UNREACHABLE();
}

}  // namespace

Reduction JSCallReducer::ReduceCollectionIteration(
    Node* node, CollectionKind collection_kind, IterationKind iteration_kind) {
  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* context = NodeProperties::GetContextInput(node);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  InstanceType type = InstanceTypeForCollectionKind(collection_kind);
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(type)) {
    return NoChange();
  }

  Node* js_create_iterator = effect = graph()->NewNode(
      javascript()->CreateCollectionIterator(collection_kind, iteration_kind),
      receiver, context, effect, control);
  ReplaceWithValue(node, js_create_iterator, effect);
  return Replace(js_create_iterator);
}

Reduction JSCallReducer::ReduceCollectionPrototypeSize(
    Node* node, CollectionKind collection_kind) {
  DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  InstanceType type = InstanceTypeForCollectionKind(collection_kind);
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(type)) {
    return NoChange();
  }

  Node* table = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
      effect, control);
  Node* value = effect = graph()->NewNode(
      simplified()->LoadField(
          AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
      table, effect, control);
  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
    Node* node, int entry_size, Handle<HeapObject> empty_collection,
    InstanceType collection_iterator_instance_type_first,
    InstanceType collection_iterator_instance_type_last) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Node* receiver = n.receiver();
  Node* context = n.context();
  Effect effect = n.effect();
  Control control = n.control();

  // A word of warning to begin with: This whole method might look a bit
  // strange at times, but that's mostly because it was carefully handcrafted
  // to allow for full escape analysis and scalar replacement of both the
  // collection iterator object and the iterator results, including the
  // key-value arrays in case of Set/Map entry iteration.
  //
  // TODO(turbofan): Currently the escape analysis (and the store-load
  // forwarding) is unable to eliminate the allocations for the key-value
  // arrays in case of Set/Map entry iteration, and we should investigate
  // how to update the escape analysis / arrange the graph in a way that
  // this becomes possible.

  InstanceType receiver_instance_type;
  {
    MapInference inference(broker(), receiver, effect);
    if (!inference.HaveMaps()) return NoChange();
    MapHandles const& receiver_maps = inference.GetMaps();
    receiver_instance_type = MapRef(broker(), receiver_maps[0]).instance_type();
    for (size_t i = 1; i < receiver_maps.size(); ++i) {
      if (MapRef(broker(), receiver_maps[i]).instance_type() !=
          receiver_instance_type) {
        return inference.NoChange();
      }
    }
    if (receiver_instance_type < collection_iterator_instance_type_first ||
        receiver_instance_type > collection_iterator_instance_type_last) {
      return inference.NoChange();
    }
    inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                        control, p.feedback());
  }

  // Transition the JSCollectionIterator {receiver} if necessary
  // (i.e. there were certain mutations while we're iterating).
  {
    Node* done_loop;
    Node* done_eloop;
    Node* loop = control =
        graph()->NewNode(common()->Loop(2), control, control);
    Node* eloop = effect =
        graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    NodeProperties::MergeControlToEnd(graph(), common(), terminate);

    // Check if reached the final table of the {receiver}.
    Node* table = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
        receiver, effect, control);
    Node* next_table = effect =
        graph()->NewNode(simplified()->LoadField(
                             AccessBuilder::ForOrderedHashMapOrSetNextTable()),
                         table, effect, control);
    Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), next_table);
    control =
        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);

    // Abort the {loop} when we reach the final table.
    done_loop = graph()->NewNode(common()->IfTrue(), control);
    done_eloop = effect;

    // Migrate to the {next_table} otherwise.
    control = graph()->NewNode(common()->IfFalse(), control);

    // Self-heal the {receiver}s index.
    Node* index = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
        receiver, effect, control);
    Callable const callable =
        Builtins::CallableFor(isolate(), Builtins::kOrderedHashTableHealIndex);
    auto call_descriptor = Linkage::GetStubCallDescriptor(
        graph()->zone(), callable.descriptor(),
        callable.descriptor().GetStackParameterCount(),
        CallDescriptor::kNoFlags, Operator::kEliminatable);
    index = effect =
        graph()->NewNode(common()->Call(call_descriptor),
                         jsgraph()->HeapConstant(callable.code()), table, index,
                         jsgraph()->NoContextConstant(), effect);

    index = effect = graph()->NewNode(
        common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), index,
        effect, control);

    // Update the {index} and {table} on the {receiver}.
    effect = graph()->NewNode(
        simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorIndex()),
        receiver, index, effect, control);
    effect = graph()->NewNode(
        simplified()->StoreField(AccessBuilder::ForJSCollectionIteratorTable()),
        receiver, next_table, effect, control);

    // Tie the knot.
    loop->ReplaceInput(1, control);
    eloop->ReplaceInput(1, effect);

    control = done_loop;
    effect = done_eloop;
  }

  // Get current index and table from the JSCollectionIterator {receiver}.
  Node* index = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorIndex()),
      receiver, effect, control);
  Node* table = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSCollectionIteratorTable()),
      receiver, effect, control);

  // Create the {JSIteratorResult} first to ensure that we always have
  // a dominating Allocate node for the allocation folding phase.
  Node* iterator_result = effect = graph()->NewNode(
      javascript()->CreateIterResultObject(), jsgraph()->UndefinedConstant(),
      jsgraph()->TrueConstant(), context, effect);

  // Look for the next non-holey key, starting from {index} in the {table}.
  Node* controls[2];
  Node* effects[3];
  {
    // Compute the currently used capacity.
    Node* number_of_buckets = effect = graph()->NewNode(
        simplified()->LoadField(
            AccessBuilder::ForOrderedHashMapOrSetNumberOfBuckets()),
        table, effect, control);
    Node* number_of_elements = effect = graph()->NewNode(
        simplified()->LoadField(
            AccessBuilder::ForOrderedHashMapOrSetNumberOfElements()),
        table, effect, control);
    Node* number_of_deleted_elements = effect = graph()->NewNode(
        simplified()->LoadField(
            AccessBuilder::ForOrderedHashMapOrSetNumberOfDeletedElements()),
        table, effect, control);
    Node* used_capacity =
        graph()->NewNode(simplified()->NumberAdd(), number_of_elements,
                         number_of_deleted_elements);

    // Skip holes and update the {index}.
    Node* loop = graph()->NewNode(common()->Loop(2), control, control);
    Node* eloop =
        graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
    Node* terminate = graph()->NewNode(common()->Terminate(), eloop, loop);
    NodeProperties::MergeControlToEnd(graph(), common(), terminate);
    Node* iloop = graph()->NewNode(
        common()->Phi(MachineRepresentation::kTagged, 2), index, index, loop);

    Node* index = effect = graph()->NewNode(
        common()->TypeGuard(TypeCache::Get()->kFixedArrayLengthType), iloop,
        eloop, control);
    {
      Node* check0 = graph()->NewNode(simplified()->NumberLessThan(), index,
                                      used_capacity);
      Node* branch0 =
          graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, loop);

      Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
      Node* efalse0 = effect;
      {
        // Mark the {receiver} as exhausted.
        efalse0 = graph()->NewNode(
            simplified()->StoreField(
                AccessBuilder::ForJSCollectionIteratorTable()),
            receiver, jsgraph()->HeapConstant(empty_collection), efalse0,
            if_false0);

        controls[0] = if_false0;
        effects[0] = efalse0;
      }

      Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
      Node* etrue0 = effect;
      {
        // Load the key of the entry.
        STATIC_ASSERT(OrderedHashMap::HashTableStartIndex() ==
                      OrderedHashSet::HashTableStartIndex());
        Node* entry_start_position = graph()->NewNode(
            simplified()->NumberAdd(),
            graph()->NewNode(
                simplified()->NumberAdd(),
                graph()->NewNode(simplified()->NumberMultiply(), index,
                                 jsgraph()->Constant(entry_size)),
                number_of_buckets),
            jsgraph()->Constant(OrderedHashMap::HashTableStartIndex()));
        Node* entry_key = etrue0 = graph()->NewNode(
            simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
            table, entry_start_position, etrue0, if_true0);

        // Advance the index.
        index = graph()->NewNode(simplified()->NumberAdd(), index,
                                 jsgraph()->OneConstant());

        Node* check1 =
            graph()->NewNode(simplified()->ReferenceEqual(), entry_key,
                             jsgraph()->TheHoleConstant());
        Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
                                         check1, if_true0);

        {
          // Abort loop with resulting value.
          Node* control = graph()->NewNode(common()->IfFalse(), branch1);
          Node* effect = etrue0;
          Node* value = effect =
              graph()->NewNode(common()->TypeGuard(Type::NonInternal()),
                               entry_key, effect, control);
          Node* done = jsgraph()->FalseConstant();

          // Advance the index on the {receiver}.
          effect = graph()->NewNode(
              simplified()->StoreField(
                  AccessBuilder::ForJSCollectionIteratorIndex()),
              receiver, index, effect, control);

          // The actual {value} depends on the {receiver} iteration type.
          switch (receiver_instance_type) {
            case JS_MAP_KEY_ITERATOR_TYPE:
            case JS_SET_VALUE_ITERATOR_TYPE:
              break;

            case JS_SET_KEY_VALUE_ITERATOR_TYPE:
              value = effect =
                  graph()->NewNode(javascript()->CreateKeyValueArray(), value,
                                   value, context, effect);
              break;

            case JS_MAP_VALUE_ITERATOR_TYPE:
              value = effect = graph()->NewNode(
                  simplified()->LoadElement(
                      AccessBuilder::ForFixedArrayElement()),
                  table,
                  graph()->NewNode(
                      simplified()->NumberAdd(), entry_start_position,
                      jsgraph()->Constant(OrderedHashMap::kValueOffset)),
                  effect, control);
              break;

            case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
              value = effect = graph()->NewNode(
                  simplified()->LoadElement(
                      AccessBuilder::ForFixedArrayElement()),
                  table,
                  graph()->NewNode(
                      simplified()->NumberAdd(), entry_start_position,
                      jsgraph()->Constant(OrderedHashMap::kValueOffset)),
                  effect, control);
              value = effect =
                  graph()->NewNode(javascript()->CreateKeyValueArray(),
                                   entry_key, value, context, effect);
              break;

            default:
              UNREACHABLE();
              break;
          }

          // Store final {value} and {done} into the {iterator_result}.
          effect =
              graph()->NewNode(simplified()->StoreField(
                                   AccessBuilder::ForJSIteratorResultValue()),
                               iterator_result, value, effect, control);
          effect =
              graph()->NewNode(simplified()->StoreField(
                                   AccessBuilder::ForJSIteratorResultDone()),
                               iterator_result, done, effect, control);

          controls[1] = control;
          effects[1] = effect;
        }

        // Continue with next loop index.
        loop->ReplaceInput(1, graph()->NewNode(common()->IfTrue(), branch1));
        eloop->ReplaceInput(1, etrue0);
        iloop->ReplaceInput(1, index);
      }
    }

    control = effects[2] = graph()->NewNode(common()->Merge(2), 2, controls);
    effect = graph()->NewNode(common()->EffectPhi(2), 3, effects);
  }

  // Yield the final {iterator_result}.
  ReplaceWithValue(node, iterator_result, effect, control);
  return Replace(iterator_result);
}

Reduction JSCallReducer::ReduceArrayBufferIsView(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  Node* value = n.ArgumentOrUndefined(0, jsgraph());
  RelaxEffectsAndControls(node);
  node->ReplaceInput(0, value);
  node->TrimInputCount(1);
  NodeProperties::ChangeOp(node, simplified()->ObjectIsArrayBufferView());
  return Changed(node);
}

Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
    Node* node, InstanceType instance_type, FieldAccess const& access) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() ||
      !inference.AllOfInstanceTypesAre(instance_type)) {
    return NoChange();
  }

  // Load the {receiver}s field.
  Node* value = effect = graph()->NewNode(simplified()->LoadField(access),
                                          receiver, effect, control);

  // See if we can skip the detaching check.
  if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
    // Check whether {receiver}s JSArrayBuffer was detached.
    Node* buffer = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
        receiver, effect, control);
    Node* buffer_bit_field = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
        buffer, effect, control);
    Node* check = graph()->NewNode(
        simplified()->NumberEqual(),
        graph()->NewNode(
            simplified()->NumberBitwiseAnd(), buffer_bit_field,
            jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
        jsgraph()->ZeroConstant());

    // TODO(turbofan): Ideally we would bail out here if the {receiver}s
    // JSArrayBuffer was detached, but there's no way to guard against
    // deoptimization loops right now, since the JSCall {node} is usually
    // created from a LOAD_IC inlining, and so there's no CALL_IC slot
    // from which we could use the speculation bit.
    value = graph()->NewNode(
        common()->Select(MachineRepresentation::kTagged, BranchHint::kTrue),
        check, value, jsgraph()->ZeroConstant());
  }

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

namespace {
uint32_t ExternalArrayElementSize(const ExternalArrayType element_type) {
  switch (element_type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
  case kExternal##Type##Array:                    \
    DCHECK_LE(sizeof(ctype), 8);                  \
    return sizeof(ctype);
    TYPED_ARRAYS(TYPED_ARRAY_CASE)
    default:
      UNREACHABLE();
#undef TYPED_ARRAY_CASE
  }
}
}  // namespace

Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access,
                                              ExternalArrayType element_type) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  size_t const element_size = ExternalArrayElementSize(element_type);
  Effect effect = n.effect();
  Control control = n.control();
  Node* receiver = n.receiver();
  Node* offset = n.ArgumentOr(0, jsgraph()->ZeroConstant());
  Node* value = nullptr;
  if (access == DataViewAccess::kSet) {
    value = n.ArgumentOrUndefined(1, jsgraph());
  }
  const int endian_index = (access == DataViewAccess::kGet ? 1 : 2);
  Node* is_little_endian =
      n.ArgumentOr(endian_index, jsgraph()->FalseConstant());

  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  // Only do stuff if the {receiver} is really a DataView.
  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() ||
      !inference.AllOfInstanceTypesAre(JS_DATA_VIEW_TYPE)) {
    return NoChange();
  }

  // Check that the {offset} is within range for the {receiver}.
  HeapObjectMatcher m(receiver);
  if (m.HasResolvedValue() && m.Ref(broker()).IsJSDataView()) {
    // We only deal with DataViews here whose [[ByteLength]] is at least
    // {element_size}, as for all other DataViews it'll be out-of-bounds.
    JSDataViewRef dataview = m.Ref(broker()).AsJSDataView();
    size_t length = dataview.byte_length();
    if (length < element_size) return NoChange();

    // Check that the {offset} is within range of the {length}.
    Node* byte_length = jsgraph()->Constant(length - (element_size - 1));
    offset = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
                                       offset, byte_length, effect, control);
  } else {
    // We only deal with DataViews here that have Smi [[ByteLength]]s.
    Node* byte_length = effect =
        graph()->NewNode(simplified()->LoadField(
                             AccessBuilder::ForJSArrayBufferViewByteLength()),
                         receiver, effect, control);

    if (element_size > 1) {
      // For non-byte accesses we also need to check that the {offset}
      // plus the {element_size}-1 fits within the given {byte_length}.
      // So to keep this as a single check on the {offset}, we subtract
      // the {element_size}-1 from the {byte_length} here (clamped to
      // positive safe integer range), and perform a check against that
      // with the {offset} below.
      byte_length = graph()->NewNode(
          simplified()->NumberMax(), jsgraph()->ZeroConstant(),
          graph()->NewNode(simplified()->NumberSubtract(), byte_length,
                           jsgraph()->Constant(element_size - 1)));
    }

    // Check that the {offset} is within range of the {byte_length}.
    offset = effect = graph()->NewNode(simplified()->CheckBounds(p.feedback()),
                                       offset, byte_length, effect, control);
  }

  // Coerce {is_little_endian} to boolean.
  is_little_endian =
      graph()->NewNode(simplified()->ToBoolean(), is_little_endian);

  // Coerce {value} to Number.
  if (access == DataViewAccess::kSet) {
    value = effect = graph()->NewNode(
        simplified()->SpeculativeToNumber(NumberOperationHint::kNumberOrOddball,
                                          p.feedback()),
        value, effect, control);
  }

  // We need to retain either the {receiver} itself or it's backing
  // JSArrayBuffer to make sure that the GC doesn't collect the raw
  // memory. We default to {receiver} here, and only use the buffer
  // if we anyways have to load it (to reduce register pressure).
  Node* buffer_or_receiver = receiver;

  if (!dependencies()->DependOnArrayBufferDetachingProtector()) {
    // Get the underlying buffer and check that it has not been detached.
    Node* buffer = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
        receiver, effect, control);

    // Bail out if the {buffer} was detached.
    Node* buffer_bit_field = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
        buffer, effect, control);
    Node* check = graph()->NewNode(
        simplified()->NumberEqual(),
        graph()->NewNode(
            simplified()->NumberBitwiseAnd(), buffer_bit_field,
            jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
        jsgraph()->ZeroConstant());
    effect = graph()->NewNode(
        simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached,
                              p.feedback()),
        check, effect, control);

    // We can reduce register pressure by holding on to the {buffer}
    // now to retain the backing store memory.
    buffer_or_receiver = buffer;
  }

  // Load the {receiver}s data pointer.
  Node* data_pointer = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSDataViewDataPointer()),
      receiver, effect, control);

  switch (access) {
    case DataViewAccess::kGet:
      // Perform the load.
      value = effect = graph()->NewNode(
          simplified()->LoadDataViewElement(element_type), buffer_or_receiver,
          data_pointer, offset, is_little_endian, effect, control);
      break;
    case DataViewAccess::kSet:
      // Perform the store.
      effect = graph()->NewNode(
          simplified()->StoreDataViewElement(element_type), buffer_or_receiver,
          data_pointer, offset, value, is_little_endian, effect, control);
      value = jsgraph()->UndefinedConstant();
      break;
  }

  ReplaceWithValue(node, value, effect, control);
  return Changed(value);
}

// ES6 section 18.2.2 isFinite ( number )
Reduction JSCallReducer::ReduceGlobalIsFinite(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->FalseConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* input = n.Argument(0);

  input = effect =
      graph()->NewNode(simplified()->SpeculativeToNumber(
                           NumberOperationHint::kNumberOrOddball, p.feedback()),
                       input, effect, control);
  Node* value = graph()->NewNode(simplified()->NumberIsFinite(), input);
  ReplaceWithValue(node, value, effect);
  return Replace(value);
}

// ES6 section 18.2.3 isNaN ( number )
Reduction JSCallReducer::ReduceGlobalIsNaN(Node* node) {
  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->TrueConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* input = n.Argument(0);

  input = effect =
      graph()->NewNode(simplified()->SpeculativeToNumber(
                           NumberOperationHint::kNumberOrOddball, p.feedback()),
                       input, effect, control);
  Node* value = graph()->NewNode(simplified()->NumberIsNaN(), input);
  ReplaceWithValue(node, value, effect);
  return Replace(value);
}

// ES6 section 20.3.4.10 Date.prototype.getTime ( )
Reduction JSCallReducer::ReduceDatePrototypeGetTime(Node* node) {
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  MapInference inference(broker(), receiver, effect);
  if (!inference.HaveMaps() || !inference.AllOfInstanceTypesAre(JS_DATE_TYPE)) {
    return NoChange();
  }

  Node* value = effect =
      graph()->NewNode(simplified()->LoadField(AccessBuilder::ForJSDateValue()),
                       receiver, effect, control);
  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES6 section 20.3.3.1 Date.now ( )
Reduction JSCallReducer::ReduceDateNow(Node* node) {
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* value = effect =
      graph()->NewNode(simplified()->DateNow(), effect, control);
  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

// ES6 section 20.1.2.13 Number.parseInt ( string, radix )
Reduction JSCallReducer::ReduceNumberParseInt(Node* node) {
  JSCallNode n(node);
  if (n.ArgumentCount() < 1) {
    Node* value = jsgraph()->NaNConstant();
    ReplaceWithValue(node, value);
    return Replace(value);
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Node* object = n.Argument(0);
  Node* radix = n.ArgumentOrUndefined(1, jsgraph());
  node->ReplaceInput(0, object);
  node->ReplaceInput(1, radix);
  node->ReplaceInput(2, context);
  node->ReplaceInput(3, frame_state);
  node->ReplaceInput(4, effect);
  node->ReplaceInput(5, control);
  node->TrimInputCount(6);
  NodeProperties::ChangeOp(node, javascript()->ParseInt());
  return Changed(node);
}

Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
  DisallowHeapAccessIf disallow_heap_access(should_disallow_heap_access());

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (FLAG_force_slow_path) return NoChange();
  if (n.ArgumentCount() < 1) return NoChange();

  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* regexp = n.receiver();

  // Only the initial JSRegExp map is valid here, since the following lastIndex
  // check as well as the lowered builtin call rely on a known location of the
  // lastIndex field.
  Handle<Map> regexp_initial_map =
      native_context().regexp_function().initial_map().object();

  MapInference inference(broker(), regexp, effect);
  if (!inference.Is(regexp_initial_map)) return inference.NoChange();
  MapHandles const& regexp_maps = inference.GetMaps();

  ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
  AccessInfoFactory access_info_factory(broker(), dependencies(),
                                        graph()->zone());
  if (should_disallow_heap_access()) {
    // Obtain precomputed access infos from the broker.
    for (auto map : regexp_maps) {
      MapRef map_ref(broker(), map);
      PropertyAccessInfo access_info = broker()->GetPropertyAccessInfo(
          map_ref, NameRef(broker(), isolate()->factory()->exec_string()),
          AccessMode::kLoad);
      access_infos.push_back(access_info);
    }
  } else {
    // Compute property access info for "exec" on {resolution}.
    access_info_factory.ComputePropertyAccessInfos(
        MapHandles(regexp_maps.begin(), regexp_maps.end()),
        factory()->exec_string(), AccessMode::kLoad, &access_infos);
  }

  PropertyAccessInfo ai_exec =
      access_info_factory.FinalizePropertyAccessInfosAsOne(access_infos,
                                                           AccessMode::kLoad);
  if (ai_exec.IsInvalid()) return inference.NoChange();

  // If "exec" has been modified on {regexp}, we can't do anything.
  if (ai_exec.IsDataConstant()) {
    Handle<JSObject> holder;
    // Do not reduce if the exec method is not on the prototype chain.
    if (!ai_exec.holder().ToHandle(&holder)) return inference.NoChange();

    JSObjectRef holder_ref(broker(), holder);

    // Bail out if the exec method is not the original one.
    base::Optional<ObjectRef> constant = holder_ref.GetOwnDataProperty(
        ai_exec.field_representation(), ai_exec.field_index());
    if (!constant.has_value() ||
        !constant->equals(native_context().regexp_exec_function())) {
      return inference.NoChange();
    }

    // Add proper dependencies on the {regexp}s [[Prototype]]s.
    dependencies()->DependOnStablePrototypeChains(
        ai_exec.lookup_start_object_maps(), kStartAtPrototype,
        JSObjectRef(broker(), holder));
  } else {
    return inference.NoChange();
  }

  inference.RelyOnMapsPreferStability(dependencies(), jsgraph(), &effect,
                                      control, p.feedback());

  Node* context = n.context();
  FrameState frame_state = n.frame_state();
  Node* search = n.Argument(0);
  Node* search_string = effect = graph()->NewNode(
      simplified()->CheckString(p.feedback()), search, effect, control);

  Node* lastIndex = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSRegExpLastIndex()), regexp,
      effect, control);

  Node* lastIndexSmi = effect = graph()->NewNode(
      simplified()->CheckSmi(p.feedback()), lastIndex, effect, control);

  Node* is_positive = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
                                       jsgraph()->ZeroConstant(), lastIndexSmi);

  effect = graph()->NewNode(
      simplified()->CheckIf(DeoptimizeReason::kNotASmi, p.feedback()),
      is_positive, effect, control);

  node->ReplaceInput(0, regexp);
  node->ReplaceInput(1, search_string);
  node->ReplaceInput(2, context);
  node->ReplaceInput(3, frame_state);
  node->ReplaceInput(4, effect);
  node->ReplaceInput(5, control);
  node->TrimInputCount(6);
  NodeProperties::ChangeOp(node, javascript()->RegExpTest());
  return Changed(node);
}

// ES section #sec-number-constructor
Reduction JSCallReducer::ReduceNumberConstructor(Node* node) {
  JSCallNode n(node);
  Node* target = n.target();
  Node* receiver = n.receiver();
  Node* value = n.ArgumentOr(0, jsgraph()->ZeroConstant());
  Node* context = n.context();
  FrameState frame_state = n.frame_state();

  // Create the artificial frame state in the middle of the Number constructor.
  SharedFunctionInfoRef shared_info =
      native_context().number_function().shared();
  Node* stack_parameters[] = {receiver};
  int stack_parameter_count = arraysize(stack_parameters);
  Node* continuation_frame_state =
      CreateJavaScriptBuiltinContinuationFrameState(
          jsgraph(), shared_info, Builtins::kGenericLazyDeoptContinuation,
          target, context, stack_parameters, stack_parameter_count, frame_state,
          ContinuationFrameStateMode::LAZY);

  // Convert the {value} to a Number.
  NodeProperties::ReplaceValueInputs(node, value);
  NodeProperties::ChangeOp(node, javascript()->ToNumberConvertBigInt());
  NodeProperties::ReplaceFrameStateInput(node, continuation_frame_state);
  return Changed(node);
}

Reduction JSCallReducer::ReduceBigIntAsUintN(Node* node) {
  if (!jsgraph()->machine()->Is64()) return NoChange();

  JSCallNode n(node);
  CallParameters const& p = n.Parameters();
  if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
    return NoChange();
  }
  if (n.ArgumentCount() < 2) {
    return NoChange();
  }

  Effect effect = n.effect();
  Control control = n.control();
  Node* bits = n.Argument(0);
  Node* value = n.Argument(1);

  NumberMatcher matcher(bits);
  if (matcher.IsInteger() && matcher.IsInRange(0, 64)) {
    const int bits_value = static_cast<int>(matcher.ResolvedValue());
    value = effect = graph()->NewNode(simplified()->CheckBigInt(p.feedback()),
                                      value, effect, control);
    value = graph()->NewNode(simplified()->BigIntAsUintN(bits_value), value);
    ReplaceWithValue(node, value, effect);
    return Replace(value);
  }

  return NoChange();
}

Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }

Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }

Factory* JSCallReducer::factory() const { return isolate()->factory(); }

NativeContextRef JSCallReducer::native_context() const {
  return broker()->target_native_context();
}

CommonOperatorBuilder* JSCallReducer::common() const {
  return jsgraph()->common();
}

JSOperatorBuilder* JSCallReducer::javascript() const {
  return jsgraph()->javascript();
}

SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
  return jsgraph()->simplified();
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
