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_BACKEND_INSTRUCTION_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_INSTRUCTION_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <iosfwd>
91cb0ef41Sopenharmony_ci#include <map>
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h"
121cb0ef41Sopenharmony_ci#include "src/base/numbers/double.h"
131cb0ef41Sopenharmony_ci#include "src/codegen/external-reference.h"
141cb0ef41Sopenharmony_ci#include "src/codegen/register.h"
151cb0ef41Sopenharmony_ci#include "src/codegen/source-position.h"
161cb0ef41Sopenharmony_ci#include "src/common/globals.h"
171cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction-codes.h"
181cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h"
191cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h"
201cb0ef41Sopenharmony_ci#include "src/compiler/frame.h"
211cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h"
221cb0ef41Sopenharmony_ci#include "src/zone/zone-allocator.h"
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cinamespace v8 {
251cb0ef41Sopenharmony_cinamespace internal {
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciclass RegisterConfiguration;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cinamespace compiler {
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciclass Schedule;
321cb0ef41Sopenharmony_ciclass SourcePositionTable;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#if defined(V8_CC_MSVC) && defined(V8_TARGET_ARCH_IA32)
351cb0ef41Sopenharmony_ci// MSVC on x86 has issues with ALIGNAS(8) on InstructionOperand, but does
361cb0ef41Sopenharmony_ci// align the object to 8 bytes anyway (covered by a static assert below).
371cb0ef41Sopenharmony_ci// See crbug.com/v8/10796
381cb0ef41Sopenharmony_ci#define INSTRUCTION_OPERAND_ALIGN
391cb0ef41Sopenharmony_ci#else
401cb0ef41Sopenharmony_ci#define INSTRUCTION_OPERAND_ALIGN ALIGNAS(8)
411cb0ef41Sopenharmony_ci#endif
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE INSTRUCTION_OPERAND_ALIGN InstructionOperand {
441cb0ef41Sopenharmony_ci public:
451cb0ef41Sopenharmony_ci  static const int kInvalidVirtualRegister = -1;
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  enum Kind {
481cb0ef41Sopenharmony_ci    INVALID,
491cb0ef41Sopenharmony_ci    UNALLOCATED,
501cb0ef41Sopenharmony_ci    CONSTANT,
511cb0ef41Sopenharmony_ci    IMMEDIATE,
521cb0ef41Sopenharmony_ci    PENDING,
531cb0ef41Sopenharmony_ci    // Location operand kinds.
541cb0ef41Sopenharmony_ci    ALLOCATED,
551cb0ef41Sopenharmony_ci    FIRST_LOCATION_OPERAND_KIND = ALLOCATED
561cb0ef41Sopenharmony_ci    // Location operand kinds must be last.
571cb0ef41Sopenharmony_ci  };
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  InstructionOperand() : InstructionOperand(INVALID) {}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  Kind kind() const { return KindField::decode(value_); }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci#define INSTRUCTION_OPERAND_PREDICATE(name, type) \
641cb0ef41Sopenharmony_ci  bool Is##name() const { return kind() == type; }
651cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
661cb0ef41Sopenharmony_ci  // UnallocatedOperands are place-holder operands created before register
671cb0ef41Sopenharmony_ci  // allocation. They later are assigned registers and become AllocatedOperands.
681cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
691cb0ef41Sopenharmony_ci  // Constant operands participate in register allocation. They are allocated to
701cb0ef41Sopenharmony_ci  // registers but have a special "spilling" behavior. When a ConstantOperand
711cb0ef41Sopenharmony_ci  // value must be rematerialized, it is loaded from an immediate constant
721cb0ef41Sopenharmony_ci  // rather from an unspilled slot.
731cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
741cb0ef41Sopenharmony_ci  // ImmediateOperands do not participate in register allocation and are only
751cb0ef41Sopenharmony_ci  // embedded directly in instructions, e.g. small integers and on some
761cb0ef41Sopenharmony_ci  // platforms Objects.
771cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
781cb0ef41Sopenharmony_ci  // PendingOperands are pending allocation during register allocation and
791cb0ef41Sopenharmony_ci  // shouldn't be seen elsewhere. They chain together multiple operators that
801cb0ef41Sopenharmony_ci  // will be replaced together with the same value when finalized.
811cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_PREDICATE(Pending, PENDING)
821cb0ef41Sopenharmony_ci  // AllocatedOperands are registers or stack slots that are assigned by the
831cb0ef41Sopenharmony_ci  // register allocator and are always associated with a virtual register.
841cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
851cb0ef41Sopenharmony_ci#undef INSTRUCTION_OPERAND_PREDICATE
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  inline bool IsAnyLocationOperand() const;
881cb0ef41Sopenharmony_ci  inline bool IsLocationOperand() const;
891cb0ef41Sopenharmony_ci  inline bool IsFPLocationOperand() const;
901cb0ef41Sopenharmony_ci  inline bool IsAnyRegister() const;
911cb0ef41Sopenharmony_ci  inline bool IsRegister() const;
921cb0ef41Sopenharmony_ci  inline bool IsFPRegister() const;
931cb0ef41Sopenharmony_ci  inline bool IsFloatRegister() const;
941cb0ef41Sopenharmony_ci  inline bool IsDoubleRegister() const;
951cb0ef41Sopenharmony_ci  inline bool IsSimd128Register() const;
961cb0ef41Sopenharmony_ci  inline bool IsAnyStackSlot() const;
971cb0ef41Sopenharmony_ci  inline bool IsStackSlot() const;
981cb0ef41Sopenharmony_ci  inline bool IsFPStackSlot() const;
991cb0ef41Sopenharmony_ci  inline bool IsFloatStackSlot() const;
1001cb0ef41Sopenharmony_ci  inline bool IsDoubleStackSlot() const;
1011cb0ef41Sopenharmony_ci  inline bool IsSimd128StackSlot() const;
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  template <typename SubKindOperand>
1041cb0ef41Sopenharmony_ci  static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
1051cb0ef41Sopenharmony_ci    return zone->New<SubKindOperand>(op);
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  static void ReplaceWith(InstructionOperand* dest,
1091cb0ef41Sopenharmony_ci                          const InstructionOperand* src) {
1101cb0ef41Sopenharmony_ci    *dest = *src;
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  bool Equals(const InstructionOperand& that) const {
1141cb0ef41Sopenharmony_ci    if (IsPending()) {
1151cb0ef41Sopenharmony_ci      // Pending operands are only equal if they are the same operand.
1161cb0ef41Sopenharmony_ci      return this == &that;
1171cb0ef41Sopenharmony_ci    }
1181cb0ef41Sopenharmony_ci    return this->value_ == that.value_;
1191cb0ef41Sopenharmony_ci  }
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  bool Compare(const InstructionOperand& that) const {
1221cb0ef41Sopenharmony_ci    return this->value_ < that.value_;
1231cb0ef41Sopenharmony_ci  }
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  bool EqualsCanonicalized(const InstructionOperand& that) const {
1261cb0ef41Sopenharmony_ci    if (IsPending()) {
1271cb0ef41Sopenharmony_ci      // Pending operands can't be canonicalized, so just compare for equality.
1281cb0ef41Sopenharmony_ci      return Equals(that);
1291cb0ef41Sopenharmony_ci    }
1301cb0ef41Sopenharmony_ci    return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  bool CompareCanonicalized(const InstructionOperand& that) const {
1341cb0ef41Sopenharmony_ci    DCHECK(!IsPending());
1351cb0ef41Sopenharmony_ci    return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
1361cb0ef41Sopenharmony_ci  }
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  bool InterferesWith(const InstructionOperand& other) const;
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  // APIs to aid debugging. For general-stream APIs, use operator<<.
1411cb0ef41Sopenharmony_ci  void Print() const;
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  bool operator==(InstructionOperand& other) const { return Equals(other); }
1441cb0ef41Sopenharmony_ci  bool operator!=(InstructionOperand& other) const { return !Equals(other); }
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci protected:
1471cb0ef41Sopenharmony_ci  explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  inline uint64_t GetCanonicalizedValue() const;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  using KindField = base::BitField64<Kind, 0, 3>;
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  uint64_t value_;
1541cb0ef41Sopenharmony_ci};
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciusing InstructionOperandVector = ZoneVector<InstructionOperand>;
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, const InstructionOperand&);
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind)      \
1611cb0ef41Sopenharmony_ci                                                                 \
1621cb0ef41Sopenharmony_ci  static OperandType* cast(InstructionOperand* op) {             \
1631cb0ef41Sopenharmony_ci    DCHECK_EQ(OperandKind, op->kind());                          \
1641cb0ef41Sopenharmony_ci    return static_cast<OperandType*>(op);                        \
1651cb0ef41Sopenharmony_ci  }                                                              \
1661cb0ef41Sopenharmony_ci                                                                 \
1671cb0ef41Sopenharmony_ci  static const OperandType* cast(const InstructionOperand* op) { \
1681cb0ef41Sopenharmony_ci    DCHECK_EQ(OperandKind, op->kind());                          \
1691cb0ef41Sopenharmony_ci    return static_cast<const OperandType*>(op);                  \
1701cb0ef41Sopenharmony_ci  }                                                              \
1711cb0ef41Sopenharmony_ci                                                                 \
1721cb0ef41Sopenharmony_ci  static OperandType cast(const InstructionOperand& op) {        \
1731cb0ef41Sopenharmony_ci    DCHECK_EQ(OperandKind, op.kind());                           \
1741cb0ef41Sopenharmony_ci    return *static_cast<const OperandType*>(&op);                \
1751cb0ef41Sopenharmony_ci  }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ciclass UnallocatedOperand final : public InstructionOperand {
1781cb0ef41Sopenharmony_ci public:
1791cb0ef41Sopenharmony_ci  enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  enum ExtendedPolicy {
1821cb0ef41Sopenharmony_ci    NONE,
1831cb0ef41Sopenharmony_ci    REGISTER_OR_SLOT,
1841cb0ef41Sopenharmony_ci    REGISTER_OR_SLOT_OR_CONSTANT,
1851cb0ef41Sopenharmony_ci    FIXED_REGISTER,
1861cb0ef41Sopenharmony_ci    FIXED_FP_REGISTER,
1871cb0ef41Sopenharmony_ci    MUST_HAVE_REGISTER,
1881cb0ef41Sopenharmony_ci    MUST_HAVE_SLOT,
1891cb0ef41Sopenharmony_ci    SAME_AS_INPUT
1901cb0ef41Sopenharmony_ci  };
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  // Lifetime of operand inside the instruction.
1931cb0ef41Sopenharmony_ci  enum Lifetime {
1941cb0ef41Sopenharmony_ci    // USED_AT_START operand is guaranteed to be live only at instruction start.
1951cb0ef41Sopenharmony_ci    // The register allocator is free to assign the same register to some other
1961cb0ef41Sopenharmony_ci    // operand used inside instruction (i.e. temporary or output).
1971cb0ef41Sopenharmony_ci    USED_AT_START,
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci    // USED_AT_END operand is treated as live until the end of instruction.
2001cb0ef41Sopenharmony_ci    // This means that register allocator will not reuse its register for any
2011cb0ef41Sopenharmony_ci    // other operand inside instruction.
2021cb0ef41Sopenharmony_ci    USED_AT_END
2031cb0ef41Sopenharmony_ci  };
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
2061cb0ef41Sopenharmony_ci      : UnallocatedOperand(virtual_register) {
2071cb0ef41Sopenharmony_ci    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
2081cb0ef41Sopenharmony_ci    value_ |= ExtendedPolicyField::encode(policy);
2091cb0ef41Sopenharmony_ci    value_ |= LifetimeField::encode(USED_AT_END);
2101cb0ef41Sopenharmony_ci  }
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  UnallocatedOperand(int virtual_register, int input_index)
2131cb0ef41Sopenharmony_ci      : UnallocatedOperand(virtual_register) {
2141cb0ef41Sopenharmony_ci    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
2151cb0ef41Sopenharmony_ci    value_ |= ExtendedPolicyField::encode(SAME_AS_INPUT);
2161cb0ef41Sopenharmony_ci    value_ |= LifetimeField::encode(USED_AT_END);
2171cb0ef41Sopenharmony_ci    value_ |= InputIndexField::encode(input_index);
2181cb0ef41Sopenharmony_ci  }
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
2211cb0ef41Sopenharmony_ci      : UnallocatedOperand(virtual_register) {
2221cb0ef41Sopenharmony_ci    DCHECK(policy == FIXED_SLOT);
2231cb0ef41Sopenharmony_ci    value_ |= BasicPolicyField::encode(policy);
2241cb0ef41Sopenharmony_ci    value_ |= static_cast<uint64_t>(static_cast<int64_t>(index))
2251cb0ef41Sopenharmony_ci              << FixedSlotIndexField::kShift;
2261cb0ef41Sopenharmony_ci    DCHECK(this->fixed_slot_index() == index);
2271cb0ef41Sopenharmony_ci  }
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
2301cb0ef41Sopenharmony_ci      : UnallocatedOperand(virtual_register) {
2311cb0ef41Sopenharmony_ci    DCHECK(policy == FIXED_REGISTER || policy == FIXED_FP_REGISTER);
2321cb0ef41Sopenharmony_ci    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
2331cb0ef41Sopenharmony_ci    value_ |= ExtendedPolicyField::encode(policy);
2341cb0ef41Sopenharmony_ci    value_ |= LifetimeField::encode(USED_AT_END);
2351cb0ef41Sopenharmony_ci    value_ |= FixedRegisterField::encode(index);
2361cb0ef41Sopenharmony_ci  }
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
2391cb0ef41Sopenharmony_ci                     int virtual_register)
2401cb0ef41Sopenharmony_ci      : UnallocatedOperand(virtual_register) {
2411cb0ef41Sopenharmony_ci    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
2421cb0ef41Sopenharmony_ci    value_ |= ExtendedPolicyField::encode(policy);
2431cb0ef41Sopenharmony_ci    value_ |= LifetimeField::encode(lifetime);
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
2471cb0ef41Sopenharmony_ci      : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
2481cb0ef41Sopenharmony_ci    value_ |= HasSecondaryStorageField::encode(true);
2491cb0ef41Sopenharmony_ci    value_ |= SecondaryStorageField::encode(slot_id);
2501cb0ef41Sopenharmony_ci  }
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci  UnallocatedOperand(const UnallocatedOperand& other, int virtual_register) {
2531cb0ef41Sopenharmony_ci    DCHECK_NE(kInvalidVirtualRegister, virtual_register);
2541cb0ef41Sopenharmony_ci    value_ = VirtualRegisterField::update(
2551cb0ef41Sopenharmony_ci        other.value_, static_cast<uint32_t>(virtual_register));
2561cb0ef41Sopenharmony_ci  }
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  // Predicates for the operand policy.
2591cb0ef41Sopenharmony_ci  bool HasRegisterOrSlotPolicy() const {
2601cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2611cb0ef41Sopenharmony_ci           extended_policy() == REGISTER_OR_SLOT;
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci  bool HasRegisterOrSlotOrConstantPolicy() const {
2641cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2651cb0ef41Sopenharmony_ci           extended_policy() == REGISTER_OR_SLOT_OR_CONSTANT;
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci  bool HasFixedPolicy() const {
2681cb0ef41Sopenharmony_ci    return basic_policy() == FIXED_SLOT ||
2691cb0ef41Sopenharmony_ci           extended_policy() == FIXED_REGISTER ||
2701cb0ef41Sopenharmony_ci           extended_policy() == FIXED_FP_REGISTER;
2711cb0ef41Sopenharmony_ci  }
2721cb0ef41Sopenharmony_ci  bool HasRegisterPolicy() const {
2731cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2741cb0ef41Sopenharmony_ci           extended_policy() == MUST_HAVE_REGISTER;
2751cb0ef41Sopenharmony_ci  }
2761cb0ef41Sopenharmony_ci  bool HasSlotPolicy() const {
2771cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2781cb0ef41Sopenharmony_ci           extended_policy() == MUST_HAVE_SLOT;
2791cb0ef41Sopenharmony_ci  }
2801cb0ef41Sopenharmony_ci  bool HasSameAsInputPolicy() const {
2811cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2821cb0ef41Sopenharmony_ci           extended_policy() == SAME_AS_INPUT;
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci  bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
2851cb0ef41Sopenharmony_ci  bool HasFixedRegisterPolicy() const {
2861cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2871cb0ef41Sopenharmony_ci           extended_policy() == FIXED_REGISTER;
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci  bool HasFixedFPRegisterPolicy() const {
2901cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2911cb0ef41Sopenharmony_ci           extended_policy() == FIXED_FP_REGISTER;
2921cb0ef41Sopenharmony_ci  }
2931cb0ef41Sopenharmony_ci  bool HasSecondaryStorage() const {
2941cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
2951cb0ef41Sopenharmony_ci           extended_policy() == FIXED_REGISTER &&
2961cb0ef41Sopenharmony_ci           HasSecondaryStorageField::decode(value_);
2971cb0ef41Sopenharmony_ci  }
2981cb0ef41Sopenharmony_ci  int GetSecondaryStorage() const {
2991cb0ef41Sopenharmony_ci    DCHECK(HasSecondaryStorage());
3001cb0ef41Sopenharmony_ci    return SecondaryStorageField::decode(value_);
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
3041cb0ef41Sopenharmony_ci  BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); }
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci  // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
3071cb0ef41Sopenharmony_ci  ExtendedPolicy extended_policy() const {
3081cb0ef41Sopenharmony_ci    DCHECK(basic_policy() == EXTENDED_POLICY);
3091cb0ef41Sopenharmony_ci    return ExtendedPolicyField::decode(value_);
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  int input_index() const {
3131cb0ef41Sopenharmony_ci    DCHECK(HasSameAsInputPolicy());
3141cb0ef41Sopenharmony_ci    return InputIndexField::decode(value_);
3151cb0ef41Sopenharmony_ci  }
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  // [fixed_slot_index]: Only for FIXED_SLOT.
3181cb0ef41Sopenharmony_ci  int fixed_slot_index() const {
3191cb0ef41Sopenharmony_ci    DCHECK(HasFixedSlotPolicy());
3201cb0ef41Sopenharmony_ci    return static_cast<int>(static_cast<int64_t>(value_) >>
3211cb0ef41Sopenharmony_ci                            FixedSlotIndexField::kShift);
3221cb0ef41Sopenharmony_ci  }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER.
3251cb0ef41Sopenharmony_ci  int fixed_register_index() const {
3261cb0ef41Sopenharmony_ci    DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy());
3271cb0ef41Sopenharmony_ci    return FixedRegisterField::decode(value_);
3281cb0ef41Sopenharmony_ci  }
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  // [virtual_register]: The virtual register ID for this operand.
3311cb0ef41Sopenharmony_ci  int32_t virtual_register() const {
3321cb0ef41Sopenharmony_ci    return static_cast<int32_t>(VirtualRegisterField::decode(value_));
3331cb0ef41Sopenharmony_ci  }
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  // [lifetime]: Only for non-FIXED_SLOT.
3361cb0ef41Sopenharmony_ci  bool IsUsedAtStart() const {
3371cb0ef41Sopenharmony_ci    return basic_policy() == EXTENDED_POLICY &&
3381cb0ef41Sopenharmony_ci           LifetimeField::decode(value_) == USED_AT_START;
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED)
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  // The encoding used for UnallocatedOperand operands depends on the policy
3441cb0ef41Sopenharmony_ci  // that is
3451cb0ef41Sopenharmony_ci  // stored within the operand. The FIXED_SLOT policy uses a compact encoding
3461cb0ef41Sopenharmony_ci  // because it accommodates a larger pay-load.
3471cb0ef41Sopenharmony_ci  //
3481cb0ef41Sopenharmony_ci  // For FIXED_SLOT policy:
3491cb0ef41Sopenharmony_ci  //     +------------------------------------------------+
3501cb0ef41Sopenharmony_ci  //     |      slot_index   | 0 | virtual_register | 001 |
3511cb0ef41Sopenharmony_ci  //     +------------------------------------------------+
3521cb0ef41Sopenharmony_ci  //
3531cb0ef41Sopenharmony_ci  // For all other (extended) policies:
3541cb0ef41Sopenharmony_ci  //     +-----------------------------------------------------+
3551cb0ef41Sopenharmony_ci  //     |  reg_index  | L | PPP |  1 | virtual_register | 001 |
3561cb0ef41Sopenharmony_ci  //     +-----------------------------------------------------+
3571cb0ef41Sopenharmony_ci  //     L ... Lifetime
3581cb0ef41Sopenharmony_ci  //     P ... Policy
3591cb0ef41Sopenharmony_ci  //
3601cb0ef41Sopenharmony_ci  // The slot index is a signed value which requires us to decode it manually
3611cb0ef41Sopenharmony_ci  // instead of using the base::BitField utility class.
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  STATIC_ASSERT(KindField::kSize == 3);
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  using VirtualRegisterField = base::BitField64<uint32_t, 3, 32>;
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci  // base::BitFields for all unallocated operands.
3681cb0ef41Sopenharmony_ci  using BasicPolicyField = base::BitField64<BasicPolicy, 35, 1>;
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci  // BitFields specific to BasicPolicy::FIXED_SLOT.
3711cb0ef41Sopenharmony_ci  using FixedSlotIndexField = base::BitField64<int, 36, 28>;
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  // BitFields specific to BasicPolicy::EXTENDED_POLICY.
3741cb0ef41Sopenharmony_ci  using ExtendedPolicyField = base::BitField64<ExtendedPolicy, 36, 3>;
3751cb0ef41Sopenharmony_ci  using LifetimeField = base::BitField64<Lifetime, 39, 1>;
3761cb0ef41Sopenharmony_ci  using HasSecondaryStorageField = base::BitField64<bool, 40, 1>;
3771cb0ef41Sopenharmony_ci  using FixedRegisterField = base::BitField64<int, 41, 6>;
3781cb0ef41Sopenharmony_ci  using SecondaryStorageField = base::BitField64<int, 47, 3>;
3791cb0ef41Sopenharmony_ci  using InputIndexField = base::BitField64<int, 50, 3>;
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci private:
3821cb0ef41Sopenharmony_ci  explicit UnallocatedOperand(int virtual_register)
3831cb0ef41Sopenharmony_ci      : InstructionOperand(UNALLOCATED) {
3841cb0ef41Sopenharmony_ci    value_ |=
3851cb0ef41Sopenharmony_ci        VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci};
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ciclass ConstantOperand : public InstructionOperand {
3901cb0ef41Sopenharmony_ci public:
3911cb0ef41Sopenharmony_ci  explicit ConstantOperand(int virtual_register)
3921cb0ef41Sopenharmony_ci      : InstructionOperand(CONSTANT) {
3931cb0ef41Sopenharmony_ci    value_ |=
3941cb0ef41Sopenharmony_ci        VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
3951cb0ef41Sopenharmony_ci  }
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  int32_t virtual_register() const {
3981cb0ef41Sopenharmony_ci    return static_cast<int32_t>(VirtualRegisterField::decode(value_));
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci  static ConstantOperand* New(Zone* zone, int virtual_register) {
4021cb0ef41Sopenharmony_ci    return InstructionOperand::New(zone, ConstantOperand(virtual_register));
4031cb0ef41Sopenharmony_ci  }
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT)
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci  STATIC_ASSERT(KindField::kSize == 3);
4081cb0ef41Sopenharmony_ci  using VirtualRegisterField = base::BitField64<uint32_t, 3, 32>;
4091cb0ef41Sopenharmony_ci};
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ciclass ImmediateOperand : public InstructionOperand {
4121cb0ef41Sopenharmony_ci public:
4131cb0ef41Sopenharmony_ci  enum ImmediateType { INLINE_INT32, INLINE_INT64, INDEXED_RPO, INDEXED_IMM };
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci  explicit ImmediateOperand(ImmediateType type, int32_t value)
4161cb0ef41Sopenharmony_ci      : InstructionOperand(IMMEDIATE) {
4171cb0ef41Sopenharmony_ci    value_ |= TypeField::encode(type);
4181cb0ef41Sopenharmony_ci    value_ |= static_cast<uint64_t>(static_cast<int64_t>(value))
4191cb0ef41Sopenharmony_ci              << ValueField::kShift;
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci  ImmediateType type() const { return TypeField::decode(value_); }
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  int32_t inline_int32_value() const {
4251cb0ef41Sopenharmony_ci    DCHECK_EQ(INLINE_INT32, type());
4261cb0ef41Sopenharmony_ci    return static_cast<int64_t>(value_) >> ValueField::kShift;
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  int64_t inline_int64_value() const {
4301cb0ef41Sopenharmony_ci    DCHECK_EQ(INLINE_INT64, type());
4311cb0ef41Sopenharmony_ci    return static_cast<int64_t>(value_) >> ValueField::kShift;
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  int32_t indexed_value() const {
4351cb0ef41Sopenharmony_ci    DCHECK(type() == INDEXED_IMM || type() == INDEXED_RPO);
4361cb0ef41Sopenharmony_ci    return static_cast<int64_t>(value_) >> ValueField::kShift;
4371cb0ef41Sopenharmony_ci  }
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci  static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
4401cb0ef41Sopenharmony_ci    return InstructionOperand::New(zone, ImmediateOperand(type, value));
4411cb0ef41Sopenharmony_ci  }
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE)
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci  STATIC_ASSERT(KindField::kSize == 3);
4461cb0ef41Sopenharmony_ci  using TypeField = base::BitField64<ImmediateType, 3, 2>;
4471cb0ef41Sopenharmony_ci  using ValueField = base::BitField64<int32_t, 32, 32>;
4481cb0ef41Sopenharmony_ci};
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ciclass PendingOperand : public InstructionOperand {
4511cb0ef41Sopenharmony_ci public:
4521cb0ef41Sopenharmony_ci  PendingOperand() : InstructionOperand(PENDING) {}
4531cb0ef41Sopenharmony_ci  explicit PendingOperand(PendingOperand* next_operand) : PendingOperand() {
4541cb0ef41Sopenharmony_ci    set_next(next_operand);
4551cb0ef41Sopenharmony_ci  }
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci  void set_next(PendingOperand* next) {
4581cb0ef41Sopenharmony_ci    DCHECK_NULL(this->next());
4591cb0ef41Sopenharmony_ci    uintptr_t shifted_value =
4601cb0ef41Sopenharmony_ci        reinterpret_cast<uintptr_t>(next) >> kPointerShift;
4611cb0ef41Sopenharmony_ci    DCHECK_EQ(reinterpret_cast<uintptr_t>(next),
4621cb0ef41Sopenharmony_ci              shifted_value << kPointerShift);
4631cb0ef41Sopenharmony_ci    value_ |= NextOperandField::encode(static_cast<uint64_t>(shifted_value));
4641cb0ef41Sopenharmony_ci  }
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci  PendingOperand* next() const {
4671cb0ef41Sopenharmony_ci    uintptr_t shifted_value =
4681cb0ef41Sopenharmony_ci        static_cast<uint64_t>(NextOperandField::decode(value_));
4691cb0ef41Sopenharmony_ci    return reinterpret_cast<PendingOperand*>(shifted_value << kPointerShift);
4701cb0ef41Sopenharmony_ci  }
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  static PendingOperand* New(Zone* zone, PendingOperand* previous_operand) {
4731cb0ef41Sopenharmony_ci    return InstructionOperand::New(zone, PendingOperand(previous_operand));
4741cb0ef41Sopenharmony_ci  }
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_CASTS(PendingOperand, PENDING)
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci private:
4791cb0ef41Sopenharmony_ci  // Operands are uint64_t values and so are aligned to 8 byte boundaries,
4801cb0ef41Sopenharmony_ci  // therefore we can shift off the bottom three zeros without losing data.
4811cb0ef41Sopenharmony_ci  static const uint64_t kPointerShift = 3;
4821cb0ef41Sopenharmony_ci  STATIC_ASSERT(alignof(InstructionOperand) >= (1 << kPointerShift));
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci  STATIC_ASSERT(KindField::kSize == 3);
4851cb0ef41Sopenharmony_ci  using NextOperandField = base::BitField64<uint64_t, 3, 61>;
4861cb0ef41Sopenharmony_ci};
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ciclass LocationOperand : public InstructionOperand {
4891cb0ef41Sopenharmony_ci public:
4901cb0ef41Sopenharmony_ci  enum LocationKind { REGISTER, STACK_SLOT };
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  LocationOperand(InstructionOperand::Kind operand_kind,
4931cb0ef41Sopenharmony_ci                  LocationOperand::LocationKind location_kind,
4941cb0ef41Sopenharmony_ci                  MachineRepresentation rep, int index)
4951cb0ef41Sopenharmony_ci      : InstructionOperand(operand_kind) {
4961cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
4971cb0ef41Sopenharmony_ci    DCHECK(IsSupportedRepresentation(rep));
4981cb0ef41Sopenharmony_ci    value_ |= LocationKindField::encode(location_kind);
4991cb0ef41Sopenharmony_ci    value_ |= RepresentationField::encode(rep);
5001cb0ef41Sopenharmony_ci    value_ |= static_cast<uint64_t>(static_cast<int64_t>(index))
5011cb0ef41Sopenharmony_ci              << IndexField::kShift;
5021cb0ef41Sopenharmony_ci  }
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci  int index() const {
5051cb0ef41Sopenharmony_ci    DCHECK(IsStackSlot() || IsFPStackSlot());
5061cb0ef41Sopenharmony_ci    return static_cast<int64_t>(value_) >> IndexField::kShift;
5071cb0ef41Sopenharmony_ci  }
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci  int register_code() const {
5101cb0ef41Sopenharmony_ci    DCHECK(IsRegister() || IsFPRegister());
5111cb0ef41Sopenharmony_ci    return static_cast<int64_t>(value_) >> IndexField::kShift;
5121cb0ef41Sopenharmony_ci  }
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci  Register GetRegister() const {
5151cb0ef41Sopenharmony_ci    DCHECK(IsRegister());
5161cb0ef41Sopenharmony_ci    return Register::from_code(register_code());
5171cb0ef41Sopenharmony_ci  }
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ci  FloatRegister GetFloatRegister() const {
5201cb0ef41Sopenharmony_ci    DCHECK(IsFloatRegister());
5211cb0ef41Sopenharmony_ci    return FloatRegister::from_code(register_code());
5221cb0ef41Sopenharmony_ci  }
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  DoubleRegister GetDoubleRegister() const {
5251cb0ef41Sopenharmony_ci    // On platforms where FloatRegister, DoubleRegister, and Simd128Register
5261cb0ef41Sopenharmony_ci    // are all the same type, it's convenient to treat everything as a
5271cb0ef41Sopenharmony_ci    // DoubleRegister, so be lax about type checking here.
5281cb0ef41Sopenharmony_ci    DCHECK(IsFPRegister());
5291cb0ef41Sopenharmony_ci    return DoubleRegister::from_code(register_code());
5301cb0ef41Sopenharmony_ci  }
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ci  Simd128Register GetSimd128Register() const {
5331cb0ef41Sopenharmony_ci    DCHECK(IsSimd128Register());
5341cb0ef41Sopenharmony_ci    return Simd128Register::from_code(register_code());
5351cb0ef41Sopenharmony_ci  }
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ci  LocationKind location_kind() const {
5381cb0ef41Sopenharmony_ci    return LocationKindField::decode(value_);
5391cb0ef41Sopenharmony_ci  }
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci  MachineRepresentation representation() const {
5421cb0ef41Sopenharmony_ci    return RepresentationField::decode(value_);
5431cb0ef41Sopenharmony_ci  }
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci  static bool IsSupportedRepresentation(MachineRepresentation rep) {
5461cb0ef41Sopenharmony_ci    switch (rep) {
5471cb0ef41Sopenharmony_ci      case MachineRepresentation::kWord32:
5481cb0ef41Sopenharmony_ci      case MachineRepresentation::kWord64:
5491cb0ef41Sopenharmony_ci      case MachineRepresentation::kFloat32:
5501cb0ef41Sopenharmony_ci      case MachineRepresentation::kFloat64:
5511cb0ef41Sopenharmony_ci      case MachineRepresentation::kSimd128:
5521cb0ef41Sopenharmony_ci      case MachineRepresentation::kTaggedSigned:
5531cb0ef41Sopenharmony_ci      case MachineRepresentation::kTaggedPointer:
5541cb0ef41Sopenharmony_ci      case MachineRepresentation::kTagged:
5551cb0ef41Sopenharmony_ci      case MachineRepresentation::kCompressedPointer:
5561cb0ef41Sopenharmony_ci      case MachineRepresentation::kCompressed:
5571cb0ef41Sopenharmony_ci      case MachineRepresentation::kSandboxedPointer:
5581cb0ef41Sopenharmony_ci        return true;
5591cb0ef41Sopenharmony_ci      case MachineRepresentation::kBit:
5601cb0ef41Sopenharmony_ci      case MachineRepresentation::kWord8:
5611cb0ef41Sopenharmony_ci      case MachineRepresentation::kWord16:
5621cb0ef41Sopenharmony_ci      case MachineRepresentation::kNone:
5631cb0ef41Sopenharmony_ci        return false;
5641cb0ef41Sopenharmony_ci      case MachineRepresentation::kMapWord:
5651cb0ef41Sopenharmony_ci        break;
5661cb0ef41Sopenharmony_ci    }
5671cb0ef41Sopenharmony_ci    UNREACHABLE();
5681cb0ef41Sopenharmony_ci  }
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  // Return true if the locations can be moved to one another.
5711cb0ef41Sopenharmony_ci  bool IsCompatible(LocationOperand* op);
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ci  static LocationOperand* cast(InstructionOperand* op) {
5741cb0ef41Sopenharmony_ci    DCHECK(op->IsAnyLocationOperand());
5751cb0ef41Sopenharmony_ci    return static_cast<LocationOperand*>(op);
5761cb0ef41Sopenharmony_ci  }
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci  static const LocationOperand* cast(const InstructionOperand* op) {
5791cb0ef41Sopenharmony_ci    DCHECK(op->IsAnyLocationOperand());
5801cb0ef41Sopenharmony_ci    return static_cast<const LocationOperand*>(op);
5811cb0ef41Sopenharmony_ci  }
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ci  static LocationOperand cast(const InstructionOperand& op) {
5841cb0ef41Sopenharmony_ci    DCHECK(op.IsAnyLocationOperand());
5851cb0ef41Sopenharmony_ci    return *static_cast<const LocationOperand*>(&op);
5861cb0ef41Sopenharmony_ci  }
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci  STATIC_ASSERT(KindField::kSize == 3);
5891cb0ef41Sopenharmony_ci  using LocationKindField = base::BitField64<LocationKind, 3, 2>;
5901cb0ef41Sopenharmony_ci  using RepresentationField = base::BitField64<MachineRepresentation, 5, 8>;
5911cb0ef41Sopenharmony_ci  using IndexField = base::BitField64<int32_t, 35, 29>;
5921cb0ef41Sopenharmony_ci};
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ciclass AllocatedOperand : public LocationOperand {
5951cb0ef41Sopenharmony_ci public:
5961cb0ef41Sopenharmony_ci  AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
5971cb0ef41Sopenharmony_ci      : LocationOperand(ALLOCATED, kind, rep, index) {}
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  static AllocatedOperand* New(Zone* zone, LocationKind kind,
6001cb0ef41Sopenharmony_ci                               MachineRepresentation rep, int index) {
6011cb0ef41Sopenharmony_ci    return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
6021cb0ef41Sopenharmony_ci  }
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED)
6051cb0ef41Sopenharmony_ci};
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ci#undef INSTRUCTION_OPERAND_CASTS
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_cibool InstructionOperand::IsAnyLocationOperand() const {
6101cb0ef41Sopenharmony_ci  return this->kind() >= FIRST_LOCATION_OPERAND_KIND;
6111cb0ef41Sopenharmony_ci}
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_cibool InstructionOperand::IsLocationOperand() const {
6141cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6151cb0ef41Sopenharmony_ci         !IsFloatingPoint(LocationOperand::cast(this)->representation());
6161cb0ef41Sopenharmony_ci}
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_cibool InstructionOperand::IsFPLocationOperand() const {
6191cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6201cb0ef41Sopenharmony_ci         IsFloatingPoint(LocationOperand::cast(this)->representation());
6211cb0ef41Sopenharmony_ci}
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_cibool InstructionOperand::IsAnyRegister() const {
6241cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6251cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->location_kind() ==
6261cb0ef41Sopenharmony_ci             LocationOperand::REGISTER;
6271cb0ef41Sopenharmony_ci}
6281cb0ef41Sopenharmony_ci
6291cb0ef41Sopenharmony_cibool InstructionOperand::IsRegister() const {
6301cb0ef41Sopenharmony_ci  return IsAnyRegister() &&
6311cb0ef41Sopenharmony_ci         !IsFloatingPoint(LocationOperand::cast(this)->representation());
6321cb0ef41Sopenharmony_ci}
6331cb0ef41Sopenharmony_ci
6341cb0ef41Sopenharmony_cibool InstructionOperand::IsFPRegister() const {
6351cb0ef41Sopenharmony_ci  return IsAnyRegister() &&
6361cb0ef41Sopenharmony_ci         IsFloatingPoint(LocationOperand::cast(this)->representation());
6371cb0ef41Sopenharmony_ci}
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_cibool InstructionOperand::IsFloatRegister() const {
6401cb0ef41Sopenharmony_ci  return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
6411cb0ef41Sopenharmony_ci                                MachineRepresentation::kFloat32;
6421cb0ef41Sopenharmony_ci}
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_cibool InstructionOperand::IsDoubleRegister() const {
6451cb0ef41Sopenharmony_ci  return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
6461cb0ef41Sopenharmony_ci                                MachineRepresentation::kFloat64;
6471cb0ef41Sopenharmony_ci}
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_cibool InstructionOperand::IsSimd128Register() const {
6501cb0ef41Sopenharmony_ci  return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
6511cb0ef41Sopenharmony_ci                                MachineRepresentation::kSimd128;
6521cb0ef41Sopenharmony_ci}
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_cibool InstructionOperand::IsAnyStackSlot() const {
6551cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6561cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->location_kind() ==
6571cb0ef41Sopenharmony_ci             LocationOperand::STACK_SLOT;
6581cb0ef41Sopenharmony_ci}
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_cibool InstructionOperand::IsStackSlot() const {
6611cb0ef41Sopenharmony_ci  return IsAnyStackSlot() &&
6621cb0ef41Sopenharmony_ci         !IsFloatingPoint(LocationOperand::cast(this)->representation());
6631cb0ef41Sopenharmony_ci}
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_cibool InstructionOperand::IsFPStackSlot() const {
6661cb0ef41Sopenharmony_ci  return IsAnyStackSlot() &&
6671cb0ef41Sopenharmony_ci         IsFloatingPoint(LocationOperand::cast(this)->representation());
6681cb0ef41Sopenharmony_ci}
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_cibool InstructionOperand::IsFloatStackSlot() const {
6711cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6721cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->location_kind() ==
6731cb0ef41Sopenharmony_ci             LocationOperand::STACK_SLOT &&
6741cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->representation() ==
6751cb0ef41Sopenharmony_ci             MachineRepresentation::kFloat32;
6761cb0ef41Sopenharmony_ci}
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_cibool InstructionOperand::IsDoubleStackSlot() const {
6791cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6801cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->location_kind() ==
6811cb0ef41Sopenharmony_ci             LocationOperand::STACK_SLOT &&
6821cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->representation() ==
6831cb0ef41Sopenharmony_ci             MachineRepresentation::kFloat64;
6841cb0ef41Sopenharmony_ci}
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_cibool InstructionOperand::IsSimd128StackSlot() const {
6871cb0ef41Sopenharmony_ci  return IsAnyLocationOperand() &&
6881cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->location_kind() ==
6891cb0ef41Sopenharmony_ci             LocationOperand::STACK_SLOT &&
6901cb0ef41Sopenharmony_ci         LocationOperand::cast(this)->representation() ==
6911cb0ef41Sopenharmony_ci             MachineRepresentation::kSimd128;
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ciuint64_t InstructionOperand::GetCanonicalizedValue() const {
6951cb0ef41Sopenharmony_ci  if (IsAnyLocationOperand()) {
6961cb0ef41Sopenharmony_ci    MachineRepresentation canonical = MachineRepresentation::kNone;
6971cb0ef41Sopenharmony_ci    if (IsFPRegister()) {
6981cb0ef41Sopenharmony_ci      if (kFPAliasing == AliasingKind::kOverlap) {
6991cb0ef41Sopenharmony_ci        // We treat all FP register operands the same for simple aliasing.
7001cb0ef41Sopenharmony_ci        canonical = MachineRepresentation::kFloat64;
7011cb0ef41Sopenharmony_ci      } else if (kFPAliasing == AliasingKind::kIndependent) {
7021cb0ef41Sopenharmony_ci        if (IsSimd128Register()) {
7031cb0ef41Sopenharmony_ci          canonical = MachineRepresentation::kSimd128;
7041cb0ef41Sopenharmony_ci        } else {
7051cb0ef41Sopenharmony_ci          canonical = MachineRepresentation::kFloat64;
7061cb0ef41Sopenharmony_ci        }
7071cb0ef41Sopenharmony_ci      } else {
7081cb0ef41Sopenharmony_ci        // We need to distinguish FP register operands of different reps when
7091cb0ef41Sopenharmony_ci        // aliasing is AliasingKind::kCombine (e.g. ARM).
7101cb0ef41Sopenharmony_ci        DCHECK_EQ(kFPAliasing, AliasingKind::kCombine);
7111cb0ef41Sopenharmony_ci        canonical = LocationOperand::cast(this)->representation();
7121cb0ef41Sopenharmony_ci      }
7131cb0ef41Sopenharmony_ci    }
7141cb0ef41Sopenharmony_ci    return InstructionOperand::KindField::update(
7151cb0ef41Sopenharmony_ci        LocationOperand::RepresentationField::update(this->value_, canonical),
7161cb0ef41Sopenharmony_ci        LocationOperand::ALLOCATED);
7171cb0ef41Sopenharmony_ci  }
7181cb0ef41Sopenharmony_ci  return this->value_;
7191cb0ef41Sopenharmony_ci}
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci// Required for maps that don't care about machine type.
7221cb0ef41Sopenharmony_cistruct CompareOperandModuloType {
7231cb0ef41Sopenharmony_ci  bool operator()(const InstructionOperand& a,
7241cb0ef41Sopenharmony_ci                  const InstructionOperand& b) const {
7251cb0ef41Sopenharmony_ci    return a.CompareCanonicalized(b);
7261cb0ef41Sopenharmony_ci  }
7271cb0ef41Sopenharmony_ci};
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE MoveOperands final
7301cb0ef41Sopenharmony_ci    : public NON_EXPORTED_BASE(ZoneObject) {
7311cb0ef41Sopenharmony_ci public:
7321cb0ef41Sopenharmony_ci  MoveOperands(const InstructionOperand& source,
7331cb0ef41Sopenharmony_ci               const InstructionOperand& destination)
7341cb0ef41Sopenharmony_ci      : source_(source), destination_(destination) {
7351cb0ef41Sopenharmony_ci    DCHECK(!source.IsInvalid() && !destination.IsInvalid());
7361cb0ef41Sopenharmony_ci  }
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci  MoveOperands(const MoveOperands&) = delete;
7391cb0ef41Sopenharmony_ci  MoveOperands& operator=(const MoveOperands&) = delete;
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_ci  const InstructionOperand& source() const { return source_; }
7421cb0ef41Sopenharmony_ci  InstructionOperand& source() { return source_; }
7431cb0ef41Sopenharmony_ci  void set_source(const InstructionOperand& operand) { source_ = operand; }
7441cb0ef41Sopenharmony_ci
7451cb0ef41Sopenharmony_ci  const InstructionOperand& destination() const { return destination_; }
7461cb0ef41Sopenharmony_ci  InstructionOperand& destination() { return destination_; }
7471cb0ef41Sopenharmony_ci  void set_destination(const InstructionOperand& operand) {
7481cb0ef41Sopenharmony_ci    destination_ = operand;
7491cb0ef41Sopenharmony_ci  }
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci  // The gap resolver marks moves as "in-progress" by clearing the
7521cb0ef41Sopenharmony_ci  // destination (but not the source).
7531cb0ef41Sopenharmony_ci  bool IsPending() const {
7541cb0ef41Sopenharmony_ci    return destination_.IsInvalid() && !source_.IsInvalid();
7551cb0ef41Sopenharmony_ci  }
7561cb0ef41Sopenharmony_ci  void SetPending() { destination_ = InstructionOperand(); }
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci  // A move is redundant if it's been eliminated or if its source and
7591cb0ef41Sopenharmony_ci  // destination are the same.
7601cb0ef41Sopenharmony_ci  bool IsRedundant() const {
7611cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
7621cb0ef41Sopenharmony_ci    return IsEliminated() || source_.EqualsCanonicalized(destination_);
7631cb0ef41Sopenharmony_ci  }
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci  // We clear both operands to indicate move that's been eliminated.
7661cb0ef41Sopenharmony_ci  void Eliminate() { source_ = destination_ = InstructionOperand(); }
7671cb0ef41Sopenharmony_ci  bool IsEliminated() const {
7681cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
7691cb0ef41Sopenharmony_ci    return source_.IsInvalid();
7701cb0ef41Sopenharmony_ci  }
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci  // APIs to aid debugging. For general-stream APIs, use operator<<.
7731cb0ef41Sopenharmony_ci  void Print() const;
7741cb0ef41Sopenharmony_ci
7751cb0ef41Sopenharmony_ci private:
7761cb0ef41Sopenharmony_ci  InstructionOperand source_;
7771cb0ef41Sopenharmony_ci  InstructionOperand destination_;
7781cb0ef41Sopenharmony_ci};
7791cb0ef41Sopenharmony_ci
7801cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const MoveOperands&);
7811cb0ef41Sopenharmony_ci
7821cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE ParallelMove final
7831cb0ef41Sopenharmony_ci    : public NON_EXPORTED_BASE(ZoneVector<MoveOperands*>),
7841cb0ef41Sopenharmony_ci      public NON_EXPORTED_BASE(ZoneObject) {
7851cb0ef41Sopenharmony_ci public:
7861cb0ef41Sopenharmony_ci  explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {}
7871cb0ef41Sopenharmony_ci  ParallelMove(const ParallelMove&) = delete;
7881cb0ef41Sopenharmony_ci  ParallelMove& operator=(const ParallelMove&) = delete;
7891cb0ef41Sopenharmony_ci
7901cb0ef41Sopenharmony_ci  MoveOperands* AddMove(const InstructionOperand& from,
7911cb0ef41Sopenharmony_ci                        const InstructionOperand& to) {
7921cb0ef41Sopenharmony_ci    Zone* zone = get_allocator().zone();
7931cb0ef41Sopenharmony_ci    return AddMove(from, to, zone);
7941cb0ef41Sopenharmony_ci  }
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci  MoveOperands* AddMove(const InstructionOperand& from,
7971cb0ef41Sopenharmony_ci                        const InstructionOperand& to,
7981cb0ef41Sopenharmony_ci                        Zone* operand_allocation_zone) {
7991cb0ef41Sopenharmony_ci    if (from.EqualsCanonicalized(to)) return nullptr;
8001cb0ef41Sopenharmony_ci    MoveOperands* move = operand_allocation_zone->New<MoveOperands>(from, to);
8011cb0ef41Sopenharmony_ci    if (empty()) reserve(4);
8021cb0ef41Sopenharmony_ci    push_back(move);
8031cb0ef41Sopenharmony_ci    return move;
8041cb0ef41Sopenharmony_ci  }
8051cb0ef41Sopenharmony_ci
8061cb0ef41Sopenharmony_ci  bool IsRedundant() const;
8071cb0ef41Sopenharmony_ci
8081cb0ef41Sopenharmony_ci  // Prepare this ParallelMove to insert move as if it happened in a subsequent
8091cb0ef41Sopenharmony_ci  // ParallelMove.  move->source() may be changed.  Any MoveOperands added to
8101cb0ef41Sopenharmony_ci  // to_eliminate must be Eliminated.
8111cb0ef41Sopenharmony_ci  void PrepareInsertAfter(MoveOperands* move,
8121cb0ef41Sopenharmony_ci                          ZoneVector<MoveOperands*>* to_eliminate) const;
8131cb0ef41Sopenharmony_ci};
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, const ParallelMove&);
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ciclass ReferenceMap final : public ZoneObject {
8181cb0ef41Sopenharmony_ci public:
8191cb0ef41Sopenharmony_ci  explicit ReferenceMap(Zone* zone)
8201cb0ef41Sopenharmony_ci      : reference_operands_(8, zone), instruction_position_(-1) {}
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_ci  const ZoneVector<InstructionOperand>& reference_operands() const {
8231cb0ef41Sopenharmony_ci    return reference_operands_;
8241cb0ef41Sopenharmony_ci  }
8251cb0ef41Sopenharmony_ci  int instruction_position() const { return instruction_position_; }
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_ci  void set_instruction_position(int pos) {
8281cb0ef41Sopenharmony_ci    DCHECK_EQ(-1, instruction_position_);
8291cb0ef41Sopenharmony_ci    instruction_position_ = pos;
8301cb0ef41Sopenharmony_ci  }
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci  void RecordReference(const AllocatedOperand& op);
8331cb0ef41Sopenharmony_ci
8341cb0ef41Sopenharmony_ci private:
8351cb0ef41Sopenharmony_ci  friend std::ostream& operator<<(std::ostream&, const ReferenceMap&);
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_ci  ZoneVector<InstructionOperand> reference_operands_;
8381cb0ef41Sopenharmony_ci  int instruction_position_;
8391cb0ef41Sopenharmony_ci};
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, const ReferenceMap&);
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ciclass InstructionBlock;
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE Instruction final {
8461cb0ef41Sopenharmony_ci public:
8471cb0ef41Sopenharmony_ci  Instruction(const Instruction&) = delete;
8481cb0ef41Sopenharmony_ci  Instruction& operator=(const Instruction&) = delete;
8491cb0ef41Sopenharmony_ci
8501cb0ef41Sopenharmony_ci  size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
8511cb0ef41Sopenharmony_ci  const InstructionOperand* OutputAt(size_t i) const {
8521cb0ef41Sopenharmony_ci    DCHECK_LT(i, OutputCount());
8531cb0ef41Sopenharmony_ci    return &operands_[i];
8541cb0ef41Sopenharmony_ci  }
8551cb0ef41Sopenharmony_ci  InstructionOperand* OutputAt(size_t i) {
8561cb0ef41Sopenharmony_ci    DCHECK_LT(i, OutputCount());
8571cb0ef41Sopenharmony_ci    return &operands_[i];
8581cb0ef41Sopenharmony_ci  }
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  bool HasOutput() const { return OutputCount() > 0; }
8611cb0ef41Sopenharmony_ci  const InstructionOperand* Output() const { return OutputAt(0); }
8621cb0ef41Sopenharmony_ci  InstructionOperand* Output() { return OutputAt(0); }
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci  size_t InputCount() const { return InputCountField::decode(bit_field_); }
8651cb0ef41Sopenharmony_ci  const InstructionOperand* InputAt(size_t i) const {
8661cb0ef41Sopenharmony_ci    DCHECK_LT(i, InputCount());
8671cb0ef41Sopenharmony_ci    return &operands_[OutputCount() + i];
8681cb0ef41Sopenharmony_ci  }
8691cb0ef41Sopenharmony_ci  InstructionOperand* InputAt(size_t i) {
8701cb0ef41Sopenharmony_ci    DCHECK_LT(i, InputCount());
8711cb0ef41Sopenharmony_ci    return &operands_[OutputCount() + i];
8721cb0ef41Sopenharmony_ci  }
8731cb0ef41Sopenharmony_ci
8741cb0ef41Sopenharmony_ci  size_t TempCount() const { return TempCountField::decode(bit_field_); }
8751cb0ef41Sopenharmony_ci  const InstructionOperand* TempAt(size_t i) const {
8761cb0ef41Sopenharmony_ci    DCHECK_LT(i, TempCount());
8771cb0ef41Sopenharmony_ci    return &operands_[OutputCount() + InputCount() + i];
8781cb0ef41Sopenharmony_ci  }
8791cb0ef41Sopenharmony_ci  InstructionOperand* TempAt(size_t i) {
8801cb0ef41Sopenharmony_ci    DCHECK_LT(i, TempCount());
8811cb0ef41Sopenharmony_ci    return &operands_[OutputCount() + InputCount() + i];
8821cb0ef41Sopenharmony_ci  }
8831cb0ef41Sopenharmony_ci
8841cb0ef41Sopenharmony_ci  InstructionCode opcode() const { return opcode_; }
8851cb0ef41Sopenharmony_ci  ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
8861cb0ef41Sopenharmony_ci  AddressingMode addressing_mode() const {
8871cb0ef41Sopenharmony_ci    return AddressingModeField::decode(opcode());
8881cb0ef41Sopenharmony_ci  }
8891cb0ef41Sopenharmony_ci  FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
8901cb0ef41Sopenharmony_ci  FlagsCondition flags_condition() const {
8911cb0ef41Sopenharmony_ci    return FlagsConditionField::decode(opcode());
8921cb0ef41Sopenharmony_ci  }
8931cb0ef41Sopenharmony_ci  int misc() const { return MiscField::decode(opcode()); }
8941cb0ef41Sopenharmony_ci  bool HasMemoryAccessMode() const {
8951cb0ef41Sopenharmony_ci    return compiler::HasMemoryAccessMode(arch_opcode());
8961cb0ef41Sopenharmony_ci  }
8971cb0ef41Sopenharmony_ci  MemoryAccessMode memory_access_mode() const {
8981cb0ef41Sopenharmony_ci    DCHECK(HasMemoryAccessMode());
8991cb0ef41Sopenharmony_ci    return AccessModeField::decode(opcode());
9001cb0ef41Sopenharmony_ci  }
9011cb0ef41Sopenharmony_ci
9021cb0ef41Sopenharmony_ci  static Instruction* New(Zone* zone, InstructionCode opcode) {
9031cb0ef41Sopenharmony_ci    return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
9041cb0ef41Sopenharmony_ci  }
9051cb0ef41Sopenharmony_ci
9061cb0ef41Sopenharmony_ci  static Instruction* New(Zone* zone, InstructionCode opcode,
9071cb0ef41Sopenharmony_ci                          size_t output_count, InstructionOperand* outputs,
9081cb0ef41Sopenharmony_ci                          size_t input_count, InstructionOperand* inputs,
9091cb0ef41Sopenharmony_ci                          size_t temp_count, InstructionOperand* temps) {
9101cb0ef41Sopenharmony_ci    DCHECK(output_count == 0 || outputs != nullptr);
9111cb0ef41Sopenharmony_ci    DCHECK(input_count == 0 || inputs != nullptr);
9121cb0ef41Sopenharmony_ci    DCHECK(temp_count == 0 || temps != nullptr);
9131cb0ef41Sopenharmony_ci    // TODO(turbofan): Handle this gracefully. See crbug.com/582702.
9141cb0ef41Sopenharmony_ci    CHECK(InputCountField::is_valid(input_count));
9151cb0ef41Sopenharmony_ci
9161cb0ef41Sopenharmony_ci    size_t total_extra_ops = output_count + input_count + temp_count;
9171cb0ef41Sopenharmony_ci    if (total_extra_ops != 0) total_extra_ops--;
9181cb0ef41Sopenharmony_ci    int size = static_cast<int>(
9191cb0ef41Sopenharmony_ci        RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
9201cb0ef41Sopenharmony_ci        total_extra_ops * sizeof(InstructionOperand));
9211cb0ef41Sopenharmony_ci    return new (zone->Allocate<Instruction>(size)) Instruction(
9221cb0ef41Sopenharmony_ci        opcode, output_count, outputs, input_count, inputs, temp_count, temps);
9231cb0ef41Sopenharmony_ci  }
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci  Instruction* MarkAsCall() {
9261cb0ef41Sopenharmony_ci    bit_field_ = IsCallField::update(bit_field_, true);
9271cb0ef41Sopenharmony_ci    return this;
9281cb0ef41Sopenharmony_ci  }
9291cb0ef41Sopenharmony_ci  bool IsCall() const { return IsCallField::decode(bit_field_); }
9301cb0ef41Sopenharmony_ci  bool NeedsReferenceMap() const { return IsCall(); }
9311cb0ef41Sopenharmony_ci  bool HasReferenceMap() const { return reference_map_ != nullptr; }
9321cb0ef41Sopenharmony_ci
9331cb0ef41Sopenharmony_ci  bool ClobbersRegisters() const { return IsCall(); }
9341cb0ef41Sopenharmony_ci  bool ClobbersTemps() const { return IsCall(); }
9351cb0ef41Sopenharmony_ci  bool ClobbersDoubleRegisters() const { return IsCall(); }
9361cb0ef41Sopenharmony_ci  ReferenceMap* reference_map() const { return reference_map_; }
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_ci  void set_reference_map(ReferenceMap* map) {
9391cb0ef41Sopenharmony_ci    DCHECK(NeedsReferenceMap());
9401cb0ef41Sopenharmony_ci    DCHECK(!reference_map_);
9411cb0ef41Sopenharmony_ci    reference_map_ = map;
9421cb0ef41Sopenharmony_ci  }
9431cb0ef41Sopenharmony_ci
9441cb0ef41Sopenharmony_ci  void OverwriteWithNop() {
9451cb0ef41Sopenharmony_ci    opcode_ = ArchOpcodeField::encode(kArchNop);
9461cb0ef41Sopenharmony_ci    bit_field_ = 0;
9471cb0ef41Sopenharmony_ci    reference_map_ = nullptr;
9481cb0ef41Sopenharmony_ci  }
9491cb0ef41Sopenharmony_ci
9501cb0ef41Sopenharmony_ci  bool IsNop() const { return arch_opcode() == kArchNop; }
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_ci  bool IsDeoptimizeCall() const {
9531cb0ef41Sopenharmony_ci    return arch_opcode() == ArchOpcode::kArchDeoptimize ||
9541cb0ef41Sopenharmony_ci           FlagsModeField::decode(opcode()) == kFlags_deoptimize;
9551cb0ef41Sopenharmony_ci  }
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ci  bool IsTrap() const {
9581cb0ef41Sopenharmony_ci    return FlagsModeField::decode(opcode()) == kFlags_trap;
9591cb0ef41Sopenharmony_ci  }
9601cb0ef41Sopenharmony_ci
9611cb0ef41Sopenharmony_ci  bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
9621cb0ef41Sopenharmony_ci  bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
9631cb0ef41Sopenharmony_ci  bool IsTailCall() const {
9641cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
9651cb0ef41Sopenharmony_ci    return arch_opcode() <= ArchOpcode::kArchTailCallWasm;
9661cb0ef41Sopenharmony_ci#else
9671cb0ef41Sopenharmony_ci    return arch_opcode() <= ArchOpcode::kArchTailCallAddress;
9681cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
9691cb0ef41Sopenharmony_ci  }
9701cb0ef41Sopenharmony_ci  bool IsThrow() const {
9711cb0ef41Sopenharmony_ci    return arch_opcode() == ArchOpcode::kArchThrowTerminator;
9721cb0ef41Sopenharmony_ci  }
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci  static constexpr bool IsCallWithDescriptorFlags(InstructionCode arch_opcode) {
9751cb0ef41Sopenharmony_ci    return arch_opcode <= ArchOpcode::kArchCallBuiltinPointer;
9761cb0ef41Sopenharmony_ci  }
9771cb0ef41Sopenharmony_ci  bool IsCallWithDescriptorFlags() const {
9781cb0ef41Sopenharmony_ci    return IsCallWithDescriptorFlags(arch_opcode());
9791cb0ef41Sopenharmony_ci  }
9801cb0ef41Sopenharmony_ci  bool HasCallDescriptorFlag(CallDescriptor::Flag flag) const {
9811cb0ef41Sopenharmony_ci    DCHECK(IsCallWithDescriptorFlags());
9821cb0ef41Sopenharmony_ci    STATIC_ASSERT(CallDescriptor::kFlagsBitsEncodedInInstructionCode == 10);
9831cb0ef41Sopenharmony_ci#ifdef DEBUG
9841cb0ef41Sopenharmony_ci    static constexpr int kInstructionCodeFlagsMask =
9851cb0ef41Sopenharmony_ci        ((1 << CallDescriptor::kFlagsBitsEncodedInInstructionCode) - 1);
9861cb0ef41Sopenharmony_ci    DCHECK_EQ(static_cast<int>(flag) & kInstructionCodeFlagsMask, flag);
9871cb0ef41Sopenharmony_ci#endif
9881cb0ef41Sopenharmony_ci    return MiscField::decode(opcode()) & flag;
9891cb0ef41Sopenharmony_ci  }
9901cb0ef41Sopenharmony_ci
9911cb0ef41Sopenharmony_ci  enum GapPosition {
9921cb0ef41Sopenharmony_ci    START,
9931cb0ef41Sopenharmony_ci    END,
9941cb0ef41Sopenharmony_ci    FIRST_GAP_POSITION = START,
9951cb0ef41Sopenharmony_ci    LAST_GAP_POSITION = END
9961cb0ef41Sopenharmony_ci  };
9971cb0ef41Sopenharmony_ci
9981cb0ef41Sopenharmony_ci  ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
9991cb0ef41Sopenharmony_ci    if (parallel_moves_[pos] == nullptr) {
10001cb0ef41Sopenharmony_ci      parallel_moves_[pos] = zone->New<ParallelMove>(zone);
10011cb0ef41Sopenharmony_ci    }
10021cb0ef41Sopenharmony_ci    return parallel_moves_[pos];
10031cb0ef41Sopenharmony_ci  }
10041cb0ef41Sopenharmony_ci
10051cb0ef41Sopenharmony_ci  ParallelMove* GetParallelMove(GapPosition pos) {
10061cb0ef41Sopenharmony_ci    return parallel_moves_[pos];
10071cb0ef41Sopenharmony_ci  }
10081cb0ef41Sopenharmony_ci
10091cb0ef41Sopenharmony_ci  const ParallelMove* GetParallelMove(GapPosition pos) const {
10101cb0ef41Sopenharmony_ci    return parallel_moves_[pos];
10111cb0ef41Sopenharmony_ci  }
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci  bool AreMovesRedundant() const;
10141cb0ef41Sopenharmony_ci
10151cb0ef41Sopenharmony_ci  ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
10161cb0ef41Sopenharmony_ci  ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
10171cb0ef41Sopenharmony_ci
10181cb0ef41Sopenharmony_ci  // The block_id may be invalidated in JumpThreading. It is only important for
10191cb0ef41Sopenharmony_ci  // register allocation, to avoid searching for blocks from instruction
10201cb0ef41Sopenharmony_ci  // indexes.
10211cb0ef41Sopenharmony_ci  InstructionBlock* block() const { return block_; }
10221cb0ef41Sopenharmony_ci  void set_block(InstructionBlock* block) {
10231cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(block);
10241cb0ef41Sopenharmony_ci    block_ = block;
10251cb0ef41Sopenharmony_ci  }
10261cb0ef41Sopenharmony_ci
10271cb0ef41Sopenharmony_ci  // APIs to aid debugging. For general-stream APIs, use operator<<.
10281cb0ef41Sopenharmony_ci  void Print() const;
10291cb0ef41Sopenharmony_ci
10301cb0ef41Sopenharmony_ci  using OutputCountField = base::BitField<size_t, 0, 8>;
10311cb0ef41Sopenharmony_ci  using InputCountField = base::BitField<size_t, 8, 16>;
10321cb0ef41Sopenharmony_ci  using TempCountField = base::BitField<size_t, 24, 6>;
10331cb0ef41Sopenharmony_ci
10341cb0ef41Sopenharmony_ci  static const size_t kMaxOutputCount = OutputCountField::kMax;
10351cb0ef41Sopenharmony_ci  static const size_t kMaxInputCount = InputCountField::kMax;
10361cb0ef41Sopenharmony_ci  static const size_t kMaxTempCount = TempCountField::kMax;
10371cb0ef41Sopenharmony_ci
10381cb0ef41Sopenharmony_ci private:
10391cb0ef41Sopenharmony_ci  explicit Instruction(InstructionCode opcode);
10401cb0ef41Sopenharmony_ci
10411cb0ef41Sopenharmony_ci  Instruction(InstructionCode opcode, size_t output_count,
10421cb0ef41Sopenharmony_ci              InstructionOperand* outputs, size_t input_count,
10431cb0ef41Sopenharmony_ci              InstructionOperand* inputs, size_t temp_count,
10441cb0ef41Sopenharmony_ci              InstructionOperand* temps);
10451cb0ef41Sopenharmony_ci
10461cb0ef41Sopenharmony_ci  using IsCallField = base::BitField<bool, 30, 1>;
10471cb0ef41Sopenharmony_ci
10481cb0ef41Sopenharmony_ci  InstructionCode opcode_;
10491cb0ef41Sopenharmony_ci  uint32_t bit_field_;
10501cb0ef41Sopenharmony_ci  ParallelMove* parallel_moves_[2];
10511cb0ef41Sopenharmony_ci  ReferenceMap* reference_map_;
10521cb0ef41Sopenharmony_ci  InstructionBlock* block_;
10531cb0ef41Sopenharmony_ci  InstructionOperand operands_[1];
10541cb0ef41Sopenharmony_ci};
10551cb0ef41Sopenharmony_ci
10561cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, const Instruction&);
10571cb0ef41Sopenharmony_ci
10581cb0ef41Sopenharmony_ciclass RpoNumber final {
10591cb0ef41Sopenharmony_ci public:
10601cb0ef41Sopenharmony_ci  static const int kInvalidRpoNumber = -1;
10611cb0ef41Sopenharmony_ci  RpoNumber() : index_(kInvalidRpoNumber) {}
10621cb0ef41Sopenharmony_ci
10631cb0ef41Sopenharmony_ci  int ToInt() const {
10641cb0ef41Sopenharmony_ci    DCHECK(IsValid());
10651cb0ef41Sopenharmony_ci    return index_;
10661cb0ef41Sopenharmony_ci  }
10671cb0ef41Sopenharmony_ci  size_t ToSize() const {
10681cb0ef41Sopenharmony_ci    DCHECK(IsValid());
10691cb0ef41Sopenharmony_ci    return static_cast<size_t>(index_);
10701cb0ef41Sopenharmony_ci  }
10711cb0ef41Sopenharmony_ci  bool IsValid() const { return index_ >= 0; }
10721cb0ef41Sopenharmony_ci  static RpoNumber FromInt(int index) { return RpoNumber(index); }
10731cb0ef41Sopenharmony_ci  static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
10741cb0ef41Sopenharmony_ci
10751cb0ef41Sopenharmony_ci  bool IsNext(const RpoNumber other) const {
10761cb0ef41Sopenharmony_ci    DCHECK(IsValid());
10771cb0ef41Sopenharmony_ci    return other.index_ == this->index_ + 1;
10781cb0ef41Sopenharmony_ci  }
10791cb0ef41Sopenharmony_ci
10801cb0ef41Sopenharmony_ci  RpoNumber Next() const {
10811cb0ef41Sopenharmony_ci    DCHECK(IsValid());
10821cb0ef41Sopenharmony_ci    return RpoNumber(index_ + 1);
10831cb0ef41Sopenharmony_ci  }
10841cb0ef41Sopenharmony_ci
10851cb0ef41Sopenharmony_ci  // Comparison operators.
10861cb0ef41Sopenharmony_ci  bool operator==(RpoNumber other) const { return index_ == other.index_; }
10871cb0ef41Sopenharmony_ci  bool operator!=(RpoNumber other) const { return index_ != other.index_; }
10881cb0ef41Sopenharmony_ci  bool operator>(RpoNumber other) const { return index_ > other.index_; }
10891cb0ef41Sopenharmony_ci  bool operator<(RpoNumber other) const { return index_ < other.index_; }
10901cb0ef41Sopenharmony_ci  bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
10911cb0ef41Sopenharmony_ci  bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
10921cb0ef41Sopenharmony_ci
10931cb0ef41Sopenharmony_ci private:
10941cb0ef41Sopenharmony_ci  explicit RpoNumber(int32_t index) : index_(index) {}
10951cb0ef41Sopenharmony_ci  int32_t index_;
10961cb0ef41Sopenharmony_ci};
10971cb0ef41Sopenharmony_ci
10981cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const RpoNumber&);
10991cb0ef41Sopenharmony_ci
11001cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE Constant final {
11011cb0ef41Sopenharmony_ci public:
11021cb0ef41Sopenharmony_ci  enum Type {
11031cb0ef41Sopenharmony_ci    kInt32,
11041cb0ef41Sopenharmony_ci    kInt64,
11051cb0ef41Sopenharmony_ci    kFloat32,
11061cb0ef41Sopenharmony_ci    kFloat64,
11071cb0ef41Sopenharmony_ci    kExternalReference,
11081cb0ef41Sopenharmony_ci    kCompressedHeapObject,
11091cb0ef41Sopenharmony_ci    kHeapObject,
11101cb0ef41Sopenharmony_ci    kRpoNumber,
11111cb0ef41Sopenharmony_ci    kDelayedStringConstant
11121cb0ef41Sopenharmony_ci  };
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_ci  explicit Constant(int32_t v);
11151cb0ef41Sopenharmony_ci  explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
11161cb0ef41Sopenharmony_ci  explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
11171cb0ef41Sopenharmony_ci  explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
11181cb0ef41Sopenharmony_ci  explicit Constant(ExternalReference ref)
11191cb0ef41Sopenharmony_ci      : type_(kExternalReference), value_(bit_cast<intptr_t>(ref.address())) {}
11201cb0ef41Sopenharmony_ci  explicit Constant(Handle<HeapObject> obj, bool is_compressed = false)
11211cb0ef41Sopenharmony_ci      : type_(is_compressed ? kCompressedHeapObject : kHeapObject),
11221cb0ef41Sopenharmony_ci        value_(bit_cast<intptr_t>(obj)) {}
11231cb0ef41Sopenharmony_ci  explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
11241cb0ef41Sopenharmony_ci  explicit Constant(const StringConstantBase* str)
11251cb0ef41Sopenharmony_ci      : type_(kDelayedStringConstant), value_(bit_cast<intptr_t>(str)) {}
11261cb0ef41Sopenharmony_ci  explicit Constant(RelocatablePtrConstantInfo info);
11271cb0ef41Sopenharmony_ci
11281cb0ef41Sopenharmony_ci  Type type() const { return type_; }
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_ci  RelocInfo::Mode rmode() const { return rmode_; }
11311cb0ef41Sopenharmony_ci
11321cb0ef41Sopenharmony_ci  bool FitsInInt32() const {
11331cb0ef41Sopenharmony_ci    if (type() == kInt32) return true;
11341cb0ef41Sopenharmony_ci    DCHECK(type() == kInt64);
11351cb0ef41Sopenharmony_ci    return value_ >= std::numeric_limits<int32_t>::min() &&
11361cb0ef41Sopenharmony_ci           value_ <= std::numeric_limits<int32_t>::max();
11371cb0ef41Sopenharmony_ci  }
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ci  int32_t ToInt32() const {
11401cb0ef41Sopenharmony_ci    DCHECK(FitsInInt32());
11411cb0ef41Sopenharmony_ci    const int32_t value = static_cast<int32_t>(value_);
11421cb0ef41Sopenharmony_ci    DCHECK_EQ(value_, static_cast<int64_t>(value));
11431cb0ef41Sopenharmony_ci    return value;
11441cb0ef41Sopenharmony_ci  }
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_ci  int64_t ToInt64() const {
11471cb0ef41Sopenharmony_ci    if (type() == kInt32) return ToInt32();
11481cb0ef41Sopenharmony_ci    DCHECK_EQ(kInt64, type());
11491cb0ef41Sopenharmony_ci    return value_;
11501cb0ef41Sopenharmony_ci  }
11511cb0ef41Sopenharmony_ci
11521cb0ef41Sopenharmony_ci  float ToFloat32() const {
11531cb0ef41Sopenharmony_ci    // TODO(ahaas): We should remove this function. If value_ has the bit
11541cb0ef41Sopenharmony_ci    // representation of a signalling NaN, then returning it as float can cause
11551cb0ef41Sopenharmony_ci    // the signalling bit to flip, and value_ is returned as a quiet NaN.
11561cb0ef41Sopenharmony_ci    DCHECK_EQ(kFloat32, type());
11571cb0ef41Sopenharmony_ci    return bit_cast<float>(static_cast<int32_t>(value_));
11581cb0ef41Sopenharmony_ci  }
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci  uint32_t ToFloat32AsInt() const {
11611cb0ef41Sopenharmony_ci    DCHECK_EQ(kFloat32, type());
11621cb0ef41Sopenharmony_ci    return bit_cast<uint32_t>(static_cast<int32_t>(value_));
11631cb0ef41Sopenharmony_ci  }
11641cb0ef41Sopenharmony_ci
11651cb0ef41Sopenharmony_ci  base::Double ToFloat64() const {
11661cb0ef41Sopenharmony_ci    DCHECK_EQ(kFloat64, type());
11671cb0ef41Sopenharmony_ci    return base::Double(bit_cast<uint64_t>(value_));
11681cb0ef41Sopenharmony_ci  }
11691cb0ef41Sopenharmony_ci
11701cb0ef41Sopenharmony_ci  ExternalReference ToExternalReference() const {
11711cb0ef41Sopenharmony_ci    DCHECK_EQ(kExternalReference, type());
11721cb0ef41Sopenharmony_ci    return ExternalReference::FromRawAddress(static_cast<Address>(value_));
11731cb0ef41Sopenharmony_ci  }
11741cb0ef41Sopenharmony_ci
11751cb0ef41Sopenharmony_ci  RpoNumber ToRpoNumber() const {
11761cb0ef41Sopenharmony_ci    DCHECK_EQ(kRpoNumber, type());
11771cb0ef41Sopenharmony_ci    return RpoNumber::FromInt(static_cast<int>(value_));
11781cb0ef41Sopenharmony_ci  }
11791cb0ef41Sopenharmony_ci
11801cb0ef41Sopenharmony_ci  Handle<HeapObject> ToHeapObject() const;
11811cb0ef41Sopenharmony_ci  Handle<CodeT> ToCode() const;
11821cb0ef41Sopenharmony_ci  const StringConstantBase* ToDelayedStringConstant() const;
11831cb0ef41Sopenharmony_ci
11841cb0ef41Sopenharmony_ci private:
11851cb0ef41Sopenharmony_ci  Type type_;
11861cb0ef41Sopenharmony_ci  RelocInfo::Mode rmode_ = RelocInfo::NO_INFO;
11871cb0ef41Sopenharmony_ci  int64_t value_;
11881cb0ef41Sopenharmony_ci};
11891cb0ef41Sopenharmony_ci
11901cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, const Constant&);
11911cb0ef41Sopenharmony_ci
11921cb0ef41Sopenharmony_ci// Forward declarations.
11931cb0ef41Sopenharmony_ciclass FrameStateDescriptor;
11941cb0ef41Sopenharmony_ci
11951cb0ef41Sopenharmony_cienum class StateValueKind : uint8_t {
11961cb0ef41Sopenharmony_ci  kArgumentsElements,
11971cb0ef41Sopenharmony_ci  kArgumentsLength,
11981cb0ef41Sopenharmony_ci  kPlain,
11991cb0ef41Sopenharmony_ci  kOptimizedOut,
12001cb0ef41Sopenharmony_ci  kNested,
12011cb0ef41Sopenharmony_ci  kDuplicate
12021cb0ef41Sopenharmony_ci};
12031cb0ef41Sopenharmony_ci
12041cb0ef41Sopenharmony_ciclass StateValueDescriptor {
12051cb0ef41Sopenharmony_ci public:
12061cb0ef41Sopenharmony_ci  StateValueDescriptor()
12071cb0ef41Sopenharmony_ci      : kind_(StateValueKind::kPlain), type_(MachineType::AnyTagged()) {}
12081cb0ef41Sopenharmony_ci
12091cb0ef41Sopenharmony_ci  static StateValueDescriptor ArgumentsElements(ArgumentsStateType type) {
12101cb0ef41Sopenharmony_ci    StateValueDescriptor descr(StateValueKind::kArgumentsElements,
12111cb0ef41Sopenharmony_ci                               MachineType::AnyTagged());
12121cb0ef41Sopenharmony_ci    descr.args_type_ = type;
12131cb0ef41Sopenharmony_ci    return descr;
12141cb0ef41Sopenharmony_ci  }
12151cb0ef41Sopenharmony_ci  static StateValueDescriptor ArgumentsLength() {
12161cb0ef41Sopenharmony_ci    return StateValueDescriptor(StateValueKind::kArgumentsLength,
12171cb0ef41Sopenharmony_ci                                MachineType::AnyTagged());
12181cb0ef41Sopenharmony_ci  }
12191cb0ef41Sopenharmony_ci  static StateValueDescriptor Plain(MachineType type) {
12201cb0ef41Sopenharmony_ci    return StateValueDescriptor(StateValueKind::kPlain, type);
12211cb0ef41Sopenharmony_ci  }
12221cb0ef41Sopenharmony_ci  static StateValueDescriptor OptimizedOut() {
12231cb0ef41Sopenharmony_ci    return StateValueDescriptor(StateValueKind::kOptimizedOut,
12241cb0ef41Sopenharmony_ci                                MachineType::AnyTagged());
12251cb0ef41Sopenharmony_ci  }
12261cb0ef41Sopenharmony_ci  static StateValueDescriptor Recursive(size_t id) {
12271cb0ef41Sopenharmony_ci    StateValueDescriptor descr(StateValueKind::kNested,
12281cb0ef41Sopenharmony_ci                               MachineType::AnyTagged());
12291cb0ef41Sopenharmony_ci    descr.id_ = id;
12301cb0ef41Sopenharmony_ci    return descr;
12311cb0ef41Sopenharmony_ci  }
12321cb0ef41Sopenharmony_ci  static StateValueDescriptor Duplicate(size_t id) {
12331cb0ef41Sopenharmony_ci    StateValueDescriptor descr(StateValueKind::kDuplicate,
12341cb0ef41Sopenharmony_ci                               MachineType::AnyTagged());
12351cb0ef41Sopenharmony_ci    descr.id_ = id;
12361cb0ef41Sopenharmony_ci    return descr;
12371cb0ef41Sopenharmony_ci  }
12381cb0ef41Sopenharmony_ci
12391cb0ef41Sopenharmony_ci  bool IsArgumentsElements() const {
12401cb0ef41Sopenharmony_ci    return kind_ == StateValueKind::kArgumentsElements;
12411cb0ef41Sopenharmony_ci  }
12421cb0ef41Sopenharmony_ci  bool IsArgumentsLength() const {
12431cb0ef41Sopenharmony_ci    return kind_ == StateValueKind::kArgumentsLength;
12441cb0ef41Sopenharmony_ci  }
12451cb0ef41Sopenharmony_ci  bool IsPlain() const { return kind_ == StateValueKind::kPlain; }
12461cb0ef41Sopenharmony_ci  bool IsOptimizedOut() const { return kind_ == StateValueKind::kOptimizedOut; }
12471cb0ef41Sopenharmony_ci  bool IsNested() const { return kind_ == StateValueKind::kNested; }
12481cb0ef41Sopenharmony_ci  bool IsDuplicate() const { return kind_ == StateValueKind::kDuplicate; }
12491cb0ef41Sopenharmony_ci  MachineType type() const { return type_; }
12501cb0ef41Sopenharmony_ci  size_t id() const {
12511cb0ef41Sopenharmony_ci    DCHECK(kind_ == StateValueKind::kDuplicate ||
12521cb0ef41Sopenharmony_ci           kind_ == StateValueKind::kNested);
12531cb0ef41Sopenharmony_ci    return id_;
12541cb0ef41Sopenharmony_ci  }
12551cb0ef41Sopenharmony_ci  ArgumentsStateType arguments_type() const {
12561cb0ef41Sopenharmony_ci    DCHECK(kind_ == StateValueKind::kArgumentsElements);
12571cb0ef41Sopenharmony_ci    return args_type_;
12581cb0ef41Sopenharmony_ci  }
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_ci private:
12611cb0ef41Sopenharmony_ci  StateValueDescriptor(StateValueKind kind, MachineType type)
12621cb0ef41Sopenharmony_ci      : kind_(kind), type_(type) {}
12631cb0ef41Sopenharmony_ci
12641cb0ef41Sopenharmony_ci  StateValueKind kind_;
12651cb0ef41Sopenharmony_ci  MachineType type_;
12661cb0ef41Sopenharmony_ci  union {
12671cb0ef41Sopenharmony_ci    size_t id_;
12681cb0ef41Sopenharmony_ci    ArgumentsStateType args_type_;
12691cb0ef41Sopenharmony_ci  };
12701cb0ef41Sopenharmony_ci};
12711cb0ef41Sopenharmony_ci
12721cb0ef41Sopenharmony_ciclass StateValueList {
12731cb0ef41Sopenharmony_ci public:
12741cb0ef41Sopenharmony_ci  explicit StateValueList(Zone* zone) : fields_(zone), nested_(zone) {}
12751cb0ef41Sopenharmony_ci
12761cb0ef41Sopenharmony_ci  size_t size() { return fields_.size(); }
12771cb0ef41Sopenharmony_ci
12781cb0ef41Sopenharmony_ci  size_t nested_count() { return nested_.size(); }
12791cb0ef41Sopenharmony_ci
12801cb0ef41Sopenharmony_ci  struct Value {
12811cb0ef41Sopenharmony_ci    StateValueDescriptor* desc;
12821cb0ef41Sopenharmony_ci    StateValueList* nested;
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ci    Value(StateValueDescriptor* desc, StateValueList* nested)
12851cb0ef41Sopenharmony_ci        : desc(desc), nested(nested) {}
12861cb0ef41Sopenharmony_ci  };
12871cb0ef41Sopenharmony_ci
12881cb0ef41Sopenharmony_ci  class iterator {
12891cb0ef41Sopenharmony_ci   public:
12901cb0ef41Sopenharmony_ci    // Bare minimum of operators needed for range iteration.
12911cb0ef41Sopenharmony_ci    bool operator!=(const iterator& other) const {
12921cb0ef41Sopenharmony_ci      return field_iterator != other.field_iterator;
12931cb0ef41Sopenharmony_ci    }
12941cb0ef41Sopenharmony_ci    bool operator==(const iterator& other) const {
12951cb0ef41Sopenharmony_ci      return field_iterator == other.field_iterator;
12961cb0ef41Sopenharmony_ci    }
12971cb0ef41Sopenharmony_ci    iterator& operator++() {
12981cb0ef41Sopenharmony_ci      if (field_iterator->IsNested()) {
12991cb0ef41Sopenharmony_ci        nested_iterator++;
13001cb0ef41Sopenharmony_ci      }
13011cb0ef41Sopenharmony_ci      ++field_iterator;
13021cb0ef41Sopenharmony_ci      return *this;
13031cb0ef41Sopenharmony_ci    }
13041cb0ef41Sopenharmony_ci    Value operator*() {
13051cb0ef41Sopenharmony_ci      StateValueDescriptor* desc = &(*field_iterator);
13061cb0ef41Sopenharmony_ci      StateValueList* nested = desc->IsNested() ? *nested_iterator : nullptr;
13071cb0ef41Sopenharmony_ci      return Value(desc, nested);
13081cb0ef41Sopenharmony_ci    }
13091cb0ef41Sopenharmony_ci
13101cb0ef41Sopenharmony_ci   private:
13111cb0ef41Sopenharmony_ci    friend class StateValueList;
13121cb0ef41Sopenharmony_ci
13131cb0ef41Sopenharmony_ci    iterator(ZoneVector<StateValueDescriptor>::iterator it,
13141cb0ef41Sopenharmony_ci             ZoneVector<StateValueList*>::iterator nested)
13151cb0ef41Sopenharmony_ci        : field_iterator(it), nested_iterator(nested) {}
13161cb0ef41Sopenharmony_ci
13171cb0ef41Sopenharmony_ci    ZoneVector<StateValueDescriptor>::iterator field_iterator;
13181cb0ef41Sopenharmony_ci    ZoneVector<StateValueList*>::iterator nested_iterator;
13191cb0ef41Sopenharmony_ci  };
13201cb0ef41Sopenharmony_ci
13211cb0ef41Sopenharmony_ci  struct Slice {
13221cb0ef41Sopenharmony_ci    Slice(ZoneVector<StateValueDescriptor>::iterator start, size_t fields)
13231cb0ef41Sopenharmony_ci        : start_position(start), fields_count(fields) {}
13241cb0ef41Sopenharmony_ci
13251cb0ef41Sopenharmony_ci    ZoneVector<StateValueDescriptor>::iterator start_position;
13261cb0ef41Sopenharmony_ci    size_t fields_count;
13271cb0ef41Sopenharmony_ci  };
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_ci  void ReserveSize(size_t size) { fields_.reserve(size); }
13301cb0ef41Sopenharmony_ci
13311cb0ef41Sopenharmony_ci  StateValueList* PushRecursiveField(Zone* zone, size_t id) {
13321cb0ef41Sopenharmony_ci    fields_.push_back(StateValueDescriptor::Recursive(id));
13331cb0ef41Sopenharmony_ci    StateValueList* nested = zone->New<StateValueList>(zone);
13341cb0ef41Sopenharmony_ci    nested_.push_back(nested);
13351cb0ef41Sopenharmony_ci    return nested;
13361cb0ef41Sopenharmony_ci  }
13371cb0ef41Sopenharmony_ci  void PushArgumentsElements(ArgumentsStateType type) {
13381cb0ef41Sopenharmony_ci    fields_.push_back(StateValueDescriptor::ArgumentsElements(type));
13391cb0ef41Sopenharmony_ci  }
13401cb0ef41Sopenharmony_ci  void PushArgumentsLength() {
13411cb0ef41Sopenharmony_ci    fields_.push_back(StateValueDescriptor::ArgumentsLength());
13421cb0ef41Sopenharmony_ci  }
13431cb0ef41Sopenharmony_ci  void PushDuplicate(size_t id) {
13441cb0ef41Sopenharmony_ci    fields_.push_back(StateValueDescriptor::Duplicate(id));
13451cb0ef41Sopenharmony_ci  }
13461cb0ef41Sopenharmony_ci  void PushPlain(MachineType type) {
13471cb0ef41Sopenharmony_ci    fields_.push_back(StateValueDescriptor::Plain(type));
13481cb0ef41Sopenharmony_ci  }
13491cb0ef41Sopenharmony_ci  void PushOptimizedOut(size_t num = 1) {
13501cb0ef41Sopenharmony_ci    fields_.insert(fields_.end(), num, StateValueDescriptor::OptimizedOut());
13511cb0ef41Sopenharmony_ci  }
13521cb0ef41Sopenharmony_ci  void PushCachedSlice(const Slice& cached) {
13531cb0ef41Sopenharmony_ci    fields_.insert(fields_.end(), cached.start_position,
13541cb0ef41Sopenharmony_ci                   cached.start_position + cached.fields_count);
13551cb0ef41Sopenharmony_ci  }
13561cb0ef41Sopenharmony_ci
13571cb0ef41Sopenharmony_ci  // Returns a Slice representing the (non-nested) fields in StateValueList from
13581cb0ef41Sopenharmony_ci  // values_start to  the current end position.
13591cb0ef41Sopenharmony_ci  Slice MakeSlice(size_t values_start) {
13601cb0ef41Sopenharmony_ci    DCHECK(!HasNestedFieldsAfter(values_start));
13611cb0ef41Sopenharmony_ci    size_t fields_count = fields_.size() - values_start;
13621cb0ef41Sopenharmony_ci    return Slice(fields_.begin() + values_start, fields_count);
13631cb0ef41Sopenharmony_ci  }
13641cb0ef41Sopenharmony_ci
13651cb0ef41Sopenharmony_ci  iterator begin() { return iterator(fields_.begin(), nested_.begin()); }
13661cb0ef41Sopenharmony_ci  iterator end() { return iterator(fields_.end(), nested_.end()); }
13671cb0ef41Sopenharmony_ci
13681cb0ef41Sopenharmony_ci private:
13691cb0ef41Sopenharmony_ci  bool HasNestedFieldsAfter(size_t values_start) {
13701cb0ef41Sopenharmony_ci    auto it = fields_.begin() + values_start;
13711cb0ef41Sopenharmony_ci    for (; it != fields_.end(); it++) {
13721cb0ef41Sopenharmony_ci      if (it->IsNested()) return true;
13731cb0ef41Sopenharmony_ci    }
13741cb0ef41Sopenharmony_ci    return false;
13751cb0ef41Sopenharmony_ci  }
13761cb0ef41Sopenharmony_ci
13771cb0ef41Sopenharmony_ci  ZoneVector<StateValueDescriptor> fields_;
13781cb0ef41Sopenharmony_ci  ZoneVector<StateValueList*> nested_;
13791cb0ef41Sopenharmony_ci};
13801cb0ef41Sopenharmony_ci
13811cb0ef41Sopenharmony_ciclass FrameStateDescriptor : public ZoneObject {
13821cb0ef41Sopenharmony_ci public:
13831cb0ef41Sopenharmony_ci  FrameStateDescriptor(Zone* zone, FrameStateType type,
13841cb0ef41Sopenharmony_ci                       BytecodeOffset bailout_id,
13851cb0ef41Sopenharmony_ci                       OutputFrameStateCombine state_combine,
13861cb0ef41Sopenharmony_ci                       size_t parameters_count, size_t locals_count,
13871cb0ef41Sopenharmony_ci                       size_t stack_count,
13881cb0ef41Sopenharmony_ci                       MaybeHandle<SharedFunctionInfo> shared_info,
13891cb0ef41Sopenharmony_ci                       FrameStateDescriptor* outer_state = nullptr);
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_ci  FrameStateType type() const { return type_; }
13921cb0ef41Sopenharmony_ci  BytecodeOffset bailout_id() const { return bailout_id_; }
13931cb0ef41Sopenharmony_ci  OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
13941cb0ef41Sopenharmony_ci  size_t parameters_count() const { return parameters_count_; }
13951cb0ef41Sopenharmony_ci  size_t locals_count() const { return locals_count_; }
13961cb0ef41Sopenharmony_ci  size_t stack_count() const { return stack_count_; }
13971cb0ef41Sopenharmony_ci  MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
13981cb0ef41Sopenharmony_ci  FrameStateDescriptor* outer_state() const { return outer_state_; }
13991cb0ef41Sopenharmony_ci  bool HasContext() const {
14001cb0ef41Sopenharmony_ci    return FrameStateFunctionInfo::IsJSFunctionType(type_) ||
14011cb0ef41Sopenharmony_ci           type_ == FrameStateType::kBuiltinContinuation ||
14021cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
14031cb0ef41Sopenharmony_ci           type_ == FrameStateType::kJSToWasmBuiltinContinuation ||
14041cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
14051cb0ef41Sopenharmony_ci           type_ == FrameStateType::kConstructStub;
14061cb0ef41Sopenharmony_ci  }
14071cb0ef41Sopenharmony_ci
14081cb0ef41Sopenharmony_ci  // The frame height on the stack, in number of slots, as serialized into a
14091cb0ef41Sopenharmony_ci  // Translation and later used by the deoptimizer. Does *not* include
14101cb0ef41Sopenharmony_ci  // information from the chain of outer states. Unlike |GetSize| this does not
14111cb0ef41Sopenharmony_ci  // always include parameters, locals, and stack slots; instead, the returned
14121cb0ef41Sopenharmony_ci  // slot kinds depend on the frame type.
14131cb0ef41Sopenharmony_ci  size_t GetHeight() const;
14141cb0ef41Sopenharmony_ci
14151cb0ef41Sopenharmony_ci  // Returns an overapproximation of the unoptimized stack frame size in bytes,
14161cb0ef41Sopenharmony_ci  // as later produced by the deoptimizer. Considers both this and the chain of
14171cb0ef41Sopenharmony_ci  // outer states.
14181cb0ef41Sopenharmony_ci  size_t total_conservative_frame_size_in_bytes() const {
14191cb0ef41Sopenharmony_ci    return total_conservative_frame_size_in_bytes_;
14201cb0ef41Sopenharmony_ci  }
14211cb0ef41Sopenharmony_ci
14221cb0ef41Sopenharmony_ci  size_t GetSize() const;
14231cb0ef41Sopenharmony_ci  size_t GetTotalSize() const;
14241cb0ef41Sopenharmony_ci  size_t GetFrameCount() const;
14251cb0ef41Sopenharmony_ci  size_t GetJSFrameCount() const;
14261cb0ef41Sopenharmony_ci
14271cb0ef41Sopenharmony_ci  StateValueList* GetStateValueDescriptors() { return &values_; }
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_ci  static const int kImpossibleValue = 0xdead;
14301cb0ef41Sopenharmony_ci
14311cb0ef41Sopenharmony_ci private:
14321cb0ef41Sopenharmony_ci  FrameStateType type_;
14331cb0ef41Sopenharmony_ci  BytecodeOffset bailout_id_;
14341cb0ef41Sopenharmony_ci  OutputFrameStateCombine frame_state_combine_;
14351cb0ef41Sopenharmony_ci  const size_t parameters_count_;
14361cb0ef41Sopenharmony_ci  const size_t locals_count_;
14371cb0ef41Sopenharmony_ci  const size_t stack_count_;
14381cb0ef41Sopenharmony_ci  const size_t total_conservative_frame_size_in_bytes_;
14391cb0ef41Sopenharmony_ci  StateValueList values_;
14401cb0ef41Sopenharmony_ci  MaybeHandle<SharedFunctionInfo> const shared_info_;
14411cb0ef41Sopenharmony_ci  FrameStateDescriptor* const outer_state_;
14421cb0ef41Sopenharmony_ci};
14431cb0ef41Sopenharmony_ci
14441cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
14451cb0ef41Sopenharmony_ciclass JSToWasmFrameStateDescriptor : public FrameStateDescriptor {
14461cb0ef41Sopenharmony_ci public:
14471cb0ef41Sopenharmony_ci  JSToWasmFrameStateDescriptor(Zone* zone, FrameStateType type,
14481cb0ef41Sopenharmony_ci                               BytecodeOffset bailout_id,
14491cb0ef41Sopenharmony_ci                               OutputFrameStateCombine state_combine,
14501cb0ef41Sopenharmony_ci                               size_t parameters_count, size_t locals_count,
14511cb0ef41Sopenharmony_ci                               size_t stack_count,
14521cb0ef41Sopenharmony_ci                               MaybeHandle<SharedFunctionInfo> shared_info,
14531cb0ef41Sopenharmony_ci                               FrameStateDescriptor* outer_state,
14541cb0ef41Sopenharmony_ci                               const wasm::FunctionSig* wasm_signature);
14551cb0ef41Sopenharmony_ci
14561cb0ef41Sopenharmony_ci  base::Optional<wasm::ValueKind> return_kind() const { return return_kind_; }
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci private:
14591cb0ef41Sopenharmony_ci  base::Optional<wasm::ValueKind> return_kind_;
14601cb0ef41Sopenharmony_ci};
14611cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
14621cb0ef41Sopenharmony_ci
14631cb0ef41Sopenharmony_ci// A deoptimization entry is a pair of the reason why we deoptimize and the
14641cb0ef41Sopenharmony_ci// frame state descriptor that we have to go back to.
14651cb0ef41Sopenharmony_ciclass DeoptimizationEntry final {
14661cb0ef41Sopenharmony_ci public:
14671cb0ef41Sopenharmony_ci  DeoptimizationEntry(FrameStateDescriptor* descriptor, DeoptimizeKind kind,
14681cb0ef41Sopenharmony_ci                      DeoptimizeReason reason, NodeId node_id,
14691cb0ef41Sopenharmony_ci                      FeedbackSource const& feedback)
14701cb0ef41Sopenharmony_ci      : descriptor_(descriptor),
14711cb0ef41Sopenharmony_ci        kind_(kind),
14721cb0ef41Sopenharmony_ci        reason_(reason),
14731cb0ef41Sopenharmony_ci#ifdef DEBUG
14741cb0ef41Sopenharmony_ci        node_id_(node_id),
14751cb0ef41Sopenharmony_ci#endif  // DEBUG
14761cb0ef41Sopenharmony_ci        feedback_(feedback) {
14771cb0ef41Sopenharmony_ci    USE(node_id);
14781cb0ef41Sopenharmony_ci  }
14791cb0ef41Sopenharmony_ci
14801cb0ef41Sopenharmony_ci  FrameStateDescriptor* descriptor() const { return descriptor_; }
14811cb0ef41Sopenharmony_ci  DeoptimizeKind kind() const { return kind_; }
14821cb0ef41Sopenharmony_ci  DeoptimizeReason reason() const { return reason_; }
14831cb0ef41Sopenharmony_ci#ifdef DEBUG
14841cb0ef41Sopenharmony_ci  NodeId node_id() const { return node_id_; }
14851cb0ef41Sopenharmony_ci#endif  // DEBUG
14861cb0ef41Sopenharmony_ci  FeedbackSource const& feedback() const { return feedback_; }
14871cb0ef41Sopenharmony_ci
14881cb0ef41Sopenharmony_ci private:
14891cb0ef41Sopenharmony_ci  FrameStateDescriptor* const descriptor_;
14901cb0ef41Sopenharmony_ci  const DeoptimizeKind kind_;
14911cb0ef41Sopenharmony_ci  const DeoptimizeReason reason_;
14921cb0ef41Sopenharmony_ci#ifdef DEBUG
14931cb0ef41Sopenharmony_ci  const NodeId node_id_;
14941cb0ef41Sopenharmony_ci#endif  // DEBUG
14951cb0ef41Sopenharmony_ci  const FeedbackSource feedback_;
14961cb0ef41Sopenharmony_ci};
14971cb0ef41Sopenharmony_ci
14981cb0ef41Sopenharmony_ciusing DeoptimizationVector = ZoneVector<DeoptimizationEntry>;
14991cb0ef41Sopenharmony_ci
15001cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE PhiInstruction final
15011cb0ef41Sopenharmony_ci    : public NON_EXPORTED_BASE(ZoneObject) {
15021cb0ef41Sopenharmony_ci public:
15031cb0ef41Sopenharmony_ci  using Inputs = ZoneVector<InstructionOperand>;
15041cb0ef41Sopenharmony_ci
15051cb0ef41Sopenharmony_ci  PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
15061cb0ef41Sopenharmony_ci
15071cb0ef41Sopenharmony_ci  void SetInput(size_t offset, int virtual_register);
15081cb0ef41Sopenharmony_ci  void RenameInput(size_t offset, int virtual_register);
15091cb0ef41Sopenharmony_ci
15101cb0ef41Sopenharmony_ci  int virtual_register() const { return virtual_register_; }
15111cb0ef41Sopenharmony_ci  const IntVector& operands() const { return operands_; }
15121cb0ef41Sopenharmony_ci
15131cb0ef41Sopenharmony_ci  // TODO(dcarney): this has no real business being here, since it's internal to
15141cb0ef41Sopenharmony_ci  // the register allocator, but putting it here was convenient.
15151cb0ef41Sopenharmony_ci  const InstructionOperand& output() const { return output_; }
15161cb0ef41Sopenharmony_ci  InstructionOperand& output() { return output_; }
15171cb0ef41Sopenharmony_ci
15181cb0ef41Sopenharmony_ci private:
15191cb0ef41Sopenharmony_ci  const int virtual_register_;
15201cb0ef41Sopenharmony_ci  InstructionOperand output_;
15211cb0ef41Sopenharmony_ci  IntVector operands_;
15221cb0ef41Sopenharmony_ci};
15231cb0ef41Sopenharmony_ci
15241cb0ef41Sopenharmony_ci// Analogue of BasicBlock for Instructions instead of Nodes.
15251cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE InstructionBlock final
15261cb0ef41Sopenharmony_ci    : public NON_EXPORTED_BASE(ZoneObject) {
15271cb0ef41Sopenharmony_ci public:
15281cb0ef41Sopenharmony_ci  InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
15291cb0ef41Sopenharmony_ci                   RpoNumber loop_end, RpoNumber dominator, bool deferred,
15301cb0ef41Sopenharmony_ci                   bool handler);
15311cb0ef41Sopenharmony_ci
15321cb0ef41Sopenharmony_ci  // Instruction indexes (used by the register allocator).
15331cb0ef41Sopenharmony_ci  int first_instruction_index() const {
15341cb0ef41Sopenharmony_ci    DCHECK_LE(0, code_start_);
15351cb0ef41Sopenharmony_ci    DCHECK_LT(0, code_end_);
15361cb0ef41Sopenharmony_ci    DCHECK_GE(code_end_, code_start_);
15371cb0ef41Sopenharmony_ci    return code_start_;
15381cb0ef41Sopenharmony_ci  }
15391cb0ef41Sopenharmony_ci  int last_instruction_index() const {
15401cb0ef41Sopenharmony_ci    DCHECK_LE(0, code_start_);
15411cb0ef41Sopenharmony_ci    DCHECK_LT(0, code_end_);
15421cb0ef41Sopenharmony_ci    DCHECK_GE(code_end_, code_start_);
15431cb0ef41Sopenharmony_ci    return code_end_ - 1;
15441cb0ef41Sopenharmony_ci  }
15451cb0ef41Sopenharmony_ci
15461cb0ef41Sopenharmony_ci  int32_t code_start() const { return code_start_; }
15471cb0ef41Sopenharmony_ci  void set_code_start(int32_t start) { code_start_ = start; }
15481cb0ef41Sopenharmony_ci
15491cb0ef41Sopenharmony_ci  int32_t code_end() const { return code_end_; }
15501cb0ef41Sopenharmony_ci  void set_code_end(int32_t end) { code_end_ = end; }
15511cb0ef41Sopenharmony_ci
15521cb0ef41Sopenharmony_ci  bool IsDeferred() const { return deferred_; }
15531cb0ef41Sopenharmony_ci  bool IsHandler() const { return handler_; }
15541cb0ef41Sopenharmony_ci  void MarkHandler() { handler_ = true; }
15551cb0ef41Sopenharmony_ci  void UnmarkHandler() { handler_ = false; }
15561cb0ef41Sopenharmony_ci
15571cb0ef41Sopenharmony_ci  RpoNumber ao_number() const { return ao_number_; }
15581cb0ef41Sopenharmony_ci  RpoNumber rpo_number() const { return rpo_number_; }
15591cb0ef41Sopenharmony_ci  RpoNumber loop_header() const { return loop_header_; }
15601cb0ef41Sopenharmony_ci  RpoNumber loop_end() const {
15611cb0ef41Sopenharmony_ci    DCHECK(IsLoopHeader());
15621cb0ef41Sopenharmony_ci    return loop_end_;
15631cb0ef41Sopenharmony_ci  }
15641cb0ef41Sopenharmony_ci  inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
15651cb0ef41Sopenharmony_ci  inline bool IsSwitchTarget() const { return switch_target_; }
15661cb0ef41Sopenharmony_ci  inline bool ShouldAlignCodeTarget() const { return code_target_alignment_; }
15671cb0ef41Sopenharmony_ci  inline bool ShouldAlignLoopHeader() const { return loop_header_alignment_; }
15681cb0ef41Sopenharmony_ci
15691cb0ef41Sopenharmony_ci  using Predecessors = ZoneVector<RpoNumber>;
15701cb0ef41Sopenharmony_ci  Predecessors& predecessors() { return predecessors_; }
15711cb0ef41Sopenharmony_ci  const Predecessors& predecessors() const { return predecessors_; }
15721cb0ef41Sopenharmony_ci  size_t PredecessorCount() const { return predecessors_.size(); }
15731cb0ef41Sopenharmony_ci  size_t PredecessorIndexOf(RpoNumber rpo_number) const;
15741cb0ef41Sopenharmony_ci
15751cb0ef41Sopenharmony_ci  using Successors = ZoneVector<RpoNumber>;
15761cb0ef41Sopenharmony_ci  Successors& successors() { return successors_; }
15771cb0ef41Sopenharmony_ci  const Successors& successors() const { return successors_; }
15781cb0ef41Sopenharmony_ci  size_t SuccessorCount() const { return successors_.size(); }
15791cb0ef41Sopenharmony_ci
15801cb0ef41Sopenharmony_ci  RpoNumber dominator() const { return dominator_; }
15811cb0ef41Sopenharmony_ci  void set_dominator(RpoNumber dominator) { dominator_ = dominator; }
15821cb0ef41Sopenharmony_ci
15831cb0ef41Sopenharmony_ci  using PhiInstructions = ZoneVector<PhiInstruction*>;
15841cb0ef41Sopenharmony_ci  const PhiInstructions& phis() const { return phis_; }
15851cb0ef41Sopenharmony_ci  PhiInstruction* PhiAt(size_t i) const { return phis_[i]; }
15861cb0ef41Sopenharmony_ci  void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
15871cb0ef41Sopenharmony_ci
15881cb0ef41Sopenharmony_ci  void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
15891cb0ef41Sopenharmony_ci
15901cb0ef41Sopenharmony_ci  void set_code_target_alignment(bool val) { code_target_alignment_ = val; }
15911cb0ef41Sopenharmony_ci  void set_loop_header_alignment(bool val) { loop_header_alignment_ = val; }
15921cb0ef41Sopenharmony_ci
15931cb0ef41Sopenharmony_ci  void set_switch_target(bool val) { switch_target_ = val; }
15941cb0ef41Sopenharmony_ci
15951cb0ef41Sopenharmony_ci  bool needs_frame() const { return needs_frame_; }
15961cb0ef41Sopenharmony_ci  void mark_needs_frame() { needs_frame_ = true; }
15971cb0ef41Sopenharmony_ci
15981cb0ef41Sopenharmony_ci  bool must_construct_frame() const { return must_construct_frame_; }
15991cb0ef41Sopenharmony_ci  void mark_must_construct_frame() { must_construct_frame_ = true; }
16001cb0ef41Sopenharmony_ci
16011cb0ef41Sopenharmony_ci  bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
16021cb0ef41Sopenharmony_ci  void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
16031cb0ef41Sopenharmony_ci  void clear_must_deconstruct_frame() { must_deconstruct_frame_ = false; }
16041cb0ef41Sopenharmony_ci
16051cb0ef41Sopenharmony_ci private:
16061cb0ef41Sopenharmony_ci  Successors successors_;
16071cb0ef41Sopenharmony_ci  Predecessors predecessors_;
16081cb0ef41Sopenharmony_ci  PhiInstructions phis_;
16091cb0ef41Sopenharmony_ci  RpoNumber ao_number_;  // Assembly order number.
16101cb0ef41Sopenharmony_ci  const RpoNumber rpo_number_;
16111cb0ef41Sopenharmony_ci  const RpoNumber loop_header_;
16121cb0ef41Sopenharmony_ci  const RpoNumber loop_end_;
16131cb0ef41Sopenharmony_ci  RpoNumber dominator_;
16141cb0ef41Sopenharmony_ci  int32_t code_start_;   // start index of arch-specific code.
16151cb0ef41Sopenharmony_ci  int32_t code_end_ = -1;     // end index of arch-specific code.
16161cb0ef41Sopenharmony_ci  const bool deferred_ : 1;   // Block contains deferred code.
16171cb0ef41Sopenharmony_ci  bool handler_ : 1;          // Block is a handler entry point.
16181cb0ef41Sopenharmony_ci  bool switch_target_ : 1;
16191cb0ef41Sopenharmony_ci  bool code_target_alignment_ : 1;  // insert code target alignment before this
16201cb0ef41Sopenharmony_ci                                    // block
16211cb0ef41Sopenharmony_ci  bool loop_header_alignment_ : 1;  // insert loop header alignment before this
16221cb0ef41Sopenharmony_ci                                    // block
16231cb0ef41Sopenharmony_ci  bool needs_frame_ : 1;
16241cb0ef41Sopenharmony_ci  bool must_construct_frame_ : 1;
16251cb0ef41Sopenharmony_ci  bool must_deconstruct_frame_ : 1;
16261cb0ef41Sopenharmony_ci};
16271cb0ef41Sopenharmony_ci
16281cb0ef41Sopenharmony_ciclass InstructionSequence;
16291cb0ef41Sopenharmony_ci
16301cb0ef41Sopenharmony_cistruct PrintableInstructionBlock {
16311cb0ef41Sopenharmony_ci  const InstructionBlock* block_;
16321cb0ef41Sopenharmony_ci  const InstructionSequence* code_;
16331cb0ef41Sopenharmony_ci};
16341cb0ef41Sopenharmony_ci
16351cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream&, const PrintableInstructionBlock&);
16361cb0ef41Sopenharmony_ci
16371cb0ef41Sopenharmony_ciusing ConstantDeque = ZoneDeque<Constant>;
16381cb0ef41Sopenharmony_ciusing ConstantMap = std::map<int, Constant, std::less<int>,
16391cb0ef41Sopenharmony_ci                             ZoneAllocator<std::pair<const int, Constant> > >;
16401cb0ef41Sopenharmony_ci
16411cb0ef41Sopenharmony_ciusing InstructionDeque = ZoneDeque<Instruction*>;
16421cb0ef41Sopenharmony_ciusing ReferenceMapDeque = ZoneDeque<ReferenceMap*>;
16431cb0ef41Sopenharmony_ciusing InstructionBlocks = ZoneVector<InstructionBlock*>;
16441cb0ef41Sopenharmony_ci
16451cb0ef41Sopenharmony_ci// Represents architecture-specific generated code before, during, and after
16461cb0ef41Sopenharmony_ci// register allocation.
16471cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE InstructionSequence final
16481cb0ef41Sopenharmony_ci    : public NON_EXPORTED_BASE(ZoneObject) {
16491cb0ef41Sopenharmony_ci public:
16501cb0ef41Sopenharmony_ci  static InstructionBlocks* InstructionBlocksFor(Zone* zone,
16511cb0ef41Sopenharmony_ci                                                 const Schedule* schedule);
16521cb0ef41Sopenharmony_ci  InstructionSequence(Isolate* isolate, Zone* zone,
16531cb0ef41Sopenharmony_ci                      InstructionBlocks* instruction_blocks);
16541cb0ef41Sopenharmony_ci  InstructionSequence(const InstructionSequence&) = delete;
16551cb0ef41Sopenharmony_ci  InstructionSequence& operator=(const InstructionSequence&) = delete;
16561cb0ef41Sopenharmony_ci
16571cb0ef41Sopenharmony_ci  int NextVirtualRegister();
16581cb0ef41Sopenharmony_ci  int VirtualRegisterCount() const { return next_virtual_register_; }
16591cb0ef41Sopenharmony_ci
16601cb0ef41Sopenharmony_ci  const InstructionBlocks& instruction_blocks() const {
16611cb0ef41Sopenharmony_ci    return *instruction_blocks_;
16621cb0ef41Sopenharmony_ci  }
16631cb0ef41Sopenharmony_ci
16641cb0ef41Sopenharmony_ci  const InstructionBlocks& ao_blocks() const { return *ao_blocks_; }
16651cb0ef41Sopenharmony_ci
16661cb0ef41Sopenharmony_ci  int InstructionBlockCount() const {
16671cb0ef41Sopenharmony_ci    return static_cast<int>(instruction_blocks_->size());
16681cb0ef41Sopenharmony_ci  }
16691cb0ef41Sopenharmony_ci
16701cb0ef41Sopenharmony_ci  InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
16711cb0ef41Sopenharmony_ci    return instruction_blocks_->at(rpo_number.ToSize());
16721cb0ef41Sopenharmony_ci  }
16731cb0ef41Sopenharmony_ci
16741cb0ef41Sopenharmony_ci  int LastLoopInstructionIndex(const InstructionBlock* block) {
16751cb0ef41Sopenharmony_ci    return instruction_blocks_->at(block->loop_end().ToSize() - 1)
16761cb0ef41Sopenharmony_ci        ->last_instruction_index();
16771cb0ef41Sopenharmony_ci  }
16781cb0ef41Sopenharmony_ci
16791cb0ef41Sopenharmony_ci  const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
16801cb0ef41Sopenharmony_ci    return instruction_blocks_->at(rpo_number.ToSize());
16811cb0ef41Sopenharmony_ci  }
16821cb0ef41Sopenharmony_ci
16831cb0ef41Sopenharmony_ci  InstructionBlock* GetInstructionBlock(int instruction_index) const;
16841cb0ef41Sopenharmony_ci
16851cb0ef41Sopenharmony_ci  static MachineRepresentation DefaultRepresentation() {
16861cb0ef41Sopenharmony_ci    return MachineType::PointerRepresentation();
16871cb0ef41Sopenharmony_ci  }
16881cb0ef41Sopenharmony_ci  MachineRepresentation GetRepresentation(int virtual_register) const;
16891cb0ef41Sopenharmony_ci  void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
16901cb0ef41Sopenharmony_ci
16911cb0ef41Sopenharmony_ci  bool IsReference(int virtual_register) const {
16921cb0ef41Sopenharmony_ci    return CanBeTaggedOrCompressedPointer(GetRepresentation(virtual_register));
16931cb0ef41Sopenharmony_ci  }
16941cb0ef41Sopenharmony_ci  bool IsFP(int virtual_register) const {
16951cb0ef41Sopenharmony_ci    return IsFloatingPoint(GetRepresentation(virtual_register));
16961cb0ef41Sopenharmony_ci  }
16971cb0ef41Sopenharmony_ci  int representation_mask() const { return representation_mask_; }
16981cb0ef41Sopenharmony_ci  bool HasFPVirtualRegisters() const {
16991cb0ef41Sopenharmony_ci    constexpr int kFPRepMask =
17001cb0ef41Sopenharmony_ci        RepresentationBit(MachineRepresentation::kFloat32) |
17011cb0ef41Sopenharmony_ci        RepresentationBit(MachineRepresentation::kFloat64) |
17021cb0ef41Sopenharmony_ci        RepresentationBit(MachineRepresentation::kSimd128);
17031cb0ef41Sopenharmony_ci    return (representation_mask() & kFPRepMask) != 0;
17041cb0ef41Sopenharmony_ci  }
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_ci  bool HasSimd128VirtualRegisters() const {
17071cb0ef41Sopenharmony_ci    constexpr int kSimd128RepMask =
17081cb0ef41Sopenharmony_ci        RepresentationBit(MachineRepresentation::kSimd128);
17091cb0ef41Sopenharmony_ci    return (representation_mask() & kSimd128RepMask) != 0;
17101cb0ef41Sopenharmony_ci  }
17111cb0ef41Sopenharmony_ci
17121cb0ef41Sopenharmony_ci  Instruction* GetBlockStart(RpoNumber rpo) const;
17131cb0ef41Sopenharmony_ci
17141cb0ef41Sopenharmony_ci  using const_iterator = InstructionDeque::const_iterator;
17151cb0ef41Sopenharmony_ci  const_iterator begin() const { return instructions_.begin(); }
17161cb0ef41Sopenharmony_ci  const_iterator end() const { return instructions_.end(); }
17171cb0ef41Sopenharmony_ci  const InstructionDeque& instructions() const { return instructions_; }
17181cb0ef41Sopenharmony_ci  int LastInstructionIndex() const {
17191cb0ef41Sopenharmony_ci    return static_cast<int>(instructions().size()) - 1;
17201cb0ef41Sopenharmony_ci  }
17211cb0ef41Sopenharmony_ci
17221cb0ef41Sopenharmony_ci  Instruction* InstructionAt(int index) const {
17231cb0ef41Sopenharmony_ci    DCHECK_LE(0, index);
17241cb0ef41Sopenharmony_ci    DCHECK_GT(instructions_.size(), index);
17251cb0ef41Sopenharmony_ci    return instructions_[index];
17261cb0ef41Sopenharmony_ci  }
17271cb0ef41Sopenharmony_ci
17281cb0ef41Sopenharmony_ci  Isolate* isolate() const { return isolate_; }
17291cb0ef41Sopenharmony_ci  const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
17301cb0ef41Sopenharmony_ci  Zone* zone() const { return zone_; }
17311cb0ef41Sopenharmony_ci
17321cb0ef41Sopenharmony_ci  // Used by the instruction selector while adding instructions.
17331cb0ef41Sopenharmony_ci  int AddInstruction(Instruction* instr);
17341cb0ef41Sopenharmony_ci  void StartBlock(RpoNumber rpo);
17351cb0ef41Sopenharmony_ci  void EndBlock(RpoNumber rpo);
17361cb0ef41Sopenharmony_ci
17371cb0ef41Sopenharmony_ci  int AddConstant(int virtual_register, Constant constant) {
17381cb0ef41Sopenharmony_ci    // TODO(titzer): allow RPO numbers as constants?
17391cb0ef41Sopenharmony_ci    DCHECK_NE(Constant::kRpoNumber, constant.type());
17401cb0ef41Sopenharmony_ci    DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
17411cb0ef41Sopenharmony_ci    DCHECK(constants_.find(virtual_register) == constants_.end());
17421cb0ef41Sopenharmony_ci    constants_.insert(std::make_pair(virtual_register, constant));
17431cb0ef41Sopenharmony_ci    return virtual_register;
17441cb0ef41Sopenharmony_ci  }
17451cb0ef41Sopenharmony_ci  Constant GetConstant(int virtual_register) const {
17461cb0ef41Sopenharmony_ci    auto it = constants_.find(virtual_register);
17471cb0ef41Sopenharmony_ci    DCHECK(it != constants_.end());
17481cb0ef41Sopenharmony_ci    DCHECK_EQ(virtual_register, it->first);
17491cb0ef41Sopenharmony_ci    return it->second;
17501cb0ef41Sopenharmony_ci  }
17511cb0ef41Sopenharmony_ci
17521cb0ef41Sopenharmony_ci  using Immediates = ZoneVector<Constant>;
17531cb0ef41Sopenharmony_ci  Immediates& immediates() { return immediates_; }
17541cb0ef41Sopenharmony_ci
17551cb0ef41Sopenharmony_ci  using RpoImmediates = ZoneVector<RpoNumber>;
17561cb0ef41Sopenharmony_ci  RpoImmediates& rpo_immediates() { return rpo_immediates_; }
17571cb0ef41Sopenharmony_ci
17581cb0ef41Sopenharmony_ci  ImmediateOperand AddImmediate(const Constant& constant) {
17591cb0ef41Sopenharmony_ci    if (RelocInfo::IsNoInfo(constant.rmode())) {
17601cb0ef41Sopenharmony_ci      if (constant.type() == Constant::kRpoNumber) {
17611cb0ef41Sopenharmony_ci        // Ideally we would inline RPO numbers into the operand, however jump-
17621cb0ef41Sopenharmony_ci        // threading modifies RPO values and so we indirect through a vector
17631cb0ef41Sopenharmony_ci        // of rpo_immediates to enable rewriting. We keep this seperate from the
17641cb0ef41Sopenharmony_ci        // immediates vector so that we don't repeatedly push the same rpo
17651cb0ef41Sopenharmony_ci        // number.
17661cb0ef41Sopenharmony_ci        RpoNumber rpo_number = constant.ToRpoNumber();
17671cb0ef41Sopenharmony_ci        DCHECK(!rpo_immediates().at(rpo_number.ToSize()).IsValid() ||
17681cb0ef41Sopenharmony_ci               rpo_immediates().at(rpo_number.ToSize()) == rpo_number);
17691cb0ef41Sopenharmony_ci        rpo_immediates()[rpo_number.ToSize()] = rpo_number;
17701cb0ef41Sopenharmony_ci        return ImmediateOperand(ImmediateOperand::INDEXED_RPO,
17711cb0ef41Sopenharmony_ci                                rpo_number.ToInt());
17721cb0ef41Sopenharmony_ci      } else if (constant.type() == Constant::kInt32) {
17731cb0ef41Sopenharmony_ci        return ImmediateOperand(ImmediateOperand::INLINE_INT32,
17741cb0ef41Sopenharmony_ci                                constant.ToInt32());
17751cb0ef41Sopenharmony_ci      } else if (constant.type() == Constant::kInt64 &&
17761cb0ef41Sopenharmony_ci                 constant.FitsInInt32()) {
17771cb0ef41Sopenharmony_ci        return ImmediateOperand(ImmediateOperand::INLINE_INT64,
17781cb0ef41Sopenharmony_ci                                constant.ToInt32());
17791cb0ef41Sopenharmony_ci      }
17801cb0ef41Sopenharmony_ci    }
17811cb0ef41Sopenharmony_ci    int index = static_cast<int>(immediates_.size());
17821cb0ef41Sopenharmony_ci    immediates_.push_back(constant);
17831cb0ef41Sopenharmony_ci    return ImmediateOperand(ImmediateOperand::INDEXED_IMM, index);
17841cb0ef41Sopenharmony_ci  }
17851cb0ef41Sopenharmony_ci
17861cb0ef41Sopenharmony_ci  Constant GetImmediate(const ImmediateOperand* op) const {
17871cb0ef41Sopenharmony_ci    switch (op->type()) {
17881cb0ef41Sopenharmony_ci      case ImmediateOperand::INLINE_INT32:
17891cb0ef41Sopenharmony_ci        return Constant(op->inline_int32_value());
17901cb0ef41Sopenharmony_ci      case ImmediateOperand::INLINE_INT64:
17911cb0ef41Sopenharmony_ci        return Constant(op->inline_int64_value());
17921cb0ef41Sopenharmony_ci      case ImmediateOperand::INDEXED_RPO: {
17931cb0ef41Sopenharmony_ci        int index = op->indexed_value();
17941cb0ef41Sopenharmony_ci        DCHECK_LE(0, index);
17951cb0ef41Sopenharmony_ci        DCHECK_GT(rpo_immediates_.size(), index);
17961cb0ef41Sopenharmony_ci        return Constant(rpo_immediates_[index]);
17971cb0ef41Sopenharmony_ci      }
17981cb0ef41Sopenharmony_ci      case ImmediateOperand::INDEXED_IMM: {
17991cb0ef41Sopenharmony_ci        int index = op->indexed_value();
18001cb0ef41Sopenharmony_ci        DCHECK_LE(0, index);
18011cb0ef41Sopenharmony_ci        DCHECK_GT(immediates_.size(), index);
18021cb0ef41Sopenharmony_ci        return immediates_[index];
18031cb0ef41Sopenharmony_ci      }
18041cb0ef41Sopenharmony_ci    }
18051cb0ef41Sopenharmony_ci    UNREACHABLE();
18061cb0ef41Sopenharmony_ci  }
18071cb0ef41Sopenharmony_ci
18081cb0ef41Sopenharmony_ci  int AddDeoptimizationEntry(FrameStateDescriptor* descriptor,
18091cb0ef41Sopenharmony_ci                             DeoptimizeKind kind, DeoptimizeReason reason,
18101cb0ef41Sopenharmony_ci                             NodeId node_id, FeedbackSource const& feedback);
18111cb0ef41Sopenharmony_ci  DeoptimizationEntry const& GetDeoptimizationEntry(int deoptimization_id);
18121cb0ef41Sopenharmony_ci  int GetDeoptimizationEntryCount() const {
18131cb0ef41Sopenharmony_ci    return static_cast<int>(deoptimization_entries_.size());
18141cb0ef41Sopenharmony_ci  }
18151cb0ef41Sopenharmony_ci
18161cb0ef41Sopenharmony_ci  RpoNumber InputRpo(Instruction* instr, size_t index);
18171cb0ef41Sopenharmony_ci
18181cb0ef41Sopenharmony_ci  bool GetSourcePosition(const Instruction* instr,
18191cb0ef41Sopenharmony_ci                         SourcePosition* result) const;
18201cb0ef41Sopenharmony_ci  void SetSourcePosition(const Instruction* instr, SourcePosition value);
18211cb0ef41Sopenharmony_ci
18221cb0ef41Sopenharmony_ci  bool ContainsCall() const {
18231cb0ef41Sopenharmony_ci    for (Instruction* instr : instructions_) {
18241cb0ef41Sopenharmony_ci      if (instr->IsCall()) return true;
18251cb0ef41Sopenharmony_ci    }
18261cb0ef41Sopenharmony_ci    return false;
18271cb0ef41Sopenharmony_ci  }
18281cb0ef41Sopenharmony_ci
18291cb0ef41Sopenharmony_ci  // APIs to aid debugging. For general-stream APIs, use operator<<.
18301cb0ef41Sopenharmony_ci  void Print() const;
18311cb0ef41Sopenharmony_ci
18321cb0ef41Sopenharmony_ci  void PrintBlock(int block_id) const;
18331cb0ef41Sopenharmony_ci
18341cb0ef41Sopenharmony_ci  void ValidateEdgeSplitForm() const;
18351cb0ef41Sopenharmony_ci  void ValidateDeferredBlockExitPaths() const;
18361cb0ef41Sopenharmony_ci  void ValidateDeferredBlockEntryPaths() const;
18371cb0ef41Sopenharmony_ci  void ValidateSSA() const;
18381cb0ef41Sopenharmony_ci
18391cb0ef41Sopenharmony_ci  static void SetRegisterConfigurationForTesting(
18401cb0ef41Sopenharmony_ci      const RegisterConfiguration* regConfig);
18411cb0ef41Sopenharmony_ci  static void ClearRegisterConfigurationForTesting();
18421cb0ef41Sopenharmony_ci
18431cb0ef41Sopenharmony_ci  void RecomputeAssemblyOrderForTesting();
18441cb0ef41Sopenharmony_ci
18451cb0ef41Sopenharmony_ci  void IncreaseRpoForTesting(size_t rpo_count) {
18461cb0ef41Sopenharmony_ci    DCHECK_GE(rpo_count, rpo_immediates().size());
18471cb0ef41Sopenharmony_ci    rpo_immediates().resize(rpo_count);
18481cb0ef41Sopenharmony_ci  }
18491cb0ef41Sopenharmony_ci
18501cb0ef41Sopenharmony_ci private:
18511cb0ef41Sopenharmony_ci  friend V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
18521cb0ef41Sopenharmony_ci                                                    const InstructionSequence&);
18531cb0ef41Sopenharmony_ci
18541cb0ef41Sopenharmony_ci  using SourcePositionMap = ZoneMap<const Instruction*, SourcePosition>;
18551cb0ef41Sopenharmony_ci
18561cb0ef41Sopenharmony_ci  static const RegisterConfiguration* RegisterConfigurationForTesting();
18571cb0ef41Sopenharmony_ci  static const RegisterConfiguration* registerConfigurationForTesting_;
18581cb0ef41Sopenharmony_ci
18591cb0ef41Sopenharmony_ci  // Puts the deferred blocks last and may rotate loops.
18601cb0ef41Sopenharmony_ci  void ComputeAssemblyOrder();
18611cb0ef41Sopenharmony_ci
18621cb0ef41Sopenharmony_ci  Isolate* isolate_;
18631cb0ef41Sopenharmony_ci  Zone* const zone_;
18641cb0ef41Sopenharmony_ci  InstructionBlocks* const instruction_blocks_;
18651cb0ef41Sopenharmony_ci  InstructionBlocks* ao_blocks_;
18661cb0ef41Sopenharmony_ci  SourcePositionMap source_positions_;
18671cb0ef41Sopenharmony_ci  ConstantMap constants_;
18681cb0ef41Sopenharmony_ci  Immediates immediates_;
18691cb0ef41Sopenharmony_ci  RpoImmediates rpo_immediates_;
18701cb0ef41Sopenharmony_ci  InstructionDeque instructions_;
18711cb0ef41Sopenharmony_ci  int next_virtual_register_;
18721cb0ef41Sopenharmony_ci  ReferenceMapDeque reference_maps_;
18731cb0ef41Sopenharmony_ci  ZoneVector<MachineRepresentation> representations_;
18741cb0ef41Sopenharmony_ci  int representation_mask_;
18751cb0ef41Sopenharmony_ci  DeoptimizationVector deoptimization_entries_;
18761cb0ef41Sopenharmony_ci
18771cb0ef41Sopenharmony_ci  // Used at construction time
18781cb0ef41Sopenharmony_ci  InstructionBlock* current_block_;
18791cb0ef41Sopenharmony_ci};
18801cb0ef41Sopenharmony_ci
18811cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
18821cb0ef41Sopenharmony_ci                                           const InstructionSequence&);
18831cb0ef41Sopenharmony_ci#undef INSTRUCTION_OPERAND_ALIGN
18841cb0ef41Sopenharmony_ci
18851cb0ef41Sopenharmony_ci}  // namespace compiler
18861cb0ef41Sopenharmony_ci}  // namespace internal
18871cb0ef41Sopenharmony_ci}  // namespace v8
18881cb0ef41Sopenharmony_ci
18891cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_BACKEND_INSTRUCTION_H_
1890