LCOV - code coverage report
Current view: top level - src/compiler - instruction.h (source / functions) Hit Total Coverage
Test: app.info Lines: 197 210 93.8 %
Date: 2017-10-20 Functions: 21 24 87.5 %

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

Generated by: LCOV version 1.10