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 ¶llel_moves_[0]; } 10161cb0ef41Sopenharmony_ci ParallelMove** parallel_moves() { return ¶llel_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