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/zone-containers.h" | 9 #include "src/zone-containers.h" |
| 10 | 10 |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 } | 482 } |
| 483 | 483 |
| 484 bool IsReference(int virtual_register) const { | 484 bool IsReference(int virtual_register) const { |
| 485 return code()->IsReference(virtual_register); | 485 return code()->IsReference(virtual_register); |
| 486 } | 486 } |
| 487 | 487 |
| 488 bool ExistsUseWithoutDefinition(); | 488 bool ExistsUseWithoutDefinition(); |
| 489 | 489 |
| 490 // Creates a new live range. | 490 // Creates a new live range. |
| 491 LiveRange* NewLiveRange(int index); | 491 LiveRange* NewLiveRange(int index); |
| 492 void Spill(LiveRange* range); | |
| 493 int GetVirtualRegister() { return code()->NextVirtualRegister(); } | |
| 494 // Live range splitting helpers. | |
| 495 | |
| 496 // Split the given range in a position from the interval [start, end]. | |
| 497 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, | |
| 498 LifetimePosition end); | |
| 499 | |
| 500 // Split the given range at the given position. | |
| 501 // If range starts at or after the given position then the | |
| 502 // original range is returned. | |
| 503 // Otherwise returns the live range that starts at pos and contains | |
| 504 // all uses from the original range that follow pos. Uses at pos will | |
| 505 // still be owned by the original range after splitting. | |
| 506 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); | |
| 507 // Find a lifetime position in the interval [start, end] which | |
| 508 // is optimal for splitting: it is either header of the outermost | |
| 509 // loop covered by this interval or the latest possible position. | |
| 510 LifetimePosition FindOptimalSplitPos(LifetimePosition start, | |
| 511 LifetimePosition end); | |
| 492 | 512 |
| 493 private: | 513 private: |
| 494 Zone* const allocation_zone_; | 514 Zone* const allocation_zone_; |
| 495 Frame* const frame_; | 515 Frame* const frame_; |
| 496 InstructionSequence* const code_; | 516 InstructionSequence* const code_; |
| 497 const char* const debug_name_; | 517 const char* const debug_name_; |
| 498 const RegisterConfiguration* const config_; | 518 const RegisterConfiguration* const config_; |
| 499 PhiMap phi_map_; | 519 PhiMap phi_map_; |
| 500 ZoneVector<BitVector*> live_in_sets_; | 520 ZoneVector<BitVector*> live_in_sets_; |
| 501 ZoneVector<LiveRange*> live_ranges_; | 521 ZoneVector<LiveRange*> live_ranges_; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 | 616 |
| 597 private: | 617 private: |
| 598 RegisterAllocationData* data() const { return data_; } | 618 RegisterAllocationData* data() const { return data_; } |
| 599 InstructionSequence* code() const { return data()->code(); } | 619 InstructionSequence* code() const { return data()->code(); } |
| 600 Zone* allocation_zone() const { return data()->allocation_zone(); } | 620 Zone* allocation_zone() const { return data()->allocation_zone(); } |
| 601 Zone* code_zone() const { return code()->zone(); } | 621 Zone* code_zone() const { return code()->zone(); } |
| 602 const RegisterConfiguration* config() const { return data()->config(); } | 622 const RegisterConfiguration* config() const { return data()->config(); } |
| 603 | 623 |
| 604 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } | 624 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } |
| 605 | 625 |
| 606 int GetVirtualRegister() { return code()->NextVirtualRegister(); } | |
| 607 | |
| 608 bool IsReference(int virtual_register) const { | 626 bool IsReference(int virtual_register) const { |
| 609 return data()->IsReference(virtual_register); | 627 return data()->IsReference(virtual_register); |
| 610 } | 628 } |
| 611 | 629 |
| 612 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } | 630 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } |
| 613 | 631 |
| 614 // Helper methods for updating the life range lists. | 632 // Helper methods for updating the life range lists. |
| 615 void AddToActive(LiveRange* range); | 633 void AddToActive(LiveRange* range); |
| 616 void AddToInactive(LiveRange* range); | 634 void AddToInactive(LiveRange* range); |
| 617 void AddToUnhandledSorted(LiveRange* range); | 635 void AddToUnhandledSorted(LiveRange* range); |
| 618 void AddToUnhandledUnsorted(LiveRange* range); | 636 void AddToUnhandledUnsorted(LiveRange* range); |
| 619 void SortUnhandled(); | 637 void SortUnhandled(); |
| 620 bool UnhandledIsSorted(); | 638 bool UnhandledIsSorted(); |
| 621 void ActiveToHandled(LiveRange* range); | 639 void ActiveToHandled(LiveRange* range); |
| 622 void ActiveToInactive(LiveRange* range); | 640 void ActiveToInactive(LiveRange* range); |
| 623 void InactiveToHandled(LiveRange* range); | 641 void InactiveToHandled(LiveRange* range); |
| 624 void InactiveToActive(LiveRange* range); | 642 void InactiveToActive(LiveRange* range); |
| 625 | 643 |
| 626 // Helper methods for allocating registers. | 644 // Helper methods for allocating registers. |
| 627 bool TryReuseSpillForPhi(LiveRange* range); | 645 bool TryReuseSpillForPhi(LiveRange* range); |
| 628 bool TryAllocateFreeReg(LiveRange* range); | 646 bool TryAllocateFreeReg(LiveRange* range); |
| 629 void AllocateBlockedReg(LiveRange* range); | 647 void AllocateBlockedReg(LiveRange* range); |
| 630 | 648 |
| 631 // Live range splitting helpers. | |
| 632 | |
| 633 // Split the given range at the given position. | |
| 634 // If range starts at or after the given position then the | |
| 635 // original range is returned. | |
| 636 // Otherwise returns the live range that starts at pos and contains | |
| 637 // all uses from the original range that follow pos. Uses at pos will | |
| 638 // still be owned by the original range after splitting. | |
| 639 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); | |
| 640 | |
| 641 // Split the given range in a position from the interval [start, end]. | |
| 642 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, | |
| 643 LifetimePosition end); | |
| 644 | |
| 645 // Find a lifetime position in the interval [start, end] which | |
| 646 // is optimal for splitting: it is either header of the outermost | |
| 647 // loop covered by this interval or the latest possible position. | |
| 648 LifetimePosition FindOptimalSplitPos(LifetimePosition start, | |
| 649 LifetimePosition end); | |
| 650 | |
| 651 // Spill the given life range after position pos. | 649 // Spill the given life range after position pos. |
| 652 void SpillAfter(LiveRange* range, LifetimePosition pos); | 650 void SpillAfter(LiveRange* range, LifetimePosition pos); |
| 653 | 651 |
| 654 // Spill the given life range after position [start] and up to position [end]. | 652 // Spill the given life range after position [start] and up to position [end]. |
| 655 void SpillBetween(LiveRange* range, LifetimePosition start, | 653 void SpillBetween(LiveRange* range, LifetimePosition start, |
| 656 LifetimePosition end); | 654 LifetimePosition end); |
| 657 | 655 |
| 658 // Spill the given life range after position [start] and up to position [end]. | 656 // Spill the given life range after position [start] and up to position [end]. |
| 659 // Range is guaranteed to be spilled at least until position [until]. | 657 // Range is guaranteed to be spilled at least until position [until]. |
| 660 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, | 658 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, |
| 661 LifetimePosition until, LifetimePosition end); | 659 LifetimePosition until, LifetimePosition end); |
| 662 | 660 |
| 663 void SplitAndSpillIntersecting(LiveRange* range); | 661 void SplitAndSpillIntersecting(LiveRange* range); |
| 664 | 662 |
| 665 // If we are trying to spill a range inside the loop try to | 663 // If we are trying to spill a range inside the loop try to |
| 666 // hoist spill position out to the point just before the loop. | 664 // hoist spill position out to the point just before the loop. |
| 667 LifetimePosition FindOptimalSpillingPos(LiveRange* range, | 665 LifetimePosition FindOptimalSpillingPos(LiveRange* range, |
| 668 LifetimePosition pos); | 666 LifetimePosition pos); |
| 669 | 667 |
| 670 void Spill(LiveRange* range); | |
| 671 | |
| 672 // Return the block which contains give lifetime position. | 668 // Return the block which contains give lifetime position. |
| 673 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const { | 669 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const { |
| 674 return data()->GetInstructionBlock(pos); | 670 return data()->GetInstructionBlock(pos); |
| 675 } | 671 } |
| 676 | 672 |
| 677 void SetLiveRangeAssignedRegister(LiveRange* range, int reg) { | 673 void SetLiveRangeAssignedRegister(LiveRange* range, int reg) { |
| 678 data()->SetLiveRangeAssignedRegister(range, reg); | 674 data()->SetLiveRangeAssignedRegister(range, reg); |
| 679 } | 675 } |
| 680 | 676 |
| 681 // Helper methods for the fixed registers. | 677 // Helper methods for the fixed registers. |
| 682 int RegisterCount() const { return num_registers_; } | 678 int RegisterCount() const { return num_registers_; } |
| 683 const char* RegisterName(int allocation_index); | 679 const char* RegisterName(int allocation_index); |
| 684 | 680 |
| 685 ZoneVector<LiveRange*>& live_ranges() { return data()->live_ranges(); } | 681 ZoneVector<LiveRange*>& live_ranges() { return data()->live_ranges(); } |
| 686 ZoneVector<LiveRange*>& fixed_live_ranges() { | |
| 687 return data()->fixed_live_ranges(); | |
| 688 } | |
| 689 ZoneVector<LiveRange*>& fixed_double_live_ranges() { | |
| 690 return data()->fixed_double_live_ranges(); | |
| 691 } | |
| 692 ZoneVector<LiveRange*>& unhandled_live_ranges() { | 682 ZoneVector<LiveRange*>& unhandled_live_ranges() { |
| 693 return unhandled_live_ranges_; | 683 return unhandled_live_ranges_; |
| 694 } | 684 } |
| 695 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } | 685 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } |
| 696 ZoneVector<LiveRange*>& inactive_live_ranges() { | 686 ZoneVector<LiveRange*>& inactive_live_ranges() { |
| 697 return inactive_live_ranges_; | 687 return inactive_live_ranges_; |
| 698 } | 688 } |
| 699 ZoneVector<SpillRange*>& spill_ranges() { return data()->spill_ranges(); } | 689 ZoneVector<SpillRange*>& spill_ranges() { return data()->spill_ranges(); } |
| 700 RegisterAllocationData::PhiMap& phi_map() { return data()->phi_map(); } | 690 RegisterAllocationData::PhiMap& phi_map() { return data()->phi_map(); } |
| 701 | 691 |
| 702 RegisterAllocationData* const data_; | 692 RegisterAllocationData* const data_; |
| 703 const RegisterKind mode_; | 693 const RegisterKind mode_; |
| 704 const int num_registers_; | 694 const int num_registers_; |
| 705 | 695 |
| 706 ZoneVector<LiveRange*> unhandled_live_ranges_; | 696 ZoneVector<LiveRange*> unhandled_live_ranges_; |
| 707 ZoneVector<LiveRange*> active_live_ranges_; | 697 ZoneVector<LiveRange*> active_live_ranges_; |
| 708 ZoneVector<LiveRange*> inactive_live_ranges_; | 698 ZoneVector<LiveRange*> inactive_live_ranges_; |
| 709 | 699 |
| 710 #ifdef DEBUG | 700 #ifdef DEBUG |
| 711 LifetimePosition allocation_finger_; | 701 LifetimePosition allocation_finger_; |
| 712 #endif | 702 #endif |
| 713 | 703 |
| 714 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator); | 704 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator); |
| 715 }; | 705 }; |
| 716 | 706 |
| 717 | 707 |
| 708 class CoallescedLiveRanges; | |
| 709 | |
| 710 | |
|
jvoung (off chromium)
2015/04/21 23:34:06
I don't know if v8 style would say to include a co
Mircea Trofin
2015/04/22 04:37:33
Done.
| |
| 711 class GreedyAllocator final : public ZoneObject { | |
| 712 public: | |
| 713 explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind); | |
| 714 | |
| 715 void AllocateRegisters(); | |
| 716 | |
| 717 private: | |
| 718 RegisterAllocationData* data() const { return data_; } | |
| 719 InstructionSequence* code() const { return data()->code(); } | |
| 720 const RegisterConfiguration* config() const { return data()->config(); } | |
| 721 | |
| 722 typedef ZonePriorityQueue<std::pair<unsigned, LiveRange*>> PQueue; | |
| 723 | |
| 724 unsigned GetLiveRangeSize(LiveRange* range); | |
| 725 void Enqueue(LiveRange* range); | |
| 726 | |
| 727 void Evict(LiveRange* range); | |
| 728 float CalculateSpillWeight(LiveRange* range); | |
| 729 float CalculateMaxSpillWeight(const ZoneSet<LiveRange*>& ranges); | |
| 730 | |
| 731 | |
| 732 bool TryAllocate(LiveRange* current, ZoneSet<LiveRange*>* conflicting); | |
| 733 bool TryAllocatePhysicalRegister(unsigned reg_id, LiveRange* range, | |
| 734 ZoneSet<LiveRange*>* conflicting); | |
| 735 bool HandleSpillOperands(LiveRange* range); | |
| 736 bool AllocateBlockedRange(LiveRange*, const ZoneSet<LiveRange*>&); | |
| 737 | |
| 738 LiveRange* SpillBetweenUntil(LiveRange* range, LifetimePosition start, | |
| 739 LifetimePosition until, LifetimePosition end); | |
| 740 void AssignRangeToRegister(int reg_id, LiveRange* range); | |
| 741 | |
| 742 RegisterAllocationData* const data_; | |
| 743 const RegisterKind mode_; | |
| 744 const int num_registers_; | |
| 745 | |
| 746 ZoneVector<CoallescedLiveRanges*> allocations_; | |
| 747 PQueue queue_; | |
| 748 DISALLOW_COPY_AND_ASSIGN(GreedyAllocator); | |
| 749 }; | |
| 750 | |
| 751 | |
| 718 class OperandAssigner final : public ZoneObject { | 752 class OperandAssigner final : public ZoneObject { |
| 719 public: | 753 public: |
| 720 explicit OperandAssigner(RegisterAllocationData* data); | 754 explicit OperandAssigner(RegisterAllocationData* data); |
| 721 | 755 |
| 722 // Phase 5: assign spill splots. | 756 // Phase 5: assign spill splots. |
| 723 void AssignSpillSlots(); | 757 void AssignSpillSlots(); |
| 724 | 758 |
| 725 // Phase 6: commit assignment. | 759 // Phase 6: commit assignment. |
| 726 void CommitAssignment(); | 760 void CommitAssignment(); |
| 727 | 761 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 782 RegisterAllocationData* const data_; | 816 RegisterAllocationData* const data_; |
| 783 | 817 |
| 784 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 818 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
| 785 }; | 819 }; |
| 786 | 820 |
| 787 } // namespace compiler | 821 } // namespace compiler |
| 788 } // namespace internal | 822 } // namespace internal |
| 789 } // namespace v8 | 823 } // namespace v8 |
| 790 | 824 |
| 791 #endif // V8_REGISTER_ALLOCATOR_H_ | 825 #endif // V8_REGISTER_ALLOCATOR_H_ |
| OLD | NEW |