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