| OLD | NEW |
| 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 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_LITHIUM_ALLOCATOR_H_ | 28 #ifndef V8_LITHIUM_ALLOCATOR_H_ |
| 29 #define V8_LITHIUM_ALLOCATOR_H_ | 29 #define V8_LITHIUM_ALLOCATOR_H_ |
| 30 | 30 |
| 31 #include "v8.h" | 31 #include "v8.h" |
| 32 | 32 |
| 33 #include "data-flow.h" |
| 33 #include "zone.h" | 34 #include "zone.h" |
| 34 | 35 |
| 35 namespace v8 { | 36 namespace v8 { |
| 36 namespace internal { | 37 namespace internal { |
| 37 | 38 |
| 38 // Forward declarations. | 39 // Forward declarations. |
| 39 class HBasicBlock; | 40 class HBasicBlock; |
| 40 class HGraph; | 41 class HGraph; |
| 41 class HInstruction; | 42 class HInstruction; |
| 42 class HPhi; | 43 class HPhi; |
| 43 class HTracer; | 44 class HTracer; |
| 44 class HValue; | 45 class HValue; |
| 45 class BitVector; | 46 class BitVector; |
| 46 class StringStream; | 47 class StringStream; |
| 47 | 48 |
| 48 class LArgument; | 49 class LArgument; |
| 49 class LChunk; | 50 class LChunk; |
| 50 class LConstantOperand; | 51 class LConstantOperand; |
| 51 class LGap; | 52 class LGap; |
| 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 |
| 59 // This class represents a single point of a LOperand's lifetime. | 59 // This class represents a single point of a LOperand's lifetime. |
| 60 // For each lithium instruction there are exactly two lifetime positions: | 60 // For each lithium instruction there are exactly two lifetime positions: |
| 61 // the beginning and the end of the instruction. Lifetime positions for | 61 // the beginning and the end of the instruction. Lifetime positions for |
| 62 // different lithium instructions are disjoint. | 62 // different lithium instructions are disjoint. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 public: | 197 public: |
| 198 enum Policy { | 198 enum Policy { |
| 199 NONE, | 199 NONE, |
| 200 ANY, | 200 ANY, |
| 201 FIXED_REGISTER, | 201 FIXED_REGISTER, |
| 202 FIXED_DOUBLE_REGISTER, | 202 FIXED_DOUBLE_REGISTER, |
| 203 FIXED_SLOT, | 203 FIXED_SLOT, |
| 204 MUST_HAVE_REGISTER, | 204 MUST_HAVE_REGISTER, |
| 205 WRITABLE_REGISTER, | 205 WRITABLE_REGISTER, |
| 206 SAME_AS_FIRST_INPUT, | 206 SAME_AS_FIRST_INPUT, |
| 207 SAME_AS_ANY_INPUT, | |
| 208 IGNORE | 207 IGNORE |
| 209 }; | 208 }; |
| 210 | 209 |
| 211 // Lifetime of operand inside the instruction. | 210 // Lifetime of operand inside the instruction. |
| 212 enum Lifetime { | 211 enum Lifetime { |
| 213 // USED_AT_START operand is guaranteed to be live only at | 212 // USED_AT_START operand is guaranteed to be live only at |
| 214 // instruction start. Register allocator is free to assign the same register | 213 // instruction start. Register allocator is free to assign the same register |
| 215 // to some other operand used inside instruction (i.e. temporary or | 214 // to some other operand used inside instruction (i.e. temporary or |
| 216 // output). | 215 // output). |
| 217 USED_AT_START, | 216 USED_AT_START, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 } | 267 } |
| 269 bool HasFixedPolicy() const { | 268 bool HasFixedPolicy() const { |
| 270 return policy() == FIXED_REGISTER || | 269 return policy() == FIXED_REGISTER || |
| 271 policy() == FIXED_DOUBLE_REGISTER || | 270 policy() == FIXED_DOUBLE_REGISTER || |
| 272 policy() == FIXED_SLOT; | 271 policy() == FIXED_SLOT; |
| 273 } | 272 } |
| 274 bool HasRegisterPolicy() const { | 273 bool HasRegisterPolicy() const { |
| 275 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; | 274 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; |
| 276 } | 275 } |
| 277 bool HasSameAsInputPolicy() const { | 276 bool HasSameAsInputPolicy() const { |
| 278 return policy() == SAME_AS_FIRST_INPUT || policy() == SAME_AS_ANY_INPUT; | 277 return policy() == SAME_AS_FIRST_INPUT; |
| 279 } | 278 } |
| 280 Policy policy() const { return PolicyField::decode(value_); } | 279 Policy policy() const { return PolicyField::decode(value_); } |
| 281 void set_policy(Policy policy) { | 280 void set_policy(Policy policy) { |
| 282 value_ &= ~PolicyField::mask(); | 281 value_ &= ~PolicyField::mask(); |
| 283 value_ |= PolicyField::encode(policy); | 282 value_ |= PolicyField::encode(policy); |
| 284 } | 283 } |
| 285 int fixed_index() const { | 284 int fixed_index() const { |
| 286 return static_cast<int>(value_) >> kFixedIndexShift; | 285 return static_cast<int>(value_) >> kFixedIndexShift; |
| 287 } | 286 } |
| 288 | 287 |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 LDoubleRegister() : LOperand() { } | 474 LDoubleRegister() : LOperand() { } |
| 476 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { } | 475 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { } |
| 477 }; | 476 }; |
| 478 | 477 |
| 479 | 478 |
| 480 // A register-allocator view of a Lithium instruction. It contains the id of | 479 // A register-allocator view of a Lithium instruction. It contains the id of |
| 481 // the output operand and a list of input operand uses. | 480 // the output operand and a list of input operand uses. |
| 482 class InstructionSummary: public ZoneObject { | 481 class InstructionSummary: public ZoneObject { |
| 483 public: | 482 public: |
| 484 InstructionSummary() | 483 InstructionSummary() |
| 485 : output_operand_(NULL), input_count_(0), operands_(4), is_call_(false) {} | 484 : output_operand_(NULL), |
| 485 input_count_(0), |
| 486 operands_(4), |
| 487 is_call_(false), |
| 488 is_save_doubles_(false) {} |
| 486 | 489 |
| 487 // Output operands. | 490 // Output operands. |
| 488 LOperand* Output() const { return output_operand_; } | 491 LOperand* Output() const { return output_operand_; } |
| 489 void SetOutput(LOperand* output) { | 492 void SetOutput(LOperand* output) { |
| 490 ASSERT(output_operand_ == NULL); | 493 ASSERT(output_operand_ == NULL); |
| 491 output_operand_ = output; | 494 output_operand_ = output; |
| 492 } | 495 } |
| 493 | 496 |
| 494 // Input operands. | 497 // Input operands. |
| 495 int InputCount() const { return input_count_; } | 498 int InputCount() const { return input_count_; } |
| 496 LOperand* InputAt(int i) const { | 499 LOperand* InputAt(int i) const { |
| 497 ASSERT(i < input_count_); | 500 ASSERT(i < input_count_); |
| 498 return operands_[i]; | 501 return operands_[i]; |
| 499 } | 502 } |
| 500 void AddInput(LOperand* input) { | 503 void AddInput(LOperand* input) { |
| 501 operands_.InsertAt(input_count_, input); | 504 operands_.InsertAt(input_count_, input); |
| 502 input_count_++; | 505 input_count_++; |
| 503 } | 506 } |
| 504 | 507 |
| 505 // Temporary operands. | 508 // Temporary operands. |
| 506 int TempCount() const { return operands_.length() - input_count_; } | 509 int TempCount() const { return operands_.length() - input_count_; } |
| 507 LOperand* TempAt(int i) const { return operands_[i + input_count_]; } | 510 LOperand* TempAt(int i) const { return operands_[i + input_count_]; } |
| 508 void AddTemp(LOperand* temp) { operands_.Add(temp); } | 511 void AddTemp(LOperand* temp) { operands_.Add(temp); } |
| 509 | 512 |
| 510 void MarkAsCall() { is_call_ = true; } | 513 void MarkAsCall() { is_call_ = true; } |
| 511 bool IsCall() const { return is_call_; } | 514 bool IsCall() const { return is_call_; } |
| 512 | 515 |
| 516 void MarkAsSaveDoubles() { is_save_doubles_ = true; } |
| 517 bool IsSaveDoubles() const { return is_save_doubles_; } |
| 518 |
| 513 private: | 519 private: |
| 514 LOperand* output_operand_; | 520 LOperand* output_operand_; |
| 515 int input_count_; | 521 int input_count_; |
| 516 ZoneList<LOperand*> operands_; | 522 ZoneList<LOperand*> operands_; |
| 517 bool is_call_; | 523 bool is_call_; |
| 524 bool is_save_doubles_; |
| 518 }; | 525 }; |
| 519 | 526 |
| 520 // Representation of the non-empty interval [start,end[. | 527 // Representation of the non-empty interval [start,end[. |
| 521 class UseInterval: public ZoneObject { | 528 class UseInterval: public ZoneObject { |
| 522 public: | 529 public: |
| 523 UseInterval(LifetimePosition start, LifetimePosition end) | 530 UseInterval(LifetimePosition start, LifetimePosition end) |
| 524 : start_(start), end_(end), next_(NULL) { | 531 : start_(start), end_(end), next_(NULL) { |
| 525 ASSERT(start.Value() < end.Value()); | 532 ASSERT(start.Value() < end.Value()); |
| 526 } | 533 } |
| 527 | 534 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 LiveRange* parent_; | 754 LiveRange* parent_; |
| 748 LiveRange* next_; | 755 LiveRange* next_; |
| 749 // This is used as a cache, it doesn't affect correctness. | 756 // This is used as a cache, it doesn't affect correctness. |
| 750 mutable UseInterval* current_interval_; | 757 mutable UseInterval* current_interval_; |
| 751 UsePosition* last_processed_use_; | 758 UsePosition* last_processed_use_; |
| 752 LOperand* spill_operand_; | 759 LOperand* spill_operand_; |
| 753 int spill_start_index_; | 760 int spill_start_index_; |
| 754 }; | 761 }; |
| 755 | 762 |
| 756 | 763 |
| 764 class GrowableBitVector BASE_EMBEDDED { |
| 765 public: |
| 766 GrowableBitVector() : bits_(NULL) { } |
| 767 |
| 768 bool Contains(int value) const { |
| 769 if (!InBitsRange(value)) return false; |
| 770 return bits_->Contains(value); |
| 771 } |
| 772 |
| 773 void Add(int value) { |
| 774 EnsureCapacity(value); |
| 775 bits_->Add(value); |
| 776 } |
| 777 |
| 778 private: |
| 779 static const int kInitialLength = 1024; |
| 780 |
| 781 bool InBitsRange(int value) const { |
| 782 return bits_ != NULL && bits_->length() > value; |
| 783 } |
| 784 |
| 785 void EnsureCapacity(int value) { |
| 786 if (InBitsRange(value)) return; |
| 787 int new_length = bits_ == NULL ? kInitialLength : bits_->length(); |
| 788 while (new_length <= value) new_length *= 2; |
| 789 BitVector* new_bits = new BitVector(new_length); |
| 790 if (bits_ != NULL) new_bits->CopyFrom(*bits_); |
| 791 bits_ = new_bits; |
| 792 } |
| 793 |
| 794 BitVector* bits_; |
| 795 }; |
| 796 |
| 797 |
| 757 class LAllocator BASE_EMBEDDED { | 798 class LAllocator BASE_EMBEDDED { |
| 758 public: | 799 public: |
| 759 explicit LAllocator(int first_virtual_register, HGraph* graph) | 800 explicit LAllocator(int first_virtual_register, HGraph* graph) |
| 760 : chunk_(NULL), | 801 : chunk_(NULL), |
| 761 summaries_(0), | 802 summaries_(0), |
| 762 next_summary_(NULL), | 803 next_summary_(NULL), |
| 763 summary_stack_(2), | 804 summary_stack_(2), |
| 764 live_in_sets_(0), | 805 live_in_sets_(0), |
| 765 live_ranges_(16), | 806 live_ranges_(16), |
| 766 fixed_live_ranges_(8), | 807 fixed_live_ranges_(8), |
| 767 fixed_double_live_ranges_(8), | 808 fixed_double_live_ranges_(8), |
| 768 unhandled_live_ranges_(8), | 809 unhandled_live_ranges_(8), |
| 769 active_live_ranges_(8), | 810 active_live_ranges_(8), |
| 770 inactive_live_ranges_(8), | 811 inactive_live_ranges_(8), |
| 771 reusable_slots_(8), | 812 reusable_slots_(8), |
| 772 next_virtual_register_(first_virtual_register), | 813 next_virtual_register_(first_virtual_register), |
| 814 first_artificial_register_(first_virtual_register), |
| 773 mode_(NONE), | 815 mode_(NONE), |
| 774 num_registers_(-1), | 816 num_registers_(-1), |
| 775 graph_(graph), | 817 graph_(graph), |
| 776 has_osr_entry_(false) {} | 818 has_osr_entry_(false) {} |
| 777 | 819 |
| 778 static void Setup(); | 820 static void Setup(); |
| 779 static void TraceAlloc(const char* msg, ...); | 821 static void TraceAlloc(const char* msg, ...); |
| 780 | 822 |
| 781 // Lithium translation support. | 823 // Lithium translation support. |
| 782 // Record a use of an input operand in the current instruction. | 824 // Record a use of an input operand in the current instruction. |
| 783 void RecordUse(HValue* value, LUnallocated* operand); | 825 void RecordUse(HValue* value, LUnallocated* operand); |
| 784 // Record the definition of the output operand. | 826 // Record the definition of the output operand. |
| 785 void RecordDefinition(HInstruction* instr, LUnallocated* operand); | 827 void RecordDefinition(HInstruction* instr, LUnallocated* operand); |
| 786 // Record a temporary operand. | 828 // Record a temporary operand. |
| 787 void RecordTemporary(LUnallocated* operand); | 829 void RecordTemporary(LUnallocated* operand); |
| 788 | 830 |
| 789 // Marks the current instruction as a call. | 831 // Marks the current instruction as a call. |
| 790 void MarkAsCall(); | 832 void MarkAsCall(); |
| 791 | 833 |
| 834 // Marks the current instruction as requiring saving double registers. |
| 835 void MarkAsSaveDoubles(); |
| 836 |
| 792 // Checks whether the value of a given virtual register is tagged. | 837 // Checks whether the value of a given virtual register is tagged. |
| 793 bool HasTaggedValue(int virtual_register) const; | 838 bool HasTaggedValue(int virtual_register) const; |
| 794 | 839 |
| 795 // Returns the register kind required by the given virtual register. | 840 // Returns the register kind required by the given virtual register. |
| 796 RegisterKind RequiredRegisterKind(int virtual_register) const; | 841 RegisterKind RequiredRegisterKind(int virtual_register) const; |
| 797 | 842 |
| 798 // Begin a new instruction. | 843 // Begin a new instruction. |
| 799 void BeginInstruction(); | 844 void BeginInstruction(); |
| 800 | 845 |
| 801 // Summarize the current instruction. | 846 // Summarize the current instruction. |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 // Lists of live ranges | 1010 // Lists of live ranges |
| 966 ZoneList<LiveRange*> fixed_live_ranges_; | 1011 ZoneList<LiveRange*> fixed_live_ranges_; |
| 967 ZoneList<LiveRange*> fixed_double_live_ranges_; | 1012 ZoneList<LiveRange*> fixed_double_live_ranges_; |
| 968 ZoneList<LiveRange*> unhandled_live_ranges_; | 1013 ZoneList<LiveRange*> unhandled_live_ranges_; |
| 969 ZoneList<LiveRange*> active_live_ranges_; | 1014 ZoneList<LiveRange*> active_live_ranges_; |
| 970 ZoneList<LiveRange*> inactive_live_ranges_; | 1015 ZoneList<LiveRange*> inactive_live_ranges_; |
| 971 ZoneList<LiveRange*> reusable_slots_; | 1016 ZoneList<LiveRange*> reusable_slots_; |
| 972 | 1017 |
| 973 // Next virtual register number to be assigned to temporaries. | 1018 // Next virtual register number to be assigned to temporaries. |
| 974 int next_virtual_register_; | 1019 int next_virtual_register_; |
| 1020 int first_artificial_register_; |
| 1021 GrowableBitVector double_artificial_registers_; |
| 975 | 1022 |
| 976 RegisterKind mode_; | 1023 RegisterKind mode_; |
| 977 int num_registers_; | 1024 int num_registers_; |
| 978 | 1025 |
| 979 HGraph* graph_; | 1026 HGraph* graph_; |
| 980 | 1027 |
| 981 bool has_osr_entry_; | 1028 bool has_osr_entry_; |
| 982 | 1029 |
| 983 DISALLOW_COPY_AND_ASSIGN(LAllocator); | 1030 DISALLOW_COPY_AND_ASSIGN(LAllocator); |
| 984 }; | 1031 }; |
| 985 | 1032 |
| 986 | 1033 |
| 987 } } // namespace v8::internal | 1034 } } // namespace v8::internal |
| 988 | 1035 |
| 989 #endif // V8_LITHIUM_ALLOCATOR_H_ | 1036 #endif // V8_LITHIUM_ALLOCATOR_H_ |
| OLD | NEW |