LCOV - code coverage report
Current view: top level - src/compiler - instruction.h (source / functions) Hit Total Coverage
Test: app.info Lines: 195 208 93.8 %
Date: 2017-04-26 Functions: 21 23 91.3 %

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

Generated by: LCOV version 1.10