11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_COMMON_OPERATOR_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_COMMON_OPERATOR_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/reloc-info.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/string-constants.h" 121cb0ef41Sopenharmony_ci#include "src/common/globals.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h" 141cb0ef41Sopenharmony_ci#include "src/compiler/frame-states.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h" 171cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimize-reason.h" 181cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 191cb0ef41Sopenharmony_ci#include "src/zone/zone-handle-set.h" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cinamespace v8 { 221cb0ef41Sopenharmony_cinamespace internal { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciclass StringConstantBase; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace compiler { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci// Forward declarations. 291cb0ef41Sopenharmony_ciclass CallDescriptor; 301cb0ef41Sopenharmony_cistruct CommonOperatorGlobalCache; 311cb0ef41Sopenharmony_ciclass Operator; 321cb0ef41Sopenharmony_ciclass Type; 331cb0ef41Sopenharmony_ciclass Node; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci// The semantics of IrOpcode::kBranch changes throughout the pipeline, and in 361cb0ef41Sopenharmony_ci// particular is not the same before SimplifiedLowering (JS semantics) and after 371cb0ef41Sopenharmony_ci// (machine branch semantics). Some passes are applied both before and after 381cb0ef41Sopenharmony_ci// SimplifiedLowering, and use the BranchSemantics enum to know how branches 391cb0ef41Sopenharmony_ci// should be treated. 401cb0ef41Sopenharmony_cienum class BranchSemantics { kJS, kMachine }; 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci// Prediction hint for branches. 431cb0ef41Sopenharmony_cienum class BranchHint : uint8_t { kNone, kTrue, kFalse }; 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciinline BranchHint NegateBranchHint(BranchHint hint) { 461cb0ef41Sopenharmony_ci switch (hint) { 471cb0ef41Sopenharmony_ci case BranchHint::kNone: 481cb0ef41Sopenharmony_ci return hint; 491cb0ef41Sopenharmony_ci case BranchHint::kTrue: 501cb0ef41Sopenharmony_ci return BranchHint::kFalse; 511cb0ef41Sopenharmony_ci case BranchHint::kFalse: 521cb0ef41Sopenharmony_ci return BranchHint::kTrue; 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci UNREACHABLE(); 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ciinline size_t hash_value(BranchHint hint) { return static_cast<size_t>(hint); } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, BranchHint); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_cienum class TrapId : uint32_t { 621cb0ef41Sopenharmony_ci#define DEF_ENUM(Name, ...) k##Name, 631cb0ef41Sopenharmony_ci FOREACH_WASM_TRAPREASON(DEF_ENUM) 641cb0ef41Sopenharmony_ci#undef DEF_ENUM 651cb0ef41Sopenharmony_ci kInvalid 661cb0ef41Sopenharmony_ci}; 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ciinline size_t hash_value(TrapId id) { return static_cast<uint32_t>(id); } 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, TrapId trap_id); 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciTrapId TrapIdOf(const Operator* const op); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE BranchHint BranchHintOf(const Operator* const) 751cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci// Helper function for return nodes, because returns have a hidden value input. 781cb0ef41Sopenharmony_ciint ValueInputCountOfReturn(Operator const* const op); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci// Parameters for the {Deoptimize} operator. 811cb0ef41Sopenharmony_ciclass DeoptimizeParameters final { 821cb0ef41Sopenharmony_ci public: 831cb0ef41Sopenharmony_ci DeoptimizeParameters(DeoptimizeReason reason, FeedbackSource const& feedback) 841cb0ef41Sopenharmony_ci : reason_(reason), feedback_(feedback) {} 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci DeoptimizeReason reason() const { return reason_; } 871cb0ef41Sopenharmony_ci const FeedbackSource& feedback() const { return feedback_; } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci private: 901cb0ef41Sopenharmony_ci DeoptimizeReason const reason_; 911cb0ef41Sopenharmony_ci FeedbackSource const feedback_; 921cb0ef41Sopenharmony_ci}; 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_cibool operator==(DeoptimizeParameters, DeoptimizeParameters); 951cb0ef41Sopenharmony_cibool operator!=(DeoptimizeParameters, DeoptimizeParameters); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_cisize_t hast_value(DeoptimizeParameters p); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, DeoptimizeParameters p); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciDeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const) 1021cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ciclass SelectParameters final { 1051cb0ef41Sopenharmony_ci public: 1061cb0ef41Sopenharmony_ci explicit SelectParameters(MachineRepresentation representation, 1071cb0ef41Sopenharmony_ci BranchHint hint = BranchHint::kNone) 1081cb0ef41Sopenharmony_ci : representation_(representation), hint_(hint) {} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci MachineRepresentation representation() const { return representation_; } 1111cb0ef41Sopenharmony_ci BranchHint hint() const { return hint_; } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci private: 1141cb0ef41Sopenharmony_ci const MachineRepresentation representation_; 1151cb0ef41Sopenharmony_ci const BranchHint hint_; 1161cb0ef41Sopenharmony_ci}; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_cibool operator==(SelectParameters const&, SelectParameters const&); 1191cb0ef41Sopenharmony_cibool operator!=(SelectParameters const&, SelectParameters const&); 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_cisize_t hash_value(SelectParameters const& p); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, SelectParameters const& p); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE SelectParameters const& SelectParametersOf( 1261cb0ef41Sopenharmony_ci const Operator* const) V8_WARN_UNUSED_RESULT; 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE CallDescriptor const* CallDescriptorOf(const Operator* const) 1291cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE size_t ProjectionIndexOf(const Operator* const) 1321cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE MachineRepresentation 1351cb0ef41Sopenharmony_ciLoopExitValueRepresentationOf(const Operator* const) V8_WARN_UNUSED_RESULT; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE MachineRepresentation 1381cb0ef41Sopenharmony_ciPhiRepresentationOf(const Operator* const) V8_WARN_UNUSED_RESULT; 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci// The {IrOpcode::kParameter} opcode represents an incoming parameter to the 1411cb0ef41Sopenharmony_ci// function. This class bundles the index and a debug name for such operators. 1421cb0ef41Sopenharmony_ciclass ParameterInfo final { 1431cb0ef41Sopenharmony_ci public: 1441cb0ef41Sopenharmony_ci static constexpr int kMinIndex = Linkage::kJSCallClosureParamIndex; 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci ParameterInfo(int index, const char* debug_name) 1471cb0ef41Sopenharmony_ci : index_(index), debug_name_(debug_name) { 1481cb0ef41Sopenharmony_ci DCHECK_LE(kMinIndex, index); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci int index() const { return index_; } 1521cb0ef41Sopenharmony_ci const char* debug_name() const { return debug_name_; } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci private: 1551cb0ef41Sopenharmony_ci int index_; 1561cb0ef41Sopenharmony_ci const char* debug_name_; 1571cb0ef41Sopenharmony_ci}; 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, ParameterInfo const&); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE int ParameterIndexOf(const Operator* const) 1621cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 1631cb0ef41Sopenharmony_ciconst ParameterInfo& ParameterInfoOf(const Operator* const) 1641cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_cistruct ObjectStateInfo final : std::pair<uint32_t, int> { 1671cb0ef41Sopenharmony_ci ObjectStateInfo(uint32_t object_id, int size) 1681cb0ef41Sopenharmony_ci : std::pair<uint32_t, int>(object_id, size) {} 1691cb0ef41Sopenharmony_ci uint32_t object_id() const { return first; } 1701cb0ef41Sopenharmony_ci int size() const { return second; } 1711cb0ef41Sopenharmony_ci}; 1721cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, ObjectStateInfo const&); 1731cb0ef41Sopenharmony_cisize_t hash_value(ObjectStateInfo const& p); 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_cistruct TypedObjectStateInfo final 1761cb0ef41Sopenharmony_ci : std::pair<uint32_t, const ZoneVector<MachineType>*> { 1771cb0ef41Sopenharmony_ci TypedObjectStateInfo(uint32_t object_id, 1781cb0ef41Sopenharmony_ci const ZoneVector<MachineType>* machine_types) 1791cb0ef41Sopenharmony_ci : std::pair<uint32_t, const ZoneVector<MachineType>*>(object_id, 1801cb0ef41Sopenharmony_ci machine_types) {} 1811cb0ef41Sopenharmony_ci uint32_t object_id() const { return first; } 1821cb0ef41Sopenharmony_ci const ZoneVector<MachineType>* machine_types() const { return second; } 1831cb0ef41Sopenharmony_ci}; 1841cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, TypedObjectStateInfo const&); 1851cb0ef41Sopenharmony_cisize_t hash_value(TypedObjectStateInfo const& p); 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ciclass RelocatablePtrConstantInfo final { 1881cb0ef41Sopenharmony_ci public: 1891cb0ef41Sopenharmony_ci enum Type { kInt32, kInt64 }; 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode) 1921cb0ef41Sopenharmony_ci : value_(value), rmode_(rmode), type_(kInt32) {} 1931cb0ef41Sopenharmony_ci RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode) 1941cb0ef41Sopenharmony_ci : value_(value), rmode_(rmode), type_(kInt64) {} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci intptr_t value() const { return value_; } 1971cb0ef41Sopenharmony_ci RelocInfo::Mode rmode() const { return rmode_; } 1981cb0ef41Sopenharmony_ci Type type() const { return type_; } 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci private: 2011cb0ef41Sopenharmony_ci intptr_t value_; 2021cb0ef41Sopenharmony_ci RelocInfo::Mode rmode_; 2031cb0ef41Sopenharmony_ci Type type_; 2041cb0ef41Sopenharmony_ci}; 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_cibool operator==(RelocatablePtrConstantInfo const& lhs, 2071cb0ef41Sopenharmony_ci RelocatablePtrConstantInfo const& rhs); 2081cb0ef41Sopenharmony_cibool operator!=(RelocatablePtrConstantInfo const& lhs, 2091cb0ef41Sopenharmony_ci RelocatablePtrConstantInfo const& rhs); 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&); 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_cisize_t hash_value(RelocatablePtrConstantInfo const& p); 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci// Used to define a sparse set of inputs. This can be used to efficiently encode 2161cb0ef41Sopenharmony_ci// nodes that can have a lot of inputs, but where many inputs can have the same 2171cb0ef41Sopenharmony_ci// value. 2181cb0ef41Sopenharmony_ciclass SparseInputMask final { 2191cb0ef41Sopenharmony_ci public: 2201cb0ef41Sopenharmony_ci using BitMaskType = uint32_t; 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci // The mask representing a dense input set. 2231cb0ef41Sopenharmony_ci static const BitMaskType kDenseBitMask = 0x0; 2241cb0ef41Sopenharmony_ci // The bits representing the end of a sparse input set. 2251cb0ef41Sopenharmony_ci static const BitMaskType kEndMarker = 0x1; 2261cb0ef41Sopenharmony_ci // The mask for accessing a sparse input entry in the bitmask. 2271cb0ef41Sopenharmony_ci static const BitMaskType kEntryMask = 0x1; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci // The number of bits in the mask, minus one for the end marker. 2301cb0ef41Sopenharmony_ci static const int kMaxSparseInputs = (sizeof(BitMaskType) * kBitsPerByte - 1); 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci // An iterator over a node's sparse inputs. 2331cb0ef41Sopenharmony_ci class InputIterator final { 2341cb0ef41Sopenharmony_ci public: 2351cb0ef41Sopenharmony_ci InputIterator() = default; 2361cb0ef41Sopenharmony_ci InputIterator(BitMaskType bit_mask, Node* parent); 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci Node* parent() const { return parent_; } 2391cb0ef41Sopenharmony_ci int real_index() const { return real_index_; } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci // Advance the iterator to the next sparse input. Only valid if the iterator 2421cb0ef41Sopenharmony_ci // has not reached the end. 2431cb0ef41Sopenharmony_ci void Advance(); 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci // Get the current sparse input's real node value. Only valid if the 2461cb0ef41Sopenharmony_ci // current sparse input is real. 2471cb0ef41Sopenharmony_ci Node* GetReal() const; 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci // Advance to the next real value or the end. Only valid if the iterator is 2501cb0ef41Sopenharmony_ci // not dense. Returns the number of empty values that were skipped. This can 2511cb0ef41Sopenharmony_ci // return 0 and in that case, it does not advance. 2521cb0ef41Sopenharmony_ci size_t AdvanceToNextRealOrEnd(); 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci // Get the current sparse input, returning either a real input node if 2551cb0ef41Sopenharmony_ci // the current sparse input is real, or the given {empty_value} if the 2561cb0ef41Sopenharmony_ci // current sparse input is empty. 2571cb0ef41Sopenharmony_ci Node* Get(Node* empty_value) const { 2581cb0ef41Sopenharmony_ci return IsReal() ? GetReal() : empty_value; 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci // True if the current sparse input is a real input node. 2621cb0ef41Sopenharmony_ci bool IsReal() const; 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci // True if the current sparse input is an empty value. 2651cb0ef41Sopenharmony_ci bool IsEmpty() const { return !IsReal(); } 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci // True if the iterator has reached the end of the sparse inputs. 2681cb0ef41Sopenharmony_ci bool IsEnd() const; 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci private: 2711cb0ef41Sopenharmony_ci BitMaskType bit_mask_; 2721cb0ef41Sopenharmony_ci Node* parent_; 2731cb0ef41Sopenharmony_ci int real_index_; 2741cb0ef41Sopenharmony_ci }; 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci explicit SparseInputMask(BitMaskType bit_mask) : bit_mask_(bit_mask) {} 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci // Provides a SparseInputMask representing a dense input set. 2791cb0ef41Sopenharmony_ci static SparseInputMask Dense() { return SparseInputMask(kDenseBitMask); } 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci BitMaskType mask() const { return bit_mask_; } 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci bool IsDense() const { return bit_mask_ == SparseInputMask::kDenseBitMask; } 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci // Counts how many real values are in the sparse array. Only valid for 2861cb0ef41Sopenharmony_ci // non-dense masks. 2871cb0ef41Sopenharmony_ci int CountReal() const; 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci // Returns an iterator over the sparse inputs of {node}. 2901cb0ef41Sopenharmony_ci InputIterator IterateOverInputs(Node* node); 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci private: 2931cb0ef41Sopenharmony_ci // 2941cb0ef41Sopenharmony_ci // The sparse input mask has a bitmask specifying if the node's inputs are 2951cb0ef41Sopenharmony_ci // represented sparsely. If the bitmask value is 0, then the inputs are dense; 2961cb0ef41Sopenharmony_ci // otherwise, they should be interpreted as follows: 2971cb0ef41Sopenharmony_ci // 2981cb0ef41Sopenharmony_ci // * The bitmask represents which values are real, with 1 for real values 2991cb0ef41Sopenharmony_ci // and 0 for empty values. 3001cb0ef41Sopenharmony_ci // * The inputs to the node are the real values, in the order of the 1s from 3011cb0ef41Sopenharmony_ci // least- to most-significant. 3021cb0ef41Sopenharmony_ci // * The top bit of the bitmask is a guard indicating the end of the values, 3031cb0ef41Sopenharmony_ci // whether real or empty (and is not representative of a real input 3041cb0ef41Sopenharmony_ci // itself). This is used so that we don't have to additionally store a 3051cb0ef41Sopenharmony_ci // value count. 3061cb0ef41Sopenharmony_ci // 3071cb0ef41Sopenharmony_ci // So, for N 1s in the bitmask, there are N - 1 inputs into the node. 3081cb0ef41Sopenharmony_ci BitMaskType bit_mask_; 3091cb0ef41Sopenharmony_ci}; 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_cibool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs); 3121cb0ef41Sopenharmony_cibool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ciclass TypedStateValueInfo final { 3151cb0ef41Sopenharmony_ci public: 3161cb0ef41Sopenharmony_ci TypedStateValueInfo(ZoneVector<MachineType> const* machine_types, 3171cb0ef41Sopenharmony_ci SparseInputMask sparse_input_mask) 3181cb0ef41Sopenharmony_ci : machine_types_(machine_types), sparse_input_mask_(sparse_input_mask) {} 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci ZoneVector<MachineType> const* machine_types() const { 3211cb0ef41Sopenharmony_ci return machine_types_; 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci SparseInputMask sparse_input_mask() const { return sparse_input_mask_; } 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci private: 3261cb0ef41Sopenharmony_ci ZoneVector<MachineType> const* machine_types_; 3271cb0ef41Sopenharmony_ci SparseInputMask sparse_input_mask_; 3281cb0ef41Sopenharmony_ci}; 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_cibool operator==(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs); 3311cb0ef41Sopenharmony_cibool operator!=(TypedStateValueInfo const& lhs, TypedStateValueInfo const& rhs); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, TypedStateValueInfo const&); 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_cisize_t hash_value(TypedStateValueInfo const& p); 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci// Used to mark a region (as identified by BeginRegion/FinishRegion) as either 3381cb0ef41Sopenharmony_ci// JavaScript-observable or not (i.e. allocations are not JavaScript observable 3391cb0ef41Sopenharmony_ci// themselves, but transitioning stores are). 3401cb0ef41Sopenharmony_cienum class RegionObservability : uint8_t { kObservable, kNotObservable }; 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_cisize_t hash_value(RegionObservability); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, RegionObservability); 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ciRegionObservability RegionObservabilityOf(Operator const*) 3471cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, 3501cb0ef41Sopenharmony_ci const ZoneVector<MachineType>* types); 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ciType TypeGuardTypeOf(Operator const*) V8_WARN_UNUSED_RESULT; 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ciint OsrValueIndexOf(Operator const*) V8_WARN_UNUSED_RESULT; 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ciSparseInputMask SparseInputMaskOf(Operator const*) V8_WARN_UNUSED_RESULT; 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ciZoneVector<MachineType> const* MachineTypesOf(Operator const*) 3591cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci// The ArgumentsElementsState and ArgumentsLengthState can describe the layout 3621cb0ef41Sopenharmony_ci// for backing stores of arguments objects of various types: 3631cb0ef41Sopenharmony_ci// 3641cb0ef41Sopenharmony_ci// +------------------------------------+ 3651cb0ef41Sopenharmony_ci// - kUnmappedArguments: | arg0, ... argK-1, argK, ... argN-1 | {length:N} 3661cb0ef41Sopenharmony_ci// +------------------------------------+ 3671cb0ef41Sopenharmony_ci// +------------------------------------+ 3681cb0ef41Sopenharmony_ci// - kMappedArguments: | hole, ... hole, argK, ... argN-1 | {length:N} 3691cb0ef41Sopenharmony_ci// +------------------------------------+ 3701cb0ef41Sopenharmony_ci// +------------------+ 3711cb0ef41Sopenharmony_ci// - kRestParameter: | argK, ... argN-1 | {length:N-K} 3721cb0ef41Sopenharmony_ci// +------------------+ 3731cb0ef41Sopenharmony_ci// 3741cb0ef41Sopenharmony_ci// Here {K} represents the number for formal parameters of the active function, 3751cb0ef41Sopenharmony_ci// whereas {N} represents the actual number of arguments passed at runtime. 3761cb0ef41Sopenharmony_ci// Note that {N < K} can happen and causes {K} to be capped accordingly. 3771cb0ef41Sopenharmony_ci// 3781cb0ef41Sopenharmony_ci// Also note that it is possible for an arguments object of {kMappedArguments} 3791cb0ef41Sopenharmony_ci// type to carry a backing store of {kUnappedArguments} type when {K == 0}. 3801cb0ef41Sopenharmony_ciusing ArgumentsStateType = CreateArgumentsType; 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ciArgumentsStateType ArgumentsStateTypeOf(Operator const*) V8_WARN_UNUSED_RESULT; 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ciuint32_t ObjectIdOf(Operator const*); 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ciMachineRepresentation DeadValueRepresentationOf(Operator const*) 3871cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ciclass IfValueParameters final { 3901cb0ef41Sopenharmony_ci public: 3911cb0ef41Sopenharmony_ci IfValueParameters(int32_t value, int32_t comparison_order, 3921cb0ef41Sopenharmony_ci BranchHint hint = BranchHint::kNone) 3931cb0ef41Sopenharmony_ci : value_(value), comparison_order_(comparison_order), hint_(hint) {} 3941cb0ef41Sopenharmony_ci 3951cb0ef41Sopenharmony_ci int32_t value() const { return value_; } 3961cb0ef41Sopenharmony_ci int32_t comparison_order() const { return comparison_order_; } 3971cb0ef41Sopenharmony_ci BranchHint hint() const { return hint_; } 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci private: 4001cb0ef41Sopenharmony_ci int32_t value_; 4011cb0ef41Sopenharmony_ci int32_t comparison_order_; 4021cb0ef41Sopenharmony_ci BranchHint hint_; 4031cb0ef41Sopenharmony_ci}; 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE bool operator==(IfValueParameters const&, 4061cb0ef41Sopenharmony_ci IfValueParameters const&); 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_cisize_t hash_value(IfValueParameters const&); 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, 4111cb0ef41Sopenharmony_ci IfValueParameters const&); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE IfValueParameters const& IfValueParametersOf( 4141cb0ef41Sopenharmony_ci const Operator* op) V8_WARN_UNUSED_RESULT; 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_ciconst FrameStateInfo& FrameStateInfoOf(const Operator* op) 4171cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE Handle<HeapObject> HeapConstantOf(const Operator* op) 4201cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ciconst StringConstantBase* StringConstantBaseOf(const Operator* op) 4231cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT; 4241cb0ef41Sopenharmony_ci 4251cb0ef41Sopenharmony_ciconst char* StaticAssertSourceOf(const Operator* op); 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ciclass SLVerifierHintParameters final { 4281cb0ef41Sopenharmony_ci public: 4291cb0ef41Sopenharmony_ci explicit SLVerifierHintParameters(const Operator* semantics, 4301cb0ef41Sopenharmony_ci base::Optional<Type> override_output_type) 4311cb0ef41Sopenharmony_ci : semantics_(semantics), override_output_type_(override_output_type) {} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci const Operator* semantics() const { return semantics_; } 4341cb0ef41Sopenharmony_ci const base::Optional<Type>& override_output_type() const { 4351cb0ef41Sopenharmony_ci return override_output_type_; 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci private: 4391cb0ef41Sopenharmony_ci const Operator* semantics_; 4401cb0ef41Sopenharmony_ci base::Optional<Type> override_output_type_; 4411cb0ef41Sopenharmony_ci}; 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE bool operator==(const SLVerifierHintParameters& p1, 4441cb0ef41Sopenharmony_ci const SLVerifierHintParameters& p2); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_cisize_t hash_value(const SLVerifierHintParameters& p); 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, 4491cb0ef41Sopenharmony_ci const SLVerifierHintParameters& p); 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE const SLVerifierHintParameters& SLVerifierHintParametersOf( 4521cb0ef41Sopenharmony_ci const Operator* op) V8_WARN_UNUSED_RESULT; 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci// Interface for building common operators that can be used at any level of IR, 4551cb0ef41Sopenharmony_ci// including JavaScript, mid-level, and low-level. 4561cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CommonOperatorBuilder final 4571cb0ef41Sopenharmony_ci : public NON_EXPORTED_BASE(ZoneObject) { 4581cb0ef41Sopenharmony_ci public: 4591cb0ef41Sopenharmony_ci explicit CommonOperatorBuilder(Zone* zone); 4601cb0ef41Sopenharmony_ci CommonOperatorBuilder(const CommonOperatorBuilder&) = delete; 4611cb0ef41Sopenharmony_ci CommonOperatorBuilder& operator=(const CommonOperatorBuilder&) = delete; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci // A dummy value node temporarily used as input when the actual value doesn't 4641cb0ef41Sopenharmony_ci // matter. This operator is inserted only in SimplifiedLowering and is 4651cb0ef41Sopenharmony_ci // expected to not survive dead code elimination. 4661cb0ef41Sopenharmony_ci const Operator* Plug(); 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci const Operator* Dead(); 4691cb0ef41Sopenharmony_ci const Operator* DeadValue(MachineRepresentation rep); 4701cb0ef41Sopenharmony_ci const Operator* Unreachable(); 4711cb0ef41Sopenharmony_ci const Operator* StaticAssert(const char* source); 4721cb0ef41Sopenharmony_ci // SLVerifierHint is used only during SimplifiedLowering. It may be introduced 4731cb0ef41Sopenharmony_ci // during lowering to provide additional hints for the verifier. These nodes 4741cb0ef41Sopenharmony_ci // are removed at the end of SimplifiedLowering after verification. 4751cb0ef41Sopenharmony_ci const Operator* SLVerifierHint( 4761cb0ef41Sopenharmony_ci const Operator* semantics, 4771cb0ef41Sopenharmony_ci const base::Optional<Type>& override_output_type); 4781cb0ef41Sopenharmony_ci const Operator* End(size_t control_input_count); 4791cb0ef41Sopenharmony_ci const Operator* Branch(BranchHint = BranchHint::kNone); 4801cb0ef41Sopenharmony_ci const Operator* IfTrue(); 4811cb0ef41Sopenharmony_ci const Operator* IfFalse(); 4821cb0ef41Sopenharmony_ci const Operator* IfSuccess(); 4831cb0ef41Sopenharmony_ci const Operator* IfException(); 4841cb0ef41Sopenharmony_ci const Operator* Switch(size_t control_output_count); 4851cb0ef41Sopenharmony_ci const Operator* IfValue(int32_t value, int32_t order = 0, 4861cb0ef41Sopenharmony_ci BranchHint hint = BranchHint::kNone); 4871cb0ef41Sopenharmony_ci const Operator* IfDefault(BranchHint hint = BranchHint::kNone); 4881cb0ef41Sopenharmony_ci const Operator* Throw(); 4891cb0ef41Sopenharmony_ci const Operator* Deoptimize(DeoptimizeReason reason, 4901cb0ef41Sopenharmony_ci FeedbackSource const& feedback); 4911cb0ef41Sopenharmony_ci const Operator* DeoptimizeIf(DeoptimizeReason reason, 4921cb0ef41Sopenharmony_ci FeedbackSource const& feedback); 4931cb0ef41Sopenharmony_ci const Operator* DeoptimizeUnless(DeoptimizeReason reason, 4941cb0ef41Sopenharmony_ci FeedbackSource const& feedback); 4951cb0ef41Sopenharmony_ci const Operator* TrapIf(TrapId trap_id); 4961cb0ef41Sopenharmony_ci const Operator* TrapUnless(TrapId trap_id); 4971cb0ef41Sopenharmony_ci const Operator* Return(int value_input_count = 1); 4981cb0ef41Sopenharmony_ci const Operator* Terminate(); 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci const Operator* Start(int value_output_count); 5011cb0ef41Sopenharmony_ci const Operator* Loop(int control_input_count); 5021cb0ef41Sopenharmony_ci const Operator* Merge(int control_input_count); 5031cb0ef41Sopenharmony_ci const Operator* Parameter(int index, const char* debug_name = nullptr); 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci const Operator* OsrValue(int index); 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci const Operator* Int32Constant(int32_t); 5081cb0ef41Sopenharmony_ci const Operator* Int64Constant(int64_t); 5091cb0ef41Sopenharmony_ci const Operator* TaggedIndexConstant(int32_t value); 5101cb0ef41Sopenharmony_ci const Operator* Float32Constant(volatile float); 5111cb0ef41Sopenharmony_ci const Operator* Float64Constant(volatile double); 5121cb0ef41Sopenharmony_ci const Operator* ExternalConstant(const ExternalReference&); 5131cb0ef41Sopenharmony_ci const Operator* NumberConstant(volatile double); 5141cb0ef41Sopenharmony_ci const Operator* PointerConstant(intptr_t); 5151cb0ef41Sopenharmony_ci const Operator* HeapConstant(const Handle<HeapObject>&); 5161cb0ef41Sopenharmony_ci const Operator* CompressedHeapConstant(const Handle<HeapObject>&); 5171cb0ef41Sopenharmony_ci const Operator* ObjectId(uint32_t); 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ci const Operator* RelocatableInt32Constant(int32_t value, 5201cb0ef41Sopenharmony_ci RelocInfo::Mode rmode); 5211cb0ef41Sopenharmony_ci const Operator* RelocatableInt64Constant(int64_t value, 5221cb0ef41Sopenharmony_ci RelocInfo::Mode rmode); 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone); 5251cb0ef41Sopenharmony_ci const Operator* Phi(MachineRepresentation representation, 5261cb0ef41Sopenharmony_ci int value_input_count); 5271cb0ef41Sopenharmony_ci const Operator* EffectPhi(int effect_input_count); 5281cb0ef41Sopenharmony_ci const Operator* InductionVariablePhi(int value_input_count); 5291cb0ef41Sopenharmony_ci const Operator* LoopExit(); 5301cb0ef41Sopenharmony_ci const Operator* LoopExitValue(MachineRepresentation rep); 5311cb0ef41Sopenharmony_ci const Operator* LoopExitEffect(); 5321cb0ef41Sopenharmony_ci const Operator* Checkpoint(); 5331cb0ef41Sopenharmony_ci const Operator* BeginRegion(RegionObservability); 5341cb0ef41Sopenharmony_ci const Operator* FinishRegion(); 5351cb0ef41Sopenharmony_ci const Operator* StateValues(int arguments, SparseInputMask bitmask); 5361cb0ef41Sopenharmony_ci const Operator* TypedStateValues(const ZoneVector<MachineType>* types, 5371cb0ef41Sopenharmony_ci SparseInputMask bitmask); 5381cb0ef41Sopenharmony_ci const Operator* ArgumentsElementsState(ArgumentsStateType type); 5391cb0ef41Sopenharmony_ci const Operator* ArgumentsLengthState(); 5401cb0ef41Sopenharmony_ci const Operator* ObjectState(uint32_t object_id, int pointer_slots); 5411cb0ef41Sopenharmony_ci const Operator* TypedObjectState(uint32_t object_id, 5421cb0ef41Sopenharmony_ci const ZoneVector<MachineType>* types); 5431cb0ef41Sopenharmony_ci const Operator* FrameState(BytecodeOffset bailout_id, 5441cb0ef41Sopenharmony_ci OutputFrameStateCombine state_combine, 5451cb0ef41Sopenharmony_ci const FrameStateFunctionInfo* function_info); 5461cb0ef41Sopenharmony_ci const Operator* Call(const CallDescriptor* call_descriptor); 5471cb0ef41Sopenharmony_ci const Operator* TailCall(const CallDescriptor* call_descriptor); 5481cb0ef41Sopenharmony_ci const Operator* Projection(size_t index); 5491cb0ef41Sopenharmony_ci const Operator* Retain(); 5501cb0ef41Sopenharmony_ci const Operator* TypeGuard(Type type); 5511cb0ef41Sopenharmony_ci const Operator* FoldConstant(); 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci // Constructs a new merge or phi operator with the same opcode as {op}, but 5541cb0ef41Sopenharmony_ci // with {size} inputs. 5551cb0ef41Sopenharmony_ci const Operator* ResizeMergeOrPhi(const Operator* op, int size); 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci // Constructs function info for frame state construction. 5581cb0ef41Sopenharmony_ci const FrameStateFunctionInfo* CreateFrameStateFunctionInfo( 5591cb0ef41Sopenharmony_ci FrameStateType type, int parameter_count, int local_count, 5601cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared_info); 5611cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 5621cb0ef41Sopenharmony_ci const FrameStateFunctionInfo* CreateJSToWasmFrameStateFunctionInfo( 5631cb0ef41Sopenharmony_ci FrameStateType type, int parameter_count, int local_count, 5641cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared_info, 5651cb0ef41Sopenharmony_ci const wasm::FunctionSig* signature); 5661cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci const Operator* DelayedStringConstant(const StringConstantBase* str); 5691cb0ef41Sopenharmony_ci 5701cb0ef41Sopenharmony_ci private: 5711cb0ef41Sopenharmony_ci Zone* zone() const { return zone_; } 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci const CommonOperatorGlobalCache& cache_; 5741cb0ef41Sopenharmony_ci Zone* const zone_; 5751cb0ef41Sopenharmony_ci}; 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci// Node wrappers. 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ciclass CommonNodeWrapperBase : public NodeWrapper { 5801cb0ef41Sopenharmony_ci public: 5811cb0ef41Sopenharmony_ci explicit constexpr CommonNodeWrapperBase(Node* node) : NodeWrapper(node) {} 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_ci // Valid iff this node has exactly one effect input. 5841cb0ef41Sopenharmony_ci Effect effect() const { 5851cb0ef41Sopenharmony_ci DCHECK_EQ(node()->op()->EffectInputCount(), 1); 5861cb0ef41Sopenharmony_ci return Effect{NodeProperties::GetEffectInput(node())}; 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci // Valid iff this node has exactly one control input. 5901cb0ef41Sopenharmony_ci Control control() const { 5911cb0ef41Sopenharmony_ci DCHECK_EQ(node()->op()->ControlInputCount(), 1); 5921cb0ef41Sopenharmony_ci return Control{NodeProperties::GetControlInput(node())}; 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci}; 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci#define DEFINE_INPUT_ACCESSORS(Name, name, TheIndex, Type) \ 5971cb0ef41Sopenharmony_ci static constexpr int Name##Index() { return TheIndex; } \ 5981cb0ef41Sopenharmony_ci TNode<Type> name() const { \ 5991cb0ef41Sopenharmony_ci return TNode<Type>::UncheckedCast( \ 6001cb0ef41Sopenharmony_ci NodeProperties::GetValueInput(node(), TheIndex)); \ 6011cb0ef41Sopenharmony_ci } 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci// TODO(jgruber): This class doesn't match the usual OpcodeNode naming 6041cb0ef41Sopenharmony_ci// convention for historical reasons (it was originally a very basic typed node 6051cb0ef41Sopenharmony_ci// wrapper similar to Effect and Control). Consider updating the name, with low 6061cb0ef41Sopenharmony_ci// priority. 6071cb0ef41Sopenharmony_ciclass FrameState : public CommonNodeWrapperBase { 6081cb0ef41Sopenharmony_ci public: 6091cb0ef41Sopenharmony_ci explicit constexpr FrameState(Node* node) : CommonNodeWrapperBase(node) { 6101cb0ef41Sopenharmony_ci DCHECK_EQ(node->opcode(), IrOpcode::kFrameState); 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci FrameStateInfo frame_state_info() const { 6141cb0ef41Sopenharmony_ci return FrameStateInfoOf(node()->op()); 6151cb0ef41Sopenharmony_ci } 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_ci static constexpr int kFrameStateParametersInput = 0; 6181cb0ef41Sopenharmony_ci static constexpr int kFrameStateLocalsInput = 1; 6191cb0ef41Sopenharmony_ci static constexpr int kFrameStateStackInput = 2; 6201cb0ef41Sopenharmony_ci static constexpr int kFrameStateContextInput = 3; 6211cb0ef41Sopenharmony_ci static constexpr int kFrameStateFunctionInput = 4; 6221cb0ef41Sopenharmony_ci static constexpr int kFrameStateOuterStateInput = 5; 6231cb0ef41Sopenharmony_ci static constexpr int kFrameStateInputCount = 6; 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci // Note: The parameters should be accessed through StateValuesAccess. 6261cb0ef41Sopenharmony_ci Node* parameters() const { 6271cb0ef41Sopenharmony_ci Node* n = node()->InputAt(kFrameStateParametersInput); 6281cb0ef41Sopenharmony_ci DCHECK(n->opcode() == IrOpcode::kStateValues || 6291cb0ef41Sopenharmony_ci n->opcode() == IrOpcode::kTypedStateValues); 6301cb0ef41Sopenharmony_ci return n; 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci Node* locals() const { 6331cb0ef41Sopenharmony_ci Node* n = node()->InputAt(kFrameStateLocalsInput); 6341cb0ef41Sopenharmony_ci DCHECK(n->opcode() == IrOpcode::kStateValues || 6351cb0ef41Sopenharmony_ci n->opcode() == IrOpcode::kTypedStateValues); 6361cb0ef41Sopenharmony_ci return n; 6371cb0ef41Sopenharmony_ci } 6381cb0ef41Sopenharmony_ci // TODO(jgruber): Consider renaming this to the more meaningful 6391cb0ef41Sopenharmony_ci // 'accumulator'. 6401cb0ef41Sopenharmony_ci Node* stack() const { return node()->InputAt(kFrameStateStackInput); } 6411cb0ef41Sopenharmony_ci Node* context() const { return node()->InputAt(kFrameStateContextInput); } 6421cb0ef41Sopenharmony_ci Node* function() const { return node()->InputAt(kFrameStateFunctionInput); } 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci // An outer frame state exists for inlined functions; otherwise it points at 6451cb0ef41Sopenharmony_ci // the start node. Could also be dead. 6461cb0ef41Sopenharmony_ci Node* outer_frame_state() const { 6471cb0ef41Sopenharmony_ci Node* result = node()->InputAt(kFrameStateOuterStateInput); 6481cb0ef41Sopenharmony_ci DCHECK(result->opcode() == IrOpcode::kFrameState || 6491cb0ef41Sopenharmony_ci result->opcode() == IrOpcode::kStart || 6501cb0ef41Sopenharmony_ci result->opcode() == IrOpcode::kDeadValue); 6511cb0ef41Sopenharmony_ci return result; 6521cb0ef41Sopenharmony_ci } 6531cb0ef41Sopenharmony_ci}; 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_ciclass StartNode final : public CommonNodeWrapperBase { 6561cb0ef41Sopenharmony_ci public: 6571cb0ef41Sopenharmony_ci explicit constexpr StartNode(Node* node) : CommonNodeWrapperBase(node) { 6581cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kStart, node->opcode()); 6591cb0ef41Sopenharmony_ci } 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci // The receiver is counted as part of formal parameters. 6621cb0ef41Sopenharmony_ci static constexpr int kReceiverOutputCount = 1; 6631cb0ef41Sopenharmony_ci // These outputs are in addition to formal parameters. 6641cb0ef41Sopenharmony_ci static constexpr int kExtraOutputCount = 4; 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_ci // Takes the formal parameter count of the current function (including 6671cb0ef41Sopenharmony_ci // receiver) and returns the number of value outputs of the start node. 6681cb0ef41Sopenharmony_ci static constexpr int OutputArityForFormalParameterCount(int argc) { 6691cb0ef41Sopenharmony_ci constexpr int kClosure = 1; 6701cb0ef41Sopenharmony_ci constexpr int kNewTarget = 1; 6711cb0ef41Sopenharmony_ci constexpr int kArgCount = 1; 6721cb0ef41Sopenharmony_ci constexpr int kContext = 1; 6731cb0ef41Sopenharmony_ci STATIC_ASSERT(kClosure + kNewTarget + kArgCount + kContext == 6741cb0ef41Sopenharmony_ci kExtraOutputCount); 6751cb0ef41Sopenharmony_ci // Checking related linkage methods here since they rely on Start node 6761cb0ef41Sopenharmony_ci // layout. 6771cb0ef41Sopenharmony_ci DCHECK_EQ(-1, Linkage::kJSCallClosureParamIndex); 6781cb0ef41Sopenharmony_ci DCHECK_EQ(argc + 0, Linkage::GetJSCallNewTargetParamIndex(argc)); 6791cb0ef41Sopenharmony_ci DCHECK_EQ(argc + 1, Linkage::GetJSCallArgCountParamIndex(argc)); 6801cb0ef41Sopenharmony_ci DCHECK_EQ(argc + 2, Linkage::GetJSCallContextParamIndex(argc)); 6811cb0ef41Sopenharmony_ci return argc + kClosure + kNewTarget + kArgCount + kContext; 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_ci int FormalParameterCount() const { 6851cb0ef41Sopenharmony_ci DCHECK_GE(node()->op()->ValueOutputCount(), 6861cb0ef41Sopenharmony_ci kExtraOutputCount + kReceiverOutputCount); 6871cb0ef41Sopenharmony_ci return node()->op()->ValueOutputCount() - kExtraOutputCount; 6881cb0ef41Sopenharmony_ci } 6891cb0ef41Sopenharmony_ci 6901cb0ef41Sopenharmony_ci int FormalParameterCountWithoutReceiver() const { 6911cb0ef41Sopenharmony_ci DCHECK_GE(node()->op()->ValueOutputCount(), 6921cb0ef41Sopenharmony_ci kExtraOutputCount + kReceiverOutputCount); 6931cb0ef41Sopenharmony_ci return node()->op()->ValueOutputCount() - kExtraOutputCount - 6941cb0ef41Sopenharmony_ci kReceiverOutputCount; 6951cb0ef41Sopenharmony_ci } 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci // Note these functions don't return the index of the Start output; instead 6981cb0ef41Sopenharmony_ci // they return the index assigned to the Parameter node. 6991cb0ef41Sopenharmony_ci // TODO(jgruber): Consider unifying the two. 7001cb0ef41Sopenharmony_ci int NewTargetParameterIndex() const { 7011cb0ef41Sopenharmony_ci return Linkage::GetJSCallNewTargetParamIndex(FormalParameterCount()); 7021cb0ef41Sopenharmony_ci } 7031cb0ef41Sopenharmony_ci int ArgCountParameterIndex() const { 7041cb0ef41Sopenharmony_ci return Linkage::GetJSCallArgCountParamIndex(FormalParameterCount()); 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci int ContextParameterIndex() const { 7071cb0ef41Sopenharmony_ci return Linkage::GetJSCallContextParamIndex(FormalParameterCount()); 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci // TODO(jgruber): Remove this function and use 7111cb0ef41Sopenharmony_ci // Linkage::GetJSCallContextParamIndex instead. This currently doesn't work 7121cb0ef41Sopenharmony_ci // because tests don't create valid Start nodes - for example, they may add 7131cb0ef41Sopenharmony_ci // only two context outputs (and not the closure, new target, argc). Once 7141cb0ef41Sopenharmony_ci // tests are fixed, remove this function. 7151cb0ef41Sopenharmony_ci int ContextParameterIndex_MaybeNonStandardLayout() const { 7161cb0ef41Sopenharmony_ci // The context is always the last parameter to a JavaScript function, and 7171cb0ef41Sopenharmony_ci // {Parameter} indices start at -1, so value outputs of {Start} look like 7181cb0ef41Sopenharmony_ci // this: closure, receiver, param0, ..., paramN, context. 7191cb0ef41Sopenharmony_ci // 7201cb0ef41Sopenharmony_ci // TODO(jgruber): This function is called from spots that operate on 7211cb0ef41Sopenharmony_ci // CSA/Torque graphs; Start node layout appears to be different there. 7221cb0ef41Sopenharmony_ci // These should be unified to avoid confusion. Once done, enable this 7231cb0ef41Sopenharmony_ci // DCHECK: DCHECK_EQ(LastOutputIndex(), ContextOutputIndex()); 7241cb0ef41Sopenharmony_ci return node()->op()->ValueOutputCount() - 2; 7251cb0ef41Sopenharmony_ci } 7261cb0ef41Sopenharmony_ci int LastParameterIndex_MaybeNonStandardLayout() const { 7271cb0ef41Sopenharmony_ci return ContextParameterIndex_MaybeNonStandardLayout(); 7281cb0ef41Sopenharmony_ci } 7291cb0ef41Sopenharmony_ci 7301cb0ef41Sopenharmony_ci // Unlike ContextParameterIndex_MaybeNonStandardLayout above, these return 7311cb0ef41Sopenharmony_ci // output indices (and not the index assigned to a Parameter). 7321cb0ef41Sopenharmony_ci int NewTargetOutputIndex() const { 7331cb0ef41Sopenharmony_ci // Indices assigned to parameters are off-by-one (Parameters indices start 7341cb0ef41Sopenharmony_ci // at -1). 7351cb0ef41Sopenharmony_ci // TODO(jgruber): Consider starting at 0. 7361cb0ef41Sopenharmony_ci DCHECK_EQ(Linkage::GetJSCallNewTargetParamIndex(FormalParameterCount()) + 1, 7371cb0ef41Sopenharmony_ci node()->op()->ValueOutputCount() - 3); 7381cb0ef41Sopenharmony_ci return node()->op()->ValueOutputCount() - 3; 7391cb0ef41Sopenharmony_ci } 7401cb0ef41Sopenharmony_ci int ArgCountOutputIndex() const { 7411cb0ef41Sopenharmony_ci // Indices assigned to parameters are off-by-one (Parameters indices start 7421cb0ef41Sopenharmony_ci // at -1). 7431cb0ef41Sopenharmony_ci // TODO(jgruber): Consider starting at 0. 7441cb0ef41Sopenharmony_ci DCHECK_EQ(Linkage::GetJSCallArgCountParamIndex(FormalParameterCount()) + 1, 7451cb0ef41Sopenharmony_ci node()->op()->ValueOutputCount() - 2); 7461cb0ef41Sopenharmony_ci return node()->op()->ValueOutputCount() - 2; 7471cb0ef41Sopenharmony_ci } 7481cb0ef41Sopenharmony_ci int ContextOutputIndex() const { 7491cb0ef41Sopenharmony_ci // Indices assigned to parameters are off-by-one (Parameters indices start 7501cb0ef41Sopenharmony_ci // at -1). 7511cb0ef41Sopenharmony_ci // TODO(jgruber): Consider starting at 0. 7521cb0ef41Sopenharmony_ci DCHECK_EQ(Linkage::GetJSCallContextParamIndex(FormalParameterCount()) + 1, 7531cb0ef41Sopenharmony_ci node()->op()->ValueOutputCount() - 1); 7541cb0ef41Sopenharmony_ci return node()->op()->ValueOutputCount() - 1; 7551cb0ef41Sopenharmony_ci } 7561cb0ef41Sopenharmony_ci int LastOutputIndex() const { return ContextOutputIndex(); } 7571cb0ef41Sopenharmony_ci}; 7581cb0ef41Sopenharmony_ci 7591cb0ef41Sopenharmony_ci#undef DEFINE_INPUT_ACCESSORS 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci} // namespace compiler 7621cb0ef41Sopenharmony_ci} // namespace internal 7631cb0ef41Sopenharmony_ci} // namespace v8 7641cb0ef41Sopenharmony_ci 7651cb0ef41Sopenharmony_ci#endif // V8_COMPILER_COMMON_OPERATOR_H_ 766