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> |
11 #include <set> | 11 #include <set> |
12 | 12 |
13 #include "src/compiler/common-operator.h" | 13 #include "src/compiler/common-operator.h" |
14 #include "src/compiler/frame.h" | 14 #include "src/compiler/frame.h" |
15 #include "src/compiler/instruction-codes.h" | 15 #include "src/compiler/instruction-codes.h" |
16 #include "src/compiler/opcodes.h" | 16 #include "src/compiler/opcodes.h" |
17 #include "src/compiler/register-configuration.h" | 17 #include "src/compiler/register-configuration.h" |
18 #include "src/compiler/source-position.h" | 18 #include "src/compiler/source-position.h" |
19 #include "src/zone-allocator.h" | 19 #include "src/zone-allocator.h" |
20 | 20 |
21 namespace v8 { | 21 namespace v8 { |
22 namespace internal { | 22 namespace internal { |
23 namespace compiler { | 23 namespace compiler { |
24 | 24 |
25 class Schedule; | 25 class Schedule; |
26 | 26 |
27 // A couple of reserved opcodes are used for internal use. | 27 // A couple of reserved opcodes are used for internal use. |
28 const InstructionCode kGapInstruction = -1; | 28 const InstructionCode kSourcePositionInstruction = -1; |
29 const InstructionCode kSourcePositionInstruction = -2; | |
30 | 29 |
31 #define INSTRUCTION_OPERAND_LIST(V) \ | 30 #define INSTRUCTION_OPERAND_LIST(V) \ |
32 V(Constant, CONSTANT) \ | 31 V(Constant, CONSTANT) \ |
33 V(Immediate, IMMEDIATE) \ | 32 V(Immediate, IMMEDIATE) \ |
34 V(StackSlot, STACK_SLOT) \ | 33 V(StackSlot, STACK_SLOT) \ |
35 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ | 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ |
36 V(Register, REGISTER) \ | 35 V(Register, REGISTER) \ |
37 V(DoubleRegister, DOUBLE_REGISTER) | 36 V(DoubleRegister, DOUBLE_REGISTER) |
38 | 37 |
39 class InstructionOperand { | 38 class InstructionOperand { |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 } | 535 } |
537 | 536 |
538 Instruction* MarkAsCall() { | 537 Instruction* MarkAsCall() { |
539 bit_field_ = IsCallField::update(bit_field_, true); | 538 bit_field_ = IsCallField::update(bit_field_, true); |
540 return this; | 539 return this; |
541 } | 540 } |
542 bool IsCall() const { return IsCallField::decode(bit_field_); } | 541 bool IsCall() const { return IsCallField::decode(bit_field_); } |
543 bool NeedsPointerMap() const { return IsCall(); } | 542 bool NeedsPointerMap() const { return IsCall(); } |
544 bool HasPointerMap() const { return pointer_map_ != NULL; } | 543 bool HasPointerMap() const { return pointer_map_ != NULL; } |
545 | 544 |
546 bool IsGapMoves() const { return opcode() == kGapInstruction; } | |
547 bool IsSourcePosition() const { | 545 bool IsSourcePosition() const { |
548 return opcode() == kSourcePositionInstruction; | 546 return opcode() == kSourcePositionInstruction; |
549 } | 547 } |
550 | 548 |
551 bool ClobbersRegisters() const { return IsCall(); } | 549 bool ClobbersRegisters() const { return IsCall(); } |
552 bool ClobbersTemps() const { return IsCall(); } | 550 bool ClobbersTemps() const { return IsCall(); } |
553 bool ClobbersDoubleRegisters() const { return IsCall(); } | 551 bool ClobbersDoubleRegisters() const { return IsCall(); } |
554 PointerMap* pointer_map() const { return pointer_map_; } | 552 PointerMap* pointer_map() const { return pointer_map_; } |
555 | 553 |
556 void set_pointer_map(PointerMap* map) { | 554 void set_pointer_map(PointerMap* map) { |
557 DCHECK(NeedsPointerMap()); | 555 DCHECK(NeedsPointerMap()); |
558 DCHECK(!pointer_map_); | 556 DCHECK(!pointer_map_); |
559 pointer_map_ = map; | 557 pointer_map_ = map; |
560 } | 558 } |
561 | 559 |
562 void OverwriteWithNop() { | 560 void OverwriteWithNop() { |
563 opcode_ = ArchOpcodeField::encode(kArchNop); | 561 opcode_ = ArchOpcodeField::encode(kArchNop); |
564 bit_field_ = 0; | 562 bit_field_ = 0; |
565 pointer_map_ = NULL; | 563 pointer_map_ = NULL; |
566 } | 564 } |
567 | 565 |
568 bool IsNop() const { | 566 bool IsNop() const { |
569 return arch_opcode() == kArchNop && InputCount() == 0 && | 567 return arch_opcode() == kArchNop && InputCount() == 0 && |
570 OutputCount() == 0 && TempCount() == 0; | 568 OutputCount() == 0 && TempCount() == 0; |
571 } | 569 } |
572 | 570 |
| 571 enum GapPosition { |
| 572 START, |
| 573 END, |
| 574 FIRST_GAP_POSITION = START, |
| 575 LAST_GAP_POSITION = END |
| 576 }; |
| 577 |
| 578 ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) { |
| 579 if (parallel_moves_[pos] == nullptr) { |
| 580 parallel_moves_[pos] = new (zone) ParallelMove(zone); |
| 581 } |
| 582 return parallel_moves_[pos]; |
| 583 } |
| 584 |
| 585 ParallelMove* GetParallelMove(GapPosition pos) { |
| 586 return parallel_moves_[pos]; |
| 587 } |
| 588 |
| 589 const ParallelMove* GetParallelMove(GapPosition pos) const { |
| 590 return parallel_moves_[pos]; |
| 591 } |
| 592 |
| 593 bool AreMovesRedundant() const; |
| 594 |
| 595 ParallelMove* const* parallel_moves() const { return ¶llel_moves_[0]; } |
| 596 ParallelMove** parallel_moves() { return ¶llel_moves_[0]; } |
| 597 |
573 protected: | 598 protected: |
574 explicit Instruction(InstructionCode opcode); | 599 explicit Instruction(InstructionCode opcode); |
| 600 |
| 601 private: |
575 Instruction(InstructionCode opcode, size_t output_count, | 602 Instruction(InstructionCode opcode, size_t output_count, |
576 InstructionOperand* outputs, size_t input_count, | 603 InstructionOperand* outputs, size_t input_count, |
577 InstructionOperand* inputs, size_t temp_count, | 604 InstructionOperand* inputs, size_t temp_count, |
578 InstructionOperand* temps); | 605 InstructionOperand* temps); |
579 | 606 |
580 typedef BitField<size_t, 0, 8> OutputCountField; | 607 typedef BitField<size_t, 0, 8> OutputCountField; |
581 typedef BitField<size_t, 8, 16> InputCountField; | 608 typedef BitField<size_t, 8, 16> InputCountField; |
582 typedef BitField<size_t, 24, 6> TempCountField; | 609 typedef BitField<size_t, 24, 6> TempCountField; |
583 typedef BitField<bool, 30, 1> IsCallField; | 610 typedef BitField<bool, 30, 1> IsCallField; |
584 | 611 |
585 InstructionCode opcode_; | 612 InstructionCode opcode_; |
586 uint32_t bit_field_; | 613 uint32_t bit_field_; |
| 614 ParallelMove* parallel_moves_[2]; |
587 PointerMap* pointer_map_; | 615 PointerMap* pointer_map_; |
588 InstructionOperand operands_[1]; | 616 InstructionOperand operands_[1]; |
589 | 617 |
590 private: | 618 private: |
591 DISALLOW_COPY_AND_ASSIGN(Instruction); | 619 DISALLOW_COPY_AND_ASSIGN(Instruction); |
592 }; | 620 }; |
593 | 621 |
594 | 622 |
595 struct PrintableInstruction { | 623 struct PrintableInstruction { |
596 const RegisterConfiguration* register_configuration_; | 624 const RegisterConfiguration* register_configuration_; |
597 const Instruction* instr_; | 625 const Instruction* instr_; |
598 }; | 626 }; |
599 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); | 627 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); |
600 | 628 |
601 | 629 |
602 // Represents moves inserted before an instruction due to register allocation. | |
603 // TODO(titzer): squash GapInstruction back into Instruction, since essentially | |
604 // every instruction can possibly have moves inserted before it. | |
605 class GapInstruction : public Instruction { | |
606 public: | |
607 enum InnerPosition { | |
608 START, | |
609 END, | |
610 FIRST_INNER_POSITION = START, | |
611 LAST_INNER_POSITION = END | |
612 }; | |
613 | |
614 ParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) { | |
615 if (parallel_moves_[pos] == NULL) { | |
616 parallel_moves_[pos] = new (zone) ParallelMove(zone); | |
617 } | |
618 return parallel_moves_[pos]; | |
619 } | |
620 | |
621 ParallelMove* GetParallelMove(InnerPosition pos) { | |
622 return parallel_moves_[pos]; | |
623 } | |
624 | |
625 const ParallelMove* GetParallelMove(InnerPosition pos) const { | |
626 return parallel_moves_[pos]; | |
627 } | |
628 | |
629 bool IsRedundant() const; | |
630 | |
631 ParallelMove** parallel_moves() { return parallel_moves_; } | |
632 | |
633 static GapInstruction* New(Zone* zone) { | |
634 void* buffer = zone->New(sizeof(GapInstruction)); | |
635 return new (buffer) GapInstruction(kGapInstruction); | |
636 } | |
637 | |
638 static GapInstruction* cast(Instruction* instr) { | |
639 DCHECK(instr->IsGapMoves()); | |
640 return static_cast<GapInstruction*>(instr); | |
641 } | |
642 | |
643 static const GapInstruction* cast(const Instruction* instr) { | |
644 DCHECK(instr->IsGapMoves()); | |
645 return static_cast<const GapInstruction*>(instr); | |
646 } | |
647 | |
648 protected: | |
649 explicit GapInstruction(InstructionCode opcode) : Instruction(opcode) { | |
650 parallel_moves_[START] = NULL; | |
651 parallel_moves_[END] = NULL; | |
652 } | |
653 | |
654 private: | |
655 friend std::ostream& operator<<(std::ostream& os, | |
656 const PrintableInstruction& instr); | |
657 ParallelMove* parallel_moves_[LAST_INNER_POSITION + 1]; | |
658 }; | |
659 | |
660 | |
661 class SourcePositionInstruction FINAL : public Instruction { | 630 class SourcePositionInstruction FINAL : public Instruction { |
662 public: | 631 public: |
663 static SourcePositionInstruction* New(Zone* zone, SourcePosition position) { | 632 static SourcePositionInstruction* New(Zone* zone, SourcePosition position) { |
664 void* buffer = zone->New(sizeof(SourcePositionInstruction)); | 633 void* buffer = zone->New(sizeof(SourcePositionInstruction)); |
665 return new (buffer) SourcePositionInstruction(position); | 634 return new (buffer) SourcePositionInstruction(position); |
666 } | 635 } |
667 | 636 |
668 SourcePosition source_position() const { return source_position_; } | 637 SourcePosition source_position() const { return source_position_; } |
669 | 638 |
670 static SourcePositionInstruction* cast(Instruction* instr) { | 639 static SourcePositionInstruction* cast(Instruction* instr) { |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 } | 944 } |
976 | 945 |
977 const InstructionBlock* GetInstructionBlock(int instruction_index) const; | 946 const InstructionBlock* GetInstructionBlock(int instruction_index) const; |
978 | 947 |
979 bool IsReference(int virtual_register) const; | 948 bool IsReference(int virtual_register) const; |
980 bool IsDouble(int virtual_register) const; | 949 bool IsDouble(int virtual_register) const; |
981 | 950 |
982 void MarkAsReference(int virtual_register); | 951 void MarkAsReference(int virtual_register); |
983 void MarkAsDouble(int virtual_register); | 952 void MarkAsDouble(int virtual_register); |
984 | 953 |
985 void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to); | 954 Instruction* GetBlockStart(RpoNumber rpo) const; |
986 | |
987 GapInstruction* GetBlockStart(RpoNumber rpo) const; | |
988 | 955 |
989 typedef InstructionDeque::const_iterator const_iterator; | 956 typedef InstructionDeque::const_iterator const_iterator; |
990 const_iterator begin() const { return instructions_.begin(); } | 957 const_iterator begin() const { return instructions_.begin(); } |
991 const_iterator end() const { return instructions_.end(); } | 958 const_iterator end() const { return instructions_.end(); } |
992 const InstructionDeque& instructions() const { return instructions_; } | 959 const InstructionDeque& instructions() const { return instructions_; } |
993 | 960 |
994 GapInstruction* GapAt(int index) const { | |
995 return GapInstruction::cast(InstructionAt(index)); | |
996 } | |
997 bool IsGapAt(int index) const { return InstructionAt(index)->IsGapMoves(); } | |
998 Instruction* InstructionAt(int index) const { | 961 Instruction* InstructionAt(int index) const { |
999 DCHECK(index >= 0); | 962 DCHECK(index >= 0); |
1000 DCHECK(index < static_cast<int>(instructions_.size())); | 963 DCHECK(index < static_cast<int>(instructions_.size())); |
1001 return instructions_[index]; | 964 return instructions_[index]; |
1002 } | 965 } |
1003 | 966 |
1004 Isolate* isolate() const { return isolate_; } | 967 Isolate* isolate() const { return isolate_; } |
1005 const PointerMapDeque* pointer_maps() const { return &pointer_maps_; } | 968 const PointerMapDeque* pointer_maps() const { return &pointer_maps_; } |
1006 Zone* zone() const { return zone_; } | 969 Zone* zone() const { return zone_; } |
1007 | 970 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 | 1053 |
1091 | 1054 |
1092 std::ostream& operator<<(std::ostream& os, | 1055 std::ostream& operator<<(std::ostream& os, |
1093 const PrintableInstructionSequence& code); | 1056 const PrintableInstructionSequence& code); |
1094 | 1057 |
1095 } // namespace compiler | 1058 } // namespace compiler |
1096 } // namespace internal | 1059 } // namespace internal |
1097 } // namespace v8 | 1060 } // namespace v8 |
1098 | 1061 |
1099 #endif // V8_COMPILER_INSTRUCTION_H_ | 1062 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |