LCOV - code coverage report
Current view: top level - src/compiler/backend - instruction.h (source / functions) Hit Total Coverage
Test: app.info Lines: 219 228 96.1 %
Date: 2019-01-20 Functions: 29 30 96.7 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_COMPILER_BACKEND_INSTRUCTION_H_
       6             : #define V8_COMPILER_BACKEND_INSTRUCTION_H_
       7             : 
       8             : #include <deque>
       9             : #include <iosfwd>
      10             : #include <map>
      11             : #include <set>
      12             : 
      13             : #include "src/base/compiler-specific.h"
      14             : #include "src/compiler/backend/instruction-codes.h"
      15             : #include "src/compiler/common-operator.h"
      16             : #include "src/compiler/frame.h"
      17             : #include "src/compiler/opcodes.h"
      18             : #include "src/double.h"
      19             : #include "src/external-reference.h"
      20             : #include "src/globals.h"
      21             : #include "src/register-arch.h"
      22             : #include "src/source-position.h"
      23             : #include "src/zone/zone-allocator.h"
      24             : 
      25             : namespace v8 {
      26             : namespace internal {
      27             : 
      28             : class RegisterConfiguration;
      29             : 
      30             : namespace compiler {
      31             : 
      32             : class Schedule;
      33             : class SourcePositionTable;
      34             : 
      35             : class V8_EXPORT_PRIVATE InstructionOperand {
      36             :  public:
      37             :   static const int kInvalidVirtualRegister = -1;
      38             : 
      39             :   enum Kind {
      40             :     INVALID,
      41             :     UNALLOCATED,
      42             :     CONSTANT,
      43             :     IMMEDIATE,
      44             :     // Location operand kinds.
      45             :     EXPLICIT,
      46             :     ALLOCATED,
      47             :     FIRST_LOCATION_OPERAND_KIND = EXPLICIT
      48             :     // Location operand kinds must be last.
      49             :   };
      50             : 
      51             :   InstructionOperand() : InstructionOperand(INVALID) {}
      52             : 
      53  4162735530 :   Kind kind() const { return KindField::decode(value_); }
      54             : 
      55             : #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
      56             :   bool Is##name() const { return kind() == type; }
      57             :   INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
      58             :   // UnallocatedOperands are place-holder operands created before register
      59             :   // allocation. They later are assigned registers and become AllocatedOperands.
      60           1 :   INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
      61             :   // Constant operands participate in register allocation. They are allocated to
      62             :   // registers but have a special "spilling" behavior. When a ConstantOperand
      63             :   // value must be rematerialized, it is loaded from an immediate constant
      64             :   // rather from an unspilled slot.
      65     2594890 :   INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
      66             :   // ImmediateOperands do not participate in register allocation and are only
      67             :   // embedded directly in instructions, e.g. small integers and on some
      68             :   // platforms Objects.
      69       83802 :   INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
      70             :   // ExplicitOperands do not participate in register allocation. They are
      71             :   // created by the instruction selector for direct access to registers and
      72             :   // stack slots, completely bypassing the register allocator. They are never
      73             :   // associated with a virtual register
      74             :   INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
      75             :   // AllocatedOperands are registers or stack slots that are assigned by the
      76             :   // register allocator and are always associated with a virtual register.
      77             :   INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
      78             : #undef INSTRUCTION_OPERAND_PREDICATE
      79             : 
      80             :   inline bool IsAnyLocationOperand() const;
      81             :   inline bool IsLocationOperand() const;
      82             :   inline bool IsFPLocationOperand() const;
      83             :   inline bool IsAnyRegister() const;
      84             :   inline bool IsRegister() const;
      85             :   inline bool IsFPRegister() const;
      86             :   inline bool IsFloatRegister() const;
      87             :   inline bool IsDoubleRegister() const;
      88             :   inline bool IsSimd128Register() const;
      89             :   inline bool IsAnyStackSlot() const;
      90             :   inline bool IsStackSlot() const;
      91             :   inline bool IsFPStackSlot() const;
      92             :   inline bool IsFloatStackSlot() const;
      93             :   inline bool IsDoubleStackSlot() const;
      94             :   inline bool IsSimd128StackSlot() const;
      95             : 
      96             :   template <typename SubKindOperand>
      97             :   static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
      98           0 :     void* buffer = zone->New(sizeof(op));
      99           0 :     return new (buffer) SubKindOperand(op);
     100             :   }
     101             : 
     102             :   static void ReplaceWith(InstructionOperand* dest,
     103             :                           const InstructionOperand* src) {
     104    45249519 :     *dest = *src;
     105             :   }
     106             : 
     107             :   bool Equals(const InstructionOperand& that) const {
     108    30844116 :     return this->value_ == that.value_;
     109             :   }
     110             : 
     111             :   bool Compare(const InstructionOperand& that) const {
     112           0 :     return this->value_ < that.value_;
     113             :   }
     114             : 
     115             :   bool EqualsCanonicalized(const InstructionOperand& that) const {
     116   996052997 :     return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
     117             :   }
     118             : 
     119             :   bool CompareCanonicalized(const InstructionOperand& that) const {
     120    62617493 :     return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
     121             :   }
     122             : 
     123             :   bool InterferesWith(const InstructionOperand& other) const;
     124             : 
     125             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     126             :   void Print() const;
     127             : 
     128             :  protected:
     129   217563394 :   explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
     130             : 
     131             :   inline uint64_t GetCanonicalizedValue() const;
     132             : 
     133             :   class KindField : public BitField64<Kind, 0, 3> {};
     134             : 
     135             :   uint64_t value_;
     136             : };
     137             : 
     138             : typedef ZoneVector<InstructionOperand> InstructionOperandVector;
     139             : 
     140             : std::ostream& operator<<(std::ostream&, const InstructionOperand&);
     141             : 
     142             : #define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind)      \
     143             :                                                                  \
     144             :   static OperandType* cast(InstructionOperand* op) {             \
     145             :     DCHECK_EQ(OperandKind, op->kind());                          \
     146             :     return static_cast<OperandType*>(op);                        \
     147             :   }                                                              \
     148             :                                                                  \
     149             :   static const OperandType* cast(const InstructionOperand* op) { \
     150             :     DCHECK_EQ(OperandKind, op->kind());                          \
     151             :     return static_cast<const OperandType*>(op);                  \
     152             :   }                                                              \
     153             :                                                                  \
     154             :   static OperandType cast(const InstructionOperand& op) {        \
     155             :     DCHECK_EQ(OperandKind, op.kind());                           \
     156             :     return *static_cast<const OperandType*>(&op);                \
     157             :   }
     158             : 
     159             : class UnallocatedOperand final : public InstructionOperand {
     160             :  public:
     161             :   enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
     162             : 
     163             :   enum ExtendedPolicy {
     164             :     NONE,
     165             :     REGISTER_OR_SLOT,
     166             :     REGISTER_OR_SLOT_OR_CONSTANT,
     167             :     FIXED_REGISTER,
     168             :     FIXED_FP_REGISTER,
     169             :     MUST_HAVE_REGISTER,
     170             :     MUST_HAVE_SLOT,
     171             :     SAME_AS_FIRST_INPUT
     172             :   };
     173             : 
     174             :   // Lifetime of operand inside the instruction.
     175             :   enum Lifetime {
     176             :     // USED_AT_START operand is guaranteed to be live only at instruction start.
     177             :     // The register allocator is free to assign the same register to some other
     178             :     // operand used inside instruction (i.e. temporary or output).
     179             :     USED_AT_START,
     180             : 
     181             :     // USED_AT_END operand is treated as live until the end of instruction.
     182             :     // This means that register allocator will not reuse its register for any
     183             :     // other operand inside instruction.
     184             :     USED_AT_END
     185             :   };
     186             : 
     187             :   UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
     188             :       : UnallocatedOperand(virtual_register) {
     189    37631219 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     190    35461411 :     value_ |= ExtendedPolicyField::encode(policy);
     191    64570905 :     value_ |= LifetimeField::encode(USED_AT_END);
     192             :   }
     193             : 
     194             :   UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
     195             :       : UnallocatedOperand(virtual_register) {
     196             :     DCHECK(policy == FIXED_SLOT);
     197           0 :     value_ |= BasicPolicyField::encode(policy);
     198     4301640 :     value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
     199             :     DCHECK(this->fixed_slot_index() == index);
     200             :   }
     201             : 
     202             :   UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
     203             :       : UnallocatedOperand(virtual_register) {
     204             :     DCHECK(policy == FIXED_REGISTER || policy == FIXED_FP_REGISTER);
     205         122 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     206         122 :     value_ |= ExtendedPolicyField::encode(policy);
     207    26315490 :     value_ |= LifetimeField::encode(USED_AT_END);
     208    26315490 :     value_ |= FixedRegisterField::encode(index);
     209             :   }
     210             : 
     211             :   UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
     212             :                      int virtual_register)
     213             :       : UnallocatedOperand(virtual_register) {
     214     5318217 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     215    28596393 :     value_ |= ExtendedPolicyField::encode(policy);
     216     2367474 :     value_ |= LifetimeField::encode(lifetime);
     217             :   }
     218             : 
     219             :   UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
     220             :       : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
     221      103597 :     value_ |= HasSecondaryStorageField::encode(true);
     222      103597 :     value_ |= SecondaryStorageField::encode(slot_id);
     223             :   }
     224             : 
     225             :   UnallocatedOperand(const UnallocatedOperand& other, int virtual_register) {
     226             :     DCHECK_NE(kInvalidVirtualRegister, virtual_register);
     227             :     value_ = VirtualRegisterField::update(
     228     5283190 :         other.value_, static_cast<uint32_t>(virtual_register));
     229             :   }
     230             : 
     231             :   // Predicates for the operand policy.
     232             :   bool HasRegisterOrSlotPolicy() const {
     233    98474965 :     return basic_policy() == EXTENDED_POLICY &&
     234             :            extended_policy() == REGISTER_OR_SLOT;
     235             :   }
     236             :   bool HasRegisterOrSlotOrConstantPolicy() const {
     237    98474858 :     return basic_policy() == EXTENDED_POLICY &&
     238             :            extended_policy() == REGISTER_OR_SLOT_OR_CONSTANT;
     239             :   }
     240             :   bool HasFixedPolicy() const {
     241    88991780 :     return basic_policy() == FIXED_SLOT ||
     242   153024654 :            extended_policy() == FIXED_REGISTER ||
     243             :            extended_policy() == FIXED_FP_REGISTER;
     244             :   }
     245             :   bool HasRegisterPolicy() const {
     246   203963968 :     return basic_policy() == EXTENDED_POLICY &&
     247             :            extended_policy() == MUST_HAVE_REGISTER;
     248             :   }
     249             :   bool HasSlotPolicy() const {
     250   220396449 :     return basic_policy() == EXTENDED_POLICY &&
     251             :            extended_policy() == MUST_HAVE_SLOT;
     252             :   }
     253             :   bool HasSameAsInputPolicy() const {
     254    44028114 :     return basic_policy() == EXTENDED_POLICY &&
     255             :            extended_policy() == SAME_AS_FIRST_INPUT;
     256             :   }
     257             :   bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
     258             :   bool HasFixedRegisterPolicy() const {
     259    52744900 :     return basic_policy() == EXTENDED_POLICY &&
     260             :            extended_policy() == FIXED_REGISTER;
     261             :   }
     262             :   bool HasFixedFPRegisterPolicy() const {
     263      348871 :     return basic_policy() == EXTENDED_POLICY &&
     264             :            extended_policy() == FIXED_FP_REGISTER;
     265             :   }
     266             :   bool HasSecondaryStorage() const {
     267     7962599 :     return basic_policy() == EXTENDED_POLICY &&
     268    16990069 :            extended_policy() == FIXED_REGISTER &&
     269             :            HasSecondaryStorageField::decode(value_);
     270             :   }
     271             :   int GetSecondaryStorage() const {
     272             :     DCHECK(HasSecondaryStorage());
     273      103536 :     return SecondaryStorageField::decode(value_);
     274             :   }
     275             : 
     276             :   // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
     277   210571046 :   BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); }
     278             : 
     279             :   // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
     280             :   ExtendedPolicy extended_policy() const {
     281             :     DCHECK(basic_policy() == EXTENDED_POLICY);
     282             :     return ExtendedPolicyField::decode(value_);
     283             :   }
     284             : 
     285             :   // [fixed_slot_index]: Only for FIXED_SLOT.
     286             :   int fixed_slot_index() const {
     287             :     DCHECK(HasFixedSlotPolicy());
     288     4294767 :     return static_cast<int>(static_cast<int64_t>(value_) >>
     289     4294767 :                             FixedSlotIndexField::kShift);
     290             :   }
     291             : 
     292             :   // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER.
     293             :   int fixed_register_index() const {
     294             :     DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy());
     295         122 :     return FixedRegisterField::decode(value_);
     296             :   }
     297             : 
     298             :   // [virtual_register]: The virtual register ID for this operand.
     299             :   int32_t virtual_register() const {
     300   401684712 :     return static_cast<int32_t>(VirtualRegisterField::decode(value_));
     301             :   }
     302             : 
     303             :   // [lifetime]: Only for non-FIXED_SLOT.
     304             :   bool IsUsedAtStart() const {
     305             :     DCHECK(basic_policy() == EXTENDED_POLICY);
     306           2 :     return LifetimeField::decode(value_) == USED_AT_START;
     307             :   }
     308             : 
     309    28430326 :   INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
     310             : 
     311             :   // The encoding used for UnallocatedOperand operands depends on the policy
     312             :   // that is
     313             :   // stored within the operand. The FIXED_SLOT policy uses a compact encoding
     314             :   // because it accommodates a larger pay-load.
     315             :   //
     316             :   // For FIXED_SLOT policy:
     317             :   //     +------------------------------------------------+
     318             :   //     |      slot_index   | 0 | virtual_register | 001 |
     319             :   //     +------------------------------------------------+
     320             :   //
     321             :   // For all other (extended) policies:
     322             :   //     +-----------------------------------------------------+
     323             :   //     |  reg_index  | L | PPP |  1 | virtual_register | 001 |
     324             :   //     +-----------------------------------------------------+
     325             :   //     L ... Lifetime
     326             :   //     P ... Policy
     327             :   //
     328             :   // The slot index is a signed value which requires us to decode it manually
     329             :   // instead of using the BitField utility class.
     330             : 
     331             :   STATIC_ASSERT(KindField::kSize == 3);
     332             : 
     333             :   class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
     334             : 
     335             :   // BitFields for all unallocated operands.
     336             :   class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
     337             : 
     338             :   // BitFields specific to BasicPolicy::FIXED_SLOT.
     339             :   class FixedSlotIndexField : public BitField64<int, 36, 28> {};
     340             : 
     341             :   // BitFields specific to BasicPolicy::EXTENDED_POLICY.
     342             :   class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
     343             :   class LifetimeField : public BitField64<Lifetime, 39, 1> {};
     344             :   class HasSecondaryStorageField : public BitField64<bool, 40, 1> {};
     345             :   class FixedRegisterField : public BitField64<int, 41, 6> {};
     346             :   class SecondaryStorageField : public BitField64<int, 47, 3> {};
     347             : 
     348             :  private:
     349             :   explicit UnallocatedOperand(int virtual_register)
     350             :       : InstructionOperand(UNALLOCATED) {
     351             :     value_ |=
     352   171233170 :         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
     353             :   }
     354             : };
     355             : 
     356             : class ConstantOperand : public InstructionOperand {
     357             :  public:
     358             :   explicit ConstantOperand(int virtual_register)
     359             :       : InstructionOperand(CONSTANT) {
     360             :     value_ |=
     361    27320439 :         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
     362             :   }
     363             : 
     364             :   int32_t virtual_register() const {
     365    59451443 :     return static_cast<int32_t>(VirtualRegisterField::decode(value_));
     366             :   }
     367             : 
     368             :   static ConstantOperand* New(Zone* zone, int virtual_register) {
     369             :     return InstructionOperand::New(zone, ConstantOperand(virtual_register));
     370             :   }
     371             : 
     372          16 :   INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
     373             : 
     374             :   STATIC_ASSERT(KindField::kSize == 3);
     375             :   class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
     376             : };
     377             : 
     378             : class ImmediateOperand : public InstructionOperand {
     379             :  public:
     380             :   enum ImmediateType { INLINE, INDEXED };
     381             : 
     382             :   explicit ImmediateOperand(ImmediateType type, int32_t value)
     383             :       : InstructionOperand(IMMEDIATE) {
     384             :     value_ |= TypeField::encode(type);
     385    60618331 :     value_ |= static_cast<int64_t>(value) << ValueField::kShift;
     386             :   }
     387             : 
     388    61368961 :   ImmediateType type() const { return TypeField::decode(value_); }
     389             : 
     390             :   int32_t inline_value() const {
     391             :     DCHECK_EQ(INLINE, type());
     392    18339226 :     return static_cast<int64_t>(value_) >> ValueField::kShift;
     393             :   }
     394             : 
     395             :   int32_t indexed_value() const {
     396             :     DCHECK_EQ(INDEXED, type());
     397    43030462 :     return static_cast<int64_t>(value_) >> ValueField::kShift;
     398             :   }
     399             : 
     400             :   static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
     401             :     return InstructionOperand::New(zone, ImmediateOperand(type, value));
     402             :   }
     403             : 
     404             :   INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
     405             : 
     406             :   STATIC_ASSERT(KindField::kSize == 3);
     407             :   class TypeField : public BitField64<ImmediateType, 3, 1> {};
     408             :   class ValueField : public BitField64<int32_t, 32, 32> {};
     409             : };
     410             : 
     411             : class LocationOperand : public InstructionOperand {
     412             :  public:
     413             :   enum LocationKind { REGISTER, STACK_SLOT };
     414             : 
     415             :   LocationOperand(InstructionOperand::Kind operand_kind,
     416             :                   LocationOperand::LocationKind location_kind,
     417             :                   MachineRepresentation rep, int index)
     418             :       : InstructionOperand(operand_kind) {
     419             :     DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
     420             :     DCHECK(IsSupportedRepresentation(rep));
     421      720583 :     value_ |= LocationKindField::encode(location_kind);
     422   133093013 :     value_ |= RepresentationField::encode(rep);
     423   133114765 :     value_ |= static_cast<int64_t>(index) << IndexField::kShift;
     424             :   }
     425             : 
     426             :   int index() const {
     427             :     DCHECK(IsStackSlot() || IsFPStackSlot());
     428    65883799 :     return static_cast<int64_t>(value_) >> IndexField::kShift;
     429             :   }
     430             : 
     431             :   int register_code() const {
     432             :     DCHECK(IsRegister() || IsFPRegister());
     433   185401381 :     return static_cast<int64_t>(value_) >> IndexField::kShift;
     434             :   }
     435             : 
     436             :   Register GetRegister() const {
     437             :     DCHECK(IsRegister());
     438             :     return Register::from_code(register_code());
     439             :   }
     440             : 
     441             :   FloatRegister GetFloatRegister() const {
     442             :     DCHECK(IsFloatRegister());
     443             :     return FloatRegister::from_code(register_code());
     444             :   }
     445             : 
     446             :   DoubleRegister GetDoubleRegister() const {
     447             :     // On platforms where FloatRegister, DoubleRegister, and Simd128Register
     448             :     // are all the same type, it's convenient to treat everything as a
     449             :     // DoubleRegister, so be lax about type checking here.
     450             :     DCHECK(IsFPRegister());
     451             :     return DoubleRegister::from_code(register_code());
     452             :   }
     453             : 
     454             :   Simd128Register GetSimd128Register() const {
     455             :     DCHECK(IsSimd128Register());
     456             :     return Simd128Register::from_code(register_code());
     457             :   }
     458             : 
     459             :   LocationKind location_kind() const {
     460             :     return LocationKindField::decode(value_);
     461             :   }
     462             : 
     463             :   MachineRepresentation representation() const {
     464       40656 :     return RepresentationField::decode(value_);
     465             :   }
     466             : 
     467             :   static bool IsSupportedRepresentation(MachineRepresentation rep) {
     468             :     switch (rep) {
     469             :       case MachineRepresentation::kWord32:
     470             :       case MachineRepresentation::kWord64:
     471             :       case MachineRepresentation::kFloat32:
     472             :       case MachineRepresentation::kFloat64:
     473             :       case MachineRepresentation::kSimd128:
     474             :       case MachineRepresentation::kTaggedSigned:
     475             :       case MachineRepresentation::kTaggedPointer:
     476             :       case MachineRepresentation::kTagged:
     477             :         return true;
     478             :       case MachineRepresentation::kBit:
     479             :       case MachineRepresentation::kWord8:
     480             :       case MachineRepresentation::kWord16:
     481             :       case MachineRepresentation::kNone:
     482             :         return false;
     483             :     }
     484             :     UNREACHABLE();
     485             :   }
     486             : 
     487             :   // Return true if the locations can be moved to one another.
     488             :   bool IsCompatible(LocationOperand* op);
     489             : 
     490             :   static LocationOperand* cast(InstructionOperand* op) {
     491             :     DCHECK(op->IsAnyLocationOperand());
     492             :     return static_cast<LocationOperand*>(op);
     493             :   }
     494             : 
     495             :   static const LocationOperand* cast(const InstructionOperand* op) {
     496             :     DCHECK(op->IsAnyLocationOperand());
     497             :     return static_cast<const LocationOperand*>(op);
     498             :   }
     499             : 
     500             :   static LocationOperand cast(const InstructionOperand& op) {
     501             :     DCHECK(op.IsAnyLocationOperand());
     502       47008 :     return *static_cast<const LocationOperand*>(&op);
     503             :   }
     504             : 
     505             :   STATIC_ASSERT(KindField::kSize == 3);
     506             :   class LocationKindField : public BitField64<LocationKind, 3, 2> {};
     507             :   class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
     508             :   class IndexField : public BitField64<int32_t, 35, 29> {};
     509             : };
     510             : 
     511             : class V8_EXPORT_PRIVATE ExplicitOperand
     512             :     : public NON_EXPORTED_BASE(LocationOperand) {
     513             :  public:
     514             :   ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
     515             : 
     516             :   static ExplicitOperand* New(Zone* zone, LocationKind kind,
     517             :                               MachineRepresentation rep, int index) {
     518             :     return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
     519             :   }
     520             : 
     521             :   INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT);
     522             : };
     523             : 
     524             : class AllocatedOperand : public LocationOperand {
     525             :  public:
     526             :   AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
     527             :       : LocationOperand(ALLOCATED, kind, rep, index) {}
     528             : 
     529           0 :   static AllocatedOperand* New(Zone* zone, LocationKind kind,
     530             :                                MachineRepresentation rep, int index) {
     531           0 :     return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
     532             :   }
     533             : 
     534       30140 :   INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
     535             : };
     536             : 
     537             : #undef INSTRUCTION_OPERAND_CASTS
     538             : 
     539             : bool InstructionOperand::IsAnyLocationOperand() const {
     540  2388580991 :   return this->kind() >= FIRST_LOCATION_OPERAND_KIND;
     541             : }
     542             : 
     543             : bool InstructionOperand::IsLocationOperand() const {
     544             :   return IsAnyLocationOperand() &&
     545             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     546             : }
     547             : 
     548             : bool InstructionOperand::IsFPLocationOperand() const {
     549             :   return IsAnyLocationOperand() &&
     550             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     551             : }
     552             : 
     553             : bool InstructionOperand::IsAnyRegister() const {
     554  4079498007 :   return IsAnyLocationOperand() &&
     555             :          LocationOperand::cast(this)->location_kind() ==
     556             :              LocationOperand::REGISTER;
     557             : }
     558             : 
     559             : bool InstructionOperand::IsRegister() const {
     560   303386686 :   return IsAnyRegister() &&
     561             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     562             : }
     563             : 
     564             : bool InstructionOperand::IsFPRegister() const {
     565  2505381036 :   return IsAnyRegister() &&
     566             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     567             : }
     568             : 
     569             : bool InstructionOperand::IsFloatRegister() const {
     570      703878 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     571             :                                 MachineRepresentation::kFloat32;
     572             : }
     573             : 
     574             : bool InstructionOperand::IsDoubleRegister() const {
     575      685256 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     576             :                                 MachineRepresentation::kFloat64;
     577             : }
     578             : 
     579             : bool InstructionOperand::IsSimd128Register() const {
     580      699962 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     581             :                                 MachineRepresentation::kSimd128;
     582             : }
     583             : 
     584             : bool InstructionOperand::IsAnyStackSlot() const {
     585   305436629 :   return IsAnyLocationOperand() &&
     586             :          LocationOperand::cast(this)->location_kind() ==
     587             :              LocationOperand::STACK_SLOT;
     588             : }
     589             : 
     590             : bool InstructionOperand::IsStackSlot() const {
     591   228404564 :   return IsAnyStackSlot() &&
     592             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     593             : }
     594             : 
     595             : bool InstructionOperand::IsFPStackSlot() const {
     596    19107402 :   return IsAnyStackSlot() &&
     597             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     598             : }
     599             : 
     600             : bool InstructionOperand::IsFloatStackSlot() const {
     601       17467 :   return IsAnyLocationOperand() &&
     602             :          LocationOperand::cast(this)->location_kind() ==
     603       34934 :              LocationOperand::STACK_SLOT &&
     604             :          LocationOperand::cast(this)->representation() ==
     605             :              MachineRepresentation::kFloat32;
     606             : }
     607             : 
     608             : bool InstructionOperand::IsDoubleStackSlot() const {
     609       12805 :   return IsAnyLocationOperand() &&
     610             :          LocationOperand::cast(this)->location_kind() ==
     611       25610 :              LocationOperand::STACK_SLOT &&
     612             :          LocationOperand::cast(this)->representation() ==
     613             :              MachineRepresentation::kFloat64;
     614             : }
     615             : 
     616             : bool InstructionOperand::IsSimd128StackSlot() const {
     617             :   return IsAnyLocationOperand() &&
     618             :          LocationOperand::cast(this)->location_kind() ==
     619             :              LocationOperand::STACK_SLOT &&
     620             :          LocationOperand::cast(this)->representation() ==
     621             :              MachineRepresentation::kSimd128;
     622             : }
     623             : 
     624  2057140964 : uint64_t InstructionOperand::GetCanonicalizedValue() const {
     625  2057140964 :   if (IsAnyLocationOperand()) {
     626             :     MachineRepresentation canonical = MachineRepresentation::kNone;
     627  1796759180 :     if (IsFPRegister()) {
     628             :       if (kSimpleFPAliasing) {
     629             :         // We treat all FP register operands the same for simple aliasing.
     630             :         canonical = MachineRepresentation::kFloat64;
     631             :       } else {
     632             :         // We need to distinguish FP register operands of different reps when
     633             :         // aliasing is not simple (e.g. ARM).
     634             :         canonical = LocationOperand::cast(this)->representation();
     635             :       }
     636             :     }
     637             :     return InstructionOperand::KindField::update(
     638             :         LocationOperand::RepresentationField::update(this->value_, canonical),
     639  1796759180 :         LocationOperand::EXPLICIT);
     640             :   }
     641             :   return this->value_;
     642             : }
     643             : 
     644             : // Required for maps that don't care about machine type.
     645             : struct CompareOperandModuloType {
     646             :   bool operator()(const InstructionOperand& a,
     647             :                   const InstructionOperand& b) const {
     648             :     return a.CompareCanonicalized(b);
     649             :   }
     650             : };
     651             : 
     652             : class V8_EXPORT_PRIVATE MoveOperands final
     653             :     : public NON_EXPORTED_BASE(ZoneObject) {
     654             :  public:
     655             :   MoveOperands(const InstructionOperand& source,
     656             :                const InstructionOperand& destination)
     657    78838734 :       : source_(source), destination_(destination) {
     658             :     DCHECK(!source.IsInvalid() && !destination.IsInvalid());
     659             :   }
     660             : 
     661             :   const InstructionOperand& source() const { return source_; }
     662             :   InstructionOperand& source() { return source_; }
     663     1318501 :   void set_source(const InstructionOperand& operand) { source_ = operand; }
     664             : 
     665             :   const InstructionOperand& destination() const { return destination_; }
     666             :   InstructionOperand& destination() { return destination_; }
     667             :   void set_destination(const InstructionOperand& operand) {
     668    12020951 :     destination_ = operand;
     669             :   }
     670             : 
     671             :   // The gap resolver marks moves as "in-progress" by clearing the
     672             :   // destination (but not the source).
     673             :   bool IsPending() const {
     674    33160592 :     return destination_.IsInvalid() && !source_.IsInvalid();
     675             :   }
     676    12099999 :   void SetPending() { destination_ = InstructionOperand(); }
     677             : 
     678             :   // A move is redundant if it's been eliminated or if its source and
     679             :   // destination are the same.
     680   286833003 :   bool IsRedundant() const {
     681             :     DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
     682   513495361 :     return IsEliminated() || source_.EqualsCanonicalized(destination_);
     683             :   }
     684             : 
     685             :   // We clear both operands to indicate move that's been eliminated.
     686    46050601 :   void Eliminate() { source_ = destination_ = InstructionOperand(); }
     687             :   bool IsEliminated() const {
     688             :     DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
     689             :     return source_.IsInvalid();
     690             :   }
     691             : 
     692             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     693             :   void Print() const;
     694             : 
     695             :  private:
     696             :   InstructionOperand source_;
     697             :   InstructionOperand destination_;
     698             : 
     699             :   DISALLOW_COPY_AND_ASSIGN(MoveOperands);
     700             : };
     701             : 
     702             : std::ostream& operator<<(std::ostream&, const MoveOperands&);
     703             : 
     704             : class V8_EXPORT_PRIVATE ParallelMove final
     705             :     : public NON_EXPORTED_BASE(ZoneVector<MoveOperands*>),
     706             :       public NON_EXPORTED_BASE(ZoneObject) {
     707             :  public:
     708             :   explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {}
     709             : 
     710             :   MoveOperands* AddMove(const InstructionOperand& from,
     711             :                         const InstructionOperand& to) {
     712             :     Zone* zone = get_allocator().zone();
     713    62980851 :     return AddMove(from, to, zone);
     714             :   }
     715             : 
     716    78133351 :   MoveOperands* AddMove(const InstructionOperand& from,
     717             :                         const InstructionOperand& to,
     718             :                         Zone* operand_allocation_zone) {
     719    78133588 :     if (from.EqualsCanonicalized(to)) return nullptr;
     720    78025848 :     MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to);
     721    78025848 :     if (empty()) reserve(4);
     722    78025781 :     push_back(move);
     723    78025901 :     return move;
     724             :   }
     725             : 
     726             :   bool IsRedundant() const;
     727             : 
     728             :   // Prepare this ParallelMove to insert move as if it happened in a subsequent
     729             :   // ParallelMove.  move->source() may be changed.  Any MoveOperands added to
     730             :   // to_eliminate must be Eliminated.
     731             :   void PrepareInsertAfter(MoveOperands* move,
     732             :                           ZoneVector<MoveOperands*>* to_eliminate) const;
     733             : 
     734             :  private:
     735             :   DISALLOW_COPY_AND_ASSIGN(ParallelMove);
     736             : };
     737             : 
     738             : std::ostream& operator<<(std::ostream&, const ParallelMove&);
     739             : 
     740             : class ReferenceMap final : public ZoneObject {
     741             :  public:
     742             :   explicit ReferenceMap(Zone* zone)
     743     5482753 :       : reference_operands_(8, zone), instruction_position_(-1) {}
     744             : 
     745             :   const ZoneVector<InstructionOperand>& reference_operands() const {
     746             :     return reference_operands_;
     747             :   }
     748             :   int instruction_position() const { return instruction_position_; }
     749             : 
     750             :   void set_instruction_position(int pos) {
     751             :     DCHECK_EQ(-1, instruction_position_);
     752     5359276 :     instruction_position_ = pos;
     753             :   }
     754             : 
     755             :   void RecordReference(const AllocatedOperand& op);
     756             : 
     757             :  private:
     758             :   friend std::ostream& operator<<(std::ostream&, const ReferenceMap&);
     759             : 
     760             :   ZoneVector<InstructionOperand> reference_operands_;
     761             :   int instruction_position_;
     762             : };
     763             : 
     764             : std::ostream& operator<<(std::ostream&, const ReferenceMap&);
     765             : 
     766             : class InstructionBlock;
     767             : 
     768             : class V8_EXPORT_PRIVATE Instruction final {
     769             :  public:
     770             :   size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
     771             :   const InstructionOperand* OutputAt(size_t i) const {
     772             :     DCHECK(i < OutputCount());
     773             :     return &operands_[i];
     774             :   }
     775             :   InstructionOperand* OutputAt(size_t i) {
     776             :     DCHECK(i < OutputCount());
     777             :     return &operands_[i];
     778             :   }
     779             : 
     780    10136212 :   bool HasOutput() const { return OutputCount() > 0; }
     781             :   const InstructionOperand* Output() const { return OutputAt(0); }
     782             :   InstructionOperand* Output() { return OutputAt(0); }
     783             : 
     784             :   size_t InputCount() const { return InputCountField::decode(bit_field_); }
     785       16060 :   const InstructionOperand* InputAt(size_t i) const {
     786             :     DCHECK(i < InputCount());
     787     8925759 :     return &operands_[OutputCount() + i];
     788             :   }
     789   115406008 :   InstructionOperand* InputAt(size_t i) {
     790             :     DCHECK(i < InputCount());
     791   542735593 :     return &operands_[OutputCount() + i];
     792             :   }
     793             : 
     794             :   size_t TempCount() const { return TempCountField::decode(bit_field_); }
     795           0 :   const InstructionOperand* TempAt(size_t i) const {
     796             :     DCHECK(i < TempCount());
     797           0 :     return &operands_[OutputCount() + InputCount() + i];
     798             :   }
     799       54490 :   InstructionOperand* TempAt(size_t i) {
     800             :     DCHECK(i < TempCount());
     801     3660734 :     return &operands_[OutputCount() + InputCount() + i];
     802             :   }
     803             : 
     804             :   InstructionCode opcode() const { return opcode_; }
     805   255242387 :   ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
     806     1297858 :   AddressingMode addressing_mode() const {
     807     1297858 :     return AddressingModeField::decode(opcode());
     808             :   }
     809           4 :   FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
     810             :   FlagsCondition flags_condition() const {
     811             :     return FlagsConditionField::decode(opcode());
     812             :   }
     813             : 
     814     2950456 :   static Instruction* New(Zone* zone, InstructionCode opcode) {
     815     2950456 :     return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
     816             :   }
     817             : 
     818    64866570 :   static Instruction* New(Zone* zone, InstructionCode opcode,
     819             :                           size_t output_count, InstructionOperand* outputs,
     820             :                           size_t input_count, InstructionOperand* inputs,
     821             :                           size_t temp_count, InstructionOperand* temps) {
     822             :     DCHECK_LE(0, opcode);
     823             :     DCHECK(output_count == 0 || outputs != nullptr);
     824             :     DCHECK(input_count == 0 || inputs != nullptr);
     825             :     DCHECK(temp_count == 0 || temps != nullptr);
     826             :     // TODO(jarin/mstarzinger): Handle this gracefully. See crbug.com/582702.
     827    64866570 :     CHECK(InputCountField::is_valid(input_count));
     828             : 
     829    64866570 :     size_t total_extra_ops = output_count + input_count + temp_count;
     830    64866570 :     if (total_extra_ops != 0) total_extra_ops--;
     831             :     int size = static_cast<int>(
     832             :         RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
     833    64866570 :         total_extra_ops * sizeof(InstructionOperand));
     834    64866570 :     return new (zone->New(size)) Instruction(
     835    64866570 :         opcode, output_count, outputs, input_count, inputs, temp_count, temps);
     836             :   }
     837             : 
     838             :   Instruction* MarkAsCall() {
     839    10718512 :     bit_field_ = IsCallField::update(bit_field_, true);
     840             :     return this;
     841             :   }
     842             :   bool IsCall() const { return IsCallField::decode(bit_field_); }
     843    64867232 :   bool NeedsReferenceMap() const { return IsCall(); }
     844             :   bool HasReferenceMap() const { return reference_map_ != nullptr; }
     845             : 
     846             :   bool ClobbersRegisters() const { return IsCall(); }
     847             :   bool ClobbersTemps() const { return IsCall(); }
     848    64856736 :   bool ClobbersDoubleRegisters() const { return IsCall(); }
     849             :   ReferenceMap* reference_map() const { return reference_map_; }
     850             : 
     851             :   void set_reference_map(ReferenceMap* map) {
     852             :     DCHECK(NeedsReferenceMap());
     853             :     DCHECK(!reference_map_);
     854     5359276 :     reference_map_ = map;
     855             :   }
     856             : 
     857             :   void OverwriteWithNop() {
     858     3892547 :     opcode_ = ArchOpcodeField::encode(kArchNop);
     859     3892547 :     bit_field_ = 0;
     860     3892547 :     reference_map_ = nullptr;
     861             :   }
     862             : 
     863             :   bool IsNop() const { return arch_opcode() == kArchNop; }
     864             : 
     865             :   bool IsDeoptimizeCall() const {
     866    32771518 :     return arch_opcode() == ArchOpcode::kArchDeoptimize ||
     867    65471239 :            FlagsModeField::decode(opcode()) == kFlags_deoptimize ||
     868             :            FlagsModeField::decode(opcode()) == kFlags_deoptimize_and_poison;
     869             :   }
     870             : 
     871             :   bool IsTrap() const {
     872             :     return FlagsModeField::decode(opcode()) == kFlags_trap;
     873             :   }
     874             : 
     875             :   bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
     876             :   bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
     877             :   bool IsTailCall() const {
     878    92063313 :     return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
     879    92059208 :            arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
     880   184042050 :            arch_opcode() == ArchOpcode::kArchTailCallAddress ||
     881             :            arch_opcode() == ArchOpcode::kArchTailCallWasm;
     882             :   }
     883             :   bool IsThrow() const {
     884             :     return arch_opcode() == ArchOpcode::kArchThrowTerminator;
     885             :   }
     886             : 
     887             :   enum GapPosition {
     888             :     START,
     889             :     END,
     890             :     FIRST_GAP_POSITION = START,
     891             :     LAST_GAP_POSITION = END
     892             :   };
     893             : 
     894    71080682 :   ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
     895    71080682 :     if (parallel_moves_[pos] == nullptr) {
     896    46028125 :       parallel_moves_[pos] = new (zone) ParallelMove(zone);
     897             :     }
     898    71080616 :     return parallel_moves_[pos];
     899             :   }
     900             : 
     901             :   ParallelMove* GetParallelMove(GapPosition pos) {
     902   259645976 :     return parallel_moves_[pos];
     903             :   }
     904             : 
     905             :   const ParallelMove* GetParallelMove(GapPosition pos) const {
     906     7934126 :     return parallel_moves_[pos];
     907             :   }
     908             : 
     909             :   bool AreMovesRedundant() const;
     910             : 
     911             :   ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
     912             :   ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
     913             : 
     914             :   // The block_id may be invalidated in JumpThreading. It is only important for
     915             :   // register allocation, to avoid searching for blocks from instruction
     916             :   // indexes.
     917             :   InstructionBlock* block() const { return block_; }
     918             :   void set_block(InstructionBlock* block) {
     919             :     DCHECK_NOT_NULL(block);
     920    64867092 :     block_ = block;
     921             :   }
     922             : 
     923             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     924             :   void Print() const;
     925             : 
     926             :   typedef BitField<size_t, 0, 8> OutputCountField;
     927             :   typedef BitField<size_t, 8, 16> InputCountField;
     928             :   typedef BitField<size_t, 24, 6> TempCountField;
     929             : 
     930             :   static const size_t kMaxOutputCount = OutputCountField::kMax;
     931             :   static const size_t kMaxInputCount = InputCountField::kMax;
     932             :   static const size_t kMaxTempCount = TempCountField::kMax;
     933             : 
     934             :  private:
     935             :   explicit Instruction(InstructionCode opcode);
     936             : 
     937             :   Instruction(InstructionCode opcode, size_t output_count,
     938             :               InstructionOperand* outputs, size_t input_count,
     939             :               InstructionOperand* inputs, size_t temp_count,
     940             :               InstructionOperand* temps);
     941             : 
     942             :   typedef BitField<bool, 30, 1> IsCallField;
     943             : 
     944             :   InstructionCode opcode_;
     945             :   uint32_t bit_field_;
     946             :   ParallelMove* parallel_moves_[2];
     947             :   ReferenceMap* reference_map_;
     948             :   InstructionBlock* block_;
     949             :   InstructionOperand operands_[1];
     950             : 
     951             :   DISALLOW_COPY_AND_ASSIGN(Instruction);
     952             : };
     953             : 
     954             : std::ostream& operator<<(std::ostream&, const Instruction&);
     955             : 
     956             : class RpoNumber final {
     957             :  public:
     958             :   static const int kInvalidRpoNumber = -1;
     959             :   int ToInt() const {
     960             :     DCHECK(IsValid());
     961    78332131 :     return index_;
     962             :   }
     963             :   size_t ToSize() const {
     964             :     DCHECK(IsValid());
     965   653457984 :     return static_cast<size_t>(index_);
     966             :   }
     967    46511931 :   bool IsValid() const { return index_ >= 0; }
     968             :   static RpoNumber FromInt(int index) { return RpoNumber(index); }
     969             :   static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
     970             : 
     971             :   bool IsNext(const RpoNumber other) const {
     972             :     DCHECK(IsValid());
     973    30472725 :     return other.index_ == this->index_ + 1;
     974             :   }
     975             : 
     976             :   // Comparison operators.
     977  1065870718 :   bool operator==(RpoNumber other) const { return index_ == other.index_; }
     978             :   bool operator!=(RpoNumber other) const { return index_ != other.index_; }
     979             :   bool operator>(RpoNumber other) const { return index_ > other.index_; }
     980     2733788 :   bool operator<(RpoNumber other) const { return index_ < other.index_; }
     981    23458876 :   bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
     982           2 :   bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
     983             : 
     984             :  private:
     985             :   explicit RpoNumber(int32_t index) : index_(index) {}
     986             :   int32_t index_;
     987             : };
     988             : 
     989             : std::ostream& operator<<(std::ostream&, const RpoNumber&);
     990             : 
     991             : class V8_EXPORT_PRIVATE Constant final {
     992             :  public:
     993             :   enum Type {
     994             :     kInt32,
     995             :     kInt64,
     996             :     kFloat32,
     997             :     kFloat64,
     998             :     kExternalReference,
     999             :     kHeapObject,
    1000             :     kRpoNumber,
    1001             :     kDelayedStringConstant
    1002             :   };
    1003             : 
    1004             :   explicit Constant(int32_t v);
    1005             :   explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
    1006       13115 :   explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
    1007             :   explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
    1008             :   explicit Constant(ExternalReference ref)
    1009             :       : type_(kExternalReference), value_(bit_cast<intptr_t>(ref.address())) {}
    1010             :   explicit Constant(Handle<HeapObject> obj)
    1011             :       : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
    1012    24582747 :   explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
    1013             :   explicit Constant(const StringConstantBase* str)
    1014             :       : type_(kDelayedStringConstant), value_(bit_cast<intptr_t>(str)) {}
    1015             :   explicit Constant(RelocatablePtrConstantInfo info);
    1016             : 
    1017             :   Type type() const { return type_; }
    1018             : 
    1019             :   RelocInfo::Mode rmode() const { return rmode_; }
    1020             : 
    1021             :   int32_t ToInt32() const {
    1022             :     DCHECK(type() == kInt32 || type() == kInt64);
    1023    52808414 :     const int32_t value = static_cast<int32_t>(value_);
    1024             :     DCHECK_EQ(value_, static_cast<int64_t>(value));
    1025             :     return value;
    1026             :   }
    1027             : 
    1028       94929 :   int64_t ToInt64() const {
    1029     2778832 :     if (type() == kInt32) return ToInt32();
    1030             :     DCHECK_EQ(kInt64, type());
    1031     2670262 :     return value_;
    1032             :   }
    1033             : 
    1034             :   float ToFloat32() const {
    1035             :     // TODO(ahaas): We should remove this function. If value_ has the bit
    1036             :     // representation of a signalling NaN, then returning it as float can cause
    1037             :     // the signalling bit to flip, and value_ is returned as a quiet NaN.
    1038             :     DCHECK_EQ(kFloat32, type());
    1039       20854 :     return bit_cast<float>(static_cast<int32_t>(value_));
    1040             :   }
    1041             : 
    1042             :   uint32_t ToFloat32AsInt() const {
    1043             :     DCHECK_EQ(kFloat32, type());
    1044             :     return bit_cast<uint32_t>(static_cast<int32_t>(value_));
    1045             :   }
    1046             : 
    1047             :   Double ToFloat64() const {
    1048             :     DCHECK_EQ(kFloat64, type());
    1049           6 :     return Double(bit_cast<uint64_t>(value_));
    1050             :   }
    1051             : 
    1052             :   ExternalReference ToExternalReference() const {
    1053             :     DCHECK_EQ(kExternalReference, type());
    1054     2563613 :     return ExternalReference::FromRawAddress(static_cast<Address>(value_));
    1055             :   }
    1056             : 
    1057             :   RpoNumber ToRpoNumber() const {
    1058             :     DCHECK_EQ(kRpoNumber, type());
    1059    42045926 :     return RpoNumber::FromInt(static_cast<int>(value_));
    1060             :   }
    1061             : 
    1062             :   Handle<HeapObject> ToHeapObject() const;
    1063             :   Handle<Code> ToCode() const;
    1064             :   const StringConstantBase* ToDelayedStringConstant() const;
    1065             : 
    1066             :  private:
    1067             :   Type type_;
    1068             :   RelocInfo::Mode rmode_ = RelocInfo::NONE;
    1069             :   int64_t value_;
    1070             : };
    1071             : 
    1072             : std::ostream& operator<<(std::ostream&, const Constant&);
    1073             : 
    1074             : // Forward declarations.
    1075             : class FrameStateDescriptor;
    1076             : 
    1077             : enum class StateValueKind : uint8_t {
    1078             :   kArgumentsElements,
    1079             :   kArgumentsLength,
    1080             :   kPlain,
    1081             :   kOptimizedOut,
    1082             :   kNested,
    1083             :   kDuplicate
    1084             : };
    1085             : 
    1086             : class StateValueDescriptor {
    1087             :  public:
    1088             :   StateValueDescriptor()
    1089             :       : kind_(StateValueKind::kPlain), type_(MachineType::AnyTagged()) {}
    1090             : 
    1091             :   static StateValueDescriptor ArgumentsElements(ArgumentsStateType type) {
    1092             :     StateValueDescriptor descr(StateValueKind::kArgumentsElements,
    1093             :                                MachineType::AnyTagged());
    1094             :     descr.args_type_ = type;
    1095             :     return descr;
    1096             :   }
    1097             :   static StateValueDescriptor ArgumentsLength(ArgumentsStateType type) {
    1098             :     StateValueDescriptor descr(StateValueKind::kArgumentsLength,
    1099             :                                MachineType::AnyTagged());
    1100             :     descr.args_type_ = type;
    1101             :     return descr;
    1102             :   }
    1103             :   static StateValueDescriptor Plain(MachineType type) {
    1104             :     return StateValueDescriptor(StateValueKind::kPlain, type);
    1105             :   }
    1106             :   static StateValueDescriptor OptimizedOut() {
    1107             :     return StateValueDescriptor(StateValueKind::kOptimizedOut,
    1108             :                                 MachineType::AnyTagged());
    1109             :   }
    1110             :   static StateValueDescriptor Recursive(size_t id) {
    1111             :     StateValueDescriptor descr(StateValueKind::kNested,
    1112             :                                MachineType::AnyTagged());
    1113             :     descr.id_ = id;
    1114             :     return descr;
    1115             :   }
    1116             :   static StateValueDescriptor Duplicate(size_t id) {
    1117             :     StateValueDescriptor descr(StateValueKind::kDuplicate,
    1118             :                                MachineType::AnyTagged());
    1119             :     descr.id_ = id;
    1120             :     return descr;
    1121             :   }
    1122             : 
    1123             :   bool IsArgumentsElements() const {
    1124             :     return kind_ == StateValueKind::kArgumentsElements;
    1125             :   }
    1126             :   bool IsArgumentsLength() const {
    1127             :     return kind_ == StateValueKind::kArgumentsLength;
    1128             :   }
    1129             :   bool IsPlain() const { return kind_ == StateValueKind::kPlain; }
    1130             :   bool IsOptimizedOut() const { return kind_ == StateValueKind::kOptimizedOut; }
    1131             :   bool IsNested() const { return kind_ == StateValueKind::kNested; }
    1132             :   bool IsDuplicate() const { return kind_ == StateValueKind::kDuplicate; }
    1133             :   MachineType type() const { return type_; }
    1134             :   size_t id() const {
    1135             :     DCHECK(kind_ == StateValueKind::kDuplicate ||
    1136             :            kind_ == StateValueKind::kNested);
    1137             :     return id_;
    1138             :   }
    1139             :   ArgumentsStateType arguments_type() const {
    1140             :     DCHECK(kind_ == StateValueKind::kArgumentsElements ||
    1141             :            kind_ == StateValueKind::kArgumentsLength);
    1142             :     return args_type_;
    1143             :   }
    1144             : 
    1145             :  private:
    1146             :   StateValueDescriptor(StateValueKind kind, MachineType type)
    1147             :       : kind_(kind), type_(type) {}
    1148             : 
    1149             :   StateValueKind kind_;
    1150             :   MachineType type_;
    1151             :   union {
    1152             :     size_t id_;
    1153             :     ArgumentsStateType args_type_;
    1154             :   };
    1155             : };
    1156             : 
    1157             : class StateValueList {
    1158             :  public:
    1159             :   explicit StateValueList(Zone* zone) : fields_(zone), nested_(zone) {}
    1160             : 
    1161       92285 :   size_t size() { return fields_.size(); }
    1162             : 
    1163             :   struct Value {
    1164             :     StateValueDescriptor* desc;
    1165             :     StateValueList* nested;
    1166             : 
    1167             :     Value(StateValueDescriptor* desc, StateValueList* nested)
    1168             :         : desc(desc), nested(nested) {}
    1169             :   };
    1170             : 
    1171             :   class iterator {
    1172             :    public:
    1173             :     // Bare minimum of operators needed for range iteration.
    1174             :     bool operator!=(const iterator& other) const {
    1175             :       return field_iterator != other.field_iterator;
    1176             :     }
    1177             :     bool operator==(const iterator& other) const {
    1178             :       return field_iterator == other.field_iterator;
    1179             :     }
    1180             :     iterator& operator++() {
    1181    42352170 :       if (field_iterator->IsNested()) {
    1182             :         nested_iterator++;
    1183             :       }
    1184             :       ++field_iterator;
    1185             :       return *this;
    1186             :     }
    1187             :     Value operator*() {
    1188    42352466 :       StateValueDescriptor* desc = &(*field_iterator);
    1189    42352466 :       StateValueList* nested = desc->IsNested() ? *nested_iterator : nullptr;
    1190             :       return Value(desc, nested);
    1191             :     }
    1192             : 
    1193             :    private:
    1194             :     friend class StateValueList;
    1195             : 
    1196             :     iterator(ZoneVector<StateValueDescriptor>::iterator it,
    1197             :              ZoneVector<StateValueList*>::iterator nested)
    1198             :         : field_iterator(it), nested_iterator(nested) {}
    1199             : 
    1200             :     ZoneVector<StateValueDescriptor>::iterator field_iterator;
    1201             :     ZoneVector<StateValueList*>::iterator nested_iterator;
    1202             :   };
    1203             : 
    1204     3357994 :   void ReserveSize(size_t size) { fields_.reserve(size); }
    1205             : 
    1206       92285 :   StateValueList* PushRecursiveField(Zone* zone, size_t id) {
    1207      184570 :     fields_.push_back(StateValueDescriptor::Recursive(id));
    1208             :     StateValueList* nested =
    1209      184570 :         new (zone->New(sizeof(StateValueList))) StateValueList(zone);
    1210       92285 :     nested_.push_back(nested);
    1211       92285 :     return nested;
    1212             :   }
    1213        6054 :   void PushArgumentsElements(ArgumentsStateType type) {
    1214       12108 :     fields_.push_back(StateValueDescriptor::ArgumentsElements(type));
    1215        6054 :   }
    1216        6336 :   void PushArgumentsLength(ArgumentsStateType type) {
    1217       12672 :     fields_.push_back(StateValueDescriptor::ArgumentsLength(type));
    1218        6336 :   }
    1219       22811 :   void PushDuplicate(size_t id) {
    1220       45622 :     fields_.push_back(StateValueDescriptor::Duplicate(id));
    1221       22811 :   }
    1222    20999549 :   void PushPlain(MachineType type) {
    1223    41999276 :     fields_.push_back(StateValueDescriptor::Plain(type));
    1224    20999727 :   }
    1225    21815927 :   void PushOptimizedOut() {
    1226    43631894 :     fields_.push_back(StateValueDescriptor::OptimizedOut());
    1227    21815967 :   }
    1228             : 
    1229             :   iterator begin() { return iterator(fields_.begin(), nested_.begin()); }
    1230             :   iterator end() { return iterator(fields_.end(), nested_.end()); }
    1231             : 
    1232             :  private:
    1233             :   ZoneVector<StateValueDescriptor> fields_;
    1234             :   ZoneVector<StateValueList*> nested_;
    1235             : };
    1236             : 
    1237             : class FrameStateDescriptor : public ZoneObject {
    1238             :  public:
    1239             :   FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
    1240             :                        OutputFrameStateCombine state_combine,
    1241             :                        size_t parameters_count, size_t locals_count,
    1242             :                        size_t stack_count,
    1243             :                        MaybeHandle<SharedFunctionInfo> shared_info,
    1244             :                        FrameStateDescriptor* outer_state = nullptr);
    1245             : 
    1246             :   FrameStateType type() const { return type_; }
    1247             :   BailoutId bailout_id() const { return bailout_id_; }
    1248             :   OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
    1249             :   size_t parameters_count() const { return parameters_count_; }
    1250             :   size_t locals_count() const { return locals_count_; }
    1251             :   size_t stack_count() const { return stack_count_; }
    1252             :   MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
    1253             :   FrameStateDescriptor* outer_state() const { return outer_state_; }
    1254             :   bool HasContext() const {
    1255      246333 :     return FrameStateFunctionInfo::IsJSFunctionType(type_) ||
    1256     9693877 :            type_ == FrameStateType::kBuiltinContinuation ||
    1257             :            type_ == FrameStateType::kConstructStub;
    1258             :   }
    1259             : 
    1260             :   size_t GetSize() const;
    1261             :   size_t GetTotalSize() const;
    1262             :   size_t GetFrameCount() const;
    1263             :   size_t GetJSFrameCount() const;
    1264             : 
    1265             :   StateValueList* GetStateValueDescriptors() { return &values_; }
    1266             : 
    1267             :   static const int kImpossibleValue = 0xdead;
    1268             : 
    1269             :  private:
    1270             :   FrameStateType type_;
    1271             :   BailoutId bailout_id_;
    1272             :   OutputFrameStateCombine frame_state_combine_;
    1273             :   size_t parameters_count_;
    1274             :   size_t locals_count_;
    1275             :   size_t stack_count_;
    1276             :   StateValueList values_;
    1277             :   MaybeHandle<SharedFunctionInfo> const shared_info_;
    1278             :   FrameStateDescriptor* outer_state_;
    1279             : };
    1280             : 
    1281             : // A deoptimization entry is a pair of the reason why we deoptimize and the
    1282             : // frame state descriptor that we have to go back to.
    1283             : class DeoptimizationEntry final {
    1284             :  public:
    1285             :   DeoptimizationEntry() = default;
    1286             :   DeoptimizationEntry(FrameStateDescriptor* descriptor, DeoptimizeKind kind,
    1287             :                       DeoptimizeReason reason, VectorSlotPair const& feedback)
    1288             :       : descriptor_(descriptor),
    1289             :         kind_(kind),
    1290             :         reason_(reason),
    1291     2998789 :         feedback_(feedback) {}
    1292             : 
    1293             :   FrameStateDescriptor* descriptor() const { return descriptor_; }
    1294             :   DeoptimizeKind kind() const { return kind_; }
    1295             :   DeoptimizeReason reason() const { return reason_; }
    1296             :   VectorSlotPair const& feedback() const { return feedback_; }
    1297             : 
    1298             :  private:
    1299             :   FrameStateDescriptor* descriptor_ = nullptr;
    1300             :   DeoptimizeKind kind_ = DeoptimizeKind::kEager;
    1301             :   DeoptimizeReason reason_ = DeoptimizeReason::kUnknown;
    1302             :   VectorSlotPair feedback_ = VectorSlotPair();
    1303             : };
    1304             : 
    1305             : typedef ZoneVector<DeoptimizationEntry> DeoptimizationVector;
    1306             : 
    1307             : class V8_EXPORT_PRIVATE PhiInstruction final
    1308             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1309             :  public:
    1310             :   typedef ZoneVector<InstructionOperand> Inputs;
    1311             : 
    1312             :   PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
    1313             : 
    1314             :   void SetInput(size_t offset, int virtual_register);
    1315             :   void RenameInput(size_t offset, int virtual_register);
    1316             : 
    1317             :   int virtual_register() const { return virtual_register_; }
    1318             :   const IntVector& operands() const { return operands_; }
    1319             : 
    1320             :   // TODO(dcarney): this has no real business being here, since it's internal to
    1321             :   // the register allocator, but putting it here was convenient.
    1322             :   const InstructionOperand& output() const { return output_; }
    1323             :   InstructionOperand& output() { return output_; }
    1324             : 
    1325             :  private:
    1326             :   const int virtual_register_;
    1327             :   InstructionOperand output_;
    1328             :   IntVector operands_;
    1329             : };
    1330             : 
    1331             : // Analogue of BasicBlock for Instructions instead of Nodes.
    1332             : class V8_EXPORT_PRIVATE InstructionBlock final
    1333             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1334             :  public:
    1335             :   InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
    1336             :                    RpoNumber loop_end, bool deferred, bool handler);
    1337             : 
    1338             :   // Instruction indexes (used by the register allocator).
    1339             :   int first_instruction_index() const {
    1340             :     DCHECK_LE(0, code_start_);
    1341             :     DCHECK_LT(0, code_end_);
    1342             :     DCHECK_GE(code_end_, code_start_);
    1343             :     return code_start_;
    1344             :   }
    1345             :   int last_instruction_index() const {
    1346             :     DCHECK_LE(0, code_start_);
    1347             :     DCHECK_LT(0, code_end_);
    1348             :     DCHECK_GE(code_end_, code_start_);
    1349   271698847 :     return code_end_ - 1;
    1350             :   }
    1351             : 
    1352             :   int32_t code_start() const { return code_start_; }
    1353    41178738 :   void set_code_start(int32_t start) { code_start_ = start; }
    1354             : 
    1355             :   int32_t code_end() const { return code_end_; }
    1356    41178999 :   void set_code_end(int32_t end) { code_end_ = end; }
    1357             : 
    1358             :   bool IsDeferred() const { return deferred_; }
    1359             :   bool IsHandler() const { return handler_; }
    1360             : 
    1361             :   RpoNumber ao_number() const { return ao_number_; }
    1362             :   RpoNumber rpo_number() const { return rpo_number_; }
    1363             :   RpoNumber loop_header() const { return loop_header_; }
    1364             :   RpoNumber loop_end() const {
    1365             :     DCHECK(IsLoopHeader());
    1366             :     return loop_end_;
    1367             :   }
    1368             :   inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
    1369             :   inline bool IsSwitchTarget() const { return switch_target_; }
    1370             :   inline bool ShouldAlign() const { return alignment_; }
    1371             : 
    1372             :   typedef ZoneVector<RpoNumber> Predecessors;
    1373             :   Predecessors& predecessors() { return predecessors_; }
    1374             :   const Predecessors& predecessors() const { return predecessors_; }
    1375    90560110 :   size_t PredecessorCount() const { return predecessors_.size(); }
    1376             :   size_t PredecessorIndexOf(RpoNumber rpo_number) const;
    1377             : 
    1378             :   typedef ZoneVector<RpoNumber> Successors;
    1379             :   Successors& successors() { return successors_; }
    1380             :   const Successors& successors() const { return successors_; }
    1381    10783618 :   size_t SuccessorCount() const { return successors_.size(); }
    1382             : 
    1383             :   typedef ZoneVector<PhiInstruction*> PhiInstructions;
    1384             :   const PhiInstructions& phis() const { return phis_; }
    1385     2169738 :   PhiInstruction* PhiAt(size_t i) const { return phis_[i]; }
    1386     2169814 :   void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
    1387             : 
    1388    36245835 :   void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
    1389             : 
    1390      500432 :   void set_alignment(bool val) { alignment_ = val; }
    1391             : 
    1392      482548 :   void set_switch_target(bool val) { switch_target_ = val; }
    1393             : 
    1394             :   bool needs_frame() const { return needs_frame_; }
    1395    20073180 :   void mark_needs_frame() { needs_frame_ = true; }
    1396             : 
    1397             :   bool must_construct_frame() const { return must_construct_frame_; }
    1398     2961187 :   void mark_must_construct_frame() { must_construct_frame_ = true; }
    1399             : 
    1400             :   bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
    1401     3268425 :   void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
    1402             : 
    1403             :  private:
    1404             :   Successors successors_;
    1405             :   Predecessors predecessors_;
    1406             :   PhiInstructions phis_;
    1407             :   RpoNumber ao_number_;  // Assembly order number.
    1408             :   const RpoNumber rpo_number_;
    1409             :   const RpoNumber loop_header_;
    1410             :   const RpoNumber loop_end_;
    1411             :   int32_t code_start_;   // start index of arch-specific code.
    1412             :   int32_t code_end_ = -1;     // end index of arch-specific code.
    1413             :   const bool deferred_ = -1;  // Block contains deferred code.
    1414             :   const bool handler_;   // Block is a handler entry point.
    1415             :   bool switch_target_ = false;
    1416             :   bool alignment_ = false;  // insert alignment before this block
    1417             :   bool needs_frame_ = false;
    1418             :   bool must_construct_frame_ = false;
    1419             :   bool must_deconstruct_frame_ = false;
    1420             : };
    1421             : 
    1422             : class InstructionSequence;
    1423             : 
    1424             : struct PrintableInstructionBlock {
    1425             :   const InstructionBlock* block_;
    1426             :   const InstructionSequence* code_;
    1427             : };
    1428             : 
    1429             : std::ostream& operator<<(std::ostream&, const PrintableInstructionBlock&);
    1430             : 
    1431             : typedef ZoneDeque<Constant> ConstantDeque;
    1432             : typedef std::map<int, Constant, std::less<int>,
    1433             :                  ZoneAllocator<std::pair<const int, Constant> > >
    1434             :     ConstantMap;
    1435             : 
    1436             : typedef ZoneDeque<Instruction*> InstructionDeque;
    1437             : typedef ZoneDeque<ReferenceMap*> ReferenceMapDeque;
    1438             : typedef ZoneVector<InstructionBlock*> InstructionBlocks;
    1439             : 
    1440             : // Represents architecture-specific generated code before, during, and after
    1441             : // register allocation.
    1442        2920 : class V8_EXPORT_PRIVATE InstructionSequence final
    1443             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1444             :  public:
    1445             :   static InstructionBlocks* InstructionBlocksFor(Zone* zone,
    1446             :                                                  const Schedule* schedule);
    1447             :   InstructionSequence(Isolate* isolate, Zone* zone,
    1448             :                       InstructionBlocks* instruction_blocks);
    1449             : 
    1450             :   int NextVirtualRegister();
    1451             :   int VirtualRegisterCount() const { return next_virtual_register_; }
    1452             : 
    1453             :   const InstructionBlocks& instruction_blocks() const {
    1454             :     return *instruction_blocks_;
    1455             :   }
    1456             : 
    1457             :   const InstructionBlocks& ao_blocks() const { return *ao_blocks_; }
    1458             : 
    1459             :   int InstructionBlockCount() const {
    1460    96267424 :     return static_cast<int>(instruction_blocks_->size());
    1461             :   }
    1462             : 
    1463   393356425 :   InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
    1464   786712850 :     return instruction_blocks_->at(rpo_number.ToSize());
    1465             :   }
    1466             : 
    1467      243403 :   int LastLoopInstructionIndex(const InstructionBlock* block) {
    1468      243403 :     return instruction_blocks_->at(block->loop_end().ToSize() - 1)
    1469      486806 :         ->last_instruction_index();
    1470             :   }
    1471             : 
    1472   181163676 :   const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
    1473   362327352 :     return instruction_blocks_->at(rpo_number.ToSize());
    1474             :   }
    1475             : 
    1476             :   InstructionBlock* GetInstructionBlock(int instruction_index) const;
    1477             : 
    1478             :   static MachineRepresentation DefaultRepresentation() {
    1479             :     return MachineType::PointerRepresentation();
    1480             :   }
    1481             :   MachineRepresentation GetRepresentation(int virtual_register) const;
    1482             :   void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
    1483             : 
    1484             :   bool IsReference(int virtual_register) const {
    1485    74296792 :     return CanBeTaggedPointer(GetRepresentation(virtual_register));
    1486             :   }
    1487             :   bool IsFP(int virtual_register) const {
    1488     2858310 :     return IsFloatingPoint(GetRepresentation(virtual_register));
    1489             :   }
    1490             :   int representation_mask() const { return representation_mask_; }
    1491     2949697 :   bool HasFPVirtualRegisters() const {
    1492             :     constexpr int kFPRepMask =
    1493             :         RepresentationBit(MachineRepresentation::kFloat32) |
    1494             :         RepresentationBit(MachineRepresentation::kFloat64) |
    1495             :         RepresentationBit(MachineRepresentation::kSimd128);
    1496     2949697 :     return (representation_mask() & kFPRepMask) != 0;
    1497             :   }
    1498             : 
    1499             :   Instruction* GetBlockStart(RpoNumber rpo) const;
    1500             : 
    1501             :   typedef InstructionDeque::const_iterator const_iterator;
    1502             :   const_iterator begin() const { return instructions_.begin(); }
    1503             :   const_iterator end() const { return instructions_.end(); }
    1504             :   const InstructionDeque& instructions() const { return instructions_; }
    1505             :   int LastInstructionIndex() const {
    1506           2 :     return static_cast<int>(instructions().size()) - 1;
    1507             :   }
    1508             : 
    1509             :   Instruction* InstructionAt(int index) const {
    1510             :     DCHECK_LE(0, index);
    1511             :     DCHECK_GT(instructions_.size(), index);
    1512   488690956 :     return instructions_[index];
    1513             :   }
    1514             : 
    1515             :   Isolate* isolate() const { return isolate_; }
    1516             :   const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
    1517             :   Zone* zone() const { return zone_; }
    1518             : 
    1519             :   // Used by the instruction selector while adding instructions.
    1520             :   int AddInstruction(Instruction* instr);
    1521             :   void StartBlock(RpoNumber rpo);
    1522             :   void EndBlock(RpoNumber rpo);
    1523             : 
    1524             :   int AddConstant(int virtual_register, Constant constant) {
    1525             :     // TODO(titzer): allow RPO numbers as constants?
    1526             :     DCHECK_NE(Constant::kRpoNumber, constant.type());
    1527             :     DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
    1528             :     DCHECK(constants_.find(virtual_register) == constants_.end());
    1529    13502486 :     constants_.insert(std::make_pair(virtual_register, constant));
    1530             :     return virtual_register;
    1531             :   }
    1532             :   Constant GetConstant(int virtual_register) const {
    1533             :     ConstantMap::const_iterator it = constants_.find(virtual_register);
    1534             :     DCHECK(it != constants_.end());
    1535             :     DCHECK_EQ(virtual_register, it->first);
    1536    18620527 :     return it->second;
    1537             :   }
    1538             : 
    1539             :   typedef ZoneVector<Constant> Immediates;
    1540             :   Immediates& immediates() { return immediates_; }
    1541             : 
    1542    99534746 :   ImmediateOperand AddImmediate(const Constant& constant) {
    1543    79978698 :     if (constant.type() == Constant::kInt32 &&
    1544             :         RelocInfo::IsNone(constant.rmode())) {
    1545    19556048 :       return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
    1546             :     }
    1547    81733184 :     int index = static_cast<int>(immediates_.size());
    1548    40866592 :     immediates_.push_back(constant);
    1549    40866775 :     return ImmediateOperand(ImmediateOperand::INDEXED, index);
    1550             :   }
    1551             : 
    1552    61368745 :   Constant GetImmediate(const ImmediateOperand* op) const {
    1553    61368745 :     switch (op->type()) {
    1554             :       case ImmediateOperand::INLINE:
    1555    18338790 :         return Constant(op->inline_value());
    1556             :       case ImmediateOperand::INDEXED: {
    1557             :         int index = op->indexed_value();
    1558             :         DCHECK_LE(0, index);
    1559             :         DCHECK_GT(immediates_.size(), index);
    1560    86059910 :         return immediates_[index];
    1561             :       }
    1562             :     }
    1563           0 :     UNREACHABLE();
    1564             :   }
    1565             : 
    1566             :   int AddDeoptimizationEntry(FrameStateDescriptor* descriptor,
    1567             :                              DeoptimizeKind kind, DeoptimizeReason reason,
    1568             :                              VectorSlotPair const& feedback);
    1569             :   DeoptimizationEntry const& GetDeoptimizationEntry(int deoptimization_id);
    1570             :   int GetDeoptimizationEntryCount() const {
    1571         506 :     return static_cast<int>(deoptimization_entries_.size());
    1572             :   }
    1573             : 
    1574             :   RpoNumber InputRpo(Instruction* instr, size_t index);
    1575             : 
    1576             :   bool GetSourcePosition(const Instruction* instr,
    1577             :                          SourcePosition* result) const;
    1578             :   void SetSourcePosition(const Instruction* instr, SourcePosition value);
    1579             : 
    1580             :   bool ContainsCall() const {
    1581             :     for (Instruction* instr : instructions_) {
    1582             :       if (instr->IsCall()) return true;
    1583             :     }
    1584             :     return false;
    1585             :   }
    1586             : 
    1587             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
    1588             :   void Print() const;
    1589             : 
    1590             :   void PrintBlock(int block_id) const;
    1591             : 
    1592             :   void ValidateEdgeSplitForm() const;
    1593             :   void ValidateDeferredBlockExitPaths() const;
    1594             :   void ValidateDeferredBlockEntryPaths() const;
    1595             :   void ValidateSSA() const;
    1596             : 
    1597             :   static void SetRegisterConfigurationForTesting(
    1598             :       const RegisterConfiguration* regConfig);
    1599             :   static void ClearRegisterConfigurationForTesting();
    1600             : 
    1601             :   void RecomputeAssemblyOrderForTesting();
    1602             : 
    1603             :  private:
    1604             :   friend V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
    1605             :                                                     const InstructionSequence&);
    1606             : 
    1607             :   typedef ZoneMap<const Instruction*, SourcePosition> SourcePositionMap;
    1608             : 
    1609             :   static const RegisterConfiguration* RegisterConfigurationForTesting();
    1610             :   static const RegisterConfiguration* registerConfigurationForTesting_;
    1611             : 
    1612             :   // Puts the deferred blocks last and may rotate loops.
    1613             :   void ComputeAssemblyOrder();
    1614             : 
    1615             :   Isolate* isolate_;
    1616             :   Zone* const zone_;
    1617             :   InstructionBlocks* const instruction_blocks_;
    1618             :   InstructionBlocks* ao_blocks_;
    1619             :   SourcePositionMap source_positions_;
    1620             :   ConstantMap constants_;
    1621             :   Immediates immediates_;
    1622             :   InstructionDeque instructions_;
    1623             :   int next_virtual_register_;
    1624             :   ReferenceMapDeque reference_maps_;
    1625             :   ZoneVector<MachineRepresentation> representations_;
    1626             :   int representation_mask_;
    1627             :   DeoptimizationVector deoptimization_entries_;
    1628             : 
    1629             :   // Used at construction time
    1630             :   InstructionBlock* current_block_;
    1631             : 
    1632             :   DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
    1633             : };
    1634             : 
    1635             : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
    1636             :                                            const InstructionSequence&);
    1637             : 
    1638             : }  // namespace compiler
    1639             : }  // namespace internal
    1640             : }  // namespace v8
    1641             : 
    1642             : #endif  // V8_COMPILER_BACKEND_INSTRUCTION_H_

Generated by: LCOV version 1.10