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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 value_ = KindField::encode(kind); | 65 value_ = KindField::encode(kind); |
66 value_ |= bit_cast<unsigned>(index << KindField::kSize); | 66 value_ |= bit_cast<unsigned>(index << KindField::kSize); |
67 DCHECK(this->index() == index); | 67 DCHECK(this->index() == index); |
68 } | 68 } |
69 | 69 |
70 // Calls SetUpCache()/TearDownCache() for each subclass. | 70 // Calls SetUpCache()/TearDownCache() for each subclass. |
71 static void SetUpCaches(); | 71 static void SetUpCaches(); |
72 static void TearDownCaches(); | 72 static void TearDownCaches(); |
73 | 73 |
74 protected: | 74 protected: |
| 75 // TODO(dcarney): remove. used to construct the Instruction operand array. |
| 76 InstructionOperand() : value_(0xffffffff) {} |
75 typedef BitField<Kind, 0, 3> KindField; | 77 typedef BitField<Kind, 0, 3> KindField; |
76 | 78 |
77 uint32_t value_; | 79 uint32_t value_; |
78 }; | 80 }; |
79 | 81 |
80 typedef ZoneVector<InstructionOperand*> InstructionOperandVector; | 82 typedef ZoneVector<InstructionOperand*> InstructionOperandVector; |
81 | 83 |
82 struct PrintableInstructionOperand { | 84 struct PrintableInstructionOperand { |
83 const RegisterConfiguration* register_configuration_; | 85 const RegisterConfiguration* register_configuration_; |
84 const InstructionOperand* op_; | 86 const InstructionOperand* op_; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 int32_t virtual_register() const { return virtual_register_; } | 258 int32_t virtual_register() const { return virtual_register_; } |
257 void set_virtual_register(int32_t id) { virtual_register_ = id; } | 259 void set_virtual_register(int32_t id) { virtual_register_ = id; } |
258 | 260 |
259 // [lifetime]: Only for non-FIXED_SLOT. | 261 // [lifetime]: Only for non-FIXED_SLOT. |
260 bool IsUsedAtStart() const { | 262 bool IsUsedAtStart() const { |
261 DCHECK(basic_policy() == EXTENDED_POLICY); | 263 DCHECK(basic_policy() == EXTENDED_POLICY); |
262 return LifetimeField::decode(value_) == USED_AT_START; | 264 return LifetimeField::decode(value_) == USED_AT_START; |
263 } | 265 } |
264 | 266 |
265 private: | 267 private: |
| 268 friend class Instruction; |
| 269 UnallocatedOperand() |
| 270 : InstructionOperand(), virtual_register_(kInvalidVirtualRegister) {} |
| 271 |
266 // TODO(dcarney): this should really be unsigned. | 272 // TODO(dcarney): this should really be unsigned. |
267 int32_t virtual_register_; | 273 int32_t virtual_register_; |
268 }; | 274 }; |
269 | 275 |
270 | 276 |
271 class MoveOperands FINAL { | 277 class MoveOperands FINAL { |
272 public: | 278 public: |
273 MoveOperands(InstructionOperand* source, InstructionOperand* destination) | 279 MoveOperands(InstructionOperand* source, InstructionOperand* destination) |
274 : source_(source), destination_(destination) {} | 280 : source_(source), destination_(destination) {} |
275 | 281 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 ZoneList<InstructionOperand*> untagged_operands_; | 421 ZoneList<InstructionOperand*> untagged_operands_; |
416 int instruction_position_; | 422 int instruction_position_; |
417 }; | 423 }; |
418 | 424 |
419 std::ostream& operator<<(std::ostream& os, const PointerMap& pm); | 425 std::ostream& operator<<(std::ostream& os, const PointerMap& pm); |
420 | 426 |
421 // TODO(titzer): s/PointerMap/ReferenceMap/ | 427 // TODO(titzer): s/PointerMap/ReferenceMap/ |
422 class Instruction : public ZoneObject { | 428 class Instruction : public ZoneObject { |
423 public: | 429 public: |
424 size_t OutputCount() const { return OutputCountField::decode(bit_field_); } | 430 size_t OutputCount() const { return OutputCountField::decode(bit_field_); } |
425 InstructionOperand* OutputAt(size_t i) const { | 431 const InstructionOperand* OutputAt(size_t i) const { |
426 DCHECK(i < OutputCount()); | 432 DCHECK(i < OutputCount()); |
427 return operands_[i]; | 433 return &operands_[i]; |
| 434 } |
| 435 InstructionOperand* OutputAt(size_t i) { |
| 436 DCHECK(i < OutputCount()); |
| 437 return &operands_[i]; |
428 } | 438 } |
429 | 439 |
430 bool HasOutput() const { return OutputCount() == 1; } | 440 bool HasOutput() const { return OutputCount() == 1; } |
431 InstructionOperand* Output() const { return OutputAt(0); } | 441 const InstructionOperand* Output() const { return OutputAt(0); } |
| 442 InstructionOperand* Output() { return OutputAt(0); } |
432 | 443 |
433 size_t InputCount() const { return InputCountField::decode(bit_field_); } | 444 size_t InputCount() const { return InputCountField::decode(bit_field_); } |
434 InstructionOperand* InputAt(size_t i) const { | 445 const InstructionOperand* InputAt(size_t i) const { |
435 DCHECK(i < InputCount()); | 446 DCHECK(i < InputCount()); |
436 return operands_[OutputCount() + i]; | 447 return &operands_[OutputCount() + i]; |
437 } | 448 } |
438 void SetInputAt(size_t i, InstructionOperand* operand) { | 449 InstructionOperand* InputAt(size_t i) { |
439 DCHECK(i < InputCount()); | 450 DCHECK(i < InputCount()); |
440 operands_[OutputCount() + i] = operand; | 451 return &operands_[OutputCount() + i]; |
441 } | 452 } |
442 | 453 |
443 size_t TempCount() const { return TempCountField::decode(bit_field_); } | 454 size_t TempCount() const { return TempCountField::decode(bit_field_); } |
444 InstructionOperand* TempAt(size_t i) const { | 455 const InstructionOperand* TempAt(size_t i) const { |
445 DCHECK(i < TempCount()); | 456 DCHECK(i < TempCount()); |
446 return operands_[OutputCount() + InputCount() + i]; | 457 return &operands_[OutputCount() + InputCount() + i]; |
| 458 } |
| 459 InstructionOperand* TempAt(size_t i) { |
| 460 DCHECK(i < TempCount()); |
| 461 return &operands_[OutputCount() + InputCount() + i]; |
447 } | 462 } |
448 | 463 |
449 InstructionCode opcode() const { return opcode_; } | 464 InstructionCode opcode() const { return opcode_; } |
450 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); } | 465 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); } |
451 AddressingMode addressing_mode() const { | 466 AddressingMode addressing_mode() const { |
452 return AddressingModeField::decode(opcode()); | 467 return AddressingModeField::decode(opcode()); |
453 } | 468 } |
454 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); } | 469 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); } |
455 FlagsCondition flags_condition() const { | 470 FlagsCondition flags_condition() const { |
456 return FlagsConditionField::decode(opcode()); | 471 return FlagsConditionField::decode(opcode()); |
457 } | 472 } |
458 | 473 |
459 // TODO(titzer): make control and call into flags. | 474 // TODO(titzer): make control and call into flags. |
460 static Instruction* New(Zone* zone, InstructionCode opcode) { | 475 static Instruction* New(Zone* zone, InstructionCode opcode) { |
461 return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL); | 476 return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL); |
462 } | 477 } |
463 | 478 |
464 static Instruction* New(Zone* zone, InstructionCode opcode, | 479 static Instruction* New(Zone* zone, InstructionCode opcode, |
465 size_t output_count, InstructionOperand** outputs, | 480 size_t output_count, InstructionOperand** outputs, |
466 size_t input_count, InstructionOperand** inputs, | 481 size_t input_count, InstructionOperand** inputs, |
467 size_t temp_count, InstructionOperand** temps) { | 482 size_t temp_count, InstructionOperand** temps) { |
468 DCHECK(opcode >= 0); | 483 DCHECK(opcode >= 0); |
469 DCHECK(output_count == 0 || outputs != NULL); | 484 DCHECK(output_count == 0 || outputs != NULL); |
470 DCHECK(input_count == 0 || inputs != NULL); | 485 DCHECK(input_count == 0 || inputs != NULL); |
471 DCHECK(temp_count == 0 || temps != NULL); | 486 DCHECK(temp_count == 0 || temps != NULL); |
472 InstructionOperand* none = NULL; | 487 size_t total_extra_ops = output_count + input_count + temp_count; |
473 USE(none); | 488 if (total_extra_ops != 0) total_extra_ops--; |
474 int size = static_cast<int>(RoundUp(sizeof(Instruction), kPointerSize) + | 489 int size = static_cast<int>( |
475 (output_count + input_count + temp_count - 1) * | 490 RoundUp(sizeof(Instruction), sizeof(UnallocatedOperand)) + |
476 sizeof(none)); | 491 total_extra_ops * sizeof(UnallocatedOperand)); |
477 return new (zone->New(size)) Instruction( | 492 return new (zone->New(size)) Instruction( |
478 opcode, output_count, outputs, input_count, inputs, temp_count, temps); | 493 opcode, output_count, outputs, input_count, inputs, temp_count, temps); |
479 } | 494 } |
480 | 495 |
481 // TODO(titzer): another holdover from lithium days; register allocator | 496 // TODO(titzer): another holdover from lithium days; register allocator |
482 // should not need to know about control instructions. | 497 // should not need to know about control instructions. |
483 Instruction* MarkAsControl() { | 498 Instruction* MarkAsControl() { |
484 bit_field_ = IsControlField::update(bit_field_, true); | 499 bit_field_ = IsControlField::update(bit_field_, true); |
485 return this; | 500 return this; |
486 } | 501 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 bit_field_ = 0; | 535 bit_field_ = 0; |
521 pointer_map_ = NULL; | 536 pointer_map_ = NULL; |
522 } | 537 } |
523 | 538 |
524 bool IsNop() const { | 539 bool IsNop() const { |
525 return arch_opcode() == kArchNop && InputCount() == 0 && | 540 return arch_opcode() == kArchNop && InputCount() == 0 && |
526 OutputCount() == 0 && TempCount() == 0; | 541 OutputCount() == 0 && TempCount() == 0; |
527 } | 542 } |
528 | 543 |
529 protected: | 544 protected: |
530 explicit Instruction(InstructionCode opcode) | 545 explicit Instruction(InstructionCode opcode); |
531 : opcode_(opcode), | |
532 bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) | | |
533 TempCountField::encode(0) | IsCallField::encode(false) | | |
534 IsControlField::encode(false)), | |
535 pointer_map_(NULL) {} | |
536 | |
537 Instruction(InstructionCode opcode, size_t output_count, | 546 Instruction(InstructionCode opcode, size_t output_count, |
538 InstructionOperand** outputs, size_t input_count, | 547 InstructionOperand** outputs, size_t input_count, |
539 InstructionOperand** inputs, size_t temp_count, | 548 InstructionOperand** inputs, size_t temp_count, |
540 InstructionOperand** temps) | 549 InstructionOperand** temps); |
541 : opcode_(opcode), | |
542 bit_field_(OutputCountField::encode(output_count) | | |
543 InputCountField::encode(input_count) | | |
544 TempCountField::encode(temp_count) | | |
545 IsCallField::encode(false) | IsControlField::encode(false)), | |
546 pointer_map_(NULL) { | |
547 for (size_t i = 0; i < output_count; ++i) { | |
548 operands_[i] = outputs[i]; | |
549 } | |
550 for (size_t i = 0; i < input_count; ++i) { | |
551 operands_[output_count + i] = inputs[i]; | |
552 } | |
553 for (size_t i = 0; i < temp_count; ++i) { | |
554 operands_[output_count + input_count + i] = temps[i]; | |
555 } | |
556 } | |
557 | 550 |
558 protected: | 551 protected: |
559 typedef BitField<size_t, 0, 8> OutputCountField; | 552 typedef BitField<size_t, 0, 8> OutputCountField; |
560 typedef BitField<size_t, 8, 16> InputCountField; | 553 typedef BitField<size_t, 8, 16> InputCountField; |
561 typedef BitField<size_t, 24, 6> TempCountField; | 554 typedef BitField<size_t, 24, 6> TempCountField; |
562 typedef BitField<bool, 30, 1> IsCallField; | 555 typedef BitField<bool, 30, 1> IsCallField; |
563 typedef BitField<bool, 31, 1> IsControlField; | 556 typedef BitField<bool, 31, 1> IsControlField; |
564 | 557 |
565 InstructionCode opcode_; | 558 InstructionCode opcode_; |
566 uint32_t bit_field_; | 559 uint32_t bit_field_; |
567 PointerMap* pointer_map_; | 560 PointerMap* pointer_map_; |
568 InstructionOperand* operands_[1]; | 561 UnallocatedOperand operands_[1]; |
569 }; | 562 }; |
570 | 563 |
571 | 564 |
572 struct PrintableInstruction { | 565 struct PrintableInstruction { |
573 const RegisterConfiguration* register_configuration_; | 566 const RegisterConfiguration* register_configuration_; |
574 const Instruction* instr_; | 567 const Instruction* instr_; |
575 }; | 568 }; |
576 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); | 569 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); |
577 | 570 |
578 | 571 |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 | 1055 |
1063 | 1056 |
1064 std::ostream& operator<<(std::ostream& os, | 1057 std::ostream& operator<<(std::ostream& os, |
1065 const PrintableInstructionSequence& code); | 1058 const PrintableInstructionSequence& code); |
1066 | 1059 |
1067 } // namespace compiler | 1060 } // namespace compiler |
1068 } // namespace internal | 1061 } // namespace internal |
1069 } // namespace v8 | 1062 } // namespace v8 |
1070 | 1063 |
1071 #endif // V8_COMPILER_INSTRUCTION_H_ | 1064 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |