LCOV - code coverage report
Current view: top level - src/compiler/backend - instruction.h (source / functions) Hit Total Coverage
Test: app.info Lines: 210 220 95.5 %
Date: 2019-04-17 Functions: 25 26 96.2 %

          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  3790103835 :   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     2603200 :   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       82794 :   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           0 :   static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
      98             :     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    48898366 :     *dest = *src;
     105             :   }
     106             : 
     107             :   bool Equals(const InstructionOperand& that) const {
     108    33002569 :     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   728396111 :     return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
     117             :   }
     118             : 
     119             :   bool CompareCanonicalized(const InstructionOperand& that) const {
     120    64364785 :     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   219341892 :   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             : using InstructionOperandVector = ZoneVector<InstructionOperand>;
     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    37685144 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     190    37685144 :     value_ |= ExtendedPolicyField::encode(policy);
     191    69369424 :     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             :     value_ |= static_cast<uint64_t>(static_cast<int64_t>(index))
     199     4803138 :               << FixedSlotIndexField::kShift;
     200             :     DCHECK(this->fixed_slot_index() == index);
     201             :   }
     202             : 
     203             :   UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
     204             :       : UnallocatedOperand(virtual_register) {
     205             :     DCHECK(policy == FIXED_REGISTER || policy == FIXED_FP_REGISTER);
     206         122 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     207         122 :     value_ |= ExtendedPolicyField::encode(policy);
     208    28765953 :     value_ |= LifetimeField::encode(USED_AT_END);
     209    28765953 :     value_ |= FixedRegisterField::encode(index);
     210             :   }
     211             : 
     212             :   UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
     213             :                      int virtual_register)
     214             :       : UnallocatedOperand(virtual_register) {
     215     5454377 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     216    30656360 :     value_ |= ExtendedPolicyField::encode(policy);
     217     2310914 :     value_ |= LifetimeField::encode(lifetime);
     218             :   }
     219             : 
     220             :   UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
     221             :       : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
     222      554497 :     value_ |= HasSecondaryStorageField::encode(true);
     223      554497 :     value_ |= SecondaryStorageField::encode(slot_id);
     224             :   }
     225             : 
     226             :   UnallocatedOperand(const UnallocatedOperand& other, int virtual_register) {
     227             :     DCHECK_NE(kInvalidVirtualRegister, virtual_register);
     228     2416000 :     value_ = VirtualRegisterField::update(
     229     2730370 :         other.value_, static_cast<uint32_t>(virtual_register));
     230             :   }
     231             : 
     232             :   // Predicates for the operand policy.
     233             :   bool HasRegisterOrSlotPolicy() const {
     234   102901105 :     return basic_policy() == EXTENDED_POLICY &&
     235             :            extended_policy() == REGISTER_OR_SLOT;
     236             :   }
     237             :   bool HasRegisterOrSlotOrConstantPolicy() const {
     238   102900268 :     return basic_policy() == EXTENDED_POLICY &&
     239             :            extended_policy() == REGISTER_OR_SLOT_OR_CONSTANT;
     240             :   }
     241             :   bool HasFixedPolicy() const {
     242    96141633 :     return basic_policy() == FIXED_SLOT ||
     243   165218845 :            extended_policy() == FIXED_REGISTER ||
     244             :            extended_policy() == FIXED_FP_REGISTER;
     245             :   }
     246             :   bool HasRegisterPolicy() const {
     247   217100896 :     return basic_policy() == EXTENDED_POLICY &&
     248             :            extended_policy() == MUST_HAVE_REGISTER;
     249             :   }
     250             :   bool HasSlotPolicy() const {
     251   234529626 :     return basic_policy() == EXTENDED_POLICY &&
     252             :            extended_policy() == MUST_HAVE_SLOT;
     253             :   }
     254             :   bool HasSameAsInputPolicy() const {
     255    48518772 :     return basic_policy() == EXTENDED_POLICY &&
     256             :            extended_policy() == SAME_AS_FIRST_INPUT;
     257             :   }
     258             :   bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
     259             :   bool HasFixedRegisterPolicy() const {
     260    57468035 :     return basic_policy() == EXTENDED_POLICY &&
     261             :            extended_policy() == FIXED_REGISTER;
     262             :   }
     263             :   bool HasFixedFPRegisterPolicy() const {
     264      824288 :     return basic_policy() == EXTENDED_POLICY &&
     265             :            extended_policy() == FIXED_FP_REGISTER;
     266             :   }
     267             :   bool HasSecondaryStorage() const {
     268     8869732 :     return basic_policy() == EXTENDED_POLICY &&
     269    18761636 :            extended_policy() == FIXED_REGISTER &&
     270             :            HasSecondaryStorageField::decode(value_);
     271             :   }
     272             :   int GetSecondaryStorage() const {
     273             :     DCHECK(HasSecondaryStorage());
     274      554111 :     return SecondaryStorageField::decode(value_);
     275             :   }
     276             : 
     277             :   // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
     278   322709089 :   BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); }
     279             : 
     280             :   // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
     281             :   ExtendedPolicy extended_policy() const {
     282             :     DCHECK(basic_policy() == EXTENDED_POLICY);
     283             :     return ExtendedPolicyField::decode(value_);
     284             :   }
     285             : 
     286             :   // [fixed_slot_index]: Only for FIXED_SLOT.
     287             :   int fixed_slot_index() const {
     288             :     DCHECK(HasFixedSlotPolicy());
     289     4797499 :     return static_cast<int>(static_cast<int64_t>(value_) >>
     290     4797499 :                             FixedSlotIndexField::kShift);
     291             :   }
     292             : 
     293             :   // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER.
     294             :   int fixed_register_index() const {
     295             :     DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy());
     296         122 :     return FixedRegisterField::decode(value_);
     297             :   }
     298             : 
     299             :   // [virtual_register]: The virtual register ID for this operand.
     300             :   int32_t virtual_register() const {
     301   518582363 :     return static_cast<int32_t>(VirtualRegisterField::decode(value_));
     302             :   }
     303             : 
     304             :   // [lifetime]: Only for non-FIXED_SLOT.
     305             :   bool IsUsedAtStart() const {
     306             :     DCHECK(basic_policy() == EXTENDED_POLICY);
     307    51943175 :     return LifetimeField::decode(value_) == USED_AT_START;
     308             :   }
     309             : 
     310    32570875 :   INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED)
     311             : 
     312             :   // The encoding used for UnallocatedOperand operands depends on the policy
     313             :   // that is
     314             :   // stored within the operand. The FIXED_SLOT policy uses a compact encoding
     315             :   // because it accommodates a larger pay-load.
     316             :   //
     317             :   // For FIXED_SLOT policy:
     318             :   //     +------------------------------------------------+
     319             :   //     |      slot_index   | 0 | virtual_register | 001 |
     320             :   //     +------------------------------------------------+
     321             :   //
     322             :   // For all other (extended) policies:
     323             :   //     +-----------------------------------------------------+
     324             :   //     |  reg_index  | L | PPP |  1 | virtual_register | 001 |
     325             :   //     +-----------------------------------------------------+
     326             :   //     L ... Lifetime
     327             :   //     P ... Policy
     328             :   //
     329             :   // The slot index is a signed value which requires us to decode it manually
     330             :   // instead of using the BitField utility class.
     331             : 
     332             :   STATIC_ASSERT(KindField::kSize == 3);
     333             : 
     334             :   class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
     335             : 
     336             :   // BitFields for all unallocated operands.
     337             :   class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
     338             : 
     339             :   // BitFields specific to BasicPolicy::FIXED_SLOT.
     340             :   class FixedSlotIndexField : public BitField64<int, 36, 28> {};
     341             : 
     342             :   // BitFields specific to BasicPolicy::EXTENDED_POLICY.
     343             :   class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
     344             :   class LifetimeField : public BitField64<Lifetime, 39, 1> {};
     345             :   class HasSecondaryStorageField : public BitField64<bool, 40, 1> {};
     346             :   class FixedRegisterField : public BitField64<int, 41, 6> {};
     347             :   class SecondaryStorageField : public BitField64<int, 47, 3> {};
     348             : 
     349             :  private:
     350             :   explicit UnallocatedOperand(int virtual_register)
     351             :       : InstructionOperand(UNALLOCATED) {
     352             :     value_ |=
     353   151224337 :         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
     354             :   }
     355             : };
     356             : 
     357             : class ConstantOperand : public InstructionOperand {
     358             :  public:
     359             :   explicit ConstantOperand(int virtual_register)
     360             :       : InstructionOperand(CONSTANT) {
     361             :     value_ |=
     362    29015459 :         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
     363             :   }
     364             : 
     365             :   int32_t virtual_register() const {
     366    91127836 :     return static_cast<int32_t>(VirtualRegisterField::decode(value_));
     367             :   }
     368             : 
     369             :   static ConstantOperand* New(Zone* zone, int virtual_register) {
     370             :     return InstructionOperand::New(zone, ConstantOperand(virtual_register));
     371             :   }
     372             : 
     373          12 :   INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT)
     374             : 
     375             :   STATIC_ASSERT(KindField::kSize == 3);
     376             :   class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
     377             : };
     378             : 
     379             : class ImmediateOperand : public InstructionOperand {
     380             :  public:
     381             :   enum ImmediateType { INLINE, INDEXED };
     382             : 
     383             :   explicit ImmediateOperand(ImmediateType type, int32_t value)
     384             :       : InstructionOperand(IMMEDIATE) {
     385             :     value_ |= TypeField::encode(type);
     386             :     value_ |= static_cast<uint64_t>(static_cast<int64_t>(value))
     387    64682543 :               << ValueField::kShift;
     388             :   }
     389             : 
     390    65221163 :   ImmediateType type() const { return TypeField::decode(value_); }
     391             : 
     392             :   int32_t inline_value() const {
     393             :     DCHECK_EQ(INLINE, type());
     394    19263027 :     return static_cast<int64_t>(value_) >> ValueField::kShift;
     395             :   }
     396             : 
     397             :   int32_t indexed_value() const {
     398             :     DCHECK_EQ(INDEXED, type());
     399    45958421 :     return static_cast<int64_t>(value_) >> ValueField::kShift;
     400             :   }
     401             : 
     402             :   static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
     403             :     return InstructionOperand::New(zone, ImmediateOperand(type, value));
     404             :   }
     405             : 
     406             :   INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE)
     407             : 
     408             :   STATIC_ASSERT(KindField::kSize == 3);
     409             :   class TypeField : public BitField64<ImmediateType, 3, 1> {};
     410             :   class ValueField : public BitField64<int32_t, 32, 32> {};
     411             : };
     412             : 
     413             : class LocationOperand : public InstructionOperand {
     414             :  public:
     415             :   enum LocationKind { REGISTER, STACK_SLOT };
     416             : 
     417             :   LocationOperand(InstructionOperand::Kind operand_kind,
     418             :                   LocationOperand::LocationKind location_kind,
     419             :                   MachineRepresentation rep, int index)
     420             :       : InstructionOperand(operand_kind) {
     421             :     DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
     422             :     DCHECK(IsSupportedRepresentation(rep));
     423      719183 :     value_ |= LocationKindField::encode(location_kind);
     424   149564686 :     value_ |= RepresentationField::encode(rep);
     425             :     value_ |= static_cast<uint64_t>(static_cast<int64_t>(index))
     426   149694056 :               << IndexField::kShift;
     427             :   }
     428             : 
     429             :   int index() const {
     430             :     DCHECK(IsStackSlot() || IsFPStackSlot());
     431    73549359 :     return static_cast<int64_t>(value_) >> IndexField::kShift;
     432             :   }
     433             : 
     434             :   int register_code() const {
     435             :     DCHECK(IsRegister() || IsFPRegister());
     436   198637420 :     return static_cast<int64_t>(value_) >> IndexField::kShift;
     437             :   }
     438             : 
     439             :   Register GetRegister() const {
     440             :     DCHECK(IsRegister());
     441             :     return Register::from_code(register_code());
     442             :   }
     443             : 
     444             :   FloatRegister GetFloatRegister() const {
     445             :     DCHECK(IsFloatRegister());
     446             :     return FloatRegister::from_code(register_code());
     447             :   }
     448             : 
     449             :   DoubleRegister GetDoubleRegister() const {
     450             :     // On platforms where FloatRegister, DoubleRegister, and Simd128Register
     451             :     // are all the same type, it's convenient to treat everything as a
     452             :     // DoubleRegister, so be lax about type checking here.
     453             :     DCHECK(IsFPRegister());
     454             :     return DoubleRegister::from_code(register_code());
     455             :   }
     456             : 
     457             :   Simd128Register GetSimd128Register() const {
     458             :     DCHECK(IsSimd128Register());
     459             :     return Simd128Register::from_code(register_code());
     460             :   }
     461             : 
     462             :   LocationKind location_kind() const {
     463             :     return LocationKindField::decode(value_);
     464             :   }
     465             : 
     466             :   MachineRepresentation representation() const {
     467       32671 :     return RepresentationField::decode(value_);
     468             :   }
     469             : 
     470             :   static bool IsSupportedRepresentation(MachineRepresentation rep) {
     471             :     switch (rep) {
     472             :       case MachineRepresentation::kWord32:
     473             :       case MachineRepresentation::kWord64:
     474             :       case MachineRepresentation::kFloat32:
     475             :       case MachineRepresentation::kFloat64:
     476             :       case MachineRepresentation::kSimd128:
     477             :       case MachineRepresentation::kTaggedSigned:
     478             :       case MachineRepresentation::kTaggedPointer:
     479             :       case MachineRepresentation::kTagged:
     480             :       case MachineRepresentation::kCompressedSigned:
     481             :       case MachineRepresentation::kCompressedPointer:
     482             :       case MachineRepresentation::kCompressed:
     483             :         return true;
     484             :       case MachineRepresentation::kBit:
     485             :       case MachineRepresentation::kWord8:
     486             :       case MachineRepresentation::kWord16:
     487             :       case MachineRepresentation::kNone:
     488             :         return false;
     489             :     }
     490             :     UNREACHABLE();
     491             :   }
     492             : 
     493             :   // Return true if the locations can be moved to one another.
     494             :   bool IsCompatible(LocationOperand* op);
     495             : 
     496             :   static LocationOperand* cast(InstructionOperand* op) {
     497             :     DCHECK(op->IsAnyLocationOperand());
     498             :     return static_cast<LocationOperand*>(op);
     499             :   }
     500             : 
     501             :   static const LocationOperand* cast(const InstructionOperand* op) {
     502             :     DCHECK(op->IsAnyLocationOperand());
     503             :     return static_cast<const LocationOperand*>(op);
     504             :   }
     505             : 
     506             :   static LocationOperand cast(const InstructionOperand& op) {
     507             :     DCHECK(op.IsAnyLocationOperand());
     508       50364 :     return *static_cast<const LocationOperand*>(&op);
     509             :   }
     510             : 
     511             :   STATIC_ASSERT(KindField::kSize == 3);
     512             :   class LocationKindField : public BitField64<LocationKind, 3, 2> {};
     513             :   class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
     514             :   class IndexField : public BitField64<int32_t, 35, 29> {};
     515             : };
     516             : 
     517             : class V8_EXPORT_PRIVATE ExplicitOperand
     518             :     : public NON_EXPORTED_BASE(LocationOperand) {
     519             :  public:
     520             :   ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
     521             : 
     522             :   static ExplicitOperand* New(Zone* zone, LocationKind kind,
     523             :                               MachineRepresentation rep, int index) {
     524             :     return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
     525             :   }
     526             : 
     527             :   INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT)
     528             : };
     529             : 
     530             : class AllocatedOperand : public LocationOperand {
     531             :  public:
     532             :   AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
     533             :       : LocationOperand(ALLOCATED, kind, rep, index) {}
     534             : 
     535             :   static AllocatedOperand* New(Zone* zone, LocationKind kind,
     536             :                                MachineRepresentation rep, int index) {
     537           0 :     return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
     538             :   }
     539             : 
     540       24067 :   INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED)
     541             : };
     542             : 
     543             : #undef INSTRUCTION_OPERAND_CASTS
     544             : 
     545             : bool InstructionOperand::IsAnyLocationOperand() const {
     546  1910908066 :   return this->kind() >= FIRST_LOCATION_OPERAND_KIND;
     547             : }
     548             : 
     549             : bool InstructionOperand::IsLocationOperand() const {
     550             :   return IsAnyLocationOperand() &&
     551             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     552             : }
     553             : 
     554             : bool InstructionOperand::IsFPLocationOperand() const {
     555             :   return IsAnyLocationOperand() &&
     556             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     557             : }
     558             : 
     559             : bool InstructionOperand::IsAnyRegister() const {
     560  3001153840 :   return IsAnyLocationOperand() &&
     561             :          LocationOperand::cast(this)->location_kind() ==
     562             :              LocationOperand::REGISTER;
     563             : }
     564             : 
     565             : bool InstructionOperand::IsRegister() const {
     566   329668412 :   return IsAnyRegister() &&
     567             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     568             : }
     569             : 
     570             : bool InstructionOperand::IsFPRegister() const {
     571  1993004545 :   return IsAnyRegister() &&
     572             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     573             : }
     574             : 
     575             : bool InstructionOperand::IsFloatRegister() const {
     576      773980 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     577             :                                 MachineRepresentation::kFloat32;
     578             : }
     579             : 
     580             : bool InstructionOperand::IsDoubleRegister() const {
     581      750345 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     582             :                                 MachineRepresentation::kFloat64;
     583             : }
     584             : 
     585             : bool InstructionOperand::IsSimd128Register() const {
     586      738176 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     587             :                                 MachineRepresentation::kSimd128;
     588             : }
     589             : 
     590             : bool InstructionOperand::IsAnyStackSlot() const {
     591   343464072 :   return IsAnyLocationOperand() &&
     592             :          LocationOperand::cast(this)->location_kind() ==
     593             :              LocationOperand::STACK_SLOT;
     594             : }
     595             : 
     596             : bool InstructionOperand::IsStackSlot() const {
     597   257170007 :   return IsAnyStackSlot() &&
     598             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     599             : }
     600             : 
     601             : bool InstructionOperand::IsFPStackSlot() const {
     602    21190153 :   return IsAnyStackSlot() &&
     603             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     604             : }
     605             : 
     606             : bool InstructionOperand::IsFloatStackSlot() const {
     607       19881 :   return IsAnyLocationOperand() &&
     608             :          LocationOperand::cast(this)->location_kind() ==
     609       39762 :              LocationOperand::STACK_SLOT &&
     610             :          LocationOperand::cast(this)->representation() ==
     611             :              MachineRepresentation::kFloat32;
     612             : }
     613             : 
     614             : bool InstructionOperand::IsDoubleStackSlot() const {
     615       13377 :   return IsAnyLocationOperand() &&
     616             :          LocationOperand::cast(this)->location_kind() ==
     617       26754 :              LocationOperand::STACK_SLOT &&
     618             :          LocationOperand::cast(this)->representation() ==
     619             :              MachineRepresentation::kFloat64;
     620             : }
     621             : 
     622             : bool InstructionOperand::IsSimd128StackSlot() const {
     623             :   return IsAnyLocationOperand() &&
     624             :          LocationOperand::cast(this)->location_kind() ==
     625             :              LocationOperand::STACK_SLOT &&
     626             :          LocationOperand::cast(this)->representation() ==
     627             :              MachineRepresentation::kSimd128;
     628             : }
     629             : 
     630  1516752860 : uint64_t InstructionOperand::GetCanonicalizedValue() const {
     631  1516752860 :   if (IsAnyLocationOperand()) {
     632             :     MachineRepresentation canonical = MachineRepresentation::kNone;
     633  1235343700 :     if (IsFPRegister()) {
     634             :       if (kSimpleFPAliasing) {
     635             :         // We treat all FP register operands the same for simple aliasing.
     636             :         canonical = MachineRepresentation::kFloat64;
     637             :       } else {
     638             :         // We need to distinguish FP register operands of different reps when
     639             :         // aliasing is not simple (e.g. ARM).
     640             :         canonical = LocationOperand::cast(this)->representation();
     641             :       }
     642             :     }
     643             :     return InstructionOperand::KindField::update(
     644             :         LocationOperand::RepresentationField::update(this->value_, canonical),
     645  1235343700 :         LocationOperand::EXPLICIT);
     646             :   }
     647             :   return this->value_;
     648             : }
     649             : 
     650             : // Required for maps that don't care about machine type.
     651             : struct CompareOperandModuloType {
     652             :   bool operator()(const InstructionOperand& a,
     653             :                   const InstructionOperand& b) const {
     654             :     return a.CompareCanonicalized(b);
     655             :   }
     656             : };
     657             : 
     658             : class V8_EXPORT_PRIVATE MoveOperands final
     659             :     : public NON_EXPORTED_BASE(ZoneObject) {
     660             :  public:
     661             :   MoveOperands(const InstructionOperand& source,
     662             :                const InstructionOperand& destination)
     663    82420192 :       : source_(source), destination_(destination) {
     664             :     DCHECK(!source.IsInvalid() && !destination.IsInvalid());
     665             :   }
     666             : 
     667    24099235 :   const InstructionOperand& source() const { return source_; }
     668   200901673 :   InstructionOperand& source() { return source_; }
     669     1750890 :   void set_source(const InstructionOperand& operand) { source_ = operand; }
     670             : 
     671     3450893 :   const InstructionOperand& destination() const { return destination_; }
     672   215497820 :   InstructionOperand& destination() { return destination_; }
     673             :   void set_destination(const InstructionOperand& operand) {
     674    14356467 :     destination_ = operand;
     675             :   }
     676             : 
     677             :   // The gap resolver marks moves as "in-progress" by clearing the
     678             :   // destination (but not the source).
     679             :   bool IsPending() const {
     680    40747994 :     return destination_.IsInvalid() && !source_.IsInvalid();
     681             :   }
     682    14427724 :   void SetPending() { destination_ = InstructionOperand(); }
     683             : 
     684             :   // A move is redundant if it's been eliminated or if its source and
     685             :   // destination are the same.
     686   298623365 :   bool IsRedundant() const {
     687             :     DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
     688   538988569 :     return IsEliminated() || source_.EqualsCanonicalized(destination_);
     689             :   }
     690             : 
     691             :   // We clear both operands to indicate move that's been eliminated.
     692    48634164 :   void Eliminate() { source_ = destination_ = InstructionOperand(); }
     693             :   bool IsEliminated() const {
     694             :     DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
     695             :     return source_.IsInvalid();
     696             :   }
     697             : 
     698             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     699             :   void Print() const;
     700             : 
     701             :  private:
     702             :   InstructionOperand source_;
     703             :   InstructionOperand destination_;
     704             : 
     705             :   DISALLOW_COPY_AND_ASSIGN(MoveOperands);
     706             : };
     707             : 
     708             : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const MoveOperands&);
     709             : 
     710    10024483 : class V8_EXPORT_PRIVATE ParallelMove final
     711             :     : public NON_EXPORTED_BASE(ZoneVector<MoveOperands*>),
     712             :       public NON_EXPORTED_BASE(ZoneObject) {
     713             :  public:
     714             :   explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {}
     715             : 
     716             :   MoveOperands* AddMove(const InstructionOperand& from,
     717             :                         const InstructionOperand& to) {
     718             :     Zone* zone = get_allocator().zone();
     719    67202770 :     return AddMove(from, to, zone);
     720             :   }
     721             : 
     722    81720097 :   MoveOperands* AddMove(const InstructionOperand& from,
     723             :                         const InstructionOperand& to,
     724             :                         Zone* operand_allocation_zone) {
     725    81721576 :     if (from.EqualsCanonicalized(to)) return nullptr;
     726    81612035 :     MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to);
     727    81612035 :     if (empty()) reserve(4);
     728    81611352 :     push_back(move);
     729    81612228 :     return move;
     730             :   }
     731             : 
     732             :   bool IsRedundant() const;
     733             : 
     734             :   // Prepare this ParallelMove to insert move as if it happened in a subsequent
     735             :   // ParallelMove.  move->source() may be changed.  Any MoveOperands added to
     736             :   // to_eliminate must be Eliminated.
     737             :   void PrepareInsertAfter(MoveOperands* move,
     738             :                           ZoneVector<MoveOperands*>* to_eliminate) const;
     739             : 
     740             :  private:
     741             :   DISALLOW_COPY_AND_ASSIGN(ParallelMove);
     742             : };
     743             : 
     744             : std::ostream& operator<<(std::ostream&, const ParallelMove&);
     745             : 
     746             : class ReferenceMap final : public ZoneObject {
     747             :  public:
     748             :   explicit ReferenceMap(Zone* zone)
     749     6301199 :       : reference_operands_(8, zone), instruction_position_(-1) {}
     750             : 
     751             :   const ZoneVector<InstructionOperand>& reference_operands() const {
     752             :     return reference_operands_;
     753             :   }
     754             :   int instruction_position() const { return instruction_position_; }
     755             : 
     756             :   void set_instruction_position(int pos) {
     757             :     DCHECK_EQ(-1, instruction_position_);
     758     6072832 :     instruction_position_ = pos;
     759             :   }
     760             : 
     761             :   void RecordReference(const AllocatedOperand& op);
     762             : 
     763             :  private:
     764             :   friend std::ostream& operator<<(std::ostream&, const ReferenceMap&);
     765             : 
     766             :   ZoneVector<InstructionOperand> reference_operands_;
     767             :   int instruction_position_;
     768             : };
     769             : 
     770             : std::ostream& operator<<(std::ostream&, const ReferenceMap&);
     771             : 
     772             : class InstructionBlock;
     773             : 
     774             : class V8_EXPORT_PRIVATE Instruction final {
     775             :  public:
     776             :   size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
     777             :   const InstructionOperand* OutputAt(size_t i) const {
     778             :     DCHECK(i < OutputCount());
     779        1341 :     return &operands_[i];
     780             :   }
     781             :   InstructionOperand* OutputAt(size_t i) {
     782             :     DCHECK(i < OutputCount());
     783   142365545 :     return &operands_[i];
     784             :   }
     785             : 
     786           0 :   bool HasOutput() const { return OutputCount() > 0; }
     787             :   const InstructionOperand* Output() const { return OutputAt(0); }
     788             :   InstructionOperand* Output() { return OutputAt(0); }
     789             : 
     790             :   size_t InputCount() const { return InputCountField::decode(bit_field_); }
     791             :   const InstructionOperand* InputAt(size_t i) const {
     792             :     DCHECK(i < InputCount());
     793     9368955 :     return &operands_[OutputCount() + i];
     794             :   }
     795             :   InstructionOperand* InputAt(size_t i) {
     796             :     DCHECK(i < InputCount());
     797   609175271 :     return &operands_[OutputCount() + i];
     798             :   }
     799             : 
     800             :   size_t TempCount() const { return TempCountField::decode(bit_field_); }
     801             :   const InstructionOperand* TempAt(size_t i) const {
     802             :     DCHECK(i < TempCount());
     803           0 :     return &operands_[OutputCount() + InputCount() + i];
     804             :   }
     805             :   InstructionOperand* TempAt(size_t i) {
     806             :     DCHECK(i < TempCount());
     807     3357979 :     return &operands_[OutputCount() + InputCount() + i];
     808             :   }
     809             : 
     810             :   InstructionCode opcode() const { return opcode_; }
     811   270267847 :   ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
     812             :   AddressingMode addressing_mode() const {
     813     1632515 :     return AddressingModeField::decode(opcode());
     814             :   }
     815           4 :   FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
     816             :   FlagsCondition flags_condition() const {
     817             :     return FlagsConditionField::decode(opcode());
     818             :   }
     819             : 
     820             :   static Instruction* New(Zone* zone, InstructionCode opcode) {
     821     2641713 :     return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
     822             :   }
     823             : 
     824    68958317 :   static Instruction* New(Zone* zone, InstructionCode opcode,
     825             :                           size_t output_count, InstructionOperand* outputs,
     826             :                           size_t input_count, InstructionOperand* inputs,
     827             :                           size_t temp_count, InstructionOperand* temps) {
     828             :     DCHECK_LE(0, opcode);
     829             :     DCHECK(output_count == 0 || outputs != nullptr);
     830             :     DCHECK(input_count == 0 || inputs != nullptr);
     831             :     DCHECK(temp_count == 0 || temps != nullptr);
     832             :     // TODO(jarin/mstarzinger): Handle this gracefully. See crbug.com/582702.
     833    68958317 :     CHECK(InputCountField::is_valid(input_count));
     834             : 
     835    68958317 :     size_t total_extra_ops = output_count + input_count + temp_count;
     836    68958317 :     if (total_extra_ops != 0) total_extra_ops--;
     837             :     int size = static_cast<int>(
     838             :         RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
     839    68958317 :         total_extra_ops * sizeof(InstructionOperand));
     840    68958317 :     return new (zone->New(size)) Instruction(
     841    68958317 :         opcode, output_count, outputs, input_count, inputs, temp_count, temps);
     842             :   }
     843             : 
     844             :   Instruction* MarkAsCall() {
     845    12145358 :     bit_field_ = IsCallField::update(bit_field_, true);
     846             :     return this;
     847             :   }
     848             :   bool IsCall() const { return IsCallField::decode(bit_field_); }
     849             :   bool NeedsReferenceMap() const { return IsCall(); }
     850             :   bool HasReferenceMap() const { return reference_map_ != nullptr; }
     851             : 
     852             :   bool ClobbersRegisters() const { return IsCall(); }
     853             :   bool ClobbersTemps() const { return IsCall(); }
     854             :   bool ClobbersDoubleRegisters() const { return IsCall(); }
     855             :   ReferenceMap* reference_map() const { return reference_map_; }
     856             : 
     857             :   void set_reference_map(ReferenceMap* map) {
     858             :     DCHECK(NeedsReferenceMap());
     859             :     DCHECK(!reference_map_);
     860     6072832 :     reference_map_ = map;
     861             :   }
     862             : 
     863             :   void OverwriteWithNop() {
     864     4054673 :     opcode_ = ArchOpcodeField::encode(kArchNop);
     865     4054673 :     bit_field_ = 0;
     866     4054673 :     reference_map_ = nullptr;
     867             :   }
     868             : 
     869             :   bool IsNop() const { return arch_opcode() == kArchNop; }
     870             : 
     871             :   bool IsDeoptimizeCall() const {
     872    33387686 :     return arch_opcode() == ArchOpcode::kArchDeoptimize ||
     873    66696256 :            FlagsModeField::decode(opcode()) == kFlags_deoptimize ||
     874             :            FlagsModeField::decode(opcode()) == kFlags_deoptimize_and_poison;
     875             :   }
     876             : 
     877             :   bool IsTrap() const {
     878             :     return FlagsModeField::decode(opcode()) == kFlags_trap;
     879             :   }
     880             : 
     881             :   bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
     882             :   bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
     883             :   bool IsTailCall() const {
     884    98524300 :     return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
     885    98520857 :            arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
     886   196937826 :            arch_opcode() == ArchOpcode::kArchTailCallAddress ||
     887             :            arch_opcode() == ArchOpcode::kArchTailCallWasm;
     888             :   }
     889             :   bool IsThrow() const {
     890             :     return arch_opcode() == ArchOpcode::kArchThrowTerminator;
     891             :   }
     892             : 
     893             :   enum GapPosition {
     894             :     START,
     895             :     END,
     896             :     FIRST_GAP_POSITION = START,
     897             :     LAST_GAP_POSITION = END
     898             :   };
     899             : 
     900             :   ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
     901    77500093 :     if (parallel_moves_[pos] == nullptr) {
     902    48925494 :       parallel_moves_[pos] = new (zone) ParallelMove(zone);
     903             :     }
     904    77499352 :     return parallel_moves_[pos];
     905             :   }
     906             : 
     907             :   ParallelMove* GetParallelMove(GapPosition pos) {
     908   276033385 :     return parallel_moves_[pos];
     909             :   }
     910             : 
     911             :   const ParallelMove* GetParallelMove(GapPosition pos) const {
     912     7654488 :     return parallel_moves_[pos];
     913             :   }
     914             : 
     915             :   bool AreMovesRedundant() const;
     916             : 
     917   122329370 :   ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
     918             :   ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
     919             : 
     920             :   // The block_id may be invalidated in JumpThreading. It is only important for
     921             :   // register allocation, to avoid searching for blocks from instruction
     922             :   // indexes.
     923             :   InstructionBlock* block() const { return block_; }
     924             :   void set_block(InstructionBlock* block) {
     925             :     DCHECK_NOT_NULL(block);
     926    68971237 :     block_ = block;
     927             :   }
     928             : 
     929             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     930             :   void Print() const;
     931             : 
     932             :   using OutputCountField = BitField<size_t, 0, 8>;
     933             :   using InputCountField = BitField<size_t, 8, 16>;
     934             :   using TempCountField = BitField<size_t, 24, 6>;
     935             : 
     936             :   static const size_t kMaxOutputCount = OutputCountField::kMax;
     937             :   static const size_t kMaxInputCount = InputCountField::kMax;
     938             :   static const size_t kMaxTempCount = TempCountField::kMax;
     939             : 
     940             :  private:
     941             :   explicit Instruction(InstructionCode opcode);
     942             : 
     943             :   Instruction(InstructionCode opcode, size_t output_count,
     944             :               InstructionOperand* outputs, size_t input_count,
     945             :               InstructionOperand* inputs, size_t temp_count,
     946             :               InstructionOperand* temps);
     947             : 
     948             :   using IsCallField = BitField<bool, 30, 1>;
     949             : 
     950             :   InstructionCode opcode_;
     951             :   uint32_t bit_field_;
     952             :   ParallelMove* parallel_moves_[2];
     953             :   ReferenceMap* reference_map_;
     954             :   InstructionBlock* block_;
     955             :   InstructionOperand operands_[1];
     956             : 
     957             :   DISALLOW_COPY_AND_ASSIGN(Instruction);
     958             : };
     959             : 
     960             : std::ostream& operator<<(std::ostream&, const Instruction&);
     961             : 
     962             : class RpoNumber final {
     963             :  public:
     964             :   static const int kInvalidRpoNumber = -1;
     965             :   int ToInt() const {
     966             :     DCHECK(IsValid());
     967    78321842 :     return index_;
     968             :   }
     969             :   size_t ToSize() const {
     970             :     DCHECK(IsValid());
     971   677829287 :     return static_cast<size_t>(index_);
     972             :   }
     973    47542420 :   bool IsValid() const { return index_ >= 0; }
     974             :   static RpoNumber FromInt(int index) { return RpoNumber(index); }
     975             :   static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
     976             : 
     977             :   bool IsNext(const RpoNumber other) const {
     978             :     DCHECK(IsValid());
     979    30970643 :     return other.index_ == this->index_ + 1;
     980             :   }
     981             : 
     982             :   RpoNumber Next() const {
     983             :     DCHECK(IsValid());
     984           0 :     return RpoNumber(index_ + 1);
     985             :   }
     986             : 
     987             :   // Comparison operators.
     988  1285145510 :   bool operator==(RpoNumber other) const { return index_ == other.index_; }
     989             :   bool operator!=(RpoNumber other) const { return index_ != other.index_; }
     990             :   bool operator>(RpoNumber other) const { return index_ > other.index_; }
     991     4348622 :   bool operator<(RpoNumber other) const { return index_ < other.index_; }
     992    23848826 :   bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
     993             :   bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
     994             : 
     995             :  private:
     996             :   explicit RpoNumber(int32_t index) : index_(index) {}
     997             :   int32_t index_;
     998             : };
     999             : 
    1000             : std::ostream& operator<<(std::ostream&, const RpoNumber&);
    1001             : 
    1002             : class V8_EXPORT_PRIVATE Constant final {
    1003             :  public:
    1004             :   enum Type {
    1005             :     kInt32,
    1006             :     kInt64,
    1007             :     kFloat32,
    1008             :     kFloat64,
    1009             :     kExternalReference,
    1010             :     kHeapObject,
    1011             :     kRpoNumber,
    1012             :     kDelayedStringConstant
    1013             :   };
    1014             : 
    1015             :   explicit Constant(int32_t v);
    1016             :   explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
    1017      112646 :   explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
    1018             :   explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
    1019             :   explicit Constant(ExternalReference ref)
    1020             :       : type_(kExternalReference), value_(bit_cast<intptr_t>(ref.address())) {}
    1021             :   explicit Constant(Handle<HeapObject> obj)
    1022             :       : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
    1023    25344688 :   explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
    1024             :   explicit Constant(const StringConstantBase* str)
    1025             :       : type_(kDelayedStringConstant), value_(bit_cast<intptr_t>(str)) {}
    1026             :   explicit Constant(RelocatablePtrConstantInfo info);
    1027             : 
    1028             :   Type type() const { return type_; }
    1029             : 
    1030             :   RelocInfo::Mode rmode() const { return rmode_; }
    1031             : 
    1032             :   int32_t ToInt32() const {
    1033             :     DCHECK(type() == kInt32 || type() == kInt64);
    1034    54447250 :     const int32_t value = static_cast<int32_t>(value_);
    1035             :     DCHECK_EQ(value_, static_cast<int64_t>(value));
    1036             :     return value;
    1037             :   }
    1038             : 
    1039             :   int64_t ToInt64() const {
    1040     3098398 :     if (type() == kInt32) return ToInt32();
    1041             :     DCHECK_EQ(kInt64, type());
    1042     2892250 :     return value_;
    1043             :   }
    1044             : 
    1045             :   float ToFloat32() const {
    1046             :     // TODO(ahaas): We should remove this function. If value_ has the bit
    1047             :     // representation of a signalling NaN, then returning it as float can cause
    1048             :     // the signalling bit to flip, and value_ is returned as a quiet NaN.
    1049             :     DCHECK_EQ(kFloat32, type());
    1050             :     return bit_cast<float>(static_cast<int32_t>(value_));
    1051             :   }
    1052             : 
    1053             :   uint32_t ToFloat32AsInt() const {
    1054             :     DCHECK_EQ(kFloat32, type());
    1055             :     return bit_cast<uint32_t>(static_cast<int32_t>(value_));
    1056             :   }
    1057             : 
    1058             :   Double ToFloat64() const {
    1059             :     DCHECK_EQ(kFloat64, type());
    1060             :     return Double(bit_cast<uint64_t>(value_));
    1061             :   }
    1062             : 
    1063             :   ExternalReference ToExternalReference() const {
    1064             :     DCHECK_EQ(kExternalReference, type());
    1065     2741380 :     return ExternalReference::FromRawAddress(static_cast<Address>(value_));
    1066             :   }
    1067             : 
    1068             :   RpoNumber ToRpoNumber() const {
    1069             :     DCHECK_EQ(kRpoNumber, type());
    1070    43654588 :     return RpoNumber::FromInt(static_cast<int>(value_));
    1071             :   }
    1072             : 
    1073             :   Handle<HeapObject> ToHeapObject() const;
    1074             :   Handle<Code> ToCode() const;
    1075             :   const StringConstantBase* ToDelayedStringConstant() const;
    1076             : 
    1077             :  private:
    1078             :   Type type_;
    1079             :   RelocInfo::Mode rmode_ = RelocInfo::NONE;
    1080             :   int64_t value_;
    1081             : };
    1082             : 
    1083             : std::ostream& operator<<(std::ostream&, const Constant&);
    1084             : 
    1085             : // Forward declarations.
    1086             : class FrameStateDescriptor;
    1087             : 
    1088             : enum class StateValueKind : uint8_t {
    1089             :   kArgumentsElements,
    1090             :   kArgumentsLength,
    1091             :   kPlain,
    1092             :   kOptimizedOut,
    1093             :   kNested,
    1094             :   kDuplicate
    1095             : };
    1096             : 
    1097             : class StateValueDescriptor {
    1098             :  public:
    1099             :   StateValueDescriptor()
    1100             :       : kind_(StateValueKind::kPlain), type_(MachineType::AnyTagged()) {}
    1101             : 
    1102             :   static StateValueDescriptor ArgumentsElements(ArgumentsStateType type) {
    1103             :     StateValueDescriptor descr(StateValueKind::kArgumentsElements,
    1104             :                                MachineType::AnyTagged());
    1105             :     descr.args_type_ = type;
    1106             :     return descr;
    1107             :   }
    1108             :   static StateValueDescriptor ArgumentsLength(ArgumentsStateType type) {
    1109             :     StateValueDescriptor descr(StateValueKind::kArgumentsLength,
    1110             :                                MachineType::AnyTagged());
    1111             :     descr.args_type_ = type;
    1112             :     return descr;
    1113             :   }
    1114             :   static StateValueDescriptor Plain(MachineType type) {
    1115             :     return StateValueDescriptor(StateValueKind::kPlain, type);
    1116             :   }
    1117             :   static StateValueDescriptor OptimizedOut() {
    1118             :     return StateValueDescriptor(StateValueKind::kOptimizedOut,
    1119             :                                 MachineType::AnyTagged());
    1120             :   }
    1121             :   static StateValueDescriptor Recursive(size_t id) {
    1122             :     StateValueDescriptor descr(StateValueKind::kNested,
    1123             :                                MachineType::AnyTagged());
    1124             :     descr.id_ = id;
    1125             :     return descr;
    1126             :   }
    1127             :   static StateValueDescriptor Duplicate(size_t id) {
    1128             :     StateValueDescriptor descr(StateValueKind::kDuplicate,
    1129             :                                MachineType::AnyTagged());
    1130             :     descr.id_ = id;
    1131             :     return descr;
    1132             :   }
    1133             : 
    1134             :   bool IsArgumentsElements() const {
    1135             :     return kind_ == StateValueKind::kArgumentsElements;
    1136             :   }
    1137             :   bool IsArgumentsLength() const {
    1138             :     return kind_ == StateValueKind::kArgumentsLength;
    1139             :   }
    1140             :   bool IsPlain() const { return kind_ == StateValueKind::kPlain; }
    1141             :   bool IsOptimizedOut() const { return kind_ == StateValueKind::kOptimizedOut; }
    1142             :   bool IsNested() const { return kind_ == StateValueKind::kNested; }
    1143             :   bool IsDuplicate() const { return kind_ == StateValueKind::kDuplicate; }
    1144             :   MachineType type() const { return type_; }
    1145             :   size_t id() const {
    1146             :     DCHECK(kind_ == StateValueKind::kDuplicate ||
    1147             :            kind_ == StateValueKind::kNested);
    1148             :     return id_;
    1149             :   }
    1150             :   ArgumentsStateType arguments_type() const {
    1151             :     DCHECK(kind_ == StateValueKind::kArgumentsElements ||
    1152             :            kind_ == StateValueKind::kArgumentsLength);
    1153             :     return args_type_;
    1154             :   }
    1155             : 
    1156             :  private:
    1157             :   StateValueDescriptor(StateValueKind kind, MachineType type)
    1158             :       : kind_(kind), type_(type) {}
    1159             : 
    1160             :   StateValueKind kind_;
    1161             :   MachineType type_;
    1162             :   union {
    1163             :     size_t id_;
    1164             :     ArgumentsStateType args_type_;
    1165             :   };
    1166             : };
    1167             : 
    1168             : class StateValueList {
    1169             :  public:
    1170             :   explicit StateValueList(Zone* zone) : fields_(zone), nested_(zone) {}
    1171             : 
    1172             :   size_t size() { return fields_.size(); }
    1173             : 
    1174             :   struct Value {
    1175             :     StateValueDescriptor* desc;
    1176             :     StateValueList* nested;
    1177             : 
    1178             :     Value(StateValueDescriptor* desc, StateValueList* nested)
    1179             :         : desc(desc), nested(nested) {}
    1180             :   };
    1181             : 
    1182             :   class iterator {
    1183             :    public:
    1184             :     // Bare minimum of operators needed for range iteration.
    1185             :     bool operator!=(const iterator& other) const {
    1186             :       return field_iterator != other.field_iterator;
    1187             :     }
    1188             :     bool operator==(const iterator& other) const {
    1189             :       return field_iterator == other.field_iterator;
    1190             :     }
    1191             :     iterator& operator++() {
    1192    49873726 :       if (field_iterator->IsNested()) {
    1193             :         nested_iterator++;
    1194             :       }
    1195             :       ++field_iterator;
    1196             :       return *this;
    1197             :     }
    1198             :     Value operator*() {
    1199             :       StateValueDescriptor* desc = &(*field_iterator);
    1200    49873708 :       StateValueList* nested = desc->IsNested() ? *nested_iterator : nullptr;
    1201             :       return Value(desc, nested);
    1202             :     }
    1203             : 
    1204             :    private:
    1205             :     friend class StateValueList;
    1206             : 
    1207             :     iterator(ZoneVector<StateValueDescriptor>::iterator it,
    1208             :              ZoneVector<StateValueList*>::iterator nested)
    1209             :         : field_iterator(it), nested_iterator(nested) {}
    1210             : 
    1211             :     ZoneVector<StateValueDescriptor>::iterator field_iterator;
    1212             :     ZoneVector<StateValueList*>::iterator nested_iterator;
    1213             :   };
    1214             : 
    1215     3689920 :   void ReserveSize(size_t size) { fields_.reserve(size); }
    1216             : 
    1217       89040 :   StateValueList* PushRecursiveField(Zone* zone, size_t id) {
    1218      178080 :     fields_.push_back(StateValueDescriptor::Recursive(id));
    1219             :     StateValueList* nested =
    1220      178080 :         new (zone->New(sizeof(StateValueList))) StateValueList(zone);
    1221       89040 :     nested_.push_back(nested);
    1222       89040 :     return nested;
    1223             :   }
    1224        5985 :   void PushArgumentsElements(ArgumentsStateType type) {
    1225       11970 :     fields_.push_back(StateValueDescriptor::ArgumentsElements(type));
    1226        5985 :   }
    1227        6293 :   void PushArgumentsLength(ArgumentsStateType type) {
    1228       12586 :     fields_.push_back(StateValueDescriptor::ArgumentsLength(type));
    1229        6293 :   }
    1230       18781 :   void PushDuplicate(size_t id) {
    1231       37562 :     fields_.push_back(StateValueDescriptor::Duplicate(id));
    1232       18781 :   }
    1233             :   void PushPlain(MachineType type) {
    1234    45156790 :     fields_.push_back(StateValueDescriptor::Plain(type));
    1235             :   }
    1236    27765778 :   void PushOptimizedOut() {
    1237    55531666 :     fields_.push_back(StateValueDescriptor::OptimizedOut());
    1238    27765888 :   }
    1239             : 
    1240             :   iterator begin() { return iterator(fields_.begin(), nested_.begin()); }
    1241             :   iterator end() { return iterator(fields_.end(), nested_.end()); }
    1242             : 
    1243             :  private:
    1244             :   ZoneVector<StateValueDescriptor> fields_;
    1245             :   ZoneVector<StateValueList*> nested_;
    1246             : };
    1247             : 
    1248             : class FrameStateDescriptor : public ZoneObject {
    1249             :  public:
    1250             :   FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
    1251             :                        OutputFrameStateCombine state_combine,
    1252             :                        size_t parameters_count, size_t locals_count,
    1253             :                        size_t stack_count,
    1254             :                        MaybeHandle<SharedFunctionInfo> shared_info,
    1255             :                        FrameStateDescriptor* outer_state = nullptr);
    1256             : 
    1257             :   FrameStateType type() const { return type_; }
    1258             :   BailoutId bailout_id() const { return bailout_id_; }
    1259             :   OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
    1260             :   size_t parameters_count() const { return parameters_count_; }
    1261             :   size_t locals_count() const { return locals_count_; }
    1262             :   size_t stack_count() const { return stack_count_; }
    1263             :   MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
    1264             :   FrameStateDescriptor* outer_state() const { return outer_state_; }
    1265             :   bool HasContext() const {
    1266      266352 :     return FrameStateFunctionInfo::IsJSFunctionType(type_) ||
    1267    10732930 :            type_ == FrameStateType::kBuiltinContinuation ||
    1268             :            type_ == FrameStateType::kConstructStub;
    1269             :   }
    1270             : 
    1271             :   size_t GetSize() const;
    1272             :   size_t GetTotalSize() const;
    1273             :   size_t GetFrameCount() const;
    1274             :   size_t GetJSFrameCount() const;
    1275             : 
    1276     3689917 :   StateValueList* GetStateValueDescriptors() { return &values_; }
    1277             : 
    1278             :   static const int kImpossibleValue = 0xdead;
    1279             : 
    1280             :  private:
    1281             :   FrameStateType type_;
    1282             :   BailoutId bailout_id_;
    1283             :   OutputFrameStateCombine frame_state_combine_;
    1284             :   size_t parameters_count_;
    1285             :   size_t locals_count_;
    1286             :   size_t stack_count_;
    1287             :   StateValueList values_;
    1288             :   MaybeHandle<SharedFunctionInfo> const shared_info_;
    1289             :   FrameStateDescriptor* outer_state_;
    1290             : };
    1291             : 
    1292             : // A deoptimization entry is a pair of the reason why we deoptimize and the
    1293             : // frame state descriptor that we have to go back to.
    1294             : class DeoptimizationEntry final {
    1295             :  public:
    1296             :   DeoptimizationEntry() = default;
    1297             :   DeoptimizationEntry(FrameStateDescriptor* descriptor, DeoptimizeKind kind,
    1298             :                       DeoptimizeReason reason, VectorSlotPair const& feedback)
    1299             :       : descriptor_(descriptor),
    1300             :         kind_(kind),
    1301             :         reason_(reason),
    1302     3335864 :         feedback_(feedback) {}
    1303             : 
    1304             :   FrameStateDescriptor* descriptor() const { return descriptor_; }
    1305             :   DeoptimizeKind kind() const { return kind_; }
    1306             :   DeoptimizeReason reason() const { return reason_; }
    1307             :   VectorSlotPair const& feedback() const { return feedback_; }
    1308             : 
    1309             :  private:
    1310             :   FrameStateDescriptor* descriptor_ = nullptr;
    1311             :   DeoptimizeKind kind_ = DeoptimizeKind::kEager;
    1312             :   DeoptimizeReason reason_ = DeoptimizeReason::kUnknown;
    1313             :   VectorSlotPair feedback_ = VectorSlotPair();
    1314             : };
    1315             : 
    1316             : using DeoptimizationVector = ZoneVector<DeoptimizationEntry>;
    1317             : 
    1318             : class V8_EXPORT_PRIVATE PhiInstruction final
    1319             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1320             :  public:
    1321             :   using Inputs = ZoneVector<InstructionOperand>;
    1322             : 
    1323             :   PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
    1324             : 
    1325             :   void SetInput(size_t offset, int virtual_register);
    1326             :   void RenameInput(size_t offset, int virtual_register);
    1327             : 
    1328             :   int virtual_register() const { return virtual_register_; }
    1329             :   const IntVector& operands() const { return operands_; }
    1330             : 
    1331             :   // TODO(dcarney): this has no real business being here, since it's internal to
    1332             :   // the register allocator, but putting it here was convenient.
    1333           0 :   const InstructionOperand& output() const { return output_; }
    1334     4181515 :   InstructionOperand& output() { return output_; }
    1335             : 
    1336             :  private:
    1337             :   const int virtual_register_;
    1338             :   InstructionOperand output_;
    1339             :   IntVector operands_;
    1340             : };
    1341             : 
    1342             : // Analogue of BasicBlock for Instructions instead of Nodes.
    1343             : class V8_EXPORT_PRIVATE InstructionBlock final
    1344             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1345             :  public:
    1346             :   InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
    1347             :                    RpoNumber loop_end, bool deferred, bool handler);
    1348             : 
    1349             :   // Instruction indexes (used by the register allocator).
    1350             :   int first_instruction_index() const {
    1351             :     DCHECK_LE(0, code_start_);
    1352             :     DCHECK_LT(0, code_end_);
    1353             :     DCHECK_GE(code_end_, code_start_);
    1354             :     return code_start_;
    1355             :   }
    1356             :   int last_instruction_index() const {
    1357             :     DCHECK_LE(0, code_start_);
    1358             :     DCHECK_LT(0, code_end_);
    1359             :     DCHECK_GE(code_end_, code_start_);
    1360   305052071 :     return code_end_ - 1;
    1361             :   }
    1362             : 
    1363             :   int32_t code_start() const { return code_start_; }
    1364    40995346 :   void set_code_start(int32_t start) { code_start_ = start; }
    1365             : 
    1366             :   int32_t code_end() const { return code_end_; }
    1367    40996396 :   void set_code_end(int32_t end) { code_end_ = end; }
    1368             : 
    1369             :   bool IsDeferred() const { return deferred_; }
    1370             :   bool IsHandler() const { return handler_; }
    1371             : 
    1372             :   RpoNumber ao_number() const { return ao_number_; }
    1373             :   RpoNumber rpo_number() const { return rpo_number_; }
    1374             :   RpoNumber loop_header() const { return loop_header_; }
    1375             :   RpoNumber loop_end() const {
    1376             :     DCHECK(IsLoopHeader());
    1377             :     return loop_end_;
    1378             :   }
    1379             :   inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
    1380             :   inline bool IsSwitchTarget() const { return switch_target_; }
    1381             :   inline bool ShouldAlign() const { return alignment_; }
    1382             : 
    1383             :   using Predecessors = ZoneVector<RpoNumber>;
    1384             :   Predecessors& predecessors() { return predecessors_; }
    1385             :   const Predecessors& predecessors() const { return predecessors_; }
    1386             :   size_t PredecessorCount() const { return predecessors_.size(); }
    1387             :   size_t PredecessorIndexOf(RpoNumber rpo_number) const;
    1388             : 
    1389             :   using Successors = ZoneVector<RpoNumber>;
    1390             :   Successors& successors() { return successors_; }
    1391             :   const Successors& successors() const { return successors_; }
    1392             :   size_t SuccessorCount() const { return successors_.size(); }
    1393             : 
    1394             :   using PhiInstructions = ZoneVector<PhiInstruction*>;
    1395             :   const PhiInstructions& phis() const { return phis_; }
    1396     2090695 :   PhiInstruction* PhiAt(size_t i) const { return phis_[i]; }
    1397     2090782 :   void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
    1398             : 
    1399    37044590 :   void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
    1400             : 
    1401      485214 :   void set_alignment(bool val) { alignment_ = val; }
    1402             : 
    1403      429860 :   void set_switch_target(bool val) { switch_target_ = val; }
    1404             : 
    1405             :   bool needs_frame() const { return needs_frame_; }
    1406    21680810 :   void mark_needs_frame() { needs_frame_ = true; }
    1407             : 
    1408             :   bool must_construct_frame() const { return must_construct_frame_; }
    1409     2662973 :   void mark_must_construct_frame() { must_construct_frame_ = true; }
    1410             : 
    1411             :   bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
    1412     3018953 :   void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
    1413             : 
    1414             :  private:
    1415             :   Successors successors_;
    1416             :   Predecessors predecessors_;
    1417             :   PhiInstructions phis_;
    1418             :   RpoNumber ao_number_;  // Assembly order number.
    1419             :   const RpoNumber rpo_number_;
    1420             :   const RpoNumber loop_header_;
    1421             :   const RpoNumber loop_end_;
    1422             :   int32_t code_start_;   // start index of arch-specific code.
    1423             :   int32_t code_end_ = -1;     // end index of arch-specific code.
    1424             :   const bool deferred_ = -1;  // Block contains deferred code.
    1425             :   const bool handler_;   // Block is a handler entry point.
    1426             :   bool switch_target_ = false;
    1427             :   bool alignment_ = false;  // insert alignment before this block
    1428             :   bool needs_frame_ = false;
    1429             :   bool must_construct_frame_ = false;
    1430             :   bool must_deconstruct_frame_ = false;
    1431             : };
    1432             : 
    1433             : class InstructionSequence;
    1434             : 
    1435             : struct PrintableInstructionBlock {
    1436             :   const InstructionBlock* block_;
    1437             :   const InstructionSequence* code_;
    1438             : };
    1439             : 
    1440             : std::ostream& operator<<(std::ostream&, const PrintableInstructionBlock&);
    1441             : 
    1442             : using ConstantDeque = ZoneDeque<Constant>;
    1443             : using ConstantMap = std::map<int, Constant, std::less<int>,
    1444             :                              ZoneAllocator<std::pair<const int, Constant> > >;
    1445             : 
    1446             : using InstructionDeque = ZoneDeque<Instruction*>;
    1447             : using ReferenceMapDeque = ZoneDeque<ReferenceMap*>;
    1448             : using InstructionBlocks = ZoneVector<InstructionBlock*>;
    1449             : 
    1450             : // Represents architecture-specific generated code before, during, and after
    1451             : // register allocation.
    1452        2910 : class V8_EXPORT_PRIVATE InstructionSequence final
    1453             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1454             :  public:
    1455             :   static InstructionBlocks* InstructionBlocksFor(Zone* zone,
    1456             :                                                  const Schedule* schedule);
    1457             :   InstructionSequence(Isolate* isolate, Zone* zone,
    1458             :                       InstructionBlocks* instruction_blocks);
    1459             : 
    1460             :   int NextVirtualRegister();
    1461             :   int VirtualRegisterCount() const { return next_virtual_register_; }
    1462             : 
    1463             :   const InstructionBlocks& instruction_blocks() const {
    1464             :     return *instruction_blocks_;
    1465             :   }
    1466             : 
    1467             :   const InstructionBlocks& ao_blocks() const { return *ao_blocks_; }
    1468             : 
    1469             :   int InstructionBlockCount() const {
    1470    50922099 :     return static_cast<int>(instruction_blocks_->size());
    1471             :   }
    1472             : 
    1473   407024911 :   InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
    1474   814049822 :     return instruction_blocks_->at(rpo_number.ToSize());
    1475             :   }
    1476             : 
    1477      231802 :   int LastLoopInstructionIndex(const InstructionBlock* block) {
    1478      231802 :     return instruction_blocks_->at(block->loop_end().ToSize() - 1)
    1479      463604 :         ->last_instruction_index();
    1480             :   }
    1481             : 
    1482   191170309 :   const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
    1483   382340618 :     return instruction_blocks_->at(rpo_number.ToSize());
    1484             :   }
    1485             : 
    1486             :   InstructionBlock* GetInstructionBlock(int instruction_index) const;
    1487             : 
    1488             :   static MachineRepresentation DefaultRepresentation() {
    1489             :     return MachineType::PointerRepresentation();
    1490             :   }
    1491             :   MachineRepresentation GetRepresentation(int virtual_register) const;
    1492             :   void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
    1493             : 
    1494             :   bool IsReference(int virtual_register) const {
    1495    79479008 :     return CanBeTaggedOrCompressedPointer(GetRepresentation(virtual_register));
    1496             :   }
    1497             :   bool IsFP(int virtual_register) const {
    1498     3023868 :     return IsFloatingPoint(GetRepresentation(virtual_register));
    1499             :   }
    1500             :   int representation_mask() const { return representation_mask_; }
    1501             :   bool HasFPVirtualRegisters() const {
    1502             :     constexpr int kFPRepMask =
    1503             :         RepresentationBit(MachineRepresentation::kFloat32) |
    1504             :         RepresentationBit(MachineRepresentation::kFloat64) |
    1505             :         RepresentationBit(MachineRepresentation::kSimd128);
    1506     2642439 :     return (representation_mask() & kFPRepMask) != 0;
    1507             :   }
    1508             : 
    1509             :   Instruction* GetBlockStart(RpoNumber rpo) const;
    1510             : 
    1511             :   using const_iterator = InstructionDeque::const_iterator;
    1512             :   const_iterator begin() const { return instructions_.begin(); }
    1513             :   const_iterator end() const { return instructions_.end(); }
    1514             :   const InstructionDeque& instructions() const { return instructions_; }
    1515             :   int LastInstructionIndex() const {
    1516           9 :     return static_cast<int>(instructions().size()) - 1;
    1517             :   }
    1518             : 
    1519             :   Instruction* InstructionAt(int index) const {
    1520             :     DCHECK_LE(0, index);
    1521             :     DCHECK_GT(instructions_.size(), index);
    1522   516015655 :     return instructions_[index];
    1523             :   }
    1524             : 
    1525             :   Isolate* isolate() const { return isolate_; }
    1526             :   const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
    1527             :   Zone* zone() const { return zone_; }
    1528             : 
    1529             :   // Used by the instruction selector while adding instructions.
    1530             :   int AddInstruction(Instruction* instr);
    1531             :   void StartBlock(RpoNumber rpo);
    1532             :   void EndBlock(RpoNumber rpo);
    1533             : 
    1534             :   int AddConstant(int virtual_register, Constant constant) {
    1535             :     // TODO(titzer): allow RPO numbers as constants?
    1536             :     DCHECK_NE(Constant::kRpoNumber, constant.type());
    1537             :     DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
    1538             :     DCHECK(constants_.find(virtual_register) == constants_.end());
    1539    14350418 :     constants_.insert(std::make_pair(virtual_register, constant));
    1540             :     return virtual_register;
    1541             :   }
    1542             :   Constant GetConstant(int virtual_register) const {
    1543             :     ConstantMap::const_iterator it = constants_.find(virtual_register);
    1544             :     DCHECK(it != constants_.end());
    1545             :     DCHECK_EQ(virtual_register, it->first);
    1546    19018765 :     return it->second;
    1547             :   }
    1548             : 
    1549             :   using Immediates = ZoneVector<Constant>;
    1550             :   Immediates& immediates() { return immediates_; }
    1551             : 
    1552    64505996 :   ImmediateOperand AddImmediate(const Constant& constant) {
    1553    64505996 :     if (constant.type() == Constant::kInt32 &&
    1554             :         RelocInfo::IsNone(constant.rmode())) {
    1555    20942118 :       return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
    1556             :     }
    1557    43563878 :     int index = static_cast<int>(immediates_.size());
    1558    43563878 :     immediates_.push_back(constant);
    1559    43564413 :     return ImmediateOperand(ImmediateOperand::INDEXED, index);
    1560             :   }
    1561             : 
    1562    65220704 :   Constant GetImmediate(const ImmediateOperand* op) const {
    1563    65220704 :     switch (op->type()) {
    1564             :       case ImmediateOperand::INLINE:
    1565    19262615 :         return Constant(op->inline_value());
    1566             :       case ImmediateOperand::INDEXED: {
    1567             :         int index = op->indexed_value();
    1568             :         DCHECK_LE(0, index);
    1569             :         DCHECK_GT(immediates_.size(), index);
    1570    91916178 :         return immediates_[index];
    1571             :       }
    1572             :     }
    1573           0 :     UNREACHABLE();
    1574             :   }
    1575             : 
    1576             :   int AddDeoptimizationEntry(FrameStateDescriptor* descriptor,
    1577             :                              DeoptimizeKind kind, DeoptimizeReason reason,
    1578             :                              VectorSlotPair const& feedback);
    1579             :   DeoptimizationEntry const& GetDeoptimizationEntry(int deoptimization_id);
    1580             :   int GetDeoptimizationEntryCount() const {
    1581         252 :     return static_cast<int>(deoptimization_entries_.size());
    1582             :   }
    1583             : 
    1584             :   RpoNumber InputRpo(Instruction* instr, size_t index);
    1585             : 
    1586             :   bool GetSourcePosition(const Instruction* instr,
    1587             :                          SourcePosition* result) const;
    1588             :   void SetSourcePosition(const Instruction* instr, SourcePosition value);
    1589             : 
    1590             :   bool ContainsCall() const {
    1591             :     for (Instruction* instr : instructions_) {
    1592             :       if (instr->IsCall()) return true;
    1593             :     }
    1594             :     return false;
    1595             :   }
    1596             : 
    1597             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
    1598             :   void Print() const;
    1599             : 
    1600             :   void PrintBlock(int block_id) const;
    1601             : 
    1602             :   void ValidateEdgeSplitForm() const;
    1603             :   void ValidateDeferredBlockExitPaths() const;
    1604             :   void ValidateDeferredBlockEntryPaths() const;
    1605             :   void ValidateSSA() const;
    1606             : 
    1607             :   static void SetRegisterConfigurationForTesting(
    1608             :       const RegisterConfiguration* regConfig);
    1609             :   static void ClearRegisterConfigurationForTesting();
    1610             : 
    1611             :   void RecomputeAssemblyOrderForTesting();
    1612             : 
    1613             :  private:
    1614             :   friend V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
    1615             :                                                     const InstructionSequence&);
    1616             : 
    1617             :   using SourcePositionMap = ZoneMap<const Instruction*, SourcePosition>;
    1618             : 
    1619             :   static const RegisterConfiguration* RegisterConfigurationForTesting();
    1620             :   static const RegisterConfiguration* registerConfigurationForTesting_;
    1621             : 
    1622             :   // Puts the deferred blocks last and may rotate loops.
    1623             :   void ComputeAssemblyOrder();
    1624             : 
    1625             :   Isolate* isolate_;
    1626             :   Zone* const zone_;
    1627             :   InstructionBlocks* const instruction_blocks_;
    1628             :   InstructionBlocks* ao_blocks_;
    1629             :   SourcePositionMap source_positions_;
    1630             :   ConstantMap constants_;
    1631             :   Immediates immediates_;
    1632             :   InstructionDeque instructions_;
    1633             :   int next_virtual_register_;
    1634             :   ReferenceMapDeque reference_maps_;
    1635             :   ZoneVector<MachineRepresentation> representations_;
    1636             :   int representation_mask_;
    1637             :   DeoptimizationVector deoptimization_entries_;
    1638             : 
    1639             :   // Used at construction time
    1640             :   InstructionBlock* current_block_;
    1641             : 
    1642             :   DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
    1643             : };
    1644             : 
    1645             : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
    1646             :                                            const InstructionSequence&);
    1647             : 
    1648             : }  // namespace compiler
    1649             : }  // namespace internal
    1650             : }  // namespace v8
    1651             : 
    1652             : #endif  // V8_COMPILER_BACKEND_INSTRUCTION_H_

Generated by: LCOV version 1.10