| 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 19 matching lines...) Expand all Loading... |
| 30 #define INSTRUCTION_OPERAND_LIST(V) \ | 30 #define INSTRUCTION_OPERAND_LIST(V) \ |
| 31 V(Constant, CONSTANT, 0) \ | 31 V(Constant, CONSTANT, 0) \ |
| 32 V(Immediate, IMMEDIATE, 0) \ | 32 V(Immediate, IMMEDIATE, 0) \ |
| 33 V(StackSlot, STACK_SLOT, 128) \ | 33 V(StackSlot, STACK_SLOT, 128) \ |
| 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \ | 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \ |
| 35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \ | 35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \ |
| 36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters) | 36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters) |
| 37 | 37 |
| 38 class InstructionOperand : public ZoneObject { | 38 class InstructionOperand : public ZoneObject { |
| 39 public: | 39 public: |
| 40 static const int kInvalidVirtualRegister = -1; |
| 41 |
| 40 enum Kind { | 42 enum Kind { |
| 43 INVALID, |
| 41 UNALLOCATED, | 44 UNALLOCATED, |
| 42 CONSTANT, | 45 CONSTANT, |
| 43 IMMEDIATE, | 46 IMMEDIATE, |
| 44 STACK_SLOT, | 47 STACK_SLOT, |
| 45 DOUBLE_STACK_SLOT, | 48 DOUBLE_STACK_SLOT, |
| 46 REGISTER, | 49 REGISTER, |
| 47 DOUBLE_REGISTER | 50 DOUBLE_REGISTER |
| 48 }; | 51 }; |
| 49 | 52 |
| 50 InstructionOperand(Kind kind, int index) { ConvertTo(kind, index); } | 53 InstructionOperand(Kind kind, int index) |
| 54 : virtual_register_(kInvalidVirtualRegister) { |
| 55 DCHECK(kind != INVALID); |
| 56 ConvertTo(kind, index); |
| 57 } |
| 51 | 58 |
| 52 Kind kind() const { return KindField::decode(value_); } | 59 Kind kind() const { return KindField::decode(value_); } |
| 53 int index() const { return static_cast<int>(value_) >> KindField::kSize; } | 60 int index() const { return static_cast<int>(value_) >> KindField::kSize; } |
| 54 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \ | 61 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \ |
| 55 bool Is##name() const { return kind() == type; } | 62 bool Is##name() const { return kind() == type; } |
| 56 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) | 63 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
| 57 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) | 64 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) |
| 58 #undef INSTRUCTION_OPERAND_PREDICATE | 65 #undef INSTRUCTION_OPERAND_PREDICATE |
| 59 bool Equals(const InstructionOperand* other) const { | 66 bool Equals(const InstructionOperand* other) const { |
| 60 return value_ == other->value_; | 67 return value_ == other->value_; |
| 61 } | 68 } |
| 62 | 69 |
| 63 void ConvertTo(Kind kind, int index) { | 70 void ConvertTo(Kind kind, int index) { |
| 64 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); | 71 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
| 65 value_ = KindField::encode(kind); | 72 value_ = KindField::encode(kind); |
| 66 value_ |= bit_cast<unsigned>(index << KindField::kSize); | 73 value_ |= bit_cast<unsigned>(index << KindField::kSize); |
| 67 DCHECK(this->index() == index); | 74 DCHECK(this->index() == index); |
| 75 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; |
| 68 } | 76 } |
| 69 | 77 |
| 70 // Calls SetUpCache()/TearDownCache() for each subclass. | 78 // Calls SetUpCache()/TearDownCache() for each subclass. |
| 71 static void SetUpCaches(); | 79 static void SetUpCaches(); |
| 72 static void TearDownCaches(); | 80 static void TearDownCaches(); |
| 73 | 81 |
| 74 protected: | 82 protected: |
| 75 // TODO(dcarney): remove. used to construct the Instruction operand array. | 83 InstructionOperand(Kind kind, int index, int virtual_register) |
| 76 InstructionOperand() : value_(0xffffffff) {} | 84 : virtual_register_(virtual_register) { |
| 85 ConvertTo(kind, index); |
| 86 } |
| 77 typedef BitField<Kind, 0, 3> KindField; | 87 typedef BitField<Kind, 0, 3> KindField; |
| 78 | 88 |
| 79 uint32_t value_; | 89 uint32_t value_; |
| 90 // TODO(dcarney): this should really be unsigned. |
| 91 int32_t virtual_register_; |
| 80 }; | 92 }; |
| 81 | 93 |
| 82 typedef ZoneVector<InstructionOperand*> InstructionOperandVector; | 94 typedef ZoneVector<InstructionOperand*> InstructionOperandVector; |
| 83 | 95 |
| 84 struct PrintableInstructionOperand { | 96 struct PrintableInstructionOperand { |
| 85 const RegisterConfiguration* register_configuration_; | 97 const RegisterConfiguration* register_configuration_; |
| 86 const InstructionOperand* op_; | 98 const InstructionOperand* op_; |
| 87 }; | 99 }; |
| 88 | 100 |
| 89 std::ostream& operator<<(std::ostream& os, | 101 std::ostream& operator<<(std::ostream& os, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 109 // to some other operand used inside instruction (i.e. temporary or | 121 // to some other operand used inside instruction (i.e. temporary or |
| 110 // output). | 122 // output). |
| 111 USED_AT_START, | 123 USED_AT_START, |
| 112 | 124 |
| 113 // USED_AT_END operand is treated as live until the end of | 125 // USED_AT_END operand is treated as live until the end of |
| 114 // instruction. This means that register allocator will not reuse it's | 126 // instruction. This means that register allocator will not reuse it's |
| 115 // register for any other operand inside instruction. | 127 // register for any other operand inside instruction. |
| 116 USED_AT_END | 128 USED_AT_END |
| 117 }; | 129 }; |
| 118 | 130 |
| 131 // TODO(dcarney): remove this. |
| 119 static const int kInvalidVirtualRegister = -1; | 132 static const int kInvalidVirtualRegister = -1; |
| 120 | 133 |
| 121 explicit UnallocatedOperand(ExtendedPolicy policy) | 134 // This is only for array initialization. |
| 122 : InstructionOperand(UNALLOCATED, 0), | 135 UnallocatedOperand() |
| 123 virtual_register_(kInvalidVirtualRegister) { | 136 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {} |
| 137 |
| 138 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) |
| 139 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
| 124 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 140 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 125 value_ |= ExtendedPolicyField::encode(policy); | 141 value_ |= ExtendedPolicyField::encode(policy); |
| 126 value_ |= LifetimeField::encode(USED_AT_END); | 142 value_ |= LifetimeField::encode(USED_AT_END); |
| 127 } | 143 } |
| 128 | 144 |
| 129 UnallocatedOperand(BasicPolicy policy, int index) | 145 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) |
| 130 : InstructionOperand(UNALLOCATED, 0), | 146 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
| 131 virtual_register_(kInvalidVirtualRegister) { | |
| 132 DCHECK(policy == FIXED_SLOT); | 147 DCHECK(policy == FIXED_SLOT); |
| 133 value_ |= BasicPolicyField::encode(policy); | 148 value_ |= BasicPolicyField::encode(policy); |
| 134 value_ |= static_cast<int32_t>(index) << FixedSlotIndexField::kShift; | 149 value_ |= static_cast<int32_t>(index) << FixedSlotIndexField::kShift; |
| 135 DCHECK(this->fixed_slot_index() == index); | 150 DCHECK(this->fixed_slot_index() == index); |
| 136 } | 151 } |
| 137 | 152 |
| 138 UnallocatedOperand(ExtendedPolicy policy, int index) | 153 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register) |
| 139 : InstructionOperand(UNALLOCATED, 0), | 154 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
| 140 virtual_register_(kInvalidVirtualRegister) { | |
| 141 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); | 155 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); |
| 142 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 156 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 143 value_ |= ExtendedPolicyField::encode(policy); | 157 value_ |= ExtendedPolicyField::encode(policy); |
| 144 value_ |= LifetimeField::encode(USED_AT_END); | 158 value_ |= LifetimeField::encode(USED_AT_END); |
| 145 value_ |= FixedRegisterField::encode(index); | 159 value_ |= FixedRegisterField::encode(index); |
| 146 } | 160 } |
| 147 | 161 |
| 148 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime) | 162 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime, |
| 149 : InstructionOperand(UNALLOCATED, 0), | 163 int virtual_register) |
| 150 virtual_register_(kInvalidVirtualRegister) { | 164 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
| 151 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 165 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 152 value_ |= ExtendedPolicyField::encode(policy); | 166 value_ |= ExtendedPolicyField::encode(policy); |
| 153 value_ |= LifetimeField::encode(lifetime); | 167 value_ |= LifetimeField::encode(lifetime); |
| 154 } | 168 } |
| 155 | 169 |
| 156 UnallocatedOperand* CopyUnconstrained(Zone* zone) { | 170 UnallocatedOperand* CopyUnconstrained(Zone* zone) { |
| 157 UnallocatedOperand* result = new (zone) UnallocatedOperand(ANY); | 171 return new (zone) UnallocatedOperand(ANY, virtual_register()); |
| 158 result->set_virtual_register(virtual_register()); | |
| 159 return result; | |
| 160 } | 172 } |
| 161 | 173 |
| 162 static const UnallocatedOperand* cast(const InstructionOperand* op) { | 174 static const UnallocatedOperand* cast(const InstructionOperand* op) { |
| 163 DCHECK(op->IsUnallocated()); | 175 DCHECK(op->IsUnallocated()); |
| 164 return static_cast<const UnallocatedOperand*>(op); | 176 return static_cast<const UnallocatedOperand*>(op); |
| 165 } | 177 } |
| 166 | 178 |
| 167 static UnallocatedOperand* cast(InstructionOperand* op) { | 179 static UnallocatedOperand* cast(InstructionOperand* op) { |
| 168 DCHECK(op->IsUnallocated()); | 180 DCHECK(op->IsUnallocated()); |
| 169 return static_cast<UnallocatedOperand*>(op); | 181 return static_cast<UnallocatedOperand*>(op); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 bool HasFixedRegisterPolicy() const { | 238 bool HasFixedRegisterPolicy() const { |
| 227 return basic_policy() == EXTENDED_POLICY && | 239 return basic_policy() == EXTENDED_POLICY && |
| 228 extended_policy() == FIXED_REGISTER; | 240 extended_policy() == FIXED_REGISTER; |
| 229 } | 241 } |
| 230 bool HasFixedDoubleRegisterPolicy() const { | 242 bool HasFixedDoubleRegisterPolicy() const { |
| 231 return basic_policy() == EXTENDED_POLICY && | 243 return basic_policy() == EXTENDED_POLICY && |
| 232 extended_policy() == FIXED_DOUBLE_REGISTER; | 244 extended_policy() == FIXED_DOUBLE_REGISTER; |
| 233 } | 245 } |
| 234 | 246 |
| 235 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. | 247 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. |
| 236 BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); } | 248 BasicPolicy basic_policy() const { |
| 249 DCHECK_EQ(UNALLOCATED, kind()); |
| 250 return BasicPolicyField::decode(value_); |
| 251 } |
| 237 | 252 |
| 238 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. | 253 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. |
| 239 ExtendedPolicy extended_policy() const { | 254 ExtendedPolicy extended_policy() const { |
| 240 DCHECK(basic_policy() == EXTENDED_POLICY); | 255 DCHECK(basic_policy() == EXTENDED_POLICY); |
| 241 return ExtendedPolicyField::decode(value_); | 256 return ExtendedPolicyField::decode(value_); |
| 242 } | 257 } |
| 243 | 258 |
| 244 // [fixed_slot_index]: Only for FIXED_SLOT. | 259 // [fixed_slot_index]: Only for FIXED_SLOT. |
| 245 int fixed_slot_index() const { | 260 int fixed_slot_index() const { |
| 246 DCHECK(HasFixedSlotPolicy()); | 261 DCHECK(HasFixedSlotPolicy()); |
| 247 return static_cast<int>(bit_cast<int32_t>(value_) >> | 262 return static_cast<int>(bit_cast<int32_t>(value_) >> |
| 248 FixedSlotIndexField::kShift); | 263 FixedSlotIndexField::kShift); |
| 249 } | 264 } |
| 250 | 265 |
| 251 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. | 266 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. |
| 252 int fixed_register_index() const { | 267 int fixed_register_index() const { |
| 253 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); | 268 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); |
| 254 return FixedRegisterField::decode(value_); | 269 return FixedRegisterField::decode(value_); |
| 255 } | 270 } |
| 256 | 271 |
| 257 // [virtual_register]: The virtual register ID for this operand. | 272 // [virtual_register]: The virtual register ID for this operand. |
| 258 int32_t virtual_register() const { return virtual_register_; } | 273 int32_t virtual_register() const { |
| 259 void set_virtual_register(int32_t id) { virtual_register_ = id; } | 274 DCHECK_EQ(UNALLOCATED, kind()); |
| 275 return virtual_register_; |
| 276 } |
| 277 |
| 278 // TODO(dcarney): remove this. |
| 279 void set_virtual_register(int32_t id) { |
| 280 DCHECK_EQ(UNALLOCATED, kind()); |
| 281 virtual_register_ = id; |
| 282 } |
| 260 | 283 |
| 261 // [lifetime]: Only for non-FIXED_SLOT. | 284 // [lifetime]: Only for non-FIXED_SLOT. |
| 262 bool IsUsedAtStart() const { | 285 bool IsUsedAtStart() const { |
| 263 DCHECK(basic_policy() == EXTENDED_POLICY); | 286 DCHECK(basic_policy() == EXTENDED_POLICY); |
| 264 return LifetimeField::decode(value_) == USED_AT_START; | 287 return LifetimeField::decode(value_) == USED_AT_START; |
| 265 } | 288 } |
| 266 | |
| 267 private: | |
| 268 friend class Instruction; | |
| 269 UnallocatedOperand() | |
| 270 : InstructionOperand(), virtual_register_(kInvalidVirtualRegister) {} | |
| 271 | |
| 272 // TODO(dcarney): this should really be unsigned. | |
| 273 int32_t virtual_register_; | |
| 274 }; | 289 }; |
| 275 | 290 |
| 276 | 291 |
| 277 class MoveOperands FINAL { | 292 class MoveOperands FINAL { |
| 278 public: | 293 public: |
| 279 MoveOperands(InstructionOperand* source, InstructionOperand* destination) | 294 MoveOperands(InstructionOperand* source, InstructionOperand* destination) |
| 280 : source_(source), destination_(destination) {} | 295 : source_(source), destination_(destination) {} |
| 281 | 296 |
| 282 InstructionOperand* source() const { return source_; } | 297 InstructionOperand* source() const { return source_; } |
| 283 void set_source(InstructionOperand* operand) { source_ = operand; } | 298 void set_source(InstructionOperand* operand) { source_ = operand; } |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 | 791 |
| 777 class PhiInstruction FINAL : public ZoneObject { | 792 class PhiInstruction FINAL : public ZoneObject { |
| 778 public: | 793 public: |
| 779 typedef ZoneVector<InstructionOperand*> Inputs; | 794 typedef ZoneVector<InstructionOperand*> Inputs; |
| 780 | 795 |
| 781 PhiInstruction(Zone* zone, int virtual_register, size_t reserved_input_count) | 796 PhiInstruction(Zone* zone, int virtual_register, size_t reserved_input_count) |
| 782 : virtual_register_(virtual_register), | 797 : virtual_register_(virtual_register), |
| 783 operands_(zone), | 798 operands_(zone), |
| 784 output_(nullptr), | 799 output_(nullptr), |
| 785 inputs_(zone) { | 800 inputs_(zone) { |
| 786 UnallocatedOperand* output = | 801 UnallocatedOperand* output = new (zone) |
| 787 new (zone) UnallocatedOperand(UnallocatedOperand::NONE); | 802 UnallocatedOperand(UnallocatedOperand::NONE, virtual_register); |
| 788 output->set_virtual_register(virtual_register); | |
| 789 output_ = output; | 803 output_ = output; |
| 790 inputs_.reserve(reserved_input_count); | 804 inputs_.reserve(reserved_input_count); |
| 791 operands_.reserve(reserved_input_count); | 805 operands_.reserve(reserved_input_count); |
| 792 } | 806 } |
| 793 | 807 |
| 794 int virtual_register() const { return virtual_register_; } | 808 int virtual_register() const { return virtual_register_; } |
| 795 const IntVector& operands() const { return operands_; } | 809 const IntVector& operands() const { return operands_; } |
| 796 | 810 |
| 797 void Extend(Zone* zone, int virtual_register) { | 811 void Extend(Zone* zone, int virtual_register) { |
| 798 UnallocatedOperand* input = | 812 UnallocatedOperand* input = new (zone) |
| 799 new (zone) UnallocatedOperand(UnallocatedOperand::ANY); | 813 UnallocatedOperand(UnallocatedOperand::ANY, virtual_register); |
| 800 input->set_virtual_register(virtual_register); | |
| 801 operands_.push_back(virtual_register); | 814 operands_.push_back(virtual_register); |
| 802 inputs_.push_back(input); | 815 inputs_.push_back(input); |
| 803 } | 816 } |
| 804 | 817 |
| 805 InstructionOperand* output() const { return output_; } | 818 InstructionOperand* output() const { return output_; } |
| 806 const Inputs& inputs() const { return inputs_; } | 819 const Inputs& inputs() const { return inputs_; } |
| 807 Inputs& inputs() { return inputs_; } | 820 Inputs& inputs() { return inputs_; } |
| 808 | 821 |
| 809 private: | 822 private: |
| 810 // TODO(dcarney): some of these fields are only for verification, move them to | 823 // TODO(dcarney): some of these fields are only for verification, move them to |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 | 1068 |
| 1056 | 1069 |
| 1057 std::ostream& operator<<(std::ostream& os, | 1070 std::ostream& operator<<(std::ostream& os, |
| 1058 const PrintableInstructionSequence& code); | 1071 const PrintableInstructionSequence& code); |
| 1059 | 1072 |
| 1060 } // namespace compiler | 1073 } // namespace compiler |
| 1061 } // namespace internal | 1074 } // namespace internal |
| 1062 } // namespace v8 | 1075 } // namespace v8 |
| 1063 | 1076 |
| 1064 #endif // V8_COMPILER_INSTRUCTION_H_ | 1077 #endif // V8_COMPILER_INSTRUCTION_H_ |
| OLD | NEW |