| 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 |