// Copyright 2013 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.

#ifndef V8_COMPILER_JS_OPERATOR_H_
#define V8_COMPILER_JS_OPERATOR_H_

#include "src/base/compiler-specific.h"
#include "src/codegen/tnode.h"
#include "src/compiler/feedback-source.h"
#include "src/compiler/globals.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/compiler/opcodes.h"
#include "src/handles/maybe-handles.h"
#include "src/objects/type-hints.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {

class AllocationSite;
class ObjectBoilerplateDescription;
class ArrayBoilerplateDescription;
class FeedbackCell;
class SharedFunctionInfo;

namespace compiler {

// Forward declarations.
class JSGraph;
class Operator;
struct JSOperatorGlobalCache;

// Macro lists.
#define JS_UNOP_WITH_FEEDBACK(V) \
  JS_BITWISE_UNOP_LIST(V)        \
  JS_ARITH_UNOP_LIST(V)

#define JS_BINOP_WITH_FEEDBACK(V) \
  JS_ARITH_BINOP_LIST(V)          \
  JS_BITWISE_BINOP_LIST(V)        \
  JS_COMPARE_BINOP_LIST(V)        \
  V(JSInstanceOf, InstanceOf)

// Predicates.
class JSOperator final : public AllStatic {
 public:
  static constexpr bool IsUnaryWithFeedback(Operator::Opcode opcode) {
#define CASE(Name, ...)   \
  case IrOpcode::k##Name: \
    return true;
    switch (opcode) {
      JS_UNOP_WITH_FEEDBACK(CASE);
      default:
        return false;
    }
#undef CASE
    return false;
  }

  static constexpr bool IsBinaryWithFeedback(Operator::Opcode opcode) {
#define CASE(Name, ...)   \
  case IrOpcode::k##Name: \
    return true;
    switch (opcode) {
      JS_BINOP_WITH_FEEDBACK(CASE);
      default:
        return false;
    }
#undef CASE
    return false;
  }
};

// Defines the frequency a given Call/Construct site was executed. For some
// call sites the frequency is not known.
class CallFrequency final {
 public:
  CallFrequency() : value_(std::numeric_limits<float>::quiet_NaN()) {}
  explicit CallFrequency(float value) : value_(value) {
    DCHECK(!std::isnan(value));
  }

  bool IsKnown() const { return !IsUnknown(); }
  bool IsUnknown() const { return std::isnan(value_); }
  float value() const {
    DCHECK(IsKnown());
    return value_;
  }

  bool operator==(CallFrequency const& that) const {
    return bit_cast<uint32_t>(this->value_) == bit_cast<uint32_t>(that.value_);
  }
  bool operator!=(CallFrequency const& that) const { return !(*this == that); }

  friend size_t hash_value(CallFrequency const& f) {
    return bit_cast<uint32_t>(f.value_);
  }

  static constexpr float kNoFeedbackCallFrequency = -1;

 private:
  float value_;
};

std::ostream& operator<<(std::ostream&, CallFrequency const&);

// Defines the flags for a JavaScript call forwarding parameters. This
// is used as parameter by JSConstructForwardVarargs operators.
class ConstructForwardVarargsParameters final {
 public:
  ConstructForwardVarargsParameters(size_t arity, uint32_t start_index)
      : bit_field_(ArityField::encode(arity) |
                   StartIndexField::encode(start_index)) {}

  size_t arity() const { return ArityField::decode(bit_field_); }
  uint32_t start_index() const { return StartIndexField::decode(bit_field_); }

  bool operator==(ConstructForwardVarargsParameters const& that) const {
    return this->bit_field_ == that.bit_field_;
  }
  bool operator!=(ConstructForwardVarargsParameters const& that) const {
    return !(*this == that);
  }

 private:
  friend size_t hash_value(ConstructForwardVarargsParameters const& p) {
    return p.bit_field_;
  }

  using ArityField = base::BitField<size_t, 0, 16>;
  using StartIndexField = base::BitField<uint32_t, 16, 16>;

  uint32_t const bit_field_;
};

std::ostream& operator<<(std::ostream&,
                         ConstructForwardVarargsParameters const&);

ConstructForwardVarargsParameters const& ConstructForwardVarargsParametersOf(
    Operator const*) V8_WARN_UNUSED_RESULT;

// Defines the arity (parameters plus the target and new target) and the
// feedback for a JavaScript constructor call. This is used as a parameter by
// JSConstruct, JSConstructWithArrayLike, and JSConstructWithSpread operators.
class ConstructParameters final {
 public:
  // A separate declaration to get around circular declaration dependencies.
  // Checked to equal JSConstructNode::kExtraInputCount below.
  static constexpr int kExtraConstructInputCount = 3;

  ConstructParameters(uint32_t arity, CallFrequency const& frequency,
                      FeedbackSource const& feedback)
      : arity_(arity), frequency_(frequency), feedback_(feedback) {
    DCHECK_GE(arity, kExtraConstructInputCount);
    DCHECK(is_int32(arity));
  }

  // TODO(jgruber): Consider removing `arity()` and just storing the arity
  // without extra args in ConstructParameters. Every spot that creates
  // ConstructParameters artifically adds the extra args. Every spot that uses
  // ConstructParameters artificially subtracts the extra args.
  // We keep them for now for consistency with other spots
  // that expect `arity()` to include extra args.
  uint32_t arity() const { return arity_; }
  int arity_without_implicit_args() const {
    return static_cast<int>(arity_ - kExtraConstructInputCount);
  }

  CallFrequency const& frequency() const { return frequency_; }
  FeedbackSource const& feedback() const { return feedback_; }

 private:
  uint32_t const arity_;
  CallFrequency const frequency_;
  FeedbackSource const feedback_;
};

bool operator==(ConstructParameters const&, ConstructParameters const&);
bool operator!=(ConstructParameters const&, ConstructParameters const&);

size_t hash_value(ConstructParameters const&);

std::ostream& operator<<(std::ostream&, ConstructParameters const&);

ConstructParameters const& ConstructParametersOf(Operator const*);

// Defines the flags for a JavaScript call forwarding parameters. This
// is used as parameter by JSCallForwardVarargs operators.
class CallForwardVarargsParameters final {
 public:
  CallForwardVarargsParameters(size_t arity, uint32_t start_index)
      : bit_field_(ArityField::encode(arity) |
                   StartIndexField::encode(start_index)) {}

  size_t arity() const { return ArityField::decode(bit_field_); }
  uint32_t start_index() const { return StartIndexField::decode(bit_field_); }

  bool operator==(CallForwardVarargsParameters const& that) const {
    return this->bit_field_ == that.bit_field_;
  }
  bool operator!=(CallForwardVarargsParameters const& that) const {
    return !(*this == that);
  }

 private:
  friend size_t hash_value(CallForwardVarargsParameters const& p) {
    return p.bit_field_;
  }

  using ArityField = base::BitField<size_t, 0, 15>;
  using StartIndexField = base::BitField<uint32_t, 15, 15>;

  uint32_t const bit_field_;
};

std::ostream& operator<<(std::ostream&, CallForwardVarargsParameters const&);

CallForwardVarargsParameters const& CallForwardVarargsParametersOf(
    Operator const*) V8_WARN_UNUSED_RESULT;

// Defines the arity (parameters plus the target and receiver) and the call
// flags for a JavaScript function call. This is used as a parameter by JSCall,
// JSCallWithArrayLike and JSCallWithSpread operators.
class CallParameters final {
 public:
  // A separate declaration to get around circular declaration dependencies.
  // Checked to equal JSCallNode::kExtraInputCount below.
  static constexpr int kExtraCallInputCount = 3;

  CallParameters(size_t arity, CallFrequency const& frequency,
                 FeedbackSource const& feedback,
                 ConvertReceiverMode convert_mode,
                 SpeculationMode speculation_mode,
                 CallFeedbackRelation feedback_relation)
      : bit_field_(ArityField::encode(arity) |
                   CallFeedbackRelationField::encode(feedback_relation) |
                   SpeculationModeField::encode(speculation_mode) |
                   ConvertReceiverModeField::encode(convert_mode)),
        frequency_(frequency),
        feedback_(feedback) {
    // CallFeedbackRelation is ignored if the feedback slot is invalid.
    DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
                   feedback.IsValid());
    DCHECK_IMPLIES(!feedback.IsValid(),
                   feedback_relation == CallFeedbackRelation::kUnrelated);
    DCHECK_GE(arity, kExtraCallInputCount);
    DCHECK(is_int32(arity));
  }

  // TODO(jgruber): Consider removing `arity()` and just storing the arity
  // without extra args in CallParameters.
  size_t arity() const { return ArityField::decode(bit_field_); }
  int arity_without_implicit_args() const {
    return static_cast<int>(arity() - kExtraCallInputCount);
  }

  CallFrequency const& frequency() const { return frequency_; }
  ConvertReceiverMode convert_mode() const {
    return ConvertReceiverModeField::decode(bit_field_);
  }
  FeedbackSource const& feedback() const { return feedback_; }

  SpeculationMode speculation_mode() const {
    return SpeculationModeField::decode(bit_field_);
  }

  CallFeedbackRelation feedback_relation() const {
    return CallFeedbackRelationField::decode(bit_field_);
  }

  bool operator==(CallParameters const& that) const {
    return this->bit_field_ == that.bit_field_ &&
           this->frequency_ == that.frequency_ &&
           this->feedback_ == that.feedback_;
  }
  bool operator!=(CallParameters const& that) const { return !(*this == that); }

 private:
  friend size_t hash_value(CallParameters const& p) {
    FeedbackSource::Hash feedback_hash;
    return base::hash_combine(p.bit_field_, p.frequency_,
                              feedback_hash(p.feedback_));
  }

  using ArityField = base::BitField<size_t, 0, 27>;
  using CallFeedbackRelationField = base::BitField<CallFeedbackRelation, 27, 1>;
  using SpeculationModeField = base::BitField<SpeculationMode, 28, 1>;
  using ConvertReceiverModeField = base::BitField<ConvertReceiverMode, 29, 2>;

  uint32_t const bit_field_;
  CallFrequency const frequency_;
  FeedbackSource const feedback_;
};

size_t hash_value(CallParameters const&);

std::ostream& operator<<(std::ostream&, CallParameters const&);

const CallParameters& CallParametersOf(const Operator* op);


// Defines the arity and the ID for a runtime function call. This is used as a
// parameter by JSCallRuntime operators.
class CallRuntimeParameters final {
 public:
  CallRuntimeParameters(Runtime::FunctionId id, size_t arity)
      : id_(id), arity_(arity) {}

  Runtime::FunctionId id() const { return id_; }
  size_t arity() const { return arity_; }

 private:
  const Runtime::FunctionId id_;
  const size_t arity_;
};

bool operator==(CallRuntimeParameters const&, CallRuntimeParameters const&);
bool operator!=(CallRuntimeParameters const&, CallRuntimeParameters const&);

size_t hash_value(CallRuntimeParameters const&);

std::ostream& operator<<(std::ostream&, CallRuntimeParameters const&);

const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op);


// Defines the location of a context slot relative to a specific scope. This is
// used as a parameter by JSLoadContext and JSStoreContext operators and allows
// accessing a context-allocated variable without keeping track of the scope.
class ContextAccess final {
 public:
  ContextAccess(size_t depth, size_t index, bool immutable);

  size_t depth() const { return depth_; }
  size_t index() const { return index_; }
  bool immutable() const { return immutable_; }

 private:
  // For space reasons, we keep this tightly packed, otherwise we could just use
  // a simple int/int/bool POD.
  const bool immutable_;
  const uint16_t depth_;
  const uint32_t index_;
};

bool operator==(ContextAccess const&, ContextAccess const&);
bool operator!=(ContextAccess const&, ContextAccess const&);

size_t hash_value(ContextAccess const&);

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ContextAccess const&);

V8_EXPORT_PRIVATE ContextAccess const& ContextAccessOf(Operator const*);

// Defines the slot count and ScopeType for a new function or eval context. This
// is used as a parameter by the JSCreateFunctionContext operator.
class CreateFunctionContextParameters final {
 public:
  CreateFunctionContextParameters(Handle<ScopeInfo> scope_info, int slot_count,
                                  ScopeType scope_type);

  Handle<ScopeInfo> scope_info() const { return scope_info_; }
  int slot_count() const { return slot_count_; }
  ScopeType scope_type() const { return scope_type_; }

 private:
  Handle<ScopeInfo> scope_info_;
  int const slot_count_;
  ScopeType const scope_type_;
};

bool operator==(CreateFunctionContextParameters const& lhs,
                CreateFunctionContextParameters const& rhs);
bool operator!=(CreateFunctionContextParameters const& lhs,
                CreateFunctionContextParameters const& rhs);

size_t hash_value(CreateFunctionContextParameters const& parameters);

std::ostream& operator<<(std::ostream& os,
                         CreateFunctionContextParameters const& parameters);

CreateFunctionContextParameters const& CreateFunctionContextParametersOf(
    Operator const*);

// Defines parameters for JSStoreNamedOwn operator.
class StoreNamedOwnParameters final {
 public:
  StoreNamedOwnParameters(Handle<Name> name, FeedbackSource const& feedback)
      : name_(name), feedback_(feedback) {}

  Handle<Name> name() const { return name_; }
  FeedbackSource const& feedback() const { return feedback_; }

 private:
  Handle<Name> const name_;
  FeedbackSource const feedback_;
};

bool operator==(StoreNamedOwnParameters const&, StoreNamedOwnParameters const&);
bool operator!=(StoreNamedOwnParameters const&, StoreNamedOwnParameters const&);

size_t hash_value(StoreNamedOwnParameters const&);

std::ostream& operator<<(std::ostream&, StoreNamedOwnParameters const&);

const StoreNamedOwnParameters& StoreNamedOwnParametersOf(const Operator* op);

// Defines the feedback, i.e., vector and index, for storing a data property in
// an object literal. This is used as a parameter by JSCreateEmptyLiteralArray
// and JSStoreDataPropertyInLiteral operators.
class FeedbackParameter final {
 public:
  explicit FeedbackParameter(FeedbackSource const& feedback)
      : feedback_(feedback) {}

  FeedbackSource const& feedback() const { return feedback_; }

 private:
  FeedbackSource const feedback_;
};

bool operator==(FeedbackParameter const&, FeedbackParameter const&);
bool operator!=(FeedbackParameter const&, FeedbackParameter const&);

size_t hash_value(FeedbackParameter const&);

std::ostream& operator<<(std::ostream&, FeedbackParameter const&);

const FeedbackParameter& FeedbackParameterOf(const Operator* op);

// Defines the property of an object for a named access. This is
// used as a parameter by the JSLoadNamed and JSStoreNamed operators.
class NamedAccess final {
 public:
  NamedAccess(LanguageMode language_mode, Handle<Name> name,
              FeedbackSource const& feedback)
      : name_(name), feedback_(feedback), language_mode_(language_mode) {}

  Handle<Name> name() const { return name_; }
  LanguageMode language_mode() const { return language_mode_; }
  FeedbackSource const& feedback() const { return feedback_; }

 private:
  Handle<Name> const name_;
  FeedbackSource const feedback_;
  LanguageMode const language_mode_;
};

bool operator==(NamedAccess const&, NamedAccess const&);
bool operator!=(NamedAccess const&, NamedAccess const&);

size_t hash_value(NamedAccess const&);

std::ostream& operator<<(std::ostream&, NamedAccess const&);

const NamedAccess& NamedAccessOf(const Operator* op);


// Defines the property being loaded from an object by a named load. This is
// used as a parameter by JSLoadGlobal operator.
class LoadGlobalParameters final {
 public:
  LoadGlobalParameters(const Handle<Name>& name, const FeedbackSource& feedback,
                       TypeofMode typeof_mode)
      : name_(name), feedback_(feedback), typeof_mode_(typeof_mode) {}

  const Handle<Name>& name() const { return name_; }
  TypeofMode typeof_mode() const { return typeof_mode_; }

  const FeedbackSource& feedback() const { return feedback_; }

 private:
  const Handle<Name> name_;
  const FeedbackSource feedback_;
  const TypeofMode typeof_mode_;
};

bool operator==(LoadGlobalParameters const&, LoadGlobalParameters const&);
bool operator!=(LoadGlobalParameters const&, LoadGlobalParameters const&);

size_t hash_value(LoadGlobalParameters const&);

std::ostream& operator<<(std::ostream&, LoadGlobalParameters const&);

const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op);


// Defines the property being stored to an object by a named store. This is
// used as a parameter by JSStoreGlobal operator.
class StoreGlobalParameters final {
 public:
  StoreGlobalParameters(LanguageMode language_mode,
                        const FeedbackSource& feedback,
                        const Handle<Name>& name)
      : language_mode_(language_mode), name_(name), feedback_(feedback) {}

  LanguageMode language_mode() const { return language_mode_; }
  FeedbackSource const& feedback() const { return feedback_; }
  Handle<Name> const& name() const { return name_; }

 private:
  LanguageMode const language_mode_;
  Handle<Name> const name_;
  FeedbackSource const feedback_;
};

bool operator==(StoreGlobalParameters const&, StoreGlobalParameters const&);
bool operator!=(StoreGlobalParameters const&, StoreGlobalParameters const&);

size_t hash_value(StoreGlobalParameters const&);

std::ostream& operator<<(std::ostream&, StoreGlobalParameters const&);

const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op);


// Defines the property of an object for a keyed access. This is used
// as a parameter by the JSLoadProperty and JSStoreProperty operators.
class PropertyAccess final {
 public:
  PropertyAccess(LanguageMode language_mode, FeedbackSource const& feedback)
      : feedback_(feedback), language_mode_(language_mode) {}

  LanguageMode language_mode() const { return language_mode_; }
  FeedbackSource const& feedback() const { return feedback_; }

 private:
  FeedbackSource const feedback_;
  LanguageMode const language_mode_;
};

bool operator==(PropertyAccess const&, PropertyAccess const&);
bool operator!=(PropertyAccess const&, PropertyAccess const&);

size_t hash_value(PropertyAccess const&);

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
                                           PropertyAccess const&);

PropertyAccess const& PropertyAccessOf(const Operator* op);


// CreateArgumentsType is used as parameter to JSCreateArguments nodes.
CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op);


// Defines shared information for the array that should be created. This is
// used as parameter by JSCreateArray operators.
class CreateArrayParameters final {
 public:
  explicit CreateArrayParameters(size_t arity, MaybeHandle<AllocationSite> site)
      : arity_(arity), site_(site) {}

  size_t arity() const { return arity_; }
  MaybeHandle<AllocationSite> site() const { return site_; }

 private:
  size_t const arity_;
  MaybeHandle<AllocationSite> const site_;
};

bool operator==(CreateArrayParameters const&, CreateArrayParameters const&);
bool operator!=(CreateArrayParameters const&, CreateArrayParameters const&);

size_t hash_value(CreateArrayParameters const&);

std::ostream& operator<<(std::ostream&, CreateArrayParameters const&);

const CreateArrayParameters& CreateArrayParametersOf(const Operator* op);

// Defines shared information for the array iterator that should be created.
// This is used as parameter by JSCreateArrayIterator operators.
class CreateArrayIteratorParameters final {
 public:
  explicit CreateArrayIteratorParameters(IterationKind kind) : kind_(kind) {}

  IterationKind kind() const { return kind_; }

 private:
  IterationKind const kind_;
};

bool operator==(CreateArrayIteratorParameters const&,
                CreateArrayIteratorParameters const&);
bool operator!=(CreateArrayIteratorParameters const&,
                CreateArrayIteratorParameters const&);

size_t hash_value(CreateArrayIteratorParameters const&);

std::ostream& operator<<(std::ostream&, CreateArrayIteratorParameters const&);

const CreateArrayIteratorParameters& CreateArrayIteratorParametersOf(
    const Operator* op);

// Defines shared information for the array iterator that should be created.
// This is used as parameter by JSCreateCollectionIterator operators.
class CreateCollectionIteratorParameters final {
 public:
  explicit CreateCollectionIteratorParameters(CollectionKind collection_kind,
                                              IterationKind iteration_kind)
      : collection_kind_(collection_kind), iteration_kind_(iteration_kind) {
    CHECK(!(collection_kind == CollectionKind::kSet &&
            iteration_kind == IterationKind::kKeys));
  }

  CollectionKind collection_kind() const { return collection_kind_; }
  IterationKind iteration_kind() const { return iteration_kind_; }

 private:
  CollectionKind const collection_kind_;
  IterationKind const iteration_kind_;
};

bool operator==(CreateCollectionIteratorParameters const&,
                CreateCollectionIteratorParameters const&);
bool operator!=(CreateCollectionIteratorParameters const&,
                CreateCollectionIteratorParameters const&);

size_t hash_value(CreateCollectionIteratorParameters const&);

std::ostream& operator<<(std::ostream&,
                         CreateCollectionIteratorParameters const&);

const CreateCollectionIteratorParameters& CreateCollectionIteratorParametersOf(
    const Operator* op);

// Defines shared information for the bound function that should be created.
// This is used as parameter by JSCreateBoundFunction operators.
class CreateBoundFunctionParameters final {
 public:
  CreateBoundFunctionParameters(size_t arity, Handle<Map> map)
      : arity_(arity), map_(map) {}

  size_t arity() const { return arity_; }
  Handle<Map> map() const { return map_; }

 private:
  size_t const arity_;
  Handle<Map> const map_;
};

bool operator==(CreateBoundFunctionParameters const&,
                CreateBoundFunctionParameters const&);
bool operator!=(CreateBoundFunctionParameters const&,
                CreateBoundFunctionParameters const&);

size_t hash_value(CreateBoundFunctionParameters const&);

std::ostream& operator<<(std::ostream&, CreateBoundFunctionParameters const&);

const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
    const Operator* op);

// Defines shared information for the closure that should be created. This is
// used as a parameter by JSCreateClosure operators.
class CreateClosureParameters final {
 public:
  CreateClosureParameters(Handle<SharedFunctionInfo> shared_info,
                          Handle<Code> code, AllocationType allocation)
      : shared_info_(shared_info), code_(code), allocation_(allocation) {}

  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
  Handle<Code> code() const { return code_; }
  AllocationType allocation() const { return allocation_; }

 private:
  Handle<SharedFunctionInfo> const shared_info_;
  Handle<Code> const code_;
  AllocationType const allocation_;
};

bool operator==(CreateClosureParameters const&, CreateClosureParameters const&);
bool operator!=(CreateClosureParameters const&, CreateClosureParameters const&);

size_t hash_value(CreateClosureParameters const&);

std::ostream& operator<<(std::ostream&, CreateClosureParameters const&);

const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);

class GetTemplateObjectParameters final {
 public:
  GetTemplateObjectParameters(Handle<TemplateObjectDescription> description,
                              Handle<SharedFunctionInfo> shared,
                              FeedbackSource const& feedback)
      : description_(description), shared_(shared), feedback_(feedback) {}

  Handle<TemplateObjectDescription> description() const { return description_; }
  Handle<SharedFunctionInfo> shared() const { return shared_; }
  FeedbackSource const& feedback() const { return feedback_; }

 private:
  Handle<TemplateObjectDescription> const description_;
  Handle<SharedFunctionInfo> const shared_;
  FeedbackSource const feedback_;
};

bool operator==(GetTemplateObjectParameters const&,
                GetTemplateObjectParameters const&);
bool operator!=(GetTemplateObjectParameters const&,
                GetTemplateObjectParameters const&);

size_t hash_value(GetTemplateObjectParameters const&);

std::ostream& operator<<(std::ostream&, GetTemplateObjectParameters const&);

const GetTemplateObjectParameters& GetTemplateObjectParametersOf(
    const Operator* op);

// Defines shared information for the literal that should be created. This is
// used as parameter by JSCreateLiteralArray, JSCreateLiteralObject and
// JSCreateLiteralRegExp operators.
class CreateLiteralParameters final {
 public:
  CreateLiteralParameters(Handle<HeapObject> constant,
                          FeedbackSource const& feedback, int length, int flags)
      : constant_(constant),
        feedback_(feedback),
        length_(length),
        flags_(flags) {}

  Handle<HeapObject> constant() const { return constant_; }
  FeedbackSource const& feedback() const { return feedback_; }
  int length() const { return length_; }
  int flags() const { return flags_; }

 private:
  Handle<HeapObject> const constant_;
  FeedbackSource const feedback_;
  int const length_;
  int const flags_;
};

bool operator==(CreateLiteralParameters const&, CreateLiteralParameters const&);
bool operator!=(CreateLiteralParameters const&, CreateLiteralParameters const&);

size_t hash_value(CreateLiteralParameters const&);

std::ostream& operator<<(std::ostream&, CreateLiteralParameters const&);

const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op);

class CloneObjectParameters final {
 public:
  CloneObjectParameters(FeedbackSource const& feedback, int flags)
      : feedback_(feedback), flags_(flags) {}

  FeedbackSource const& feedback() const { return feedback_; }
  int flags() const { return flags_; }

 private:
  FeedbackSource const feedback_;
  int const flags_;
};

bool operator==(CloneObjectParameters const&, CloneObjectParameters const&);
bool operator!=(CloneObjectParameters const&, CloneObjectParameters const&);

size_t hash_value(CloneObjectParameters const&);

std::ostream& operator<<(std::ostream&, CloneObjectParameters const&);

const CloneObjectParameters& CloneObjectParametersOf(const Operator* op);

// Defines the shared information for the iterator symbol thats loaded and
// called. This is used as a parameter by JSGetIterator operator.
class GetIteratorParameters final {
 public:
  GetIteratorParameters(const FeedbackSource& load_feedback,
                        const FeedbackSource& call_feedback)
      : load_feedback_(load_feedback), call_feedback_(call_feedback) {}

  FeedbackSource const& loadFeedback() const { return load_feedback_; }
  FeedbackSource const& callFeedback() const { return call_feedback_; }

 private:
  FeedbackSource const load_feedback_;
  FeedbackSource const call_feedback_;
};

bool operator==(GetIteratorParameters const&, GetIteratorParameters const&);
bool operator!=(GetIteratorParameters const&, GetIteratorParameters const&);

size_t hash_value(GetIteratorParameters const&);

std::ostream& operator<<(std::ostream&, GetIteratorParameters const&);

const GetIteratorParameters& GetIteratorParametersOf(const Operator* op);

enum class ForInMode : uint8_t {
  kUseEnumCacheKeysAndIndices,
  kUseEnumCacheKeys,
  kGeneric
};
size_t hash_value(ForInMode const&);
std::ostream& operator<<(std::ostream&, ForInMode const&);

class ForInParameters final {
 public:
  ForInParameters(const FeedbackSource& feedback, ForInMode mode)
      : feedback_(feedback), mode_(mode) {}

  const FeedbackSource& feedback() const { return feedback_; }
  ForInMode mode() const { return mode_; }

 private:
  const FeedbackSource feedback_;
  const ForInMode mode_;
};

bool operator==(ForInParameters const&, ForInParameters const&);
bool operator!=(ForInParameters const&, ForInParameters const&);
size_t hash_value(ForInParameters const&);
std::ostream& operator<<(std::ostream&, ForInParameters const&);
const ForInParameters& ForInParametersOf(const Operator* op);

int RegisterCountOf(Operator const* op) V8_WARN_UNUSED_RESULT;

int GeneratorStoreValueCountOf(const Operator* op) V8_WARN_UNUSED_RESULT;
int RestoreRegisterIndexOf(const Operator* op) V8_WARN_UNUSED_RESULT;

Handle<ScopeInfo> ScopeInfoOf(const Operator* op) V8_WARN_UNUSED_RESULT;

// Interface for building JavaScript-level operators, e.g. directly from the
// AST. Most operators have no parameters, thus can be globally shared for all
// graphs.
class V8_EXPORT_PRIVATE JSOperatorBuilder final
    : public NON_EXPORTED_BASE(ZoneObject) {
 public:
  explicit JSOperatorBuilder(Zone* zone);
  JSOperatorBuilder(const JSOperatorBuilder&) = delete;
  JSOperatorBuilder& operator=(const JSOperatorBuilder&) = delete;

  const Operator* Equal(FeedbackSource const& feedback);
  const Operator* StrictEqual(FeedbackSource const& feedback);
  const Operator* LessThan(FeedbackSource const& feedback);
  const Operator* GreaterThan(FeedbackSource const& feedback);
  const Operator* LessThanOrEqual(FeedbackSource const& feedback);
  const Operator* GreaterThanOrEqual(FeedbackSource const& feedback);

  const Operator* BitwiseOr(FeedbackSource const& feedback);
  const Operator* BitwiseXor(FeedbackSource const& feedback);
  const Operator* BitwiseAnd(FeedbackSource const& feedback);
  const Operator* ShiftLeft(FeedbackSource const& feedback);
  const Operator* ShiftRight(FeedbackSource const& feedback);
  const Operator* ShiftRightLogical(FeedbackSource const& feedback);
  const Operator* Add(FeedbackSource const& feedback);
  const Operator* Subtract(FeedbackSource const& feedback);
  const Operator* Multiply(FeedbackSource const& feedback);
  const Operator* Divide(FeedbackSource const& feedback);
  const Operator* Modulus(FeedbackSource const& feedback);
  const Operator* Exponentiate(FeedbackSource const& feedback);

  const Operator* BitwiseNot(FeedbackSource const& feedback);
  const Operator* Decrement(FeedbackSource const& feedback);
  const Operator* Increment(FeedbackSource const& feedback);
  const Operator* Negate(FeedbackSource const& feedback);

  const Operator* ToLength();
  const Operator* ToName();
  const Operator* ToNumber();
  const Operator* ToNumberConvertBigInt();
  const Operator* ToNumeric();
  const Operator* ToObject();
  const Operator* ToString();

  const Operator* Create();
  const Operator* CreateArguments(CreateArgumentsType type);
  const Operator* CreateArray(size_t arity, MaybeHandle<AllocationSite> site);
  const Operator* CreateArrayIterator(IterationKind);
  const Operator* CreateAsyncFunctionObject(int register_count);
  const Operator* CreateCollectionIterator(CollectionKind, IterationKind);
  const Operator* CreateBoundFunction(size_t arity, Handle<Map> map);
  const Operator* CreateClosure(
      Handle<SharedFunctionInfo> shared_info, Handle<Code> code,
      AllocationType allocation = AllocationType::kYoung);
  const Operator* CreateIterResultObject();
  const Operator* CreateStringIterator();
  const Operator* CreateKeyValueArray();
  const Operator* CreateObject();
  const Operator* CreatePromise();
  const Operator* CreateTypedArray();
  const Operator* CreateLiteralArray(
      Handle<ArrayBoilerplateDescription> constant,
      FeedbackSource const& feedback, int literal_flags,
      int number_of_elements);
  const Operator* CreateEmptyLiteralArray(FeedbackSource const& feedback);
  const Operator* CreateArrayFromIterable();
  const Operator* CreateEmptyLiteralObject();
  const Operator* CreateLiteralObject(
      Handle<ObjectBoilerplateDescription> constant,
      FeedbackSource const& feedback, int literal_flags,
      int number_of_properties);
  const Operator* CloneObject(FeedbackSource const& feedback,
                              int literal_flags);
  const Operator* CreateLiteralRegExp(Handle<String> constant_pattern,
                                      FeedbackSource const& feedback,
                                      int literal_flags);

  const Operator* GetTemplateObject(
      Handle<TemplateObjectDescription> description,
      Handle<SharedFunctionInfo> shared, FeedbackSource const& feedback);

  const Operator* CallForwardVarargs(size_t arity, uint32_t start_index);
  const Operator* Call(
      size_t arity, CallFrequency const& frequency = CallFrequency(),
      FeedbackSource const& feedback = FeedbackSource(),
      ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
      SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
      CallFeedbackRelation feedback_relation =
          CallFeedbackRelation::kUnrelated);
  const Operator* CallWithArrayLike(
      CallFrequency const& frequency,
      const FeedbackSource& feedback = FeedbackSource{},
      SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
      CallFeedbackRelation feedback_relation = CallFeedbackRelation::kRelated);
  const Operator* CallWithSpread(
      uint32_t arity, CallFrequency const& frequency = CallFrequency(),
      FeedbackSource const& feedback = FeedbackSource(),
      SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
      CallFeedbackRelation feedback_relation = CallFeedbackRelation::kRelated);
  const Operator* CallRuntime(Runtime::FunctionId id);
  const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
  const Operator* CallRuntime(const Runtime::Function* function, size_t arity);

  const Operator* ConstructForwardVarargs(size_t arity, uint32_t start_index);
  const Operator* Construct(uint32_t arity,
                            CallFrequency const& frequency = CallFrequency(),
                            FeedbackSource const& feedback = FeedbackSource());
  const Operator* ConstructWithArrayLike(CallFrequency const& frequency,
                                         FeedbackSource const& feedback);
  const Operator* ConstructWithSpread(
      uint32_t arity, CallFrequency const& frequency = CallFrequency(),
      FeedbackSource const& feedback = FeedbackSource());

  const Operator* LoadProperty(FeedbackSource const& feedback);
  const Operator* LoadNamed(Handle<Name> name, FeedbackSource const& feedback);
  const Operator* LoadNamedFromSuper(Handle<Name> name,
                                     FeedbackSource const& feedback);

  const Operator* StoreProperty(LanguageMode language_mode,
                                FeedbackSource const& feedback);
  const Operator* StoreNamed(LanguageMode language_mode, Handle<Name> name,
                             FeedbackSource const& feedback);

  const Operator* StoreNamedOwn(Handle<Name> name,
                                FeedbackSource const& feedback);
  const Operator* StoreDataPropertyInLiteral(const FeedbackSource& feedback);
  const Operator* StoreInArrayLiteral(const FeedbackSource& feedback);

  const Operator* DeleteProperty();

  const Operator* HasProperty(FeedbackSource const& feedback);

  const Operator* GetSuperConstructor();

  const Operator* CreateGeneratorObject();

  const Operator* LoadGlobal(const Handle<Name>& name,
                             const FeedbackSource& feedback,
                             TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
  const Operator* StoreGlobal(LanguageMode language_mode,
                              const Handle<Name>& name,
                              const FeedbackSource& feedback);

  const Operator* HasContextExtension(size_t depth);
  const Operator* LoadContext(size_t depth, size_t index, bool immutable);
  const Operator* StoreContext(size_t depth, size_t index);

  const Operator* LoadModule(int32_t cell_index);
  const Operator* StoreModule(int32_t cell_index);

  const Operator* GetImportMeta();

  const Operator* HasInPrototypeChain();
  const Operator* InstanceOf(const FeedbackSource& feedback);
  const Operator* OrdinaryHasInstance();

  const Operator* AsyncFunctionEnter();
  const Operator* AsyncFunctionReject();
  const Operator* AsyncFunctionResolve();

  const Operator* ForInEnumerate();
  const Operator* ForInNext(ForInMode mode, const FeedbackSource& feedback);
  const Operator* ForInPrepare(ForInMode mode, const FeedbackSource& feedback);

  const Operator* LoadMessage();
  const Operator* StoreMessage();

  // Used to implement Ignition's SuspendGenerator bytecode.
  const Operator* GeneratorStore(int value_count);

  // Used to implement Ignition's SwitchOnGeneratorState bytecode.
  const Operator* GeneratorRestoreContinuation();
  const Operator* GeneratorRestoreContext();

  // Used to implement Ignition's ResumeGenerator bytecode.
  const Operator* GeneratorRestoreRegister(int index);
  const Operator* GeneratorRestoreInputOrDebugPos();

  const Operator* StackCheck(StackCheckKind kind);
  const Operator* Debugger();

  const Operator* FulfillPromise();
  const Operator* PerformPromiseThen();
  const Operator* PromiseResolve();
  const Operator* RejectPromise();
  const Operator* ResolvePromise();

  const Operator* CreateFunctionContext(Handle<ScopeInfo> scope_info,
                                        int slot_count, ScopeType scope_type);
  const Operator* CreateCatchContext(const Handle<ScopeInfo>& scope_info);
  const Operator* CreateWithContext(const Handle<ScopeInfo>& scope_info);
  const Operator* CreateBlockContext(const Handle<ScopeInfo>& scpope_info);

  const Operator* ObjectIsArray();
  const Operator* ParseInt();
  const Operator* RegExpTest();

  const Operator* GetIterator(FeedbackSource const& load_feedback,
                              FeedbackSource const& call_feedback);

 private:
  Zone* zone() const { return zone_; }

  const JSOperatorGlobalCache& cache_;
  Zone* const zone_;
};

// Node wrappers.

class JSNodeWrapperBase : public NodeWrapper {
 public:
  explicit constexpr JSNodeWrapperBase(Node* node) : NodeWrapper(node) {}

  // Valid iff this node has a context input.
  TNode<Object> context() const {
    // Could be a Context or NoContextConstant.
    return TNode<Object>::UncheckedCast(
        NodeProperties::GetContextInput(node()));
  }

  // Valid iff this node has exactly one effect input.
  Effect effect() const {
    DCHECK_EQ(node()->op()->EffectInputCount(), 1);
    return Effect{NodeProperties::GetEffectInput(node())};
  }

  // Valid iff this node has exactly one control input.
  Control control() const {
    DCHECK_EQ(node()->op()->ControlInputCount(), 1);
    return Control{NodeProperties::GetControlInput(node())};
  }

  // Valid iff this node has a frame state input.
  FrameState frame_state() const {
    return FrameState{NodeProperties::GetFrameStateInput(node())};
  }
};

#define DEFINE_INPUT_ACCESSORS(Name, name, TheIndex, Type) \
  static constexpr int Name##Index() { return TheIndex; }  \
  TNode<Type> name() const {                               \
    return TNode<Type>::UncheckedCast(                     \
        NodeProperties::GetValueInput(node(), TheIndex));  \
  }

class JSUnaryOpNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSUnaryOpNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(JSOperator::IsUnaryWithFeedback(node->opcode()));
  }

#define INPUTS(V)            \
  V(Value, value, 0, Object) \
  V(FeedbackVector, feedback_vector, 1, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

#define V(JSName, ...) using JSName##Node = JSUnaryOpNode;
JS_UNOP_WITH_FEEDBACK(V)
#undef V

class JSBinaryOpNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSBinaryOpNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
  }

  const FeedbackParameter& Parameters() const {
    return FeedbackParameterOf(node()->op());
  }

#define INPUTS(V)            \
  V(Left, left, 0, Object)   \
  V(Right, right, 1, Object) \
  V(FeedbackVector, feedback_vector, 2, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

#define V(JSName, ...) using JSName##Node = JSBinaryOpNode;
JS_BINOP_WITH_FEEDBACK(V)
#undef V

class JSGetIteratorNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSGetIteratorNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSGetIterator);
  }

  const GetIteratorParameters& Parameters() const {
    return GetIteratorParametersOf(node()->op());
  }

#define INPUTS(V)                  \
  V(Receiver, receiver, 0, Object) \
  V(FeedbackVector, feedback_vector, 1, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSCloneObjectNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSCloneObjectNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCloneObject);
  }

  const CloneObjectParameters& Parameters() const {
    return CloneObjectParametersOf(node()->op());
  }

#define INPUTS(V)              \
  V(Source, source, 0, Object) \
  V(FeedbackVector, feedback_vector, 1, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSGetTemplateObjectNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSGetTemplateObjectNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSGetTemplateObject);
  }

  const GetTemplateObjectParameters& Parameters() const {
    return GetTemplateObjectParametersOf(node()->op());
  }

#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSCreateLiteralOpNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSCreateLiteralOpNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
                     node->opcode() == IrOpcode::kJSCreateLiteralObject ||
                     node->opcode() == IrOpcode::kJSCreateLiteralRegExp);
  }

  const CreateLiteralParameters& Parameters() const {
    return CreateLiteralParametersOf(node()->op());
  }

#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

using JSCreateLiteralArrayNode = JSCreateLiteralOpNode;
using JSCreateLiteralObjectNode = JSCreateLiteralOpNode;
using JSCreateLiteralRegExpNode = JSCreateLiteralOpNode;

class JSHasPropertyNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSHasPropertyNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSHasProperty);
  }

  const PropertyAccess& Parameters() const {
    return PropertyAccessOf(node()->op());
  }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(Key, key, 1, Object)       \
  V(FeedbackVector, feedback_vector, 2, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSLoadPropertyNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSLoadPropertyNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSLoadProperty);
  }

  const PropertyAccess& Parameters() const {
    return PropertyAccessOf(node()->op());
  }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(Key, key, 1, Object)       \
  V(FeedbackVector, feedback_vector, 2, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSStorePropertyNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSStorePropertyNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreProperty);
  }

  const PropertyAccess& Parameters() const {
    return PropertyAccessOf(node()->op());
  }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(Key, key, 1, Object)       \
  V(Value, value, 2, Object)   \
  V(FeedbackVector, feedback_vector, 3, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

namespace js_node_wrapper_utils {
// Avoids template definitions in the .cc file.
TNode<Oddball> UndefinedConstant(JSGraph* jsgraph);
}  // namespace js_node_wrapper_utils

class JSCallOrConstructNode : public JSNodeWrapperBase {
 public:
  explicit constexpr JSCallOrConstructNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCall ||
                     node->opcode() == IrOpcode::kJSCallWithArrayLike ||
                     node->opcode() == IrOpcode::kJSCallWithSpread ||
                     node->opcode() == IrOpcode::kJSConstruct ||
                     node->opcode() == IrOpcode::kJSConstructWithArrayLike ||
                     node->opcode() == IrOpcode::kJSConstructWithSpread);
  }

#define INPUTS(V)              \
  V(Target, target, 0, Object) \
  V(ReceiverOrNewTarget, receiver_or_new_target, 1, Object)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS

  // Besides actual arguments, JSCall nodes (and variants) also take the
  // following. Note that we rely on the fact that all variants (JSCall,
  // JSCallWithArrayLike, JSCallWithSpread, JSConstruct,
  // JSConstructWithArrayLike, JSConstructWithSpread) have the same underlying
  // node layout.
  static constexpr int kTargetInputCount = 1;
  static constexpr int kReceiverOrNewTargetInputCount = 1;
  static constexpr int kFeedbackVectorInputCount = 1;
  static constexpr int kExtraInputCount = kTargetInputCount +
                                          kReceiverOrNewTargetInputCount +
                                          kFeedbackVectorInputCount;
  STATIC_ASSERT(kExtraInputCount == CallParameters::kExtraCallInputCount);
  STATIC_ASSERT(kExtraInputCount ==
                ConstructParameters::kExtraConstructInputCount);

  // Just for static asserts for spots that rely on node layout.
  static constexpr bool kFeedbackVectorIsLastInput = true;

  // Some spots rely on the fact that call and construct variants have the same
  // layout.
  static constexpr bool kHaveIdenticalLayouts = true;

  // This is the arity fed into Call/ConstructArguments.
  static constexpr int ArityForArgc(int parameters) {
    return parameters + kExtraInputCount;
  }

  static constexpr int FirstArgumentIndex() {
    return ReceiverOrNewTargetIndex() + 1;
  }
  static constexpr int ArgumentIndex(int i) { return FirstArgumentIndex() + i; }

  TNode<Object> Argument(int i) const {
    DCHECK_LT(i, ArgumentCount());
    return TNode<Object>::UncheckedCast(
        NodeProperties::GetValueInput(node(), ArgumentIndex(i)));
  }
  int LastArgumentIndex() const {
    DCHECK_GT(ArgumentCount(), 0);
    return ArgumentIndex(ArgumentCount() - 1);
  }
  TNode<Object> LastArgument() const {
    DCHECK_GT(ArgumentCount(), 0);
    return Argument(ArgumentCount() - 1);
  }
  TNode<Object> ArgumentOr(int i, Node* default_value) const {
    return i < ArgumentCount() ? Argument(i)
                               : TNode<Object>::UncheckedCast(default_value);
  }
  TNode<Object> ArgumentOrUndefined(int i, JSGraph* jsgraph) const {
    return ArgumentOr(i, js_node_wrapper_utils::UndefinedConstant(jsgraph));
  }
  virtual int ArgumentCount() const = 0;

  static constexpr int FeedbackVectorIndexForArgc(int argc) {
    STATIC_ASSERT(kFeedbackVectorIsLastInput);
    return ArgumentIndex(argc - 1) + 1;
  }
  int FeedbackVectorIndex() const {
    return FeedbackVectorIndexForArgc(ArgumentCount());
  }
  TNode<HeapObject> feedback_vector() const {
    return TNode<HeapObject>::UncheckedCast(
        NodeProperties::GetValueInput(node(), FeedbackVectorIndex()));
  }
};

template <int kOpcode>
class JSCallNodeBase final : public JSCallOrConstructNode {
 public:
  explicit constexpr JSCallNodeBase(Node* node) : JSCallOrConstructNode(node) {
    CONSTEXPR_DCHECK(node->opcode() == kOpcode);
  }

  const CallParameters& Parameters() const {
    return CallParametersOf(node()->op());
  }

#define INPUTS(V)              \
  V(Target, target, 0, Object) \
  V(Receiver, receiver, 1, Object)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS

  static constexpr int kReceiverInputCount = 1;
  STATIC_ASSERT(kReceiverInputCount ==
                JSCallOrConstructNode::kReceiverOrNewTargetInputCount);

  int ArgumentCount() const override {
    // Note: The count reported by this function depends only on the parameter,
    // thus adding/removing inputs will not affect it.
    return Parameters().arity_without_implicit_args();
  }
};

using JSCallNode = JSCallNodeBase<IrOpcode::kJSCall>;
using JSCallWithSpreadNode = JSCallNodeBase<IrOpcode::kJSCallWithSpread>;
using JSCallWithArrayLikeNode = JSCallNodeBase<IrOpcode::kJSCallWithArrayLike>;

template <int kOpcode>
class JSConstructNodeBase final : public JSCallOrConstructNode {
 public:
  explicit constexpr JSConstructNodeBase(Node* node)
      : JSCallOrConstructNode(node) {
    CONSTEXPR_DCHECK(node->opcode() == kOpcode);
  }

  const ConstructParameters& Parameters() const {
    return ConstructParametersOf(node()->op());
  }

#define INPUTS(V)              \
  V(Target, target, 0, Object) \
  V(NewTarget, new_target, 1, Object)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS

  static constexpr int kNewTargetInputCount = 1;
  STATIC_ASSERT(kNewTargetInputCount ==
                JSCallOrConstructNode::kReceiverOrNewTargetInputCount);

  int ArgumentCount() const {
    // Note: The count reported by this function depends only on the parameter,
    // thus adding/removing inputs will not affect it.
    return Parameters().arity_without_implicit_args();
  }
};

using JSConstructNode = JSConstructNodeBase<IrOpcode::kJSConstruct>;
using JSConstructWithSpreadNode =
    JSConstructNodeBase<IrOpcode::kJSConstructWithSpread>;
using JSConstructWithArrayLikeNode =
    JSConstructNodeBase<IrOpcode::kJSConstructWithArrayLike>;

class JSLoadNamedNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSLoadNamedNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSLoadNamed);
  }

  const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(FeedbackVector, feedback_vector, 1, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSLoadNamedFromSuperNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSLoadNamedFromSuperNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSLoadNamedFromSuper);
  }

  const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }

  // TODO(marja, v8:9237): A more intuitive order would be (home_object,
  // receiver, feedback_vector). The order can be changed once we no longer
  // delegate to Runtime_LoadFromSuper.
#define INPUTS(V)                       \
  V(Receiver, receiver, 0, Object)      \
  V(HomeObject, home_object, 1, Object) \
  V(FeedbackVector, feedback_vector, 2, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSStoreNamedNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSStoreNamedNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreNamed);
  }

  const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(Value, value, 1, Object)   \
  V(FeedbackVector, feedback_vector, 2, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSStoreNamedOwnNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSStoreNamedOwnNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreNamedOwn);
  }

  const StoreNamedOwnParameters& Parameters() const {
    return StoreNamedOwnParametersOf(node()->op());
  }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(Value, value, 1, Object)   \
  V(FeedbackVector, feedback_vector, 2, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSStoreGlobalNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSStoreGlobalNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreGlobal);
  }

  const StoreGlobalParameters& Parameters() const {
    return StoreGlobalParametersOf(node()->op());
  }

#define INPUTS(V)            \
  V(Value, value, 0, Object) \
  V(FeedbackVector, feedback_vector, 1, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSLoadGlobalNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSLoadGlobalNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSLoadGlobal);
  }

  const LoadGlobalParameters& Parameters() const {
    return LoadGlobalParametersOf(node()->op());
  }

#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSCreateEmptyLiteralArrayNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSCreateEmptyLiteralArrayNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
  }

  const FeedbackParameter& Parameters() const {
    return FeedbackParameterOf(node()->op());
  }

#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSStoreDataPropertyInLiteralNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSStoreDataPropertyInLiteralNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral);
  }

  const FeedbackParameter& Parameters() const {
    return FeedbackParameterOf(node()->op());
  }

#define INPUTS(V)              \
  V(Object, object, 0, Object) \
  V(Name, name, 1, Object)     \
  V(Value, value, 2, Object)   \
  V(Flags, flags, 3, Object)   \
  V(FeedbackVector, feedback_vector, 4, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSStoreInArrayLiteralNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSStoreInArrayLiteralNode(Node* node)
      : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreInArrayLiteral);
  }

  const FeedbackParameter& Parameters() const {
    return FeedbackParameterOf(node()->op());
  }

#define INPUTS(V)            \
  V(Array, array, 0, Object) \
  V(Index, index, 1, Object) \
  V(Value, value, 2, Object) \
  V(FeedbackVector, feedback_vector, 3, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSCreateClosureNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSCreateClosureNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCreateClosure);
  }

  const CreateClosureParameters& Parameters() const {
    return CreateClosureParametersOf(node()->op());
  }

#define INPUTS(V) V(FeedbackCell, feedback_cell, 0, FeedbackCell)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS

  FeedbackCellRef GetFeedbackCellRefChecked(JSHeapBroker* broker) const;
};

class JSForInPrepareNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSForInPrepareNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSForInPrepare);
  }

  const ForInParameters& Parameters() const {
    return ForInParametersOf(node()->op());
  }

#define INPUTS(V)                      \
  V(Enumerator, enumerator, 0, Object) \
  V(FeedbackVector, feedback_vector, 1, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

class JSForInNextNode final : public JSNodeWrapperBase {
 public:
  explicit constexpr JSForInNextNode(Node* node) : JSNodeWrapperBase(node) {
    CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSForInNext);
  }

  const ForInParameters& Parameters() const {
    return ForInParametersOf(node()->op());
  }

#define INPUTS(V)                       \
  V(Receiver, receiver, 0, Object)      \
  V(CacheArray, cache_array, 1, Object) \
  V(CacheType, cache_type, 2, Object)   \
  V(Index, index, 3, Smi)               \
  V(FeedbackVector, feedback_vector, 4, HeapObject)
  INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};

#undef DEFINE_INPUT_ACCESSORS

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_JS_OPERATOR_H_
