| OLD | NEW | 
|     1 // Copyright 2014 the V8 project authors. All rights reserved. |     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 |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #ifndef V8_COMPILER_INSTRUCTION_H_ |     5 #ifndef V8_COMPILER_INSTRUCTION_H_ | 
|     6 #define V8_COMPILER_INSTRUCTION_H_ |     6 #define V8_COMPILER_INSTRUCTION_H_ | 
|     7  |     7  | 
|     8 #include <deque> |     8 #include <deque> | 
|     9 #include <iosfwd> |     9 #include <iosfwd> | 
|    10 #include <map> |    10 #include <map> | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|    43     INVALID, |    43     INVALID, | 
|    44     UNALLOCATED, |    44     UNALLOCATED, | 
|    45     CONSTANT, |    45     CONSTANT, | 
|    46     IMMEDIATE, |    46     IMMEDIATE, | 
|    47     STACK_SLOT, |    47     STACK_SLOT, | 
|    48     DOUBLE_STACK_SLOT, |    48     DOUBLE_STACK_SLOT, | 
|    49     REGISTER, |    49     REGISTER, | 
|    50     DOUBLE_REGISTER |    50     DOUBLE_REGISTER | 
|    51   }; |    51   }; | 
|    52  |    52  | 
|    53   InstructionOperand() : virtual_register_(kInvalidVirtualRegister) { |    53   InstructionOperand() { ConvertTo(INVALID, 0, kInvalidVirtualRegister); } | 
|    54     ConvertTo(INVALID, 0); |  | 
|    55   } |  | 
|    56  |    54  | 
|    57   InstructionOperand(Kind kind, int index) |    55   InstructionOperand(Kind kind, int index) { | 
|    58       : virtual_register_(kInvalidVirtualRegister) { |    56     DCHECK(kind != UNALLOCATED && kind != INVALID); | 
|    59     DCHECK(kind != INVALID); |    57     ConvertTo(kind, index, kInvalidVirtualRegister); | 
|    60     ConvertTo(kind, index); |  | 
|    61   } |    58   } | 
|    62  |    59  | 
|    63   static InstructionOperand* New(Zone* zone, Kind kind, int index) { |    60   static InstructionOperand* New(Zone* zone, Kind kind, int index) { | 
|    64     return New(zone, InstructionOperand(kind, index)); |    61     return New(zone, InstructionOperand(kind, index)); | 
|    65   } |    62   } | 
|    66  |    63  | 
|    67   Kind kind() const { return KindField::decode(value_); } |    64   Kind kind() const { return KindField::decode(value_); } | 
|    68   int index() const { return static_cast<int>(value_) >> KindField::kSize; } |    65   // TODO(dcarney): move this to subkind operand. | 
 |    66   int index() const { | 
 |    67     DCHECK(kind() != UNALLOCATED && kind() != INVALID); | 
 |    68     return static_cast<int64_t>(value_) >> IndexField::kShift; | 
 |    69   } | 
|    69 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |    70 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ | 
|    70   bool Is##name() const { return kind() == type; } |    71   bool Is##name() const { return kind() == type; } | 
|    71   INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |    72   INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) | 
|    72   INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |    73   INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) | 
|    73   INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |    74   INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) | 
|    74 #undef INSTRUCTION_OPERAND_PREDICATE |    75 #undef INSTRUCTION_OPERAND_PREDICATE | 
|    75   bool Equals(const InstructionOperand* other) const { |    76   bool Equals(const InstructionOperand* other) const { | 
|    76     return value_ == other->value_; |    77     return value_ == other->value_; | 
|    77   } |    78   } | 
|    78  |    79  | 
|    79   void ConvertTo(Kind kind, int index) { |    80   void ConvertTo(Kind kind, int index) { | 
|    80     if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |    81     DCHECK(kind != UNALLOCATED && kind != INVALID); | 
|    81     value_ = KindField::encode(kind); |    82     ConvertTo(kind, index, kInvalidVirtualRegister); | 
|    82     value_ |= bit_cast<unsigned>(index << KindField::kSize); |  | 
|    83     DCHECK(this->index() == index); |  | 
|    84     if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; |  | 
|    85   } |    83   } | 
|    86  |    84  | 
|    87  protected: |    85  protected: | 
|    88   template <typename SubKindOperand> |    86   template <typename SubKindOperand> | 
|    89   static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { |    87   static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { | 
|    90     void* buffer = zone->New(sizeof(op)); |    88     void* buffer = zone->New(sizeof(op)); | 
|    91     return new (buffer) SubKindOperand(op); |    89     return new (buffer) SubKindOperand(op); | 
|    92   } |    90   } | 
|    93  |    91  | 
|    94   InstructionOperand(Kind kind, int index, int virtual_register) |    92   InstructionOperand(Kind kind, int index, int virtual_register) { | 
|    95       : virtual_register_(virtual_register) { |    93     ConvertTo(kind, index, virtual_register); | 
|    96     ConvertTo(kind, index); |  | 
|    97   } |    94   } | 
|    98   typedef BitField<Kind, 0, 3> KindField; |  | 
|    99  |    95  | 
|   100   uint32_t value_; |    96   void ConvertTo(Kind kind, int index, int virtual_register) { | 
|   101   // TODO(dcarney): this should really be unsigned. |    97     if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); | 
|   102   int32_t virtual_register_; |    98     if (kind != UNALLOCATED) { | 
 |    99       DCHECK(virtual_register == kInvalidVirtualRegister); | 
 |   100     } | 
 |   101     value_ = KindField::encode(kind); | 
 |   102     value_ |= | 
 |   103         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register)); | 
 |   104     value_ |= static_cast<int64_t>(index) << IndexField::kShift; | 
 |   105     DCHECK(((kind == UNALLOCATED || kind == INVALID) && index == 0) || | 
 |   106            this->index() == index); | 
 |   107   } | 
 |   108  | 
 |   109   typedef BitField64<Kind, 0, 3> KindField; | 
 |   110   typedef BitField64<uint32_t, 3, 32> VirtualRegisterField; | 
 |   111   typedef BitField64<int32_t, 35, 29> IndexField; | 
 |   112  | 
 |   113   uint64_t value_; | 
|   103 }; |   114 }; | 
|   104  |   115  | 
|   105 struct PrintableInstructionOperand { |   116 struct PrintableInstructionOperand { | 
|   106   const RegisterConfiguration* register_configuration_; |   117   const RegisterConfiguration* register_configuration_; | 
|   107   const InstructionOperand* op_; |   118   const InstructionOperand* op_; | 
|   108 }; |   119 }; | 
|   109  |   120  | 
|   110 std::ostream& operator<<(std::ostream& os, |   121 std::ostream& operator<<(std::ostream& os, | 
|   111                          const PrintableInstructionOperand& op); |   122                          const PrintableInstructionOperand& op); | 
|   112  |   123  | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|   141       : InstructionOperand(UNALLOCATED, 0, virtual_register) { |   152       : InstructionOperand(UNALLOCATED, 0, virtual_register) { | 
|   142     value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |   153     value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 
|   143     value_ |= ExtendedPolicyField::encode(policy); |   154     value_ |= ExtendedPolicyField::encode(policy); | 
|   144     value_ |= LifetimeField::encode(USED_AT_END); |   155     value_ |= LifetimeField::encode(USED_AT_END); | 
|   145   } |   156   } | 
|   146  |   157  | 
|   147   UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) |   158   UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) | 
|   148       : InstructionOperand(UNALLOCATED, 0, virtual_register) { |   159       : InstructionOperand(UNALLOCATED, 0, virtual_register) { | 
|   149     DCHECK(policy == FIXED_SLOT); |   160     DCHECK(policy == FIXED_SLOT); | 
|   150     value_ |= BasicPolicyField::encode(policy); |   161     value_ |= BasicPolicyField::encode(policy); | 
|   151     value_ |= static_cast<int32_t>(index) << FixedSlotIndexField::kShift; |   162     value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift; | 
|   152     DCHECK(this->fixed_slot_index() == index); |   163     DCHECK(this->fixed_slot_index() == index); | 
|   153   } |   164   } | 
|   154  |   165  | 
|   155   UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register) |   166   UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register) | 
|   156       : InstructionOperand(UNALLOCATED, 0, virtual_register) { |   167       : InstructionOperand(UNALLOCATED, 0, virtual_register) { | 
|   157     DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); |   168     DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); | 
|   158     value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |   169     value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 
|   159     value_ |= ExtendedPolicyField::encode(policy); |   170     value_ |= ExtendedPolicyField::encode(policy); | 
|   160     value_ |= LifetimeField::encode(USED_AT_END); |   171     value_ |= LifetimeField::encode(USED_AT_END); | 
|   161     value_ |= FixedRegisterField::encode(index); |   172     value_ |= FixedRegisterField::encode(index); | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|   189     DCHECK(op.IsUnallocated()); |   200     DCHECK(op.IsUnallocated()); | 
|   190     return *static_cast<const UnallocatedOperand*>(&op); |   201     return *static_cast<const UnallocatedOperand*>(&op); | 
|   191   } |   202   } | 
|   192  |   203  | 
|   193   // The encoding used for UnallocatedOperand operands depends on the policy |   204   // The encoding used for UnallocatedOperand operands depends on the policy | 
|   194   // that is |   205   // that is | 
|   195   // stored within the operand. The FIXED_SLOT policy uses a compact encoding |   206   // stored within the operand. The FIXED_SLOT policy uses a compact encoding | 
|   196   // because it accommodates a larger pay-load. |   207   // because it accommodates a larger pay-load. | 
|   197   // |   208   // | 
|   198   // For FIXED_SLOT policy: |   209   // For FIXED_SLOT policy: | 
|   199   //     +-----------------------------+ |   210   //     +------------------------------------------------+ | 
|   200   //     |      slot_index   | 0 | 001 | |   211   //     |      slot_index   | 0 | virtual_register | 001 | | 
|   201   //     +-----------------------------+ |   212   //     +------------------------------------------------+ | 
|   202   // |   213   // | 
|   203   // For all other (extended) policies: |   214   // For all other (extended) policies: | 
|   204   //     +----------------------------------+ |   215   //     +-----------------------------------------------------+ | 
|   205   //     |  reg_index  | L | PPP |  1 | 001 |    L ... Lifetime |   216   //     |  reg_index  | L | PPP |  1 | virtual_register | 001 | | 
|   206   //     +----------------------------------+    P ... Policy |   217   //     +-----------------------------------------------------+ | 
 |   218   //     L ... Lifetime | 
 |   219   //     P ... Policy | 
|   207   // |   220   // | 
|   208   // The slot index is a signed value which requires us to decode it manually |   221   // The slot index is a signed value which requires us to decode it manually | 
|   209   // instead of using the BitField utility class. |   222   // instead of using the BitField utility class. | 
|   210  |   223  | 
|   211   // The superclass has a KindField. |   224   // All bits fit into the index field. | 
|   212   STATIC_ASSERT(KindField::kSize == 3); |   225   STATIC_ASSERT(IndexField::kShift == 35); | 
|   213  |   226  | 
|   214   // BitFields for all unallocated operands. |   227   // BitFields for all unallocated operands. | 
|   215   class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {}; |   228   class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {}; | 
|   216  |   229  | 
|   217   // BitFields specific to BasicPolicy::FIXED_SLOT. |   230   // BitFields specific to BasicPolicy::FIXED_SLOT. | 
|   218   class FixedSlotIndexField : public BitField<int, 4, 28> {}; |   231   class FixedSlotIndexField : public BitField64<int, 36, 28> {}; | 
|   219  |   232  | 
|   220   // BitFields specific to BasicPolicy::EXTENDED_POLICY. |   233   // BitFields specific to BasicPolicy::EXTENDED_POLICY. | 
|   221   class ExtendedPolicyField : public BitField<ExtendedPolicy, 4, 3> {}; |   234   class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {}; | 
|   222   class LifetimeField : public BitField<Lifetime, 7, 1> {}; |   235   class LifetimeField : public BitField64<Lifetime, 39, 1> {}; | 
|   223   class FixedRegisterField : public BitField<int, 8, 6> {}; |   236   class FixedRegisterField : public BitField64<int, 40, 6> {}; | 
|   224  |  | 
|   225   static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize; |  | 
|   226   static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1; |  | 
|   227   static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1)); |  | 
|   228  |   237  | 
|   229   // Predicates for the operand policy. |   238   // Predicates for the operand policy. | 
|   230   bool HasAnyPolicy() const { |   239   bool HasAnyPolicy() const { | 
|   231     return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY; |   240     return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY; | 
|   232   } |   241   } | 
|   233   bool HasFixedPolicy() const { |   242   bool HasFixedPolicy() const { | 
|   234     return basic_policy() == FIXED_SLOT || |   243     return basic_policy() == FIXED_SLOT || | 
|   235            extended_policy() == FIXED_REGISTER || |   244            extended_policy() == FIXED_REGISTER || | 
|   236            extended_policy() == FIXED_DOUBLE_REGISTER; |   245            extended_policy() == FIXED_DOUBLE_REGISTER; | 
|   237   } |   246   } | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
|   261  |   270  | 
|   262   // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. |   271   // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. | 
|   263   ExtendedPolicy extended_policy() const { |   272   ExtendedPolicy extended_policy() const { | 
|   264     DCHECK(basic_policy() == EXTENDED_POLICY); |   273     DCHECK(basic_policy() == EXTENDED_POLICY); | 
|   265     return ExtendedPolicyField::decode(value_); |   274     return ExtendedPolicyField::decode(value_); | 
|   266   } |   275   } | 
|   267  |   276  | 
|   268   // [fixed_slot_index]: Only for FIXED_SLOT. |   277   // [fixed_slot_index]: Only for FIXED_SLOT. | 
|   269   int fixed_slot_index() const { |   278   int fixed_slot_index() const { | 
|   270     DCHECK(HasFixedSlotPolicy()); |   279     DCHECK(HasFixedSlotPolicy()); | 
|   271     return static_cast<int>(bit_cast<int32_t>(value_) >> |   280     return static_cast<int>(static_cast<int64_t>(value_) >> | 
|   272                             FixedSlotIndexField::kShift); |   281                             FixedSlotIndexField::kShift); | 
|   273   } |   282   } | 
|   274  |   283  | 
|   275   // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. |   284   // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. | 
|   276   int fixed_register_index() const { |   285   int fixed_register_index() const { | 
|   277     DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); |   286     DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); | 
|   278     return FixedRegisterField::decode(value_); |   287     return FixedRegisterField::decode(value_); | 
|   279   } |   288   } | 
|   280  |   289  | 
|   281   // [virtual_register]: The virtual register ID for this operand. |   290   // [virtual_register]: The virtual register ID for this operand. | 
|   282   int32_t virtual_register() const { |   291   int32_t virtual_register() const { | 
|   283     DCHECK_EQ(UNALLOCATED, kind()); |   292     DCHECK_EQ(UNALLOCATED, kind()); | 
|   284     return virtual_register_; |   293     return static_cast<int32_t>(VirtualRegisterField::decode(value_)); | 
|   285   } |   294   } | 
|   286  |   295  | 
|   287   // TODO(dcarney): remove this. |   296   // TODO(dcarney): remove this. | 
|   288   void set_virtual_register(int32_t id) { |   297   void set_virtual_register(int32_t id) { | 
|   289     DCHECK_EQ(UNALLOCATED, kind()); |   298     DCHECK_EQ(UNALLOCATED, kind()); | 
|   290     virtual_register_ = id; |   299     value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id)); | 
|   291   } |   300   } | 
|   292  |   301  | 
|   293   // [lifetime]: Only for non-FIXED_SLOT. |   302   // [lifetime]: Only for non-FIXED_SLOT. | 
|   294   bool IsUsedAtStart() const { |   303   bool IsUsedAtStart() const { | 
|   295     DCHECK(basic_policy() == EXTENDED_POLICY); |   304     DCHECK(basic_policy() == EXTENDED_POLICY); | 
|   296     return LifetimeField::decode(value_) == USED_AT_START; |   305     return LifetimeField::decode(value_) == USED_AT_START; | 
|   297   } |   306   } | 
|   298 }; |   307 }; | 
|   299  |   308  | 
|   300  |   309  | 
| (...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1051  |  1060  | 
|  1052  |  1061  | 
|  1053 std::ostream& operator<<(std::ostream& os, |  1062 std::ostream& operator<<(std::ostream& os, | 
|  1054                          const PrintableInstructionSequence& code); |  1063                          const PrintableInstructionSequence& code); | 
|  1055  |  1064  | 
|  1056 }  // namespace compiler |  1065 }  // namespace compiler | 
|  1057 }  // namespace internal |  1066 }  // namespace internal | 
|  1058 }  // namespace v8 |  1067 }  // namespace v8 | 
|  1059  |  1068  | 
|  1060 #endif  // V8_COMPILER_INSTRUCTION_H_ |  1069 #endif  // V8_COMPILER_INSTRUCTION_H_ | 
| OLD | NEW |