Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: src/lithium-allocator.h

Issue 5720001: Fix issue 962. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/lithium-allocator.cc » ('j') | src/lithium-allocator.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 class LArgument; 48 class LArgument;
49 class LChunk; 49 class LChunk;
50 class LConstantOperand; 50 class LConstantOperand;
51 class LGap; 51 class LGap;
52 class LInstruction; 52 class LInstruction;
53 class LParallelMove; 53 class LParallelMove;
54 class LPointerMap; 54 class LPointerMap;
55 class LStackSlot; 55 class LStackSlot;
56 class LRegister; 56 class LRegister;
57 57
58
58 // This class represents a single point of a LOperand's lifetime. 59 // This class represents a single point of a LOperand's lifetime.
59 // For each lithium instruction there are exactly two lifetime positions: 60 // For each lithium instruction there are exactly two lifetime positions:
60 // the beginning and the end of the instruction. Lifetime positions for 61 // the beginning and the end of the instruction. Lifetime positions for
61 // different lithium instructions are disjoint. 62 // different lithium instructions are disjoint.
62 class LifetimePosition { 63 class LifetimePosition {
63 public: 64 public:
64 // Return the lifetime position that corresponds to the beginning of 65 // Return the lifetime position that corresponds to the beginning of
65 // the instruction with the given index. 66 // the instruction with the given index.
66 static LifetimePosition FromInstructionIndex(int index) { 67 static LifetimePosition FromInstructionIndex(int index) {
67 return LifetimePosition(index * kStep); 68 return LifetimePosition(index * kStep);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 } 115 }
115 116
116 // Constructs the lifetime position which does not correspond to any 117 // Constructs the lifetime position which does not correspond to any
117 // instruction. 118 // instruction.
118 LifetimePosition() : value_(-1) {} 119 LifetimePosition() : value_(-1) {}
119 120
120 // Returns true if this lifetime positions corrensponds to some 121 // Returns true if this lifetime positions corrensponds to some
121 // instruction. 122 // instruction.
122 bool IsValid() const { return value_ != -1; } 123 bool IsValid() const { return value_ != -1; }
123 124
124 static LifetimePosition Invalid() { return LifetimePosition(); } 125 static inline LifetimePosition Invalid() { return LifetimePosition(); }
Kevin Millikin (Chromium) 2010/12/10 07:39:19 I don't usually write inline here.
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 I prefer to state intention clearly.
126
127 static inline LifetimePosition MaxPosition() {
128 // We have to use this kind of getter instead of static member due to
129 // crash bug in GDB.
130 return LifetimePosition(kMaxInt);
131 }
125 132
126 private: 133 private:
127 static const int kStep = 2; 134 static const int kStep = 2;
128 135
129 // Code relies on kStep being a power of two. 136 // Code relies on kStep being a power of two.
130 STATIC_ASSERT(IS_POWER_OF_TWO(kStep)); 137 STATIC_ASSERT(IS_POWER_OF_TWO(kStep));
131 138
132 explicit LifetimePosition(int value) : value_(value) { } 139 explicit LifetimePosition(int value) : value_(value) { }
133 140
134 int value_; 141 int value_;
135 }; 142 };
136 143
137 144
145 enum RegistersClass {
Kevin Millikin (Chromium) 2010/12/10 07:39:19 RegisterKind?
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
146 NONE,
147 CPU_REGISTERS,
Kevin Millikin (Chromium) 2010/12/10 07:39:19 Maybe GENERAL_REGISTERS is better? They're all CP
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
148 DOUBLE_REGISTERS
149 };
150
151
138 class LOperand: public ZoneObject { 152 class LOperand: public ZoneObject {
139 public: 153 public:
140 enum Kind { 154 enum Kind {
141 INVALID, 155 INVALID,
142 UNALLOCATED, 156 UNALLOCATED,
143 CONSTANT_OPERAND, 157 CONSTANT_OPERAND,
144 STACK_SLOT, 158 STACK_SLOT,
145 DOUBLE_STACK_SLOT, 159 DOUBLE_STACK_SLOT,
146 REGISTER, 160 REGISTER,
147 DOUBLE_REGISTER, 161 DOUBLE_REGISTER,
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 601
588 // Representation of SSA values' live ranges as a collection of (continuous) 602 // Representation of SSA values' live ranges as a collection of (continuous)
589 // intervals over the instruction ordering. 603 // intervals over the instruction ordering.
590 class LiveRange: public ZoneObject { 604 class LiveRange: public ZoneObject {
591 public: 605 public:
592 static const int kInvalidAssignment = 0x7fffffff; 606 static const int kInvalidAssignment = 0x7fffffff;
593 607
594 explicit LiveRange(int id) 608 explicit LiveRange(int id)
595 : id_(id), 609 : id_(id),
596 spilled_(false), 610 spilled_(false),
597 assigned_double_(false),
598 assigned_register_(kInvalidAssignment), 611 assigned_register_(kInvalidAssignment),
612 assigned_register_class_(NONE),
Kevin Millikin (Chromium) 2010/12/10 07:39:19 assigned_register_kind_?
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
599 last_interval_(NULL), 613 last_interval_(NULL),
600 first_interval_(NULL), 614 first_interval_(NULL),
601 first_pos_(NULL), 615 first_pos_(NULL),
602 parent_(NULL), 616 parent_(NULL),
603 next_(NULL), 617 next_(NULL),
604 current_interval_(NULL), 618 current_interval_(NULL),
605 last_processed_use_(NULL), 619 last_processed_use_(NULL),
606 spill_start_index_(kMaxInt) { 620 spill_start_index_(kMaxInt) {
607 spill_operand_ = new LUnallocated(LUnallocated::IGNORE); 621 spill_operand_ = new LUnallocated(LUnallocated::IGNORE);
608 } 622 }
609 623
610 UseInterval* first_interval() const { return first_interval_; } 624 UseInterval* first_interval() const { return first_interval_; }
611 UsePosition* first_pos() const { return first_pos_; } 625 UsePosition* first_pos() const { return first_pos_; }
612 LiveRange* parent() const { return parent_; } 626 LiveRange* parent() const { return parent_; }
613 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } 627 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; }
614 LiveRange* next() const { return next_; } 628 LiveRange* next() const { return next_; }
615 bool IsChild() const { return parent() != NULL; } 629 bool IsChild() const { return parent() != NULL; }
616 bool IsParent() const { return parent() == NULL; } 630 bool IsParent() const { return parent() == NULL; }
617 int id() const { return id_; } 631 int id() const { return id_; }
618 bool IsFixed() const { return id_ < 0; } 632 bool IsFixed() const { return id_ < 0; }
619 bool IsEmpty() const { return first_interval() == NULL; } 633 bool IsEmpty() const { return first_interval() == NULL; }
620 LOperand* CreateAssignedOperand(); 634 LOperand* CreateAssignedOperand();
621 int assigned_register() const { return assigned_register_; } 635 int assigned_register() const { return assigned_register_; }
622 int spill_start_index() const { return spill_start_index_; } 636 int spill_start_index() const { return spill_start_index_; }
623 void set_assigned_register(int reg, bool double_reg) { 637 void set_assigned_register(int reg, RegistersClass reg_class) {
624 ASSERT(!HasRegisterAssigned() && !IsSpilled()); 638 ASSERT(!HasRegisterAssigned() && !IsSpilled());
625 assigned_register_ = reg; 639 assigned_register_ = reg;
626 assigned_double_ = double_reg; 640 assigned_register_class_ = reg_class;
627 ConvertOperands(); 641 ConvertOperands();
628 } 642 }
629 void MakeSpilled() { 643 void MakeSpilled() {
630 ASSERT(!IsSpilled()); 644 ASSERT(!IsSpilled());
631 ASSERT(TopLevel()->HasAllocatedSpillOperand()); 645 ASSERT(TopLevel()->HasAllocatedSpillOperand());
632 spilled_ = true; 646 spilled_ = true;
633 assigned_register_ = kInvalidAssignment; 647 assigned_register_ = kInvalidAssignment;
634 ConvertOperands(); 648 ConvertOperands();
635 } 649 }
636 650
637 // Returns use position in this live range that follows both start 651 // Returns use position in this live range that follows both start
638 // and last processed use position. 652 // and last processed use position.
639 // Modifies internal state of live range! 653 // Modifies internal state of live range!
640 UsePosition* NextUsePosition(LifetimePosition start); 654 UsePosition* NextUsePosition(LifetimePosition start);
641 655
642 // Returns use position for which register is required in this live 656 // Returns use position for which register is required in this live
643 // range and which follows both start and last processed use position 657 // range and which follows both start and last processed use position
644 // Modifies internal state of live range! 658 // Modifies internal state of live range!
645 UsePosition* NextRegisterPosition(LifetimePosition start); 659 UsePosition* NextRegisterPosition(LifetimePosition start);
646 660
647 // Returns use position for which register is beneficial in this live 661 // Returns use position for which register is beneficial in this live
648 // range and which follows both start and last processed use position 662 // range and which follows both start and last processed use position
649 // Modifies internal state of live range! 663 // Modifies internal state of live range!
650 UsePosition* NextUsePositionRegisterIsBeneficial(LifetimePosition start); 664 UsePosition* NextUsePositionRegisterIsBeneficial(LifetimePosition start);
651 665
652 // Can this live range be spilled at this position. 666 // Can this live range be spilled at this position.
653 bool CanBeSpilled(LifetimePosition pos); 667 bool CanBeSpilled(LifetimePosition pos);
654 668
669 // Split this live range at given position which must follow start of
Kevin Millikin (Chromium) 2010/12/10 07:39:19 follow the start of
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
670 // the range.
671 // All uses following the given position will be moved from this
672 // live range to result live range.
Kevin Millikin (Chromium) 2010/12/10 07:39:19 to the result
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
655 void SplitAt(LifetimePosition position, LiveRange* result); 673 void SplitAt(LifetimePosition position, LiveRange* result);
656 674
657 bool IsDouble() const { return assigned_double_; } 675 bool IsDouble() const { return assigned_register_class_ == DOUBLE_REGISTERS; }
658 bool HasRegisterAssigned() const { 676 bool HasRegisterAssigned() const {
659 return assigned_register_ != kInvalidAssignment; 677 return assigned_register_ != kInvalidAssignment;
660 } 678 }
661 bool IsSpilled() const { return spilled_; } 679 bool IsSpilled() const { return spilled_; }
662 UsePosition* FirstPosWithHint() const; 680 UsePosition* FirstPosWithHint() const;
663 681
664 LOperand* FirstHint() const { 682 LOperand* FirstHint() const {
665 UsePosition* pos = FirstPosWithHint(); 683 UsePosition* pos = FirstPosWithHint();
666 if (pos != NULL) return pos->hint(); 684 if (pos != NULL) return pos->hint();
667 return NULL; 685 return NULL;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 #endif 732 #endif
715 733
716 private: 734 private:
717 void ConvertOperands(); 735 void ConvertOperands();
718 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 736 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
719 void AdvanceLastProcessedMarker(UseInterval* to_start_of, 737 void AdvanceLastProcessedMarker(UseInterval* to_start_of,
720 LifetimePosition but_not_past) const; 738 LifetimePosition but_not_past) const;
721 739
722 int id_; 740 int id_;
723 bool spilled_; 741 bool spilled_;
724 bool assigned_double_;
725 int assigned_register_; 742 int assigned_register_;
743 RegistersClass assigned_register_class_;
726 UseInterval* last_interval_; 744 UseInterval* last_interval_;
727 UseInterval* first_interval_; 745 UseInterval* first_interval_;
728 UsePosition* first_pos_; 746 UsePosition* first_pos_;
729 LiveRange* parent_; 747 LiveRange* parent_;
730 LiveRange* next_; 748 LiveRange* next_;
731 // This is used as a cache, it doesn't affect correctness. 749 // This is used as a cache, it doesn't affect correctness.
732 mutable UseInterval* current_interval_; 750 mutable UseInterval* current_interval_;
733 UsePosition* last_processed_use_; 751 UsePosition* last_processed_use_;
734 LOperand* spill_operand_; 752 LOperand* spill_operand_;
735 int spill_start_index_; 753 int spill_start_index_;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 void RecordDefinition(HInstruction* instr, LUnallocated* operand); 785 void RecordDefinition(HInstruction* instr, LUnallocated* operand);
768 // Record a temporary operand. 786 // Record a temporary operand.
769 void RecordTemporary(LUnallocated* operand); 787 void RecordTemporary(LUnallocated* operand);
770 788
771 // Marks the current instruction as a call. 789 // Marks the current instruction as a call.
772 void MarkAsCall(); 790 void MarkAsCall();
773 791
774 // Checks whether the value of a given virtual register is tagged. 792 // Checks whether the value of a given virtual register is tagged.
775 bool HasTaggedValue(int virtual_register) const; 793 bool HasTaggedValue(int virtual_register) const;
776 794
777 // Checks whether the value of a given virtual register is a double. 795 // Returns register class required by given virtual register.
Kevin Millikin (Chromium) 2010/12/10 07:39:19 Returns the register kind
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
778 bool HasDoubleValue(int virtual_register) const; 796 RegistersClass RequiredRegisterClass(int virtual_register) const;
779 797
780 // Begin a new instruction. 798 // Begin a new instruction.
781 void BeginInstruction(); 799 void BeginInstruction();
782 800
783 // Summarize the current instruction. 801 // Summarize the current instruction.
784 void SummarizeInstruction(int index); 802 void SummarizeInstruction(int index);
785 803
786 // Summarize the current instruction. 804 // Summarize the current instruction.
787 void OmitInstruction(); 805 void OmitInstruction();
788 806
(...skipping 18 matching lines...) Expand all
807 ASSERT(!has_osr_entry_); 825 ASSERT(!has_osr_entry_);
808 // Simply set a flag to find and process instruction later. 826 // Simply set a flag to find and process instruction later.
809 has_osr_entry_ = true; 827 has_osr_entry_ = true;
810 } 828 }
811 829
812 #ifdef DEBUG 830 #ifdef DEBUG
813 void Verify() const; 831 void Verify() const;
814 #endif 832 #endif
815 833
816 private: 834 private:
817 enum OperationMode {
818 NONE,
819 CPU_REGISTERS,
820 XMM_REGISTERS
821 };
822
823 void MeetRegisterConstraints(); 835 void MeetRegisterConstraints();
824 void ResolvePhis(); 836 void ResolvePhis();
825 void BuildLiveRanges(); 837 void BuildLiveRanges();
826 void AllocateGeneralRegisters(); 838 void AllocateGeneralRegisters();
827 void AllocateDoubleRegisters(); 839 void AllocateDoubleRegisters();
828 void ConnectRanges(); 840 void ConnectRanges();
829 void ResolveControlFlow(); 841 void ResolveControlFlow();
830 void PopulatePointerMaps(); 842 void PopulatePointerMaps();
831 void ProcessOsrEntry(); 843 void ProcessOsrEntry();
832 void AllocateRegisters(); 844 void AllocateRegisters();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 void ActiveToHandled(LiveRange* range); 876 void ActiveToHandled(LiveRange* range);
865 void ActiveToInactive(LiveRange* range); 877 void ActiveToInactive(LiveRange* range);
866 void InactiveToHandled(LiveRange* range); 878 void InactiveToHandled(LiveRange* range);
867 void InactiveToActive(LiveRange* range); 879 void InactiveToActive(LiveRange* range);
868 void FreeSpillSlot(LiveRange* range); 880 void FreeSpillSlot(LiveRange* range);
869 LOperand* TryReuseSpillSlot(LiveRange* range); 881 LOperand* TryReuseSpillSlot(LiveRange* range);
870 882
871 // Helper methods for allocating registers. 883 // Helper methods for allocating registers.
872 bool TryAllocateFreeReg(LiveRange* range); 884 bool TryAllocateFreeReg(LiveRange* range);
873 void AllocateBlockedReg(LiveRange* range); 885 void AllocateBlockedReg(LiveRange* range);
874 void SplitAndSpillIntersecting(LiveRange* range); 886
887 // Live range splitting helpers.
888
889 // Split given range at position pos.
Kevin Millikin (Chromium) 2010/12/10 07:39:19 the given range
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
890 // If range starts at pos or range start follows pos then
Kevin Millikin (Chromium) 2010/12/10 07:39:19 Something like: If the range starts at or after po
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
891 // original range is returned.
892 // Otherwise returns live range that starts at pos and contains
Kevin Millikin (Chromium) 2010/12/10 07:39:19 the live range
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
893 // all uses from original range that follow pos. Uses at pos will
Kevin Millikin (Chromium) 2010/12/10 07:39:19 from the origiinal
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
894 // still be owned by original range after splitting.
Kevin Millikin (Chromium) 2010/12/10 07:39:19 by the original
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
895 LiveRange* SplitAt(LiveRange* range, LifetimePosition pos);
896
897 // Split given range in position from interval [start, end].
898 LiveRange* SplitBetween(LiveRange* range,
899 LifetimePosition start,
900 LifetimePosition end);
901
902 // Find lifetime position in interval [start, end] that
903 // is optimal for splitting: it is either header of outermost
904 // loop covered by this interval or latest possible position.
875 LifetimePosition FindOptimalSplitPos(LifetimePosition start, 905 LifetimePosition FindOptimalSplitPos(LifetimePosition start,
876 LifetimePosition end); 906 LifetimePosition end);
877 LiveRange* Split(LiveRange* range, 907
878 LifetimePosition start, 908 // Spill give life range after position pos.
Kevin Millikin (Chromium) 2010/12/10 07:39:19 the given live range
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
879 LifetimePosition end); 909 void SpillAfter(LiveRange* range, LifetimePosition pos);
880 LiveRange* Split(LiveRange* range, LifetimePosition split_pos); 910
881 void SplitAndSpill(LiveRange* range, 911 // Spill given life range after position start and up to end.
Kevin Millikin (Chromium) 2010/12/10 07:39:19 the given live range
Vyacheslav Egorov (Chromium) 2010/12/10 14:18:27 Done.
882 LifetimePosition start, 912 void SpillBetween(LiveRange* range,
883 LifetimePosition end); 913 LifetimePosition start,
884 void SplitAndSpill(LiveRange* range, LifetimePosition at); 914 LifetimePosition end);
915
916
917 void SplitAndSpillIntersecting(LiveRange* range);
918
885 void Spill(LiveRange* range); 919 void Spill(LiveRange* range);
886 bool IsBlockBoundary(LifetimePosition pos); 920 bool IsBlockBoundary(LifetimePosition pos);
887 void AddGapMove(int pos, LiveRange* prev, LiveRange* next); 921 void AddGapMove(int pos, LiveRange* prev, LiveRange* next);
888 922
889 // Helper methods for resolving control flow. 923 // Helper methods for resolving control flow.
890 void ResolveControlFlow(LiveRange* range, 924 void ResolveControlFlow(LiveRange* range,
891 HBasicBlock* block, 925 HBasicBlock* block,
892 HBasicBlock* pred); 926 HBasicBlock* pred);
893 927
894 // Return parallel move that should be used to connect ranges split at the 928 // Return parallel move that should be used to connect ranges split at the
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 ZoneList<LiveRange*> fixed_live_ranges_; 965 ZoneList<LiveRange*> fixed_live_ranges_;
932 ZoneList<LiveRange*> fixed_double_live_ranges_; 966 ZoneList<LiveRange*> fixed_double_live_ranges_;
933 ZoneList<LiveRange*> unhandled_live_ranges_; 967 ZoneList<LiveRange*> unhandled_live_ranges_;
934 ZoneList<LiveRange*> active_live_ranges_; 968 ZoneList<LiveRange*> active_live_ranges_;
935 ZoneList<LiveRange*> inactive_live_ranges_; 969 ZoneList<LiveRange*> inactive_live_ranges_;
936 ZoneList<LiveRange*> reusable_slots_; 970 ZoneList<LiveRange*> reusable_slots_;
937 971
938 // Next virtual register number to be assigned to temporaries. 972 // Next virtual register number to be assigned to temporaries.
939 int next_virtual_register_; 973 int next_virtual_register_;
940 974
941 OperationMode mode_; 975 RegistersClass mode_;
942 int num_registers_; 976 int num_registers_;
943 977
944 HGraph* graph_; 978 HGraph* graph_;
945 979
946 bool has_osr_entry_; 980 bool has_osr_entry_;
947 981
948 DISALLOW_COPY_AND_ASSIGN(LAllocator); 982 DISALLOW_COPY_AND_ASSIGN(LAllocator);
949 }; 983 };
950 984
951 985
952 } } // namespace v8::internal 986 } } // namespace v8::internal
953 987
954 #endif // V8_LITHIUM_ALLOCATOR_H_ 988 #endif // V8_LITHIUM_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « no previous file | src/lithium-allocator.cc » ('j') | src/lithium-allocator.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698