|  | // Copyright 2014 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_COMMON_OPERATOR_H_ | 
|  | #define V8_COMPILER_COMMON_OPERATOR_H_ | 
|  |  | 
|  | #include "src/base/compiler-specific.h" | 
|  | #include "src/codegen/machine-type.h" | 
|  | #include "src/codegen/reloc-info.h" | 
|  | #include "src/codegen/string-constants.h" | 
|  | #include "src/common/globals.h" | 
|  | #include "src/compiler/feedback-source.h" | 
|  | #include "src/compiler/frame-states.h" | 
|  | #include "src/compiler/linkage.h" | 
|  | #include "src/compiler/node-properties.h" | 
|  | #include "src/deoptimizer/deoptimize-reason.h" | 
|  | #include "src/zone/zone-containers.h" | 
|  | #include "src/zone/zone-handle-set.h" | 
|  |  | 
|  | namespace v8 { | 
|  | namespace internal { | 
|  |  | 
|  | class StringConstantBase; | 
|  |  | 
|  | namespace compiler { | 
|  |  | 
|  | // Forward declarations. | 
|  | class CallDescriptor; | 
|  | struct CommonOperatorGlobalCache; | 
|  | class Operator; | 
|  | class Type; | 
|  | class Node; | 
|  |  | 
|  | // Prediction hint for branches. | 
|  | enum class BranchHint : uint8_t { kNone, kTrue, kFalse }; | 
|  |  | 
|  | inline BranchHint NegateBranchHint(BranchHint hint) { | 
|  | switch (hint) { | 
|  | case BranchHint::kNone: | 
|  | return hint; | 
|  | case BranchHint::kTrue: | 
|  | return BranchHint::kFalse; | 
|  | case BranchHint::kFalse: | 
|  | return BranchHint::kTrue; | 
|  | } | 
|  | UNREACHABLE(); | 
|  | } | 
|  |  | 
|  | inline size_t hash_value(BranchHint hint) { return static_cast<size_t>(hint); } | 
|  |  | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchHint); | 
|  |  | 
|  | enum class IsSafetyCheck : uint8_t { | 
|  | kCriticalSafetyCheck, | 
|  | kSafetyCheck, | 
|  | kNoSafetyCheck | 
|  | }; | 
|  |  | 
|  | // Get the more critical safety check of the two arguments. | 
|  | IsSafetyCheck CombineSafetyChecks(IsSafetyCheck, IsSafetyCheck); | 
|  |  | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, IsSafetyCheck); | 
|  | inline size_t hash_value(IsSafetyCheck is_safety_check) { | 
|  | return static_cast<size_t>(is_safety_check); | 
|  | } | 
|  |  | 
|  | enum class TrapId : uint32_t { | 
|  | #define DEF_ENUM(Name, ...) k##Name, | 
|  | FOREACH_WASM_TRAPREASON(DEF_ENUM) | 
|  | #undef DEF_ENUM | 
|  | kInvalid | 
|  | }; | 
|  |  | 
|  | inline size_t hash_value(TrapId id) { return static_cast<uint32_t>(id); } | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, TrapId trap_id); | 
|  |  | 
|  | TrapId TrapIdOf(const Operator* const op); | 
|  |  | 
|  | struct BranchOperatorInfo { | 
|  | BranchHint hint; | 
|  | IsSafetyCheck is_safety_check; | 
|  | }; | 
|  |  | 
|  | inline size_t hash_value(const BranchOperatorInfo& info) { | 
|  | return base::hash_combine(info.hint, info.is_safety_check); | 
|  | } | 
|  |  | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchOperatorInfo); | 
|  |  | 
|  | inline bool operator==(const BranchOperatorInfo& a, | 
|  | const BranchOperatorInfo& b) { | 
|  | return a.hint == b.hint && a.is_safety_check == b.is_safety_check; | 
|  | } | 
|  |  | 
|  | V8_EXPORT_PRIVATE const BranchOperatorInfo& BranchOperatorInfoOf( | 
|  | const Operator* const) V8_WARN_UNUSED_RESULT; | 
|  | V8_EXPORT_PRIVATE BranchHint BranchHintOf(const Operator* const) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | // Helper function for return nodes, because returns have a hidden value input. | 
|  | int ValueInputCountOfReturn(Operator const* const op); | 
|  |  | 
|  | // Parameters for the {Deoptimize} operator. | 
|  | class DeoptimizeParameters final { | 
|  | public: | 
|  | DeoptimizeParameters(DeoptimizeKind kind, DeoptimizeReason reason, | 
|  | FeedbackSource const& feedback, | 
|  | IsSafetyCheck is_safety_check) | 
|  | : kind_(kind), | 
|  | reason_(reason), | 
|  | feedback_(feedback), | 
|  | is_safety_check_(is_safety_check) {} | 
|  |  | 
|  | DeoptimizeKind kind() const { return kind_; } | 
|  | DeoptimizeReason reason() const { return reason_; } | 
|  | const FeedbackSource& feedback() const { return feedback_; } | 
|  | IsSafetyCheck is_safety_check() const { return is_safety_check_; } | 
|  |  | 
|  | private: | 
|  | DeoptimizeKind const kind_; | 
|  | DeoptimizeReason const reason_; | 
|  | FeedbackSource const feedback_; | 
|  | IsSafetyCheck is_safety_check_; | 
|  | }; | 
|  |  | 
|  | bool operator==(DeoptimizeParameters, DeoptimizeParameters); | 
|  | bool operator!=(DeoptimizeParameters, DeoptimizeParameters); | 
|  |  | 
|  | size_t hast_value(DeoptimizeParameters p); | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, DeoptimizeParameters p); | 
|  |  | 
|  | DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | IsSafetyCheck IsSafetyCheckOf(const Operator* op) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | class SelectParameters final { | 
|  | public: | 
|  | explicit SelectParameters(MachineRepresentation representation, | 
|  | BranchHint hint = BranchHint::kNone) | 
|  | : representation_(representation), hint_(hint) {} | 
|  |  | 
|  | MachineRepresentation representation() const { return representation_; } | 
|  | BranchHint hint() const { return hint_; } | 
|  |  | 
|  | private: | 
|  | const MachineRepresentation representation_; | 
|  | const BranchHint hint_; | 
|  | }; | 
|  |  | 
|  | bool operator==(SelectParameters const&, SelectParameters const&); | 
|  | bool operator!=(SelectParameters const&, SelectParameters const&); | 
|  |  | 
|  | size_t hash_value(SelectParameters const& p); | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, SelectParameters const& p); | 
|  |  | 
|  | V8_EXPORT_PRIVATE SelectParameters const& SelectParametersOf( | 
|  | const Operator* const) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | V8_EXPORT_PRIVATE CallDescriptor const* CallDescriptorOf(const Operator* const) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | V8_EXPORT_PRIVATE size_t ProjectionIndexOf(const Operator* const) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | V8_EXPORT_PRIVATE MachineRepresentation | 
|  | PhiRepresentationOf(const Operator* const) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | // The {IrOpcode::kParameter} opcode represents an incoming parameter to the | 
|  | // function. This class bundles the index and a debug name for such operators. | 
|  | class ParameterInfo final { | 
|  | public: | 
|  | ParameterInfo(int index, const char* debug_name) | 
|  | : index_(index), debug_name_(debug_name) {} | 
|  |  | 
|  | int index() const { return index_; } | 
|  | const char* debug_name() const { return debug_name_; } | 
|  |  | 
|  | private: | 
|  | int index_; | 
|  | const char* debug_name_; | 
|  | }; | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, ParameterInfo const&); | 
|  |  | 
|  | V8_EXPORT_PRIVATE int ParameterIndexOf(const Operator* const) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  | const ParameterInfo& ParameterInfoOf(const Operator* const) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | struct ObjectStateInfo final : std::pair<uint32_t, int> { | 
|  | ObjectStateInfo(uint32_t object_id, int size) | 
|  | : std::pair<uint32_t, int>(object_id, size) {} | 
|  | uint32_t object_id() const { return first; } | 
|  | int size() const { return second; } | 
|  | }; | 
|  | std::ostream& operator<<(std::ostream&, ObjectStateInfo const&); | 
|  | size_t hash_value(ObjectStateInfo const& p); | 
|  |  | 
|  | struct TypedObjectStateInfo final | 
|  | : std::pair<uint32_t, const ZoneVector<MachineType>*> { | 
|  | TypedObjectStateInfo(uint32_t object_id, | 
|  | const ZoneVector<MachineType>* machine_types) | 
|  | : std::pair<uint32_t, const ZoneVector<MachineType>*>(object_id, | 
|  | machine_types) {} | 
|  | uint32_t object_id() const { return first; } | 
|  | const ZoneVector<MachineType>* machine_types() const { return second; } | 
|  | }; | 
|  | std::ostream& operator<<(std::ostream&, TypedObjectStateInfo const&); | 
|  | size_t hash_value(TypedObjectStateInfo const& p); | 
|  |  | 
|  | class RelocatablePtrConstantInfo final { | 
|  | public: | 
|  | enum Type { kInt32, kInt64 }; | 
|  |  | 
|  | RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode) | 
|  | : value_(value), rmode_(rmode), type_(kInt32) {} | 
|  | RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode) | 
|  | : value_(value), rmode_(rmode), type_(kInt64) {} | 
|  |  | 
|  | intptr_t value() const { return value_; } | 
|  | RelocInfo::Mode rmode() const { return rmode_; } | 
|  | Type type() const { return type_; } | 
|  |  | 
|  | private: | 
|  | intptr_t value_; | 
|  | RelocInfo::Mode rmode_; | 
|  | Type type_; | 
|  | }; | 
|  |  | 
|  | bool operator==(RelocatablePtrConstantInfo const& lhs, | 
|  | RelocatablePtrConstantInfo const& rhs); | 
|  | bool operator!=(RelocatablePtrConstantInfo const& lhs, | 
|  | RelocatablePtrConstantInfo const& rhs); | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&); | 
|  |  | 
|  | size_t hash_value(RelocatablePtrConstantInfo const& p); | 
|  |  | 
|  | // Used to define a sparse set of inputs. This can be used to efficiently encode | 
|  | // nodes that can have a lot of inputs, but where many inputs can have the same | 
|  | // value. | 
|  | class SparseInputMask final { | 
|  | public: | 
|  | using BitMaskType = uint32_t; | 
|  |  | 
|  | // The mask representing a dense input set. | 
|  | static const BitMaskType kDenseBitMask = 0x0; | 
|  | // The bits representing the end of a sparse input set. | 
|  | static const BitMaskType kEndMarker = 0x1; | 
|  | // The mask for accessing a sparse input entry in the bitmask. | 
|  | static const BitMaskType kEntryMask = 0x1; | 
|  |  | 
|  | // The number of bits in the mask, minus one for the end marker. | 
|  | static const int kMaxSparseInputs = (sizeof(BitMaskType) * kBitsPerByte - 1); | 
|  |  | 
|  | // An iterator over a node's sparse inputs. | 
|  | class InputIterator final { | 
|  | public: | 
|  | InputIterator() = default; | 
|  | InputIterator(BitMaskType bit_mask, Node* parent); | 
|  |  | 
|  | Node* parent() const { return parent_; } | 
|  | int real_index() const { return real_index_; } | 
|  |  | 
|  | // Advance the iterator to the next sparse input. Only valid if the iterator | 
|  | // has not reached the end. | 
|  | void Advance(); | 
|  |  | 
|  | // Get the current sparse input's real node value. Only valid if the | 
|  | // current sparse input is real. | 
|  | Node* GetReal() const; | 
|  |  | 
|  | // Advance to the next real value or the end. Only valid if the iterator is | 
|  | // not dense. Returns the number of empty values that were skipped. This can | 
|  | // return 0 and in that case, it does not advance. | 
|  | size_t AdvanceToNextRealOrEnd(); | 
|  |  | 
|  | // Get the current sparse input, returning either a real input node if | 
|  | // the current sparse input is real, or the given {empty_value} if the | 
|  | // current sparse input is empty. | 
|  | Node* Get(Node* empty_value) const { | 
|  | return IsReal() ? GetReal() : empty_value; | 
|  | } | 
|  |  | 
|  | // True if the current sparse input is a real input node. | 
|  | bool IsReal() const; | 
|  |  | 
|  | // True if the current sparse input is an empty value. | 
|  | bool IsEmpty() const { return !IsReal(); } | 
|  |  | 
|  | // True if the iterator has reached the end of the sparse inputs. | 
|  | bool IsEnd() const; | 
|  |  | 
|  | private: | 
|  | BitMaskType bit_mask_; | 
|  | Node* parent_; | 
|  | int real_index_; | 
|  | }; | 
|  |  | 
|  | explicit SparseInputMask(BitMaskType bit_mask) : bit_mask_(bit_mask) {} | 
|  |  | 
|  | // Provides a SparseInputMask representing a dense input set. | 
|  | static SparseInputMask Dense() { return SparseInputMask(kDenseBitMask); } | 
|  |  | 
|  | BitMaskType mask() const { return bit_mask_; } | 
|  |  | 
|  | bool IsDense() const { return bit_mask_ == SparseInputMask::kDenseBitMask; } | 
|  |  | 
|  | // Counts how many real values are in the sparse array. Only valid for | 
|  | // non-dense masks. | 
|  | int CountReal() const; | 
|  |  | 
|  | // Returns an iterator over the sparse inputs of {node}. | 
|  | InputIterator IterateOverInputs(Node* node); | 
|  |  | 
|  | private: | 
|  | // | 
|  | // The sparse input mask has a bitmask specifying if the node's inputs are | 
|  | // represented sparsely. If the bitmask value is 0, then the inputs are dense; | 
|  | // otherwise, they should be interpreted as follows: | 
|  | // | 
|  | //   * The bitmask represents which values are real, with 1 for real values | 
|  | //     and 0 for empty values. | 
|  | //   * The inputs to the node are the real values, in the order of the 1s from | 
|  | //     least- to most-significant. | 
|  | //   * The top bit of the bitmask is a guard indicating the end of the values, | 
|  | //     whether real or empty (and is not representative of a real input | 
|  | //     itself). This is used so that we don't have to additionally store a | 
|  | //     value count. | 
|  | // | 
|  | // So, for N 1s in the bitmask, there are N - 1 inputs into the node. | 
|  | BitMaskType bit_mask_; | 
|  | }; | 
|  |  | 
|  | bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs); | 
|  | bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs); | 
|  |  | 
|  | class TypedStateValueInfo final { | 
|  | public: | 
|  | TypedStateValueInfo(ZoneVector<MachineType> const* machine_types, | 
|  | SparseInputMask sparse_input_mask) | 
|  | : machine_types_(machine_types), sparse_input_mask_(sparse_input_mask) {} | 
|  |  | 
|  | ZoneVector<MachineType> const* machine_types() const { | 
|  | return machine_types_; | 
|  | } | 
|  | SparseInputMask sparse_input_mask() const { return sparse_input_mask_; } | 
|  |  | 
|  | private: | 
|  | ZoneVector<MachineType> const* machine_types_; | 
|  | SparseInputMask sparse_input_mask_; | 
|  | }; | 
|  |  | 
|  | bool operator==(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs); | 
|  | bool operator!=(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs); | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, TypedStateValueInfo const&); | 
|  |  | 
|  | size_t hash_value(TypedStateValueInfo const& p); | 
|  |  | 
|  | // Used to mark a region (as identified by BeginRegion/FinishRegion) as either | 
|  | // JavaScript-observable or not (i.e. allocations are not JavaScript observable | 
|  | // themselves, but transitioning stores are). | 
|  | enum class RegionObservability : uint8_t { kObservable, kNotObservable }; | 
|  |  | 
|  | size_t hash_value(RegionObservability); | 
|  |  | 
|  | std::ostream& operator<<(std::ostream&, RegionObservability); | 
|  |  | 
|  | RegionObservability RegionObservabilityOf(Operator const*) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | std::ostream& operator<<(std::ostream& os, | 
|  | const ZoneVector<MachineType>* types); | 
|  |  | 
|  | Type TypeGuardTypeOf(Operator const*) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | int OsrValueIndexOf(Operator const*) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | SparseInputMask SparseInputMaskOf(Operator const*) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | ZoneVector<MachineType> const* MachineTypesOf(Operator const*) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | // The ArgumentsElementsState and ArgumentsLengthState can describe the layout | 
|  | // for backing stores of arguments objects of various types: | 
|  | // | 
|  | //                        +------------------------------------+ | 
|  | //  - kUnmappedArguments: | arg0, ... argK-1, argK, ... argN-1 |  {length:N} | 
|  | //                        +------------------------------------+ | 
|  | //                        +------------------------------------+ | 
|  | //  - kMappedArguments:   | hole, ...   hole, argK, ... argN-1 |  {length:N} | 
|  | //                        +------------------------------------+ | 
|  | //                                          +------------------+ | 
|  | //  - kRestParameter:                       | argK, ... argN-1 |  {length:N-K} | 
|  | //                                          +------------------+ | 
|  | // | 
|  | // Here {K} represents the number for formal parameters of the active function, | 
|  | // whereas {N} represents the actual number of arguments passed at runtime. | 
|  | // Note that {N < K} can happen and causes {K} to be capped accordingly. | 
|  | // | 
|  | // Also note that it is possible for an arguments object of {kMappedArguments} | 
|  | // type to carry a backing store of {kUnappedArguments} type when {K == 0}. | 
|  | using ArgumentsStateType = CreateArgumentsType; | 
|  |  | 
|  | ArgumentsStateType ArgumentsStateTypeOf(Operator const*) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | uint32_t ObjectIdOf(Operator const*); | 
|  |  | 
|  | MachineRepresentation DeadValueRepresentationOf(Operator const*) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | class IfValueParameters final { | 
|  | public: | 
|  | IfValueParameters(int32_t value, int32_t comparison_order, | 
|  | BranchHint hint = BranchHint::kNone) | 
|  | : value_(value), comparison_order_(comparison_order), hint_(hint) {} | 
|  |  | 
|  | int32_t value() const { return value_; } | 
|  | int32_t comparison_order() const { return comparison_order_; } | 
|  | BranchHint hint() const { return hint_; } | 
|  |  | 
|  | private: | 
|  | int32_t value_; | 
|  | int32_t comparison_order_; | 
|  | BranchHint hint_; | 
|  | }; | 
|  |  | 
|  | V8_EXPORT_PRIVATE bool operator==(IfValueParameters const&, | 
|  | IfValueParameters const&); | 
|  |  | 
|  | size_t hash_value(IfValueParameters const&); | 
|  |  | 
|  | V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, | 
|  | IfValueParameters const&); | 
|  |  | 
|  | V8_EXPORT_PRIVATE IfValueParameters const& IfValueParametersOf( | 
|  | const Operator* op) V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | const FrameStateInfo& FrameStateInfoOf(const Operator* op) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | V8_EXPORT_PRIVATE Handle<HeapObject> HeapConstantOf(const Operator* op) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | const StringConstantBase* StringConstantBaseOf(const Operator* op) | 
|  | V8_WARN_UNUSED_RESULT; | 
|  |  | 
|  | const char* StaticAssertSourceOf(const Operator* op); | 
|  |  | 
|  | // Interface for building common operators that can be used at any level of IR, | 
|  | // including JavaScript, mid-level, and low-level. | 
|  | class V8_EXPORT_PRIVATE CommonOperatorBuilder final | 
|  | : public NON_EXPORTED_BASE(ZoneObject) { | 
|  | public: | 
|  | explicit CommonOperatorBuilder(Zone* zone); | 
|  | CommonOperatorBuilder(const CommonOperatorBuilder&) = delete; | 
|  | CommonOperatorBuilder& operator=(const CommonOperatorBuilder&) = delete; | 
|  |  | 
|  | const Operator* Dead(); | 
|  | const Operator* DeadValue(MachineRepresentation rep); | 
|  | const Operator* Unreachable(); | 
|  | const Operator* StaticAssert(const char* source); | 
|  | const Operator* End(size_t control_input_count); | 
|  | const Operator* Branch(BranchHint = BranchHint::kNone, | 
|  | IsSafetyCheck = IsSafetyCheck::kSafetyCheck); | 
|  | const Operator* IfTrue(); | 
|  | const Operator* IfFalse(); | 
|  | const Operator* IfSuccess(); | 
|  | const Operator* IfException(); | 
|  | const Operator* Switch(size_t control_output_count); | 
|  | const Operator* IfValue(int32_t value, int32_t order = 0, | 
|  | BranchHint hint = BranchHint::kNone); | 
|  | const Operator* IfDefault(BranchHint hint = BranchHint::kNone); | 
|  | const Operator* Throw(); | 
|  | const Operator* Deoptimize(DeoptimizeKind kind, DeoptimizeReason reason, | 
|  | FeedbackSource const& feedback); | 
|  | const Operator* DeoptimizeIf( | 
|  | DeoptimizeKind kind, DeoptimizeReason reason, | 
|  | FeedbackSource const& feedback, | 
|  | IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck); | 
|  | const Operator* DeoptimizeUnless( | 
|  | DeoptimizeKind kind, DeoptimizeReason reason, | 
|  | FeedbackSource const& feedback, | 
|  | IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck); | 
|  | const Operator* TrapIf(TrapId trap_id); | 
|  | const Operator* TrapUnless(TrapId trap_id); | 
|  | const Operator* Return(int value_input_count = 1); | 
|  | const Operator* Terminate(); | 
|  |  | 
|  | const Operator* Start(int value_output_count); | 
|  | const Operator* Loop(int control_input_count); | 
|  | const Operator* Merge(int control_input_count); | 
|  | const Operator* Parameter(int index, const char* debug_name = nullptr); | 
|  |  | 
|  | const Operator* OsrValue(int index); | 
|  |  | 
|  | const Operator* Int32Constant(int32_t); | 
|  | const Operator* Int64Constant(int64_t); | 
|  | const Operator* TaggedIndexConstant(int32_t value); | 
|  | const Operator* Float32Constant(volatile float); | 
|  | const Operator* Float64Constant(volatile double); | 
|  | const Operator* ExternalConstant(const ExternalReference&); | 
|  | const Operator* NumberConstant(volatile double); | 
|  | const Operator* PointerConstant(intptr_t); | 
|  | const Operator* HeapConstant(const Handle<HeapObject>&); | 
|  | const Operator* CompressedHeapConstant(const Handle<HeapObject>&); | 
|  | const Operator* ObjectId(uint32_t); | 
|  |  | 
|  | const Operator* RelocatableInt32Constant(int32_t value, | 
|  | RelocInfo::Mode rmode); | 
|  | const Operator* RelocatableInt64Constant(int64_t value, | 
|  | RelocInfo::Mode rmode); | 
|  |  | 
|  | const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone); | 
|  | const Operator* Phi(MachineRepresentation representation, | 
|  | int value_input_count); | 
|  | const Operator* EffectPhi(int effect_input_count); | 
|  | const Operator* InductionVariablePhi(int value_input_count); | 
|  | const Operator* LoopExit(); | 
|  | const Operator* LoopExitValue(); | 
|  | const Operator* LoopExitEffect(); | 
|  | const Operator* Checkpoint(); | 
|  | const Operator* BeginRegion(RegionObservability); | 
|  | const Operator* FinishRegion(); | 
|  | const Operator* StateValues(int arguments, SparseInputMask bitmask); | 
|  | const Operator* TypedStateValues(const ZoneVector<MachineType>* types, | 
|  | SparseInputMask bitmask); | 
|  | const Operator* ArgumentsElementsState(ArgumentsStateType type); | 
|  | const Operator* ArgumentsLengthState(); | 
|  | const Operator* ObjectState(uint32_t object_id, int pointer_slots); | 
|  | const Operator* TypedObjectState(uint32_t object_id, | 
|  | const ZoneVector<MachineType>* types); | 
|  | const Operator* FrameState(BailoutId bailout_id, | 
|  | OutputFrameStateCombine state_combine, | 
|  | const FrameStateFunctionInfo* function_info); | 
|  | const Operator* Call(const CallDescriptor* call_descriptor); | 
|  | const Operator* TailCall(const CallDescriptor* call_descriptor); | 
|  | const Operator* Projection(size_t index); | 
|  | const Operator* Retain(); | 
|  | const Operator* TypeGuard(Type type); | 
|  | const Operator* FoldConstant(); | 
|  |  | 
|  | // Constructs a new merge or phi operator with the same opcode as {op}, but | 
|  | // with {size} inputs. | 
|  | const Operator* ResizeMergeOrPhi(const Operator* op, int size); | 
|  |  | 
|  | // Constructs function info for frame state construction. | 
|  | const FrameStateFunctionInfo* CreateFrameStateFunctionInfo( | 
|  | FrameStateType type, int parameter_count, int local_count, | 
|  | Handle<SharedFunctionInfo> shared_info); | 
|  |  | 
|  | const Operator* MarkAsSafetyCheck(const Operator* op, | 
|  | IsSafetyCheck safety_check); | 
|  |  | 
|  | const Operator* DelayedStringConstant(const StringConstantBase* str); | 
|  |  | 
|  | private: | 
|  | Zone* zone() const { return zone_; } | 
|  |  | 
|  | const CommonOperatorGlobalCache& cache_; | 
|  | Zone* const zone_; | 
|  | }; | 
|  |  | 
|  | // Node wrappers. | 
|  |  | 
|  | class CommonNodeWrapperBase : public NodeWrapper { | 
|  | public: | 
|  | explicit constexpr CommonNodeWrapperBase(Node* node) : NodeWrapper(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())}; | 
|  | } | 
|  | }; | 
|  |  | 
|  | #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 StartNode final : public CommonNodeWrapperBase { | 
|  | public: | 
|  | explicit constexpr StartNode(Node* node) : CommonNodeWrapperBase(node) { | 
|  | CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kStart); | 
|  | } | 
|  |  | 
|  | // The receiver is counted as part of formal parameters. | 
|  | static constexpr int kReceiverOutputCount = 1; | 
|  | // These outputs are in addition to formal parameters. | 
|  | static constexpr int kExtraOutputCount = 4; | 
|  |  | 
|  | // Takes the formal parameter count of the current function (including | 
|  | // receiver) and returns the number of value outputs of the start node. | 
|  | static constexpr int OutputArityForFormalParameterCount(int argc) { | 
|  | constexpr int kClosure = 1; | 
|  | constexpr int kNewTarget = 1; | 
|  | constexpr int kArgCount = 1; | 
|  | constexpr int kContext = 1; | 
|  | STATIC_ASSERT(kClosure + kNewTarget + kArgCount + kContext == | 
|  | kExtraOutputCount); | 
|  | // Checking related linkage methods here since they rely on Start node | 
|  | // layout. | 
|  | CONSTEXPR_DCHECK(Linkage::kJSCallClosureParamIndex == -1); | 
|  | CONSTEXPR_DCHECK(Linkage::GetJSCallNewTargetParamIndex(argc) == argc + 0); | 
|  | CONSTEXPR_DCHECK(Linkage::GetJSCallArgCountParamIndex(argc) == argc + 1); | 
|  | CONSTEXPR_DCHECK(Linkage::GetJSCallContextParamIndex(argc) == argc + 2); | 
|  | return argc + kClosure + kNewTarget + kArgCount + kContext; | 
|  | } | 
|  |  | 
|  | int FormalParameterCount() const { | 
|  | DCHECK_GE(node()->op()->ValueOutputCount(), | 
|  | kExtraOutputCount + kReceiverOutputCount); | 
|  | return node()->op()->ValueOutputCount() - kExtraOutputCount; | 
|  | } | 
|  |  | 
|  | int FormalParameterCountWithoutReceiver() const { | 
|  | DCHECK_GE(node()->op()->ValueOutputCount(), | 
|  | kExtraOutputCount + kReceiverOutputCount); | 
|  | return node()->op()->ValueOutputCount() - kExtraOutputCount - | 
|  | kReceiverOutputCount; | 
|  | } | 
|  | }; | 
|  |  | 
|  | #undef DEFINE_INPUT_ACCESSORS | 
|  |  | 
|  | }  // namespace compiler | 
|  | }  // namespace internal | 
|  | }  // namespace v8 | 
|  |  | 
|  | #endif  // V8_COMPILER_COMMON_OPERATOR_H_ |