Chromium Code Reviews| 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/zone-containers.h" | 10 #include "src/zone-containers.h" |
| (...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 InstructionOperand* operand) { | 721 InstructionOperand* operand) { |
| 722 Use(block_start, position, operand, nullptr, UsePositionHintType::kNone); | 722 Use(block_start, position, operand, nullptr, UsePositionHintType::kNone); |
| 723 } | 723 } |
| 724 | 724 |
| 725 RegisterAllocationData* const data_; | 725 RegisterAllocationData* const data_; |
| 726 ZoneMap<InstructionOperand*, UsePosition*> phi_hints_; | 726 ZoneMap<InstructionOperand*, UsePosition*> phi_hints_; |
| 727 | 727 |
| 728 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); | 728 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); |
| 729 }; | 729 }; |
| 730 | 730 |
| 731 struct AllocatorStats { | |
| 732 unsigned spills; | |
| 733 unsigned wins; | |
| 734 unsigned losses_no_eviction; | |
| 735 unsigned losses_after_eviction; | |
| 736 unsigned good_split_attempts; | |
| 737 unsigned good_split_successes; | |
| 738 unsigned good_split_smart_above; | |
| 739 unsigned good_split_smart_below; | |
| 740 unsigned good_split_above; | |
| 741 unsigned good_split_below; | |
| 742 | |
| 743 void reset() { *this = {0}; } | |
| 744 }; | |
|
Jarin
2015/05/13 13:12:57
Could we have a proper constructor that sets every
| |
| 745 | |
| 746 | |
| 747 std::ostream& operator<<(std::ostream& os, const AllocatorStats& stats); | |
| 748 | |
| 731 | 749 |
| 732 class RegisterAllocator : public ZoneObject { | 750 class RegisterAllocator : public ZoneObject { |
| 733 public: | 751 public: |
| 734 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); | 752 explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind); |
| 735 | 753 |
| 736 protected: | 754 protected: |
| 755 AllocatorStats stats_; | |
| 737 RegisterAllocationData* data() const { return data_; } | 756 RegisterAllocationData* data() const { return data_; } |
| 738 InstructionSequence* code() const { return data()->code(); } | 757 InstructionSequence* code() const { return data()->code(); } |
| 739 RegisterKind mode() const { return mode_; } | 758 RegisterKind mode() const { return mode_; } |
| 740 int num_registers() const { return num_registers_; } | 759 int num_registers() const { return num_registers_; } |
| 741 | 760 |
| 742 Zone* allocation_zone() const { return data()->allocation_zone(); } | 761 Zone* allocation_zone() const { return data()->allocation_zone(); } |
| 743 | 762 |
| 744 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | 763 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } |
| 745 | 764 |
| 746 // Split the given range at the given position. | 765 // Split the given range at the given position. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 760 // loop covered by this interval or the latest possible position. | 779 // loop covered by this interval or the latest possible position. |
| 761 LifetimePosition FindOptimalSplitPos(LifetimePosition start, | 780 LifetimePosition FindOptimalSplitPos(LifetimePosition start, |
| 762 LifetimePosition end); | 781 LifetimePosition end); |
| 763 | 782 |
| 764 void Spill(LiveRange* range); | 783 void Spill(LiveRange* range); |
| 765 | 784 |
| 766 // If we are trying to spill a range inside the loop try to | 785 // If we are trying to spill a range inside the loop try to |
| 767 // hoist spill position out to the point just before the loop. | 786 // hoist spill position out to the point just before the loop. |
| 768 LifetimePosition FindOptimalSpillingPos(LiveRange* range, | 787 LifetimePosition FindOptimalSpillingPos(LiveRange* range, |
| 769 LifetimePosition pos); | 788 LifetimePosition pos); |
| 789 const char* RegisterName(int allocation_index) const; | |
| 770 | 790 |
| 771 private: | 791 private: |
| 772 RegisterAllocationData* const data_; | 792 RegisterAllocationData* const data_; |
| 773 const RegisterKind mode_; | 793 const RegisterKind mode_; |
| 774 const int num_registers_; | 794 const int num_registers_; |
| 775 | 795 |
| 776 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); | 796 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); |
| 777 }; | 797 }; |
| 778 | 798 |
| 779 | 799 |
| 780 class LinearScanAllocator final : public RegisterAllocator { | 800 class LinearScanAllocator final : public RegisterAllocator { |
| 781 public: | 801 public: |
| 782 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, | 802 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind, |
| 783 Zone* local_zone); | 803 Zone* local_zone); |
| 784 | 804 |
| 785 // Phase 4: compute register assignments. | 805 // Phase 4: compute register assignments. |
| 786 void AllocateRegisters(); | 806 void AllocateRegisters(); |
| 787 | 807 |
| 788 private: | 808 private: |
| 789 const char* RegisterName(int allocation_index) const; | |
| 790 | |
| 791 ZoneVector<LiveRange*>& unhandled_live_ranges() { | 809 ZoneVector<LiveRange*>& unhandled_live_ranges() { |
| 792 return unhandled_live_ranges_; | 810 return unhandled_live_ranges_; |
| 793 } | 811 } |
| 794 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } | 812 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } |
| 795 ZoneVector<LiveRange*>& inactive_live_ranges() { | 813 ZoneVector<LiveRange*>& inactive_live_ranges() { |
| 796 return inactive_live_ranges_; | 814 return inactive_live_ranges_; |
| 797 } | 815 } |
| 798 | 816 |
| 799 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); | 817 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); |
| 800 | 818 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 846 // A variant of the LLVM Greedy Register Allocator. See | 864 // A variant of the LLVM Greedy Register Allocator. See |
| 847 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html | 865 // http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html |
| 848 class GreedyAllocator final : public RegisterAllocator { | 866 class GreedyAllocator final : public RegisterAllocator { |
| 849 public: | 867 public: |
| 850 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, | 868 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind, |
| 851 Zone* local_zone); | 869 Zone* local_zone); |
| 852 | 870 |
| 853 void AllocateRegisters(); | 871 void AllocateRegisters(); |
| 854 | 872 |
| 855 private: | 873 private: |
| 856 LifetimePosition GetSplittablePos(LifetimePosition pos); | 874 bool FindGoodSplitPoint(LiveRange* range, |
| 875 const ZoneSet<LiveRange*>& conflicts); | |
| 876 LifetimePosition GetSplittablePos(UsePosition* use_pos, LiveRange* range); | |
| 877 LifetimePosition GetCorrectSplitPos(LifetimePosition pos); | |
|
Jarin
2015/05/13 13:12:57
Nit: ...Pos -> ...Position)
| |
| 857 const RegisterConfiguration* config() const { return data()->config(); } | 878 const RegisterConfiguration* config() const { return data()->config(); } |
| 858 Zone* local_zone() const { return local_zone_; } | 879 Zone* local_zone() const { return local_zone_; } |
| 859 bool TryReuseSpillForPhi(LiveRange* range); | 880 bool TryReuseSpillForPhi(LiveRange* range); |
| 860 int GetHintedRegister(LiveRange* range); | 881 int GetHintedRegister(LiveRange* range); |
| 861 | 882 |
| 862 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; | 883 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; |
| 863 | 884 |
| 885 unsigned GetLiveRangeSize(LiveRange* range, LifetimePosition start, | |
| 886 LifetimePosition end); | |
| 864 unsigned GetLiveRangeSize(LiveRange* range); | 887 unsigned GetLiveRangeSize(LiveRange* range); |
| 865 void Enqueue(LiveRange* range); | 888 void Enqueue(LiveRange* range); |
| 866 | 889 |
| 867 void Evict(LiveRange* range); | 890 void Evict(LiveRange* range); |
| 868 float CalculateSpillWeight(LiveRange* range); | 891 float CalculateSpillWeight(LiveRange* range); |
| 869 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); | 892 float CalculateSpillWeight(LiveRange* range, LifetimePosition start, |
| 870 | 893 LifetimePosition end); |
| 871 | 894 |
| 872 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); | 895 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); |
| 873 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, | 896 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, |
| 874 ZoneSet<LiveRange*>* conflicting); | 897 ZoneSet<LiveRange*>* conflicting); |
| 875 bool HandleSpillOperands(LiveRange* range); | 898 bool HandleSpillOperands(LiveRange* range); |
| 876 void AllocateBlockedRange(LiveRange* current, LifetimePosition pos, | 899 void AllocateBlockedRange(LiveRange* current, |
| 877 bool spill); | 900 const ZoneSet<LiveRange*>& conflicts); |
| 878 | 901 |
| 879 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, | 902 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, |
| 880 LifetimePosition until, LifetimePosition end); | 903 LifetimePosition until, LifetimePosition end); |
| 881 void AssignRangeToRegister(int reg_id, LiveRange* range); | 904 void AssignRangeToRegister(int reg_id, LiveRange* range); |
| 882 | 905 |
| 883 LifetimePosition FindProgressingSplitPosition(LiveRange* range, | 906 bool RangeHasSplitOrSpillPosition(LiveRange* range, LifetimePosition start, |
| 884 bool* is_spill_pos); | 907 LifetimePosition end); |
| 885 | 908 |
| 886 Zone* local_zone_; | 909 Zone* local_zone_; |
| 887 ZoneVector<CoalescedLiveRanges*> allocations_; | 910 ZoneVector<CoalescedLiveRanges*> allocations_; |
| 888 PQueue queue_; | 911 PQueue queue_; |
| 889 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); | 912 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); |
| 890 }; | 913 }; |
| 891 | 914 |
| 892 | 915 |
| 893 class SpillSlotLocator final : public ZoneObject { | 916 class SpillSlotLocator final : public ZoneObject { |
| 894 public: | 917 public: |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 966 RegisterAllocationData* const data_; | 989 RegisterAllocationData* const data_; |
| 967 | 990 |
| 968 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 991 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
| 969 }; | 992 }; |
| 970 | 993 |
| 971 } // namespace compiler | 994 } // namespace compiler |
| 972 } // namespace internal | 995 } // namespace internal |
| 973 } // namespace v8 | 996 } // namespace v8 |
| 974 | 997 |
| 975 #endif // V8_REGISTER_ALLOCATOR_H_ | 998 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |