blob: 7e61bf376061109a7a58e407ad89fda0880823d6 [file] [log] [blame]
// 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_