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

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_COMPILER_BACKEND_INSTRUCTION_H_
       6             : #define V8_COMPILER_BACKEND_INSTRUCTION_H_
       7             : 
       8             : #include <deque>
       9             : #include <iosfwd>
      10             : #include <map>
      11             : #include <set>
      12             : 
      13             : #include "src/base/compiler-specific.h"
      14             : #include "src/compiler/backend/instruction-codes.h"
      15             : #include "src/compiler/common-operator.h"
      16             : #include "src/compiler/frame.h"
      17             : #include "src/compiler/opcodes.h"
      18             : #include "src/double.h"
      19             : #include "src/external-reference.h"
      20             : #include "src/globals.h"
      21             : #include "src/register-arch.h"
      22             : #include "src/source-position.h"
      23             : #include "src/zone/zone-allocator.h"
      24             : 
      25             : namespace v8 {
      26             : namespace internal {
      27             : 
      28             : class RegisterConfiguration;
      29             : 
      30             : namespace compiler {
      31             : 
      32             : class Schedule;
      33             : class SourcePositionTable;
      34             : 
      35             : class V8_EXPORT_PRIVATE InstructionOperand {
      36             :  public:
      37             :   static const int kInvalidVirtualRegister = -1;
      38             : 
      39             :   enum Kind {
      40             :     INVALID,
      41             :     UNALLOCATED,
      42             :     CONSTANT,
      43             :     IMMEDIATE,
      44             :     // Location operand kinds.
      45             :     EXPLICIT,
      46             :     ALLOCATED,
      47             :     FIRST_LOCATION_OPERAND_KIND = EXPLICIT
      48             :     // Location operand kinds must be last.
      49             :   };
      50             : 
      51             :   InstructionOperand() : InstructionOperand(INVALID) {}
      52             : 
      53  3528417530 :   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     2594825 :   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       84754 :   INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
      70             :   // ExplicitOperands do not participate in register allocation. They are
      71             :   // created by the instruction selector for direct access to registers and
      72             :   // stack slots, completely bypassing the register allocator. They are never
      73             :   // associated with a virtual register
      74             :   INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
      75             :   // AllocatedOperands are registers or stack slots that are assigned by the
      76             :   // register allocator and are always associated with a virtual register.
      77             :   INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
      78             : #undef INSTRUCTION_OPERAND_PREDICATE
      79             : 
      80             :   inline bool IsAnyLocationOperand() const;
      81             :   inline bool IsLocationOperand() const;
      82             :   inline bool IsFPLocationOperand() const;
      83             :   inline bool IsAnyRegister() const;
      84             :   inline bool IsRegister() const;
      85             :   inline bool IsFPRegister() const;
      86             :   inline bool IsFloatRegister() const;
      87             :   inline bool IsDoubleRegister() const;
      88             :   inline bool IsSimd128Register() const;
      89             :   inline bool IsAnyStackSlot() const;
      90             :   inline bool IsStackSlot() const;
      91             :   inline bool IsFPStackSlot() const;
      92             :   inline bool IsFloatStackSlot() const;
      93             :   inline bool IsDoubleStackSlot() const;
      94             :   inline bool IsSimd128StackSlot() const;
      95             : 
      96             :   template <typename SubKindOperand>
      97             :   static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
      98           0 :     void* buffer = zone->New(sizeof(op));
      99           0 :     return new (buffer) SubKindOperand(op);
     100             :   }
     101             : 
     102             :   static void ReplaceWith(InstructionOperand* dest,
     103             :                           const InstructionOperand* src) {
     104    47681941 :     *dest = *src;
     105             :   }
     106             : 
     107             :   bool Equals(const InstructionOperand& that) const {
     108    29947701 :     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   665044717 :     return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
     117             :   }
     118             : 
     119             :   bool CompareCanonicalized(const InstructionOperand& that) const {
     120    58690751 :     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   210397168 :   explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
     130             : 
     131             :   inline uint64_t GetCanonicalizedValue() const;
     132             : 
     133             :   class KindField : public BitField64<Kind, 0, 3> {};
     134             : 
     135             :   uint64_t value_;
     136             : };
     137             : 
     138             : typedef ZoneVector<InstructionOperand> InstructionOperandVector;
     139             : 
     140             : std::ostream& operator<<(std::ostream&, const InstructionOperand&);
     141             : 
     142             : #define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind)      \
     143             :                                                                  \
     144             :   static OperandType* cast(InstructionOperand* op) {             \
     145             :     DCHECK_EQ(OperandKind, op->kind());                          \
     146             :     return static_cast<OperandType*>(op);                        \
     147             :   }                                                              \
     148             :                                                                  \
     149             :   static const OperandType* cast(const InstructionOperand* op) { \
     150             :     DCHECK_EQ(OperandKind, op->kind());                          \
     151             :     return static_cast<const OperandType*>(op);                  \
     152             :   }                                                              \
     153             :                                                                  \
     154             :   static OperandType cast(const InstructionOperand& op) {        \
     155             :     DCHECK_EQ(OperandKind, op.kind());                           \
     156             :     return *static_cast<const OperandType*>(&op);                \
     157             :   }
     158             : 
     159             : class UnallocatedOperand final : public InstructionOperand {
     160             :  public:
     161             :   enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
     162             : 
     163             :   enum ExtendedPolicy {
     164             :     NONE,
     165             :     REGISTER_OR_SLOT,
     166             :     REGISTER_OR_SLOT_OR_CONSTANT,
     167             :     FIXED_REGISTER,
     168             :     FIXED_FP_REGISTER,
     169             :     MUST_HAVE_REGISTER,
     170             :     MUST_HAVE_SLOT,
     171             :     SAME_AS_FIRST_INPUT
     172             :   };
     173             : 
     174             :   // Lifetime of operand inside the instruction.
     175             :   enum Lifetime {
     176             :     // USED_AT_START operand is guaranteed to be live only at instruction start.
     177             :     // The register allocator is free to assign the same register to some other
     178             :     // operand used inside instruction (i.e. temporary or output).
     179             :     USED_AT_START,
     180             : 
     181             :     // USED_AT_END operand is treated as live until the end of instruction.
     182             :     // This means that register allocator will not reuse its register for any
     183             :     // other operand inside instruction.
     184             :     USED_AT_END
     185             :   };
     186             : 
     187             :   UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
     188             :       : UnallocatedOperand(virtual_register) {
     189    37769296 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     190    35670394 :     value_ |= ExtendedPolicyField::encode(policy);
     191    66743682 :     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     4305908 :               << 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    26724527 :     value_ |= LifetimeField::encode(USED_AT_END);
     209    26724527 :     value_ |= FixedRegisterField::encode(index);
     210             :   }
     211             : 
     212             :   UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
     213             :                      int virtual_register)
     214             :       : UnallocatedOperand(virtual_register) {
     215     5312263 :     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     216    29184287 :     value_ |= ExtendedPolicyField::encode(policy);
     217     2379411 :     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       73100 :     value_ |= HasSecondaryStorageField::encode(true);
     223       73100 :     value_ |= SecondaryStorageField::encode(slot_id);
     224             :   }
     225             : 
     226             :   UnallocatedOperand(const UnallocatedOperand& other, int virtual_register) {
     227             :     DCHECK_NE(kInvalidVirtualRegister, virtual_register);
     228             :     value_ = VirtualRegisterField::update(
     229     5268174 :         other.value_, static_cast<uint32_t>(virtual_register));
     230             :   }
     231             : 
     232             :   // Predicates for the operand policy.
     233             :   bool HasRegisterOrSlotPolicy() const {
     234    99051918 :     return basic_policy() == EXTENDED_POLICY &&
     235             :            extended_policy() == REGISTER_OR_SLOT;
     236             :   }
     237             :   bool HasRegisterOrSlotOrConstantPolicy() const {
     238    99052108 :     return basic_policy() == EXTENDED_POLICY &&
     239             :            extended_policy() == REGISTER_OR_SLOT_OR_CONSTANT;
     240             :   }
     241             :   bool HasFixedPolicy() const {
     242    91934379 :     return basic_policy() == FIXED_SLOT ||
     243   158537024 :            extended_policy() == FIXED_REGISTER ||
     244             :            extended_policy() == FIXED_FP_REGISTER;
     245             :   }
     246             :   bool HasRegisterPolicy() const {
     247   209311880 :     return basic_policy() == EXTENDED_POLICY &&
     248             :            extended_policy() == MUST_HAVE_REGISTER;
     249             :   }
     250             :   bool HasSlotPolicy() const {
     251   230969098 :     return basic_policy() == EXTENDED_POLICY &&
     252             :            extended_policy() == MUST_HAVE_SLOT;
     253             :   }
     254             :   bool HasSameAsInputPolicy() const {
     255    43749962 :     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    53382245 :     return basic_policy() == EXTENDED_POLICY &&
     261             :            extended_policy() == FIXED_REGISTER;
     262             :   }
     263             :   bool HasFixedFPRegisterPolicy() const {
     264      290443 :     return basic_policy() == EXTENDED_POLICY &&
     265             :            extended_policy() == FIXED_FP_REGISTER;
     266             :   }
     267             :   bool HasSecondaryStorage() const {
     268     7978201 :     return basic_policy() == EXTENDED_POLICY &&
     269    17013595 :            extended_policy() == FIXED_REGISTER &&
     270             :            HasSecondaryStorageField::decode(value_);
     271             :   }
     272             :   int GetSecondaryStorage() const {
     273             :     DCHECK(HasSecondaryStorage());
     274       73043 :     return SecondaryStorageField::decode(value_);
     275             :   }
     276             : 
     277             :   // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
     278   216062979 :   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     4300277 :     return static_cast<int>(static_cast<int64_t>(value_) >>
     290     4300277 :                             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   410915718 :     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           2 :     return LifetimeField::decode(value_) == USED_AT_START;
     308             :   }
     309             : 
     310    30632148 :   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   174626380 :         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    25373633 :         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
     363             :   }
     364             : 
     365             :   int32_t virtual_register() const {
     366    56470797 :     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          16 :   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    62970662 :               << ValueField::kShift;
     388             :   }
     389             : 
     390    63591860 :   ImmediateType type() const { return TypeField::decode(value_); }
     391             : 
     392             :   int32_t inline_value() const {
     393             :     DCHECK_EQ(INLINE, type());
     394    17200079 :     return static_cast<int64_t>(value_) >> ValueField::kShift;
     395             :   }
     396             : 
     397             :   int32_t indexed_value() const {
     398             :     DCHECK_EQ(INDEXED, type());
     399    46392508 :     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      719998 :     value_ |= LocationKindField::encode(location_kind);
     424   134858879 :     value_ |= RepresentationField::encode(rep);
     425             :     value_ |= static_cast<uint64_t>(static_cast<int64_t>(index))
     426   134877879 :               << IndexField::kShift;
     427             :   }
     428             : 
     429             :   int index() const {
     430             :     DCHECK(IsStackSlot() || IsFPStackSlot());
     431    73624451 :     return static_cast<int64_t>(value_) >> IndexField::kShift;
     432             :   }
     433             : 
     434             :   int register_code() const {
     435             :     DCHECK(IsRegister() || IsFPRegister());
     436   185896725 :     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       32754 :     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             :         return true;
     481             :       case MachineRepresentation::kBit:
     482             :       case MachineRepresentation::kWord8:
     483             :       case MachineRepresentation::kWord16:
     484             :       case MachineRepresentation::kNone:
     485             :         return false;
     486             :     }
     487             :     UNREACHABLE();
     488             :   }
     489             : 
     490             :   // Return true if the locations can be moved to one another.
     491             :   bool IsCompatible(LocationOperand* op);
     492             : 
     493             :   static LocationOperand* cast(InstructionOperand* op) {
     494             :     DCHECK(op->IsAnyLocationOperand());
     495             :     return static_cast<LocationOperand*>(op);
     496             :   }
     497             : 
     498             :   static const LocationOperand* cast(const InstructionOperand* op) {
     499             :     DCHECK(op->IsAnyLocationOperand());
     500             :     return static_cast<const LocationOperand*>(op);
     501             :   }
     502             : 
     503             :   static LocationOperand cast(const InstructionOperand& op) {
     504             :     DCHECK(op.IsAnyLocationOperand());
     505       46824 :     return *static_cast<const LocationOperand*>(&op);
     506             :   }
     507             : 
     508             :   STATIC_ASSERT(KindField::kSize == 3);
     509             :   class LocationKindField : public BitField64<LocationKind, 3, 2> {};
     510             :   class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
     511             :   class IndexField : public BitField64<int32_t, 35, 29> {};
     512             : };
     513             : 
     514             : class V8_EXPORT_PRIVATE ExplicitOperand
     515             :     : public NON_EXPORTED_BASE(LocationOperand) {
     516             :  public:
     517             :   ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
     518             : 
     519             :   static ExplicitOperand* New(Zone* zone, LocationKind kind,
     520             :                               MachineRepresentation rep, int index) {
     521             :     return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
     522             :   }
     523             : 
     524             :   INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT)
     525             : };
     526             : 
     527             : class AllocatedOperand : public LocationOperand {
     528             :  public:
     529             :   AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
     530             :       : LocationOperand(ALLOCATED, kind, rep, index) {}
     531             : 
     532           0 :   static AllocatedOperand* New(Zone* zone, LocationKind kind,
     533             :                                MachineRepresentation rep, int index) {
     534           0 :     return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
     535             :   }
     536             : 
     537       24243 :   INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED)
     538             : };
     539             : 
     540             : #undef INSTRUCTION_OPERAND_CASTS
     541             : 
     542             : bool InstructionOperand::IsAnyLocationOperand() const {
     543  1734779187 :   return this->kind() >= FIRST_LOCATION_OPERAND_KIND;
     544             : }
     545             : 
     546             : bool InstructionOperand::IsLocationOperand() const {
     547             :   return IsAnyLocationOperand() &&
     548             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     549             : }
     550             : 
     551             : bool InstructionOperand::IsFPLocationOperand() const {
     552             :   return IsAnyLocationOperand() &&
     553             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     554             : }
     555             : 
     556             : bool InstructionOperand::IsAnyRegister() const {
     557  2742097699 :   return IsAnyLocationOperand() &&
     558             :          LocationOperand::cast(this)->location_kind() ==
     559             :              LocationOperand::REGISTER;
     560             : }
     561             : 
     562             : bool InstructionOperand::IsRegister() const {
     563   311967152 :   return IsAnyRegister() &&
     564             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     565             : }
     566             : 
     567             : bool InstructionOperand::IsFPRegister() const {
     568  1814121486 :   return IsAnyRegister() &&
     569             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     570             : }
     571             : 
     572             : bool InstructionOperand::IsFloatRegister() const {
     573      743781 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     574             :                                 MachineRepresentation::kFloat32;
     575             : }
     576             : 
     577             : bool InstructionOperand::IsDoubleRegister() const {
     578      728099 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     579             :                                 MachineRepresentation::kFloat64;
     580             : }
     581             : 
     582             : bool InstructionOperand::IsSimd128Register() const {
     583      723609 :   return IsAnyRegister() && LocationOperand::cast(this)->representation() ==
     584             :                                 MachineRepresentation::kSimd128;
     585             : }
     586             : 
     587             : bool InstructionOperand::IsAnyStackSlot() const {
     588   335244291 :   return IsAnyLocationOperand() &&
     589             :          LocationOperand::cast(this)->location_kind() ==
     590             :              LocationOperand::STACK_SLOT;
     591             : }
     592             : 
     593             : bool InstructionOperand::IsStackSlot() const {
     594   252365167 :   return IsAnyStackSlot() &&
     595             :          !IsFloatingPoint(LocationOperand::cast(this)->representation());
     596             : }
     597             : 
     598             : bool InstructionOperand::IsFPStackSlot() const {
     599    20353103 :   return IsAnyStackSlot() &&
     600             :          IsFloatingPoint(LocationOperand::cast(this)->representation());
     601             : }
     602             : 
     603             : bool InstructionOperand::IsFloatStackSlot() const {
     604       14673 :   return IsAnyLocationOperand() &&
     605             :          LocationOperand::cast(this)->location_kind() ==
     606       29346 :              LocationOperand::STACK_SLOT &&
     607             :          LocationOperand::cast(this)->representation() ==
     608             :              MachineRepresentation::kFloat32;
     609             : }
     610             : 
     611             : bool InstructionOperand::IsDoubleStackSlot() const {
     612       10785 :   return IsAnyLocationOperand() &&
     613             :          LocationOperand::cast(this)->location_kind() ==
     614       21570 :              LocationOperand::STACK_SLOT &&
     615             :          LocationOperand::cast(this)->representation() ==
     616             :              MachineRepresentation::kFloat64;
     617             : }
     618             : 
     619             : bool InstructionOperand::IsSimd128StackSlot() const {
     620             :   return IsAnyLocationOperand() &&
     621             :          LocationOperand::cast(this)->location_kind() ==
     622             :              LocationOperand::STACK_SLOT &&
     623             :          LocationOperand::cast(this)->representation() ==
     624             :              MachineRepresentation::kSimd128;
     625             : }
     626             : 
     627  1384570547 : uint64_t InstructionOperand::GetCanonicalizedValue() const {
     628  1384570547 :   if (IsAnyLocationOperand()) {
     629             :     MachineRepresentation canonical = MachineRepresentation::kNone;
     630  1121208136 :     if (IsFPRegister()) {
     631             :       if (kSimpleFPAliasing) {
     632             :         // We treat all FP register operands the same for simple aliasing.
     633             :         canonical = MachineRepresentation::kFloat64;
     634             :       } else {
     635             :         // We need to distinguish FP register operands of different reps when
     636             :         // aliasing is not simple (e.g. ARM).
     637             :         canonical = LocationOperand::cast(this)->representation();
     638             :       }
     639             :     }
     640             :     return InstructionOperand::KindField::update(
     641             :         LocationOperand::RepresentationField::update(this->value_, canonical),
     642  1121208136 :         LocationOperand::EXPLICIT);
     643             :   }
     644             :   return this->value_;
     645             : }
     646             : 
     647             : // Required for maps that don't care about machine type.
     648             : struct CompareOperandModuloType {
     649             :   bool operator()(const InstructionOperand& a,
     650             :                   const InstructionOperand& b) const {
     651             :     return a.CompareCanonicalized(b);
     652             :   }
     653             : };
     654             : 
     655             : class V8_EXPORT_PRIVATE MoveOperands final
     656             :     : public NON_EXPORTED_BASE(ZoneObject) {
     657             :  public:
     658             :   MoveOperands(const InstructionOperand& source,
     659             :                const InstructionOperand& destination)
     660    76361282 :       : source_(source), destination_(destination) {
     661             :     DCHECK(!source.IsInvalid() && !destination.IsInvalid());
     662             :   }
     663             : 
     664             :   const InstructionOperand& source() const { return source_; }
     665             :   InstructionOperand& source() { return source_; }
     666     1439779 :   void set_source(const InstructionOperand& operand) { source_ = operand; }
     667             : 
     668             :   const InstructionOperand& destination() const { return destination_; }
     669             :   InstructionOperand& destination() { return destination_; }
     670             :   void set_destination(const InstructionOperand& operand) {
     671    12331987 :     destination_ = operand;
     672             :   }
     673             : 
     674             :   // The gap resolver marks moves as "in-progress" by clearing the
     675             :   // destination (but not the source).
     676             :   bool IsPending() const {
     677    34406856 :     return destination_.IsInvalid() && !source_.IsInvalid();
     678             :   }
     679    12401643 :   void SetPending() { destination_ = InstructionOperand(); }
     680             : 
     681             :   // A move is redundant if it's been eliminated or if its source and
     682             :   // destination are the same.
     683   275942743 :   bool IsRedundant() const {
     684             :     DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
     685   498423905 :     return IsEliminated() || source_.EqualsCanonicalized(destination_);
     686             :   }
     687             : 
     688             :   // We clear both operands to indicate move that's been eliminated.
     689    43512115 :   void Eliminate() { source_ = destination_ = InstructionOperand(); }
     690             :   bool IsEliminated() const {
     691             :     DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
     692             :     return source_.IsInvalid();
     693             :   }
     694             : 
     695             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     696             :   void Print() const;
     697             : 
     698             :  private:
     699             :   InstructionOperand source_;
     700             :   InstructionOperand destination_;
     701             : 
     702             :   DISALLOW_COPY_AND_ASSIGN(MoveOperands);
     703             : };
     704             : 
     705             : std::ostream& operator<<(std::ostream&, const MoveOperands&);
     706             : 
     707             : class V8_EXPORT_PRIVATE ParallelMove final
     708             :     : public NON_EXPORTED_BASE(ZoneVector<MoveOperands*>),
     709             :       public NON_EXPORTED_BASE(ZoneObject) {
     710             :  public:
     711             :   explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {}
     712             : 
     713             :   MoveOperands* AddMove(const InstructionOperand& from,
     714             :                         const InstructionOperand& to) {
     715             :     Zone* zone = get_allocator().zone();
     716    63049163 :     return AddMove(from, to, zone);
     717             :   }
     718             : 
     719    75662120 :   MoveOperands* AddMove(const InstructionOperand& from,
     720             :                         const InstructionOperand& to,
     721             :                         Zone* operand_allocation_zone) {
     722    75662332 :     if (from.EqualsCanonicalized(to)) return nullptr;
     723    75553185 :     MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to);
     724    75553185 :     if (empty()) reserve(4);
     725    75553043 :     push_back(move);
     726    75553213 :     return move;
     727             :   }
     728             : 
     729             :   bool IsRedundant() const;
     730             : 
     731             :   // Prepare this ParallelMove to insert move as if it happened in a subsequent
     732             :   // ParallelMove.  move->source() may be changed.  Any MoveOperands added to
     733             :   // to_eliminate must be Eliminated.
     734             :   void PrepareInsertAfter(MoveOperands* move,
     735             :                           ZoneVector<MoveOperands*>* to_eliminate) const;
     736             : 
     737             :  private:
     738             :   DISALLOW_COPY_AND_ASSIGN(ParallelMove);
     739             : };
     740             : 
     741             : std::ostream& operator<<(std::ostream&, const ParallelMove&);
     742             : 
     743             : class ReferenceMap final : public ZoneObject {
     744             :  public:
     745             :   explicit ReferenceMap(Zone* zone)
     746     5842500 :       : reference_operands_(8, zone), instruction_position_(-1) {}
     747             : 
     748             :   const ZoneVector<InstructionOperand>& reference_operands() const {
     749             :     return reference_operands_;
     750             :   }
     751             :   int instruction_position() const { return instruction_position_; }
     752             : 
     753             :   void set_instruction_position(int pos) {
     754             :     DCHECK_EQ(-1, instruction_position_);
     755     5723976 :     instruction_position_ = pos;
     756             :   }
     757             : 
     758             :   void RecordReference(const AllocatedOperand& op);
     759             : 
     760             :  private:
     761             :   friend std::ostream& operator<<(std::ostream&, const ReferenceMap&);
     762             : 
     763             :   ZoneVector<InstructionOperand> reference_operands_;
     764             :   int instruction_position_;
     765             : };
     766             : 
     767             : std::ostream& operator<<(std::ostream&, const ReferenceMap&);
     768             : 
     769             : class InstructionBlock;
     770             : 
     771             : class V8_EXPORT_PRIVATE Instruction final {
     772             :  public:
     773             :   size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
     774             :   const InstructionOperand* OutputAt(size_t i) const {
     775             :     DCHECK(i < OutputCount());
     776             :     return &operands_[i];
     777             :   }
     778             :   InstructionOperand* OutputAt(size_t i) {
     779             :     DCHECK(i < OutputCount());
     780             :     return &operands_[i];
     781             :   }
     782             : 
     783    10600404 :   bool HasOutput() const { return OutputCount() > 0; }
     784             :   const InstructionOperand* Output() const { return OutputAt(0); }
     785             :   InstructionOperand* Output() { return OutputAt(0); }
     786             : 
     787             :   size_t InputCount() const { return InputCountField::decode(bit_field_); }
     788       22796 :   const InstructionOperand* InputAt(size_t i) const {
     789             :     DCHECK(i < InputCount());
     790     9209601 :     return &operands_[OutputCount() + i];
     791             :   }
     792   120948630 :   InstructionOperand* InputAt(size_t i) {
     793             :     DCHECK(i < InputCount());
     794   567055948 :     return &operands_[OutputCount() + i];
     795             :   }
     796             : 
     797             :   size_t TempCount() const { return TempCountField::decode(bit_field_); }
     798           0 :   const InstructionOperand* TempAt(size_t i) const {
     799             :     DCHECK(i < TempCount());
     800           0 :     return &operands_[OutputCount() + InputCount() + i];
     801             :   }
     802       50900 :   InstructionOperand* TempAt(size_t i) {
     803             :     DCHECK(i < TempCount());
     804     3386581 :     return &operands_[OutputCount() + InputCount() + i];
     805             :   }
     806             : 
     807             :   InstructionCode opcode() const { return opcode_; }
     808   249476009 :   ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
     809     1377949 :   AddressingMode addressing_mode() const {
     810     1377949 :     return AddressingModeField::decode(opcode());
     811             :   }
     812           4 :   FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
     813             :   FlagsCondition flags_condition() const {
     814             :     return FlagsConditionField::decode(opcode());
     815             :   }
     816             : 
     817     2142472 :   static Instruction* New(Zone* zone, InstructionCode opcode) {
     818     2142472 :     return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
     819             :   }
     820             : 
     821    63182657 :   static Instruction* New(Zone* zone, InstructionCode opcode,
     822             :                           size_t output_count, InstructionOperand* outputs,
     823             :                           size_t input_count, InstructionOperand* inputs,
     824             :                           size_t temp_count, InstructionOperand* temps) {
     825             :     DCHECK_LE(0, opcode);
     826             :     DCHECK(output_count == 0 || outputs != nullptr);
     827             :     DCHECK(input_count == 0 || inputs != nullptr);
     828             :     DCHECK(temp_count == 0 || temps != nullptr);
     829             :     // TODO(jarin/mstarzinger): Handle this gracefully. See crbug.com/582702.
     830    63182657 :     CHECK(InputCountField::is_valid(input_count));
     831             : 
     832    63182657 :     size_t total_extra_ops = output_count + input_count + temp_count;
     833    63182657 :     if (total_extra_ops != 0) total_extra_ops--;
     834             :     int size = static_cast<int>(
     835             :         RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
     836    63182657 :         total_extra_ops * sizeof(InstructionOperand));
     837    63182657 :     return new (zone->New(size)) Instruction(
     838    63182657 :         opcode, output_count, outputs, input_count, inputs, temp_count, temps);
     839             :   }
     840             : 
     841             :   Instruction* MarkAsCall() {
     842    11447940 :     bit_field_ = IsCallField::update(bit_field_, true);
     843             :     return this;
     844             :   }
     845             :   bool IsCall() const { return IsCallField::decode(bit_field_); }
     846    63182779 :   bool NeedsReferenceMap() const { return IsCall(); }
     847             :   bool HasReferenceMap() const { return reference_map_ != nullptr; }
     848             : 
     849             :   bool ClobbersRegisters() const { return IsCall(); }
     850             :   bool ClobbersTemps() const { return IsCall(); }
     851    63172767 :   bool ClobbersDoubleRegisters() const { return IsCall(); }
     852             :   ReferenceMap* reference_map() const { return reference_map_; }
     853             : 
     854             :   void set_reference_map(ReferenceMap* map) {
     855             :     DCHECK(NeedsReferenceMap());
     856             :     DCHECK(!reference_map_);
     857     5723976 :     reference_map_ = map;
     858             :   }
     859             : 
     860             :   void OverwriteWithNop() {
     861     4151829 :     opcode_ = ArchOpcodeField::encode(kArchNop);
     862     4151829 :     bit_field_ = 0;
     863     4151829 :     reference_map_ = nullptr;
     864             :   }
     865             : 
     866             :   bool IsNop() const { return arch_opcode() == kArchNop; }
     867             : 
     868             :   bool IsDeoptimizeCall() const {
     869    32296892 :     return arch_opcode() == ArchOpcode::kArchDeoptimize ||
     870    64515547 :            FlagsModeField::decode(opcode()) == kFlags_deoptimize ||
     871             :            FlagsModeField::decode(opcode()) == kFlags_deoptimize_and_poison;
     872             :   }
     873             : 
     874             :   bool IsTrap() const {
     875             :     return FlagsModeField::decode(opcode()) == kFlags_trap;
     876             :   }
     877             : 
     878             :   bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
     879             :   bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
     880             :   bool IsTailCall() const {
     881    89753789 :     return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
     882    89749649 :            arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
     883   179385079 :            arch_opcode() == ArchOpcode::kArchTailCallAddress ||
     884             :            arch_opcode() == ArchOpcode::kArchTailCallWasm;
     885             :   }
     886             :   bool IsThrow() const {
     887             :     return arch_opcode() == ArchOpcode::kArchThrowTerminator;
     888             :   }
     889             : 
     890             :   enum GapPosition {
     891             :     START,
     892             :     END,
     893             :     FIRST_GAP_POSITION = START,
     894             :     LAST_GAP_POSITION = END
     895             :   };
     896             : 
     897    71614078 :   ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
     898    71614078 :     if (parallel_moves_[pos] == nullptr) {
     899    45158782 :       parallel_moves_[pos] = new (zone) ParallelMove(zone);
     900             :     }
     901    71614040 :     return parallel_moves_[pos];
     902             :   }
     903             : 
     904             :   ParallelMove* GetParallelMove(GapPosition pos) {
     905   252912903 :     return parallel_moves_[pos];
     906             :   }
     907             : 
     908             :   const ParallelMove* GetParallelMove(GapPosition pos) const {
     909     7647816 :     return parallel_moves_[pos];
     910             :   }
     911             : 
     912             :   bool AreMovesRedundant() const;
     913             : 
     914             :   ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
     915             :   ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
     916             : 
     917             :   // The block_id may be invalidated in JumpThreading. It is only important for
     918             :   // register allocation, to avoid searching for blocks from instruction
     919             :   // indexes.
     920             :   InstructionBlock* block() const { return block_; }
     921             :   void set_block(InstructionBlock* block) {
     922             :     DCHECK_NOT_NULL(block);
     923    63182769 :     block_ = block;
     924             :   }
     925             : 
     926             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
     927             :   void Print() const;
     928             : 
     929             :   typedef BitField<size_t, 0, 8> OutputCountField;
     930             :   typedef BitField<size_t, 8, 16> InputCountField;
     931             :   typedef BitField<size_t, 24, 6> TempCountField;
     932             : 
     933             :   static const size_t kMaxOutputCount = OutputCountField::kMax;
     934             :   static const size_t kMaxInputCount = InputCountField::kMax;
     935             :   static const size_t kMaxTempCount = TempCountField::kMax;
     936             : 
     937             :  private:
     938             :   explicit Instruction(InstructionCode opcode);
     939             : 
     940             :   Instruction(InstructionCode opcode, size_t output_count,
     941             :               InstructionOperand* outputs, size_t input_count,
     942             :               InstructionOperand* inputs, size_t temp_count,
     943             :               InstructionOperand* temps);
     944             : 
     945             :   typedef BitField<bool, 30, 1> IsCallField;
     946             : 
     947             :   InstructionCode opcode_;
     948             :   uint32_t bit_field_;
     949             :   ParallelMove* parallel_moves_[2];
     950             :   ReferenceMap* reference_map_;
     951             :   InstructionBlock* block_;
     952             :   InstructionOperand operands_[1];
     953             : 
     954             :   DISALLOW_COPY_AND_ASSIGN(Instruction);
     955             : };
     956             : 
     957             : std::ostream& operator<<(std::ostream&, const Instruction&);
     958             : 
     959             : class RpoNumber final {
     960             :  public:
     961             :   static const int kInvalidRpoNumber = -1;
     962             :   int ToInt() const {
     963             :     DCHECK(IsValid());
     964    75706300 :     return index_;
     965             :   }
     966             :   size_t ToSize() const {
     967             :     DCHECK(IsValid());
     968   670731634 :     return static_cast<size_t>(index_);
     969             :   }
     970    45541248 :   bool IsValid() const { return index_ >= 0; }
     971             :   static RpoNumber FromInt(int index) { return RpoNumber(index); }
     972             :   static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
     973             : 
     974             :   bool IsNext(const RpoNumber other) const {
     975             :     DCHECK(IsValid());
     976    30346382 :     return other.index_ == this->index_ + 1;
     977             :   }
     978             : 
     979             :   // Comparison operators.
     980   978232591 :   bool operator==(RpoNumber other) const { return index_ == other.index_; }
     981             :   bool operator!=(RpoNumber other) const { return index_ != other.index_; }
     982             :   bool operator>(RpoNumber other) const { return index_ > other.index_; }
     983     2672278 :   bool operator<(RpoNumber other) const { return index_ < other.index_; }
     984    23279866 :   bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
     985           2 :   bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
     986             : 
     987             :  private:
     988             :   explicit RpoNumber(int32_t index) : index_(index) {}
     989             :   int32_t index_;
     990             : };
     991             : 
     992             : std::ostream& operator<<(std::ostream&, const RpoNumber&);
     993             : 
     994             : class V8_EXPORT_PRIVATE Constant final {
     995             :  public:
     996             :   enum Type {
     997             :     kInt32,
     998             :     kInt64,
     999             :     kFloat32,
    1000             :     kFloat64,
    1001             :     kExternalReference,
    1002             :     kHeapObject,
    1003             :     kRpoNumber,
    1004             :     kDelayedStringConstant
    1005             :   };
    1006             : 
    1007             :   explicit Constant(int32_t v);
    1008             :   explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
    1009       10408 :   explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
    1010             :   explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
    1011             :   explicit Constant(ExternalReference ref)
    1012             :       : type_(kExternalReference), value_(bit_cast<intptr_t>(ref.address())) {}
    1013             :   explicit Constant(Handle<HeapObject> obj)
    1014             :       : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
    1015    25457976 :   explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
    1016             :   explicit Constant(const StringConstantBase* str)
    1017             :       : type_(kDelayedStringConstant), value_(bit_cast<intptr_t>(str)) {}
    1018             :   explicit Constant(RelocatablePtrConstantInfo info);
    1019             : 
    1020             :   Type type() const { return type_; }
    1021             : 
    1022             :   RelocInfo::Mode rmode() const { return rmode_; }
    1023             : 
    1024             :   int32_t ToInt32() const {
    1025             :     DCHECK(type() == kInt32 || type() == kInt64);
    1026    51339769 :     const int32_t value = static_cast<int32_t>(value_);
    1027             :     DCHECK_EQ(value_, static_cast<int64_t>(value));
    1028             :     return value;
    1029             :   }
    1030             : 
    1031       80812 :   int64_t ToInt64() const {
    1032     2827098 :     if (type() == kInt32) return ToInt32();
    1033             :     DCHECK_EQ(kInt64, type());
    1034     2732976 :     return value_;
    1035             :   }
    1036             : 
    1037             :   float ToFloat32() const {
    1038             :     // TODO(ahaas): We should remove this function. If value_ has the bit
    1039             :     // representation of a signalling NaN, then returning it as float can cause
    1040             :     // the signalling bit to flip, and value_ is returned as a quiet NaN.
    1041             :     DCHECK_EQ(kFloat32, type());
    1042       16678 :     return bit_cast<float>(static_cast<int32_t>(value_));
    1043             :   }
    1044             : 
    1045             :   uint32_t ToFloat32AsInt() const {
    1046             :     DCHECK_EQ(kFloat32, type());
    1047             :     return bit_cast<uint32_t>(static_cast<int32_t>(value_));
    1048             :   }
    1049             : 
    1050             :   Double ToFloat64() const {
    1051             :     DCHECK_EQ(kFloat64, type());
    1052           6 :     return Double(bit_cast<uint64_t>(value_));
    1053             :   }
    1054             : 
    1055             :   ExternalReference ToExternalReference() const {
    1056             :     DCHECK_EQ(kExternalReference, type());
    1057     2376715 :     return ExternalReference::FromRawAddress(static_cast<Address>(value_));
    1058             :   }
    1059             : 
    1060             :   RpoNumber ToRpoNumber() const {
    1061             :     DCHECK_EQ(kRpoNumber, type());
    1062    43649054 :     return RpoNumber::FromInt(static_cast<int>(value_));
    1063             :   }
    1064             : 
    1065             :   Handle<HeapObject> ToHeapObject() const;
    1066             :   Handle<Code> ToCode() const;
    1067             :   const StringConstantBase* ToDelayedStringConstant() const;
    1068             : 
    1069             :  private:
    1070             :   Type type_;
    1071             :   RelocInfo::Mode rmode_ = RelocInfo::NONE;
    1072             :   int64_t value_;
    1073             : };
    1074             : 
    1075             : std::ostream& operator<<(std::ostream&, const Constant&);
    1076             : 
    1077             : // Forward declarations.
    1078             : class FrameStateDescriptor;
    1079             : 
    1080             : enum class StateValueKind : uint8_t {
    1081             :   kArgumentsElements,
    1082             :   kArgumentsLength,
    1083             :   kPlain,
    1084             :   kOptimizedOut,
    1085             :   kNested,
    1086             :   kDuplicate
    1087             : };
    1088             : 
    1089             : class StateValueDescriptor {
    1090             :  public:
    1091             :   StateValueDescriptor()
    1092             :       : kind_(StateValueKind::kPlain), type_(MachineType::AnyTagged()) {}
    1093             : 
    1094             :   static StateValueDescriptor ArgumentsElements(ArgumentsStateType type) {
    1095             :     StateValueDescriptor descr(StateValueKind::kArgumentsElements,
    1096             :                                MachineType::AnyTagged());
    1097             :     descr.args_type_ = type;
    1098             :     return descr;
    1099             :   }
    1100             :   static StateValueDescriptor ArgumentsLength(ArgumentsStateType type) {
    1101             :     StateValueDescriptor descr(StateValueKind::kArgumentsLength,
    1102             :                                MachineType::AnyTagged());
    1103             :     descr.args_type_ = type;
    1104             :     return descr;
    1105             :   }
    1106             :   static StateValueDescriptor Plain(MachineType type) {
    1107             :     return StateValueDescriptor(StateValueKind::kPlain, type);
    1108             :   }
    1109             :   static StateValueDescriptor OptimizedOut() {
    1110             :     return StateValueDescriptor(StateValueKind::kOptimizedOut,
    1111             :                                 MachineType::AnyTagged());
    1112             :   }
    1113             :   static StateValueDescriptor Recursive(size_t id) {
    1114             :     StateValueDescriptor descr(StateValueKind::kNested,
    1115             :                                MachineType::AnyTagged());
    1116             :     descr.id_ = id;
    1117             :     return descr;
    1118             :   }
    1119             :   static StateValueDescriptor Duplicate(size_t id) {
    1120             :     StateValueDescriptor descr(StateValueKind::kDuplicate,
    1121             :                                MachineType::AnyTagged());
    1122             :     descr.id_ = id;
    1123             :     return descr;
    1124             :   }
    1125             : 
    1126             :   bool IsArgumentsElements() const {
    1127             :     return kind_ == StateValueKind::kArgumentsElements;
    1128             :   }
    1129             :   bool IsArgumentsLength() const {
    1130             :     return kind_ == StateValueKind::kArgumentsLength;
    1131             :   }
    1132             :   bool IsPlain() const { return kind_ == StateValueKind::kPlain; }
    1133             :   bool IsOptimizedOut() const { return kind_ == StateValueKind::kOptimizedOut; }
    1134             :   bool IsNested() const { return kind_ == StateValueKind::kNested; }
    1135             :   bool IsDuplicate() const { return kind_ == StateValueKind::kDuplicate; }
    1136             :   MachineType type() const { return type_; }
    1137             :   size_t id() const {
    1138             :     DCHECK(kind_ == StateValueKind::kDuplicate ||
    1139             :            kind_ == StateValueKind::kNested);
    1140             :     return id_;
    1141             :   }
    1142             :   ArgumentsStateType arguments_type() const {
    1143             :     DCHECK(kind_ == StateValueKind::kArgumentsElements ||
    1144             :            kind_ == StateValueKind::kArgumentsLength);
    1145             :     return args_type_;
    1146             :   }
    1147             : 
    1148             :  private:
    1149             :   StateValueDescriptor(StateValueKind kind, MachineType type)
    1150             :       : kind_(kind), type_(type) {}
    1151             : 
    1152             :   StateValueKind kind_;
    1153             :   MachineType type_;
    1154             :   union {
    1155             :     size_t id_;
    1156             :     ArgumentsStateType args_type_;
    1157             :   };
    1158             : };
    1159             : 
    1160             : class StateValueList {
    1161             :  public:
    1162             :   explicit StateValueList(Zone* zone) : fields_(zone), nested_(zone) {}
    1163             : 
    1164       98457 :   size_t size() { return fields_.size(); }
    1165             : 
    1166             :   struct Value {
    1167             :     StateValueDescriptor* desc;
    1168             :     StateValueList* nested;
    1169             : 
    1170             :     Value(StateValueDescriptor* desc, StateValueList* nested)
    1171             :         : desc(desc), nested(nested) {}
    1172             :   };
    1173             : 
    1174             :   class iterator {
    1175             :    public:
    1176             :     // Bare minimum of operators needed for range iteration.
    1177             :     bool operator!=(const iterator& other) const {
    1178             :       return field_iterator != other.field_iterator;
    1179             :     }
    1180             :     bool operator==(const iterator& other) const {
    1181             :       return field_iterator == other.field_iterator;
    1182             :     }
    1183             :     iterator& operator++() {
    1184    51188760 :       if (field_iterator->IsNested()) {
    1185             :         nested_iterator++;
    1186             :       }
    1187             :       ++field_iterator;
    1188             :       return *this;
    1189             :     }
    1190             :     Value operator*() {
    1191    51188747 :       StateValueDescriptor* desc = &(*field_iterator);
    1192    51188747 :       StateValueList* nested = desc->IsNested() ? *nested_iterator : nullptr;
    1193             :       return Value(desc, nested);
    1194             :     }
    1195             : 
    1196             :    private:
    1197             :     friend class StateValueList;
    1198             : 
    1199             :     iterator(ZoneVector<StateValueDescriptor>::iterator it,
    1200             :              ZoneVector<StateValueList*>::iterator nested)
    1201             :         : field_iterator(it), nested_iterator(nested) {}
    1202             : 
    1203             :     ZoneVector<StateValueDescriptor>::iterator field_iterator;
    1204             :     ZoneVector<StateValueList*>::iterator nested_iterator;
    1205             :   };
    1206             : 
    1207     3946957 :   void ReserveSize(size_t size) { fields_.reserve(size); }
    1208             : 
    1209       98457 :   StateValueList* PushRecursiveField(Zone* zone, size_t id) {
    1210      196914 :     fields_.push_back(StateValueDescriptor::Recursive(id));
    1211             :     StateValueList* nested =
    1212      196914 :         new (zone->New(sizeof(StateValueList))) StateValueList(zone);
    1213       98457 :     nested_.push_back(nested);
    1214       98457 :     return nested;
    1215             :   }
    1216        6180 :   void PushArgumentsElements(ArgumentsStateType type) {
    1217       12360 :     fields_.push_back(StateValueDescriptor::ArgumentsElements(type));
    1218        6180 :   }
    1219        6500 :   void PushArgumentsLength(ArgumentsStateType type) {
    1220       13000 :     fields_.push_back(StateValueDescriptor::ArgumentsLength(type));
    1221        6500 :   }
    1222       22779 :   void PushDuplicate(size_t id) {
    1223       45558 :     fields_.push_back(StateValueDescriptor::Duplicate(id));
    1224       22779 :   }
    1225    23807388 :   void PushPlain(MachineType type) {
    1226    47615228 :     fields_.push_back(StateValueDescriptor::Plain(type));
    1227    23807840 :   }
    1228    27837124 :   void PushOptimizedOut() {
    1229    55674414 :     fields_.push_back(StateValueDescriptor::OptimizedOut());
    1230    27837290 :   }
    1231             : 
    1232             :   iterator begin() { return iterator(fields_.begin(), nested_.begin()); }
    1233             :   iterator end() { return iterator(fields_.end(), nested_.end()); }
    1234             : 
    1235             :  private:
    1236             :   ZoneVector<StateValueDescriptor> fields_;
    1237             :   ZoneVector<StateValueList*> nested_;
    1238             : };
    1239             : 
    1240             : class FrameStateDescriptor : public ZoneObject {
    1241             :  public:
    1242             :   FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
    1243             :                        OutputFrameStateCombine state_combine,
    1244             :                        size_t parameters_count, size_t locals_count,
    1245             :                        size_t stack_count,
    1246             :                        MaybeHandle<SharedFunctionInfo> shared_info,
    1247             :                        FrameStateDescriptor* outer_state = nullptr);
    1248             : 
    1249             :   FrameStateType type() const { return type_; }
    1250             :   BailoutId bailout_id() const { return bailout_id_; }
    1251             :   OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
    1252             :   size_t parameters_count() const { return parameters_count_; }
    1253             :   size_t locals_count() const { return locals_count_; }
    1254             :   size_t stack_count() const { return stack_count_; }
    1255             :   MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
    1256             :   FrameStateDescriptor* outer_state() const { return outer_state_; }
    1257             :   bool HasContext() const {
    1258      263298 :     return FrameStateFunctionInfo::IsJSFunctionType(type_) ||
    1259    11487900 :            type_ == FrameStateType::kBuiltinContinuation ||
    1260             :            type_ == FrameStateType::kConstructStub;
    1261             :   }
    1262             : 
    1263             :   size_t GetSize() const;
    1264             :   size_t GetTotalSize() const;
    1265             :   size_t GetFrameCount() const;
    1266             :   size_t GetJSFrameCount() const;
    1267             : 
    1268             :   StateValueList* GetStateValueDescriptors() { return &values_; }
    1269             : 
    1270             :   static const int kImpossibleValue = 0xdead;
    1271             : 
    1272             :  private:
    1273             :   FrameStateType type_;
    1274             :   BailoutId bailout_id_;
    1275             :   OutputFrameStateCombine frame_state_combine_;
    1276             :   size_t parameters_count_;
    1277             :   size_t locals_count_;
    1278             :   size_t stack_count_;
    1279             :   StateValueList values_;
    1280             :   MaybeHandle<SharedFunctionInfo> const shared_info_;
    1281             :   FrameStateDescriptor* outer_state_;
    1282             : };
    1283             : 
    1284             : // A deoptimization entry is a pair of the reason why we deoptimize and the
    1285             : // frame state descriptor that we have to go back to.
    1286             : class DeoptimizationEntry final {
    1287             :  public:
    1288             :   DeoptimizationEntry() = default;
    1289             :   DeoptimizationEntry(FrameStateDescriptor* descriptor, DeoptimizeKind kind,
    1290             :                       DeoptimizeReason reason, VectorSlotPair const& feedback)
    1291             :       : descriptor_(descriptor),
    1292             :         kind_(kind),
    1293             :         reason_(reason),
    1294     3569045 :         feedback_(feedback) {}
    1295             : 
    1296             :   FrameStateDescriptor* descriptor() const { return descriptor_; }
    1297             :   DeoptimizeKind kind() const { return kind_; }
    1298             :   DeoptimizeReason reason() const { return reason_; }
    1299             :   VectorSlotPair const& feedback() const { return feedback_; }
    1300             : 
    1301             :  private:
    1302             :   FrameStateDescriptor* descriptor_ = nullptr;
    1303             :   DeoptimizeKind kind_ = DeoptimizeKind::kEager;
    1304             :   DeoptimizeReason reason_ = DeoptimizeReason::kUnknown;
    1305             :   VectorSlotPair feedback_ = VectorSlotPair();
    1306             : };
    1307             : 
    1308             : typedef ZoneVector<DeoptimizationEntry> DeoptimizationVector;
    1309             : 
    1310             : class V8_EXPORT_PRIVATE PhiInstruction final
    1311             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1312             :  public:
    1313             :   typedef ZoneVector<InstructionOperand> Inputs;
    1314             : 
    1315             :   PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
    1316             : 
    1317             :   void SetInput(size_t offset, int virtual_register);
    1318             :   void RenameInput(size_t offset, int virtual_register);
    1319             : 
    1320             :   int virtual_register() const { return virtual_register_; }
    1321             :   const IntVector& operands() const { return operands_; }
    1322             : 
    1323             :   // TODO(dcarney): this has no real business being here, since it's internal to
    1324             :   // the register allocator, but putting it here was convenient.
    1325             :   const InstructionOperand& output() const { return output_; }
    1326             :   InstructionOperand& output() { return output_; }
    1327             : 
    1328             :  private:
    1329             :   const int virtual_register_;
    1330             :   InstructionOperand output_;
    1331             :   IntVector operands_;
    1332             : };
    1333             : 
    1334             : // Analogue of BasicBlock for Instructions instead of Nodes.
    1335             : class V8_EXPORT_PRIVATE InstructionBlock final
    1336             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1337             :  public:
    1338             :   InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
    1339             :                    RpoNumber loop_end, bool deferred, bool handler);
    1340             : 
    1341             :   // Instruction indexes (used by the register allocator).
    1342             :   int first_instruction_index() const {
    1343             :     DCHECK_LE(0, code_start_);
    1344             :     DCHECK_LT(0, code_end_);
    1345             :     DCHECK_GE(code_end_, code_start_);
    1346             :     return code_start_;
    1347             :   }
    1348             :   int last_instruction_index() const {
    1349             :     DCHECK_LE(0, code_start_);
    1350             :     DCHECK_LT(0, code_end_);
    1351             :     DCHECK_GE(code_end_, code_start_);
    1352   281574563 :     return code_end_ - 1;
    1353             :   }
    1354             : 
    1355             :   int32_t code_start() const { return code_start_; }
    1356    38891235 :   void set_code_start(int32_t start) { code_start_ = start; }
    1357             : 
    1358             :   int32_t code_end() const { return code_end_; }
    1359    38891382 :   void set_code_end(int32_t end) { code_end_ = end; }
    1360             : 
    1361             :   bool IsDeferred() const { return deferred_; }
    1362             :   bool IsHandler() const { return handler_; }
    1363             : 
    1364             :   RpoNumber ao_number() const { return ao_number_; }
    1365             :   RpoNumber rpo_number() const { return rpo_number_; }
    1366             :   RpoNumber loop_header() const { return loop_header_; }
    1367             :   RpoNumber loop_end() const {
    1368             :     DCHECK(IsLoopHeader());
    1369             :     return loop_end_;
    1370             :   }
    1371             :   inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
    1372             :   inline bool IsSwitchTarget() const { return switch_target_; }
    1373             :   inline bool ShouldAlign() const { return alignment_; }
    1374             : 
    1375             :   typedef ZoneVector<RpoNumber> Predecessors;
    1376             :   Predecessors& predecessors() { return predecessors_; }
    1377             :   const Predecessors& predecessors() const { return predecessors_; }
    1378    85997096 :   size_t PredecessorCount() const { return predecessors_.size(); }
    1379             :   size_t PredecessorIndexOf(RpoNumber rpo_number) const;
    1380             : 
    1381             :   typedef ZoneVector<RpoNumber> Successors;
    1382             :   Successors& successors() { return successors_; }
    1383             :   const Successors& successors() const { return successors_; }
    1384    11214438 :   size_t SuccessorCount() const { return successors_.size(); }
    1385             : 
    1386             :   typedef ZoneVector<PhiInstruction*> PhiInstructions;
    1387             :   const PhiInstructions& phis() const { return phis_; }
    1388     2098796 :   PhiInstruction* PhiAt(size_t i) const { return phis_[i]; }
    1389     2098904 :   void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
    1390             : 
    1391    35680381 :   void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
    1392             : 
    1393      505470 :   void set_alignment(bool val) { alignment_ = val; }
    1394             : 
    1395      438325 :   void set_switch_target(bool val) { switch_target_ = val; }
    1396             : 
    1397             :   bool needs_frame() const { return needs_frame_; }
    1398    20222009 :   void mark_needs_frame() { needs_frame_ = true; }
    1399             : 
    1400             :   bool must_construct_frame() const { return must_construct_frame_; }
    1401     2151238 :   void mark_must_construct_frame() { must_construct_frame_ = true; }
    1402             : 
    1403             :   bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
    1404     2431779 :   void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
    1405             : 
    1406             :  private:
    1407             :   Successors successors_;
    1408             :   Predecessors predecessors_;
    1409             :   PhiInstructions phis_;
    1410             :   RpoNumber ao_number_;  // Assembly order number.
    1411             :   const RpoNumber rpo_number_;
    1412             :   const RpoNumber loop_header_;
    1413             :   const RpoNumber loop_end_;
    1414             :   int32_t code_start_;   // start index of arch-specific code.
    1415             :   int32_t code_end_ = -1;     // end index of arch-specific code.
    1416             :   const bool deferred_ = -1;  // Block contains deferred code.
    1417             :   const bool handler_;   // Block is a handler entry point.
    1418             :   bool switch_target_ = false;
    1419             :   bool alignment_ = false;  // insert alignment before this block
    1420             :   bool needs_frame_ = false;
    1421             :   bool must_construct_frame_ = false;
    1422             :   bool must_deconstruct_frame_ = false;
    1423             : };
    1424             : 
    1425             : class InstructionSequence;
    1426             : 
    1427             : struct PrintableInstructionBlock {
    1428             :   const InstructionBlock* block_;
    1429             :   const InstructionSequence* code_;
    1430             : };
    1431             : 
    1432             : std::ostream& operator<<(std::ostream&, const PrintableInstructionBlock&);
    1433             : 
    1434             : typedef ZoneDeque<Constant> ConstantDeque;
    1435             : typedef std::map<int, Constant, std::less<int>,
    1436             :                  ZoneAllocator<std::pair<const int, Constant> > >
    1437             :     ConstantMap;
    1438             : 
    1439             : typedef ZoneDeque<Instruction*> InstructionDeque;
    1440             : typedef ZoneDeque<ReferenceMap*> ReferenceMapDeque;
    1441             : typedef ZoneVector<InstructionBlock*> InstructionBlocks;
    1442             : 
    1443             : // Represents architecture-specific generated code before, during, and after
    1444             : // register allocation.
    1445        2912 : class V8_EXPORT_PRIVATE InstructionSequence final
    1446             :     : public NON_EXPORTED_BASE(ZoneObject) {
    1447             :  public:
    1448             :   static InstructionBlocks* InstructionBlocksFor(Zone* zone,
    1449             :                                                  const Schedule* schedule);
    1450             :   InstructionSequence(Isolate* isolate, Zone* zone,
    1451             :                       InstructionBlocks* instruction_blocks);
    1452             : 
    1453             :   int NextVirtualRegister();
    1454             :   int VirtualRegisterCount() const { return next_virtual_register_; }
    1455             : 
    1456             :   const InstructionBlocks& instruction_blocks() const {
    1457             :     return *instruction_blocks_;
    1458             :   }
    1459             : 
    1460             :   const InstructionBlocks& ao_blocks() const { return *ao_blocks_; }
    1461             : 
    1462             :   int InstructionBlockCount() const {
    1463    88379334 :     return static_cast<int>(instruction_blocks_->size());
    1464             :   }
    1465             : 
    1466   402710862 :   InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
    1467   805421724 :     return instruction_blocks_->at(rpo_number.ToSize());
    1468             :   }
    1469             : 
    1470      243537 :   int LastLoopInstructionIndex(const InstructionBlock* block) {
    1471      243537 :     return instruction_blocks_->at(block->loop_end().ToSize() - 1)
    1472      487074 :         ->last_instruction_index();
    1473             :   }
    1474             : 
    1475   191308678 :   const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
    1476   382617356 :     return instruction_blocks_->at(rpo_number.ToSize());
    1477             :   }
    1478             : 
    1479             :   InstructionBlock* GetInstructionBlock(int instruction_index) const;
    1480             : 
    1481             :   static MachineRepresentation DefaultRepresentation() {
    1482             :     return MachineType::PointerRepresentation();
    1483             :   }
    1484             :   MachineRepresentation GetRepresentation(int virtual_register) const;
    1485             :   void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
    1486             : 
    1487             :   bool IsReference(int virtual_register) const {
    1488    73338366 :     return CanBeTaggedPointer(GetRepresentation(virtual_register));
    1489             :   }
    1490             :   bool IsFP(int virtual_register) const {
    1491     2931035 :     return IsFloatingPoint(GetRepresentation(virtual_register));
    1492             :   }
    1493             :   int representation_mask() const { return representation_mask_; }
    1494     2141575 :   bool HasFPVirtualRegisters() const {
    1495             :     constexpr int kFPRepMask =
    1496             :         RepresentationBit(MachineRepresentation::kFloat32) |
    1497             :         RepresentationBit(MachineRepresentation::kFloat64) |
    1498             :         RepresentationBit(MachineRepresentation::kSimd128);
    1499     2141575 :     return (representation_mask() & kFPRepMask) != 0;
    1500             :   }
    1501             : 
    1502             :   Instruction* GetBlockStart(RpoNumber rpo) const;
    1503             : 
    1504             :   typedef InstructionDeque::const_iterator const_iterator;
    1505             :   const_iterator begin() const { return instructions_.begin(); }
    1506             :   const_iterator end() const { return instructions_.end(); }
    1507             :   const InstructionDeque& instructions() const { return instructions_; }
    1508             :   int LastInstructionIndex() const {
    1509           2 :     return static_cast<int>(instructions().size()) - 1;
    1510             :   }
    1511             : 
    1512             :   Instruction* InstructionAt(int index) const {
    1513             :     DCHECK_LE(0, index);
    1514             :     DCHECK_GT(instructions_.size(), index);
    1515   483363253 :     return instructions_[index];
    1516             :   }
    1517             : 
    1518             :   Isolate* isolate() const { return isolate_; }
    1519             :   const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
    1520             :   Zone* zone() const { return zone_; }
    1521             : 
    1522             :   // Used by the instruction selector while adding instructions.
    1523             :   int AddInstruction(Instruction* instr);
    1524             :   void StartBlock(RpoNumber rpo);
    1525             :   void EndBlock(RpoNumber rpo);
    1526             : 
    1527             :   int AddConstant(int virtual_register, Constant constant) {
    1528             :     // TODO(titzer): allow RPO numbers as constants?
    1529             :     DCHECK_NE(Constant::kRpoNumber, constant.type());
    1530             :     DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
    1531             :     DCHECK(constants_.find(virtual_register) == constants_.end());
    1532    12528165 :     constants_.insert(std::make_pair(virtual_register, constant));
    1533             :     return virtual_register;
    1534             :   }
    1535             :   Constant GetConstant(int virtual_register) const {
    1536             :     ConstantMap::const_iterator it = constants_.find(virtual_register);
    1537             :     DCHECK(it != constants_.end());
    1538             :     DCHECK_EQ(virtual_register, it->first);
    1539    18561431 :     return it->second;
    1540             :   }
    1541             : 
    1542             :   typedef ZoneVector<Constant> Immediates;
    1543             :   Immediates& immediates() { return immediates_; }
    1544             : 
    1545   100378744 :   ImmediateOperand AddImmediate(const Constant& constant) {
    1546    81586679 :     if (constant.type() == Constant::kInt32 &&
    1547             :         RelocInfo::IsNone(constant.rmode())) {
    1548    18792065 :       return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
    1549             :     }
    1550    88005124 :     int index = static_cast<int>(immediates_.size());
    1551    44002562 :     immediates_.push_back(constant);
    1552    44002840 :     return ImmediateOperand(ImmediateOperand::INDEXED, index);
    1553             :   }
    1554             : 
    1555    63591644 :   Constant GetImmediate(const ImmediateOperand* op) const {
    1556    63591644 :     switch (op->type()) {
    1557             :       case ImmediateOperand::INLINE:
    1558    17199643 :         return Constant(op->inline_value());
    1559             :       case ImmediateOperand::INDEXED: {
    1560             :         int index = op->indexed_value();
    1561             :         DCHECK_LE(0, index);
    1562             :         DCHECK_GT(immediates_.size(), index);
    1563    92784002 :         return immediates_[index];
    1564             :       }
    1565             :     }
    1566           0 :     UNREACHABLE();
    1567             :   }
    1568             : 
    1569             :   int AddDeoptimizationEntry(FrameStateDescriptor* descriptor,
    1570             :                              DeoptimizeKind kind, DeoptimizeReason reason,
    1571             :                              VectorSlotPair const& feedback);
    1572             :   DeoptimizationEntry const& GetDeoptimizationEntry(int deoptimization_id);
    1573             :   int GetDeoptimizationEntryCount() const {
    1574         506 :     return static_cast<int>(deoptimization_entries_.size());
    1575             :   }
    1576             : 
    1577             :   RpoNumber InputRpo(Instruction* instr, size_t index);
    1578             : 
    1579             :   bool GetSourcePosition(const Instruction* instr,
    1580             :                          SourcePosition* result) const;
    1581             :   void SetSourcePosition(const Instruction* instr, SourcePosition value);
    1582             : 
    1583             :   bool ContainsCall() const {
    1584             :     for (Instruction* instr : instructions_) {
    1585             :       if (instr->IsCall()) return true;
    1586             :     }
    1587             :     return false;
    1588             :   }
    1589             : 
    1590             :   // APIs to aid debugging. For general-stream APIs, use operator<<.
    1591             :   void Print() const;
    1592             : 
    1593             :   void PrintBlock(int block_id) const;
    1594             : 
    1595             :   void ValidateEdgeSplitForm() const;
    1596             :   void ValidateDeferredBlockExitPaths() const;
    1597             :   void ValidateDeferredBlockEntryPaths() const;
    1598             :   void ValidateSSA() const;
    1599             : 
    1600             :   static void SetRegisterConfigurationForTesting(
    1601             :       const RegisterConfiguration* regConfig);
    1602             :   static void ClearRegisterConfigurationForTesting();
    1603             : 
    1604             :   void RecomputeAssemblyOrderForTesting();
    1605             : 
    1606             :  private:
    1607             :   friend V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
    1608             :                                                     const InstructionSequence&);
    1609             : 
    1610             :   typedef ZoneMap<const Instruction*, SourcePosition> SourcePositionMap;
    1611             : 
    1612             :   static const RegisterConfiguration* RegisterConfigurationForTesting();
    1613             :   static const RegisterConfiguration* registerConfigurationForTesting_;
    1614             : 
    1615             :   // Puts the deferred blocks last and may rotate loops.
    1616             :   void ComputeAssemblyOrder();
    1617             : 
    1618             :   Isolate* isolate_;
    1619             :   Zone* const zone_;
    1620             :   InstructionBlocks* const instruction_blocks_;
    1621             :   InstructionBlocks* ao_blocks_;
    1622             :   SourcePositionMap source_positions_;
    1623             :   ConstantMap constants_;
    1624             :   Immediates immediates_;
    1625             :   InstructionDeque instructions_;
    1626             :   int next_virtual_register_;
    1627             :   ReferenceMapDeque reference_maps_;
    1628             :   ZoneVector<MachineRepresentation> representations_;
    1629             :   int representation_mask_;
    1630             :   DeoptimizationVector deoptimization_entries_;
    1631             : 
    1632             :   // Used at construction time
    1633             :   InstructionBlock* current_block_;
    1634             : 
    1635             :   DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
    1636             : };
    1637             : 
    1638             : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
    1639             :                                            const InstructionSequence&);
    1640             : 
    1641             : }  // namespace compiler
    1642             : }  // namespace internal
    1643             : }  // namespace v8
    1644             : 
    1645             : #endif  // V8_COMPILER_BACKEND_INSTRUCTION_H_

Generated by: LCOV version 1.10