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_REGISTER_ALLOCATOR_H_ | 5 #ifndef V8_REGISTER_ALLOCATOR_H_ |
6 #define V8_REGISTER_ALLOCATOR_H_ | 6 #define V8_REGISTER_ALLOCATOR_H_ |
7 | 7 |
8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
9 #include "src/ostreams.h" | 9 #include "src/ostreams.h" |
10 #include "src/register-configuration.h" | 10 #include "src/register-configuration.h" |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 const InstructionOperand& operand, | 572 const InstructionOperand& operand, |
573 bool might_be_duplicated); | 573 bool might_be_duplicated); |
574 | 574 |
575 // If all the children of this range are spilled in deferred blocks, and if | 575 // If all the children of this range are spilled in deferred blocks, and if |
576 // for any non-spilled child with a use position requiring a slot, that range | 576 // for any non-spilled child with a use position requiring a slot, that range |
577 // is contained in a deferred block, mark the range as | 577 // is contained in a deferred block, mark the range as |
578 // IsSpilledOnlyInDeferredBlocks, so that we avoid spilling at definition, | 578 // IsSpilledOnlyInDeferredBlocks, so that we avoid spilling at definition, |
579 // and instead let the LiveRangeConnector perform the spills within the | 579 // and instead let the LiveRangeConnector perform the spills within the |
580 // deferred blocks. If so, we insert here spills for non-spilled ranges | 580 // deferred blocks. If so, we insert here spills for non-spilled ranges |
581 // with slot use positions. | 581 // with slot use positions. |
582 void MarkSpilledInDeferredBlock() { | 582 void TreatAsSpilledInDeferredBlock(Zone* zone, int total_block_count) { |
583 spill_start_index_ = -1; | 583 spill_start_index_ = -1; |
584 spilled_in_deferred_blocks_ = true; | 584 spilled_in_deferred_blocks_ = true; |
585 spill_move_insertion_locations_ = nullptr; | 585 spill_move_insertion_locations_ = nullptr; |
| 586 list_of_blocks_requiring_spill_operands_ = |
| 587 new (zone) BitVector(total_block_count, zone); |
586 } | 588 } |
587 | 589 |
588 bool TryCommitSpillInDeferredBlock(InstructionSequence* code, | 590 void CommitSpillInDeferredBlocks(RegisterAllocationData* data, |
589 const InstructionOperand& spill_operand); | 591 const InstructionOperand& spill_operand, |
| 592 BitVector* necessary_spill_points); |
590 | 593 |
591 TopLevelLiveRange* splintered_from() const { return splintered_from_; } | 594 TopLevelLiveRange* splintered_from() const { return splintered_from_; } |
592 bool IsSplinter() const { return splintered_from_ != nullptr; } | 595 bool IsSplinter() const { return splintered_from_ != nullptr; } |
593 bool MayRequireSpillRange() const { | 596 bool MayRequireSpillRange() const { |
594 DCHECK(!IsSplinter()); | 597 DCHECK(!IsSplinter()); |
595 return !HasSpillOperand() && spill_range_ == nullptr; | 598 return !HasSpillOperand() && spill_range_ == nullptr; |
596 } | 599 } |
597 void UpdateSpillRangePostMerge(TopLevelLiveRange* merged); | 600 void UpdateSpillRangePostMerge(TopLevelLiveRange* merged); |
598 int vreg() const { return vreg_; } | 601 int vreg() const { return vreg_; } |
599 | 602 |
(...skipping 10 matching lines...) Expand all Loading... |
610 } | 613 } |
611 | 614 |
612 int GetChildCount() const { return last_child_id_ + 1; } | 615 int GetChildCount() const { return last_child_id_ + 1; } |
613 | 616 |
614 bool IsSpilledOnlyInDeferredBlocks() const { | 617 bool IsSpilledOnlyInDeferredBlocks() const { |
615 return spilled_in_deferred_blocks_; | 618 return spilled_in_deferred_blocks_; |
616 } | 619 } |
617 | 620 |
618 struct SpillMoveInsertionList; | 621 struct SpillMoveInsertionList; |
619 | 622 |
620 SpillMoveInsertionList* spill_move_insertion_locations() const { | 623 SpillMoveInsertionList* GetSpillMoveInsertionLocations() const { |
| 624 DCHECK(!IsSpilledOnlyInDeferredBlocks()); |
621 return spill_move_insertion_locations_; | 625 return spill_move_insertion_locations_; |
622 } | 626 } |
623 TopLevelLiveRange* splinter() const { return splinter_; } | 627 TopLevelLiveRange* splinter() const { return splinter_; } |
624 void SetSplinter(TopLevelLiveRange* splinter) { | 628 void SetSplinter(TopLevelLiveRange* splinter) { |
625 DCHECK_NULL(splinter_); | 629 DCHECK_NULL(splinter_); |
626 DCHECK_NOT_NULL(splinter); | 630 DCHECK_NOT_NULL(splinter); |
627 | 631 |
628 splinter_ = splinter; | 632 splinter_ = splinter; |
629 splinter->relative_id_ = GetNextChildId(); | 633 splinter->relative_id_ = GetNextChildId(); |
630 splinter->set_spill_type(spill_type()); | 634 splinter->set_spill_type(spill_type()); |
631 splinter->SetSplinteredFrom(this); | 635 splinter->SetSplinteredFrom(this); |
632 } | 636 } |
633 | 637 |
634 void MarkHasPreassignedSlot() { has_preassigned_slot_ = true; } | 638 void MarkHasPreassignedSlot() { has_preassigned_slot_ = true; } |
635 bool has_preassigned_slot() const { return has_preassigned_slot_; } | 639 bool has_preassigned_slot() const { return has_preassigned_slot_; } |
636 | 640 |
| 641 void AddBlockRequiringSpillOperand(RpoNumber block_id) { |
| 642 DCHECK(IsSpilledOnlyInDeferredBlocks()); |
| 643 GetListOfBlocksRequiringSpillOperands()->Add(block_id.ToInt()); |
| 644 } |
| 645 |
| 646 BitVector* GetListOfBlocksRequiringSpillOperands() const { |
| 647 DCHECK(IsSpilledOnlyInDeferredBlocks()); |
| 648 return list_of_blocks_requiring_spill_operands_; |
| 649 } |
| 650 |
637 private: | 651 private: |
638 void SetSplinteredFrom(TopLevelLiveRange* splinter_parent); | 652 void SetSplinteredFrom(TopLevelLiveRange* splinter_parent); |
639 | 653 |
640 typedef BitField<bool, 1, 1> HasSlotUseField; | 654 typedef BitField<bool, 1, 1> HasSlotUseField; |
641 typedef BitField<bool, 2, 1> IsPhiField; | 655 typedef BitField<bool, 2, 1> IsPhiField; |
642 typedef BitField<bool, 3, 1> IsNonLoopPhiField; | 656 typedef BitField<bool, 3, 1> IsNonLoopPhiField; |
643 typedef BitField<SpillType, 4, 2> SpillTypeField; | 657 typedef BitField<SpillType, 4, 2> SpillTypeField; |
644 | 658 |
645 int vreg_; | 659 int vreg_; |
646 int last_child_id_; | 660 int last_child_id_; |
647 TopLevelLiveRange* splintered_from_; | 661 TopLevelLiveRange* splintered_from_; |
648 union { | 662 union { |
649 // Correct value determined by spill_type() | 663 // Correct value determined by spill_type() |
650 InstructionOperand* spill_operand_; | 664 InstructionOperand* spill_operand_; |
651 SpillRange* spill_range_; | 665 SpillRange* spill_range_; |
652 }; | 666 }; |
653 SpillMoveInsertionList* spill_move_insertion_locations_; | 667 |
| 668 union { |
| 669 SpillMoveInsertionList* spill_move_insertion_locations_; |
| 670 BitVector* list_of_blocks_requiring_spill_operands_; |
| 671 }; |
| 672 |
654 // TODO(mtrofin): generalize spilling after definition, currently specialized | 673 // TODO(mtrofin): generalize spilling after definition, currently specialized |
655 // just for spill in a single deferred block. | 674 // just for spill in a single deferred block. |
656 bool spilled_in_deferred_blocks_; | 675 bool spilled_in_deferred_blocks_; |
657 int spill_start_index_; | 676 int spill_start_index_; |
658 UsePosition* last_pos_; | 677 UsePosition* last_pos_; |
659 TopLevelLiveRange* splinter_; | 678 TopLevelLiveRange* splinter_; |
660 bool has_preassigned_slot_; | 679 bool has_preassigned_slot_; |
661 | 680 |
662 DISALLOW_COPY_AND_ASSIGN(TopLevelLiveRange); | 681 DISALLOW_COPY_AND_ASSIGN(TopLevelLiveRange); |
663 }; | 682 }; |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 RegisterAllocationData* data() const { return data_; } | 1137 RegisterAllocationData* data() const { return data_; } |
1119 | 1138 |
1120 bool SafePointsAreInOrder() const; | 1139 bool SafePointsAreInOrder() const; |
1121 | 1140 |
1122 RegisterAllocationData* const data_; | 1141 RegisterAllocationData* const data_; |
1123 | 1142 |
1124 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator); | 1143 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator); |
1125 }; | 1144 }; |
1126 | 1145 |
1127 | 1146 |
| 1147 class LiveRangeBoundArray; |
1128 // Insert moves of the form | 1148 // Insert moves of the form |
1129 // | 1149 // |
1130 // Operand(child_(k+1)) = Operand(child_k) | 1150 // Operand(child_(k+1)) = Operand(child_k) |
1131 // | 1151 // |
1132 // where child_k and child_(k+1) are consecutive children of a range (so | 1152 // where child_k and child_(k+1) are consecutive children of a range (so |
1133 // child_k->next() == child_(k+1)), and Operand(...) refers to the | 1153 // child_k->next() == child_(k+1)), and Operand(...) refers to the |
1134 // assigned operand, be it a register or a slot. | 1154 // assigned operand, be it a register or a slot. |
1135 class LiveRangeConnector final : public ZoneObject { | 1155 class LiveRangeConnector final : public ZoneObject { |
1136 public: | 1156 public: |
1137 explicit LiveRangeConnector(RegisterAllocationData* data); | 1157 explicit LiveRangeConnector(RegisterAllocationData* data); |
(...skipping 12 matching lines...) Expand all Loading... |
1150 InstructionSequence* code() const { return data()->code(); } | 1170 InstructionSequence* code() const { return data()->code(); } |
1151 Zone* code_zone() const { return code()->zone(); } | 1171 Zone* code_zone() const { return code()->zone(); } |
1152 | 1172 |
1153 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; | 1173 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; |
1154 | 1174 |
1155 int ResolveControlFlow(const InstructionBlock* block, | 1175 int ResolveControlFlow(const InstructionBlock* block, |
1156 const InstructionOperand& cur_op, | 1176 const InstructionOperand& cur_op, |
1157 const InstructionBlock* pred, | 1177 const InstructionBlock* pred, |
1158 const InstructionOperand& pred_op); | 1178 const InstructionOperand& pred_op); |
1159 | 1179 |
| 1180 void CommitSpillsInDeferredBlocks(TopLevelLiveRange* range, |
| 1181 LiveRangeBoundArray* array, |
| 1182 Zone* temp_zone); |
| 1183 |
1160 RegisterAllocationData* const data_; | 1184 RegisterAllocationData* const data_; |
1161 | 1185 |
1162 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 1186 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
1163 }; | 1187 }; |
1164 | 1188 |
1165 } // namespace compiler | 1189 } // namespace compiler |
1166 } // namespace internal | 1190 } // namespace internal |
1167 } // namespace v8 | 1191 } // namespace v8 |
1168 | 1192 |
1169 #endif // V8_REGISTER_ALLOCATOR_H_ | 1193 #endif // V8_REGISTER_ALLOCATOR_H_ |
OLD | NEW |