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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 static const OperandType* cast(const InstructionOperand* op) { \ | 160 static const OperandType* cast(const InstructionOperand* op) { \ |
161 DCHECK_EQ(OperandKind, op->kind()); \ | 161 DCHECK_EQ(OperandKind, op->kind()); \ |
162 return static_cast<const OperandType*>(op); \ | 162 return static_cast<const OperandType*>(op); \ |
163 } \ | 163 } \ |
164 \ | 164 \ |
165 static OperandType cast(const InstructionOperand& op) { \ | 165 static OperandType cast(const InstructionOperand& op) { \ |
166 DCHECK_EQ(OperandKind, op.kind()); \ | 166 DCHECK_EQ(OperandKind, op.kind()); \ |
167 return *static_cast<const OperandType*>(&op); \ | 167 return *static_cast<const OperandType*>(&op); \ |
168 } | 168 } |
169 | 169 |
170 class UnallocatedOperand : public InstructionOperand { | 170 class UnallocatedOperand final : public InstructionOperand { |
171 public: | 171 public: |
172 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY }; | 172 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY }; |
173 | 173 |
174 enum ExtendedPolicy { | 174 enum ExtendedPolicy { |
175 NONE, | 175 NONE, |
176 ANY, | 176 ANY, |
177 FIXED_REGISTER, | 177 FIXED_REGISTER, |
178 FIXED_FP_REGISTER, | 178 FIXED_FP_REGISTER, |
179 MUST_HAVE_REGISTER, | 179 MUST_HAVE_REGISTER, |
180 MUST_HAVE_SLOT, | 180 MUST_HAVE_SLOT, |
181 SAME_AS_FIRST_INPUT | 181 SAME_AS_FIRST_INPUT |
182 }; | 182 }; |
183 | 183 |
184 // Lifetime of operand inside the instruction. | 184 // Lifetime of operand inside the instruction. |
185 enum Lifetime { | 185 enum Lifetime { |
186 // USED_AT_START operand is guaranteed to be live only at | 186 // USED_AT_START operand is guaranteed to be live only at instruction start. |
187 // instruction start. Register allocator is free to assign the same register | 187 // The register allocator is free to assign the same register to some other |
188 // to some other operand used inside instruction (i.e. temporary or | 188 // operand used inside instruction (i.e. temporary or output). |
189 // output). | |
190 USED_AT_START, | 189 USED_AT_START, |
191 | 190 |
192 // USED_AT_END operand is treated as live until the end of | 191 // USED_AT_END operand is treated as live until the end of instruction. |
193 // instruction. This means that register allocator will not reuse it's | 192 // This means that register allocator will not reuse its register for any |
194 // register for any other operand inside instruction. | 193 // other operand inside instruction. |
195 USED_AT_END | 194 USED_AT_END |
196 }; | 195 }; |
197 | 196 |
198 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) | 197 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) |
199 : UnallocatedOperand(virtual_register) { | 198 : UnallocatedOperand(virtual_register) { |
200 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 199 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
201 value_ |= ExtendedPolicyField::encode(policy); | 200 value_ |= ExtendedPolicyField::encode(policy); |
202 value_ |= LifetimeField::encode(USED_AT_END); | 201 value_ |= LifetimeField::encode(USED_AT_END); |
203 } | 202 } |
204 | 203 |
(...skipping 21 matching lines...) Expand all Loading... |
226 value_ |= ExtendedPolicyField::encode(policy); | 225 value_ |= ExtendedPolicyField::encode(policy); |
227 value_ |= LifetimeField::encode(lifetime); | 226 value_ |= LifetimeField::encode(lifetime); |
228 } | 227 } |
229 | 228 |
230 UnallocatedOperand(int reg_id, int slot_id, int virtual_register) | 229 UnallocatedOperand(int reg_id, int slot_id, int virtual_register) |
231 : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) { | 230 : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) { |
232 value_ |= HasSecondaryStorageField::encode(true); | 231 value_ |= HasSecondaryStorageField::encode(true); |
233 value_ |= SecondaryStorageField::encode(slot_id); | 232 value_ |= SecondaryStorageField::encode(slot_id); |
234 } | 233 } |
235 | 234 |
| 235 UnallocatedOperand(const UnallocatedOperand& other, int virtual_register) { |
| 236 DCHECK_NE(kInvalidVirtualRegister, virtual_register); |
| 237 value_ = VirtualRegisterField::update( |
| 238 other.value_, static_cast<uint32_t>(virtual_register)); |
| 239 } |
| 240 |
236 // Predicates for the operand policy. | 241 // Predicates for the operand policy. |
237 bool HasAnyPolicy() const { | 242 bool HasAnyPolicy() const { |
238 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY; | 243 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY; |
239 } | 244 } |
240 bool HasFixedPolicy() const { | 245 bool HasFixedPolicy() const { |
241 return basic_policy() == FIXED_SLOT || | 246 return basic_policy() == FIXED_SLOT || |
242 extended_policy() == FIXED_REGISTER || | 247 extended_policy() == FIXED_REGISTER || |
243 extended_policy() == FIXED_FP_REGISTER; | 248 extended_policy() == FIXED_FP_REGISTER; |
244 } | 249 } |
245 bool HasRegisterPolicy() const { | 250 bool HasRegisterPolicy() const { |
(...skipping 22 matching lines...) Expand all Loading... |
268 extended_policy() == FIXED_REGISTER && | 273 extended_policy() == FIXED_REGISTER && |
269 HasSecondaryStorageField::decode(value_); | 274 HasSecondaryStorageField::decode(value_); |
270 } | 275 } |
271 int GetSecondaryStorage() const { | 276 int GetSecondaryStorage() const { |
272 DCHECK(HasSecondaryStorage()); | 277 DCHECK(HasSecondaryStorage()); |
273 return SecondaryStorageField::decode(value_); | 278 return SecondaryStorageField::decode(value_); |
274 } | 279 } |
275 | 280 |
276 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. | 281 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. |
277 BasicPolicy basic_policy() const { | 282 BasicPolicy basic_policy() const { |
278 DCHECK_EQ(UNALLOCATED, kind()); | |
279 return BasicPolicyField::decode(value_); | 283 return BasicPolicyField::decode(value_); |
280 } | 284 } |
281 | 285 |
282 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. | 286 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. |
283 ExtendedPolicy extended_policy() const { | 287 ExtendedPolicy extended_policy() const { |
284 DCHECK(basic_policy() == EXTENDED_POLICY); | 288 DCHECK(basic_policy() == EXTENDED_POLICY); |
285 return ExtendedPolicyField::decode(value_); | 289 return ExtendedPolicyField::decode(value_); |
286 } | 290 } |
287 | 291 |
288 // [fixed_slot_index]: Only for FIXED_SLOT. | 292 // [fixed_slot_index]: Only for FIXED_SLOT. |
289 int fixed_slot_index() const { | 293 int fixed_slot_index() const { |
290 DCHECK(HasFixedSlotPolicy()); | 294 DCHECK(HasFixedSlotPolicy()); |
291 return static_cast<int>(static_cast<int64_t>(value_) >> | 295 return static_cast<int>(static_cast<int64_t>(value_) >> |
292 FixedSlotIndexField::kShift); | 296 FixedSlotIndexField::kShift); |
293 } | 297 } |
294 | 298 |
295 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER. | 299 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER. |
296 int fixed_register_index() const { | 300 int fixed_register_index() const { |
297 DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy()); | 301 DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy()); |
298 return FixedRegisterField::decode(value_); | 302 return FixedRegisterField::decode(value_); |
299 } | 303 } |
300 | 304 |
301 // [virtual_register]: The virtual register ID for this operand. | 305 // [virtual_register]: The virtual register ID for this operand. |
302 int32_t virtual_register() const { | 306 int32_t virtual_register() const { |
303 DCHECK_EQ(UNALLOCATED, kind()); | |
304 return static_cast<int32_t>(VirtualRegisterField::decode(value_)); | 307 return static_cast<int32_t>(VirtualRegisterField::decode(value_)); |
305 } | 308 } |
306 | 309 |
307 // TODO(dcarney): remove this. | |
308 void set_virtual_register(int32_t id) { | |
309 DCHECK_EQ(UNALLOCATED, kind()); | |
310 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id)); | |
311 } | |
312 | |
313 // [lifetime]: Only for non-FIXED_SLOT. | 310 // [lifetime]: Only for non-FIXED_SLOT. |
314 bool IsUsedAtStart() const { | 311 bool IsUsedAtStart() const { |
315 DCHECK(basic_policy() == EXTENDED_POLICY); | 312 DCHECK(basic_policy() == EXTENDED_POLICY); |
316 return LifetimeField::decode(value_) == USED_AT_START; | 313 return LifetimeField::decode(value_) == USED_AT_START; |
317 } | 314 } |
318 | 315 |
319 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED); | 316 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED); |
320 | 317 |
321 // The encoding used for UnallocatedOperand operands depends on the policy | 318 // The encoding used for UnallocatedOperand operands depends on the policy |
322 // that is | 319 // that is |
(...skipping 1348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 }; | 1668 }; |
1672 | 1669 |
1673 V8_EXPORT_PRIVATE std::ostream& operator<<( | 1670 V8_EXPORT_PRIVATE std::ostream& operator<<( |
1674 std::ostream& os, const PrintableInstructionSequence& code); | 1671 std::ostream& os, const PrintableInstructionSequence& code); |
1675 | 1672 |
1676 } // namespace compiler | 1673 } // namespace compiler |
1677 } // namespace internal | 1674 } // namespace internal |
1678 } // namespace v8 | 1675 } // namespace v8 |
1679 | 1676 |
1680 #endif // V8_COMPILER_INSTRUCTION_H_ | 1677 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |