| 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 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 #include "lithium-allocator.h" | 28 #include "lithium-allocator-inl.h" |
| 29 | 29 |
| 30 #include "hydrogen.h" | 30 #include "hydrogen.h" |
| 31 #include "string-stream.h" | 31 #include "string-stream.h" |
| 32 | 32 |
| 33 #if V8_TARGET_ARCH_IA32 | 33 #if V8_TARGET_ARCH_IA32 |
| 34 #include "ia32/lithium-ia32.h" | 34 #include "ia32/lithium-ia32.h" |
| 35 #elif V8_TARGET_ARCH_X64 | 35 #elif V8_TARGET_ARCH_X64 |
| 36 #include "x64/lithium-x64.h" | 36 #include "x64/lithium-x64.h" |
| 37 #elif V8_TARGET_ARCH_ARM | 37 #elif V8_TARGET_ARCH_ARM |
| 38 #include "arm/lithium-arm.h" | 38 #include "arm/lithium-arm.h" |
| 39 #else | 39 #else |
| 40 #error "Unknown architecture." | 40 #error "Unknown architecture." |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 namespace v8 { | 43 namespace v8 { |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 | 46 |
| 47 #define DEFINE_OPERAND_CACHE(name, type) \ | 47 #define DEFINE_OPERAND_CACHE(name, type) \ |
| 48 name name::cache[name::kNumCachedOperands]; \ | 48 name name::cache[name::kNumCachedOperands]; \ |
| 49 void name::SetupCache() { \ | 49 void name::SetupCache() { \ |
| 50 for (int i = 0; i < kNumCachedOperands; i++) { \ | 50 for (int i = 0; i < kNumCachedOperands; i++) { \ |
| 51 cache[i].ConvertTo(type, i); \ | 51 cache[i].ConvertTo(type, i); \ |
| 52 } \ | 52 } \ |
| 53 } | 53 } \ |
| 54 static bool name##_initialize() { \ |
| 55 name::SetupCache(); \ |
| 56 return true; \ |
| 57 } \ |
| 58 static bool name##_cache_initialized = name##_initialize(); |
| 54 | 59 |
| 55 DEFINE_OPERAND_CACHE(LConstantOperand, CONSTANT_OPERAND) | 60 DEFINE_OPERAND_CACHE(LConstantOperand, CONSTANT_OPERAND) |
| 56 DEFINE_OPERAND_CACHE(LStackSlot, STACK_SLOT) | 61 DEFINE_OPERAND_CACHE(LStackSlot, STACK_SLOT) |
| 57 DEFINE_OPERAND_CACHE(LDoubleStackSlot, DOUBLE_STACK_SLOT) | 62 DEFINE_OPERAND_CACHE(LDoubleStackSlot, DOUBLE_STACK_SLOT) |
| 58 DEFINE_OPERAND_CACHE(LRegister, REGISTER) | 63 DEFINE_OPERAND_CACHE(LRegister, REGISTER) |
| 59 DEFINE_OPERAND_CACHE(LDoubleRegister, DOUBLE_REGISTER) | 64 DEFINE_OPERAND_CACHE(LDoubleRegister, DOUBLE_REGISTER) |
| 60 | 65 |
| 61 #undef DEFINE_OPERAND_CACHE | 66 #undef DEFINE_OPERAND_CACHE |
| 62 | 67 |
| 63 | 68 |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 } else { | 530 } else { |
| 526 b = b->next(); | 531 b = b->next(); |
| 527 } | 532 } |
| 528 } | 533 } |
| 529 return LifetimePosition::Invalid(); | 534 return LifetimePosition::Invalid(); |
| 530 } | 535 } |
| 531 | 536 |
| 532 | 537 |
| 533 void LAllocator::InitializeLivenessAnalysis() { | 538 void LAllocator::InitializeLivenessAnalysis() { |
| 534 // Initialize the live_in sets for each block to NULL. | 539 // Initialize the live_in sets for each block to NULL. |
| 535 int block_count = graph()->blocks()->length(); | 540 int block_count = graph_->blocks()->length(); |
| 536 live_in_sets_.Initialize(block_count); | 541 live_in_sets_.Initialize(block_count); |
| 537 live_in_sets_.AddBlock(NULL, block_count); | 542 live_in_sets_.AddBlock(NULL, block_count); |
| 538 } | 543 } |
| 539 | 544 |
| 540 | 545 |
| 541 BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) { | 546 BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) { |
| 542 // Compute live out for the given block, except not including backward | 547 // Compute live out for the given block, except not including backward |
| 543 // successor edges. | 548 // successor edges. |
| 544 BitVector* live_out = new BitVector(next_virtual_register_); | 549 BitVector* live_out = new BitVector(next_virtual_register_); |
| 545 | 550 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 int reg_index = operand->fixed_index(); | 611 int reg_index = operand->fixed_index(); |
| 607 operand->ConvertTo(LOperand::REGISTER, reg_index); | 612 operand->ConvertTo(LOperand::REGISTER, reg_index); |
| 608 } else if (operand->policy() == LUnallocated::FIXED_DOUBLE_REGISTER) { | 613 } else if (operand->policy() == LUnallocated::FIXED_DOUBLE_REGISTER) { |
| 609 int reg_index = operand->fixed_index(); | 614 int reg_index = operand->fixed_index(); |
| 610 operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); | 615 operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); |
| 611 } else { | 616 } else { |
| 612 UNREACHABLE(); | 617 UNREACHABLE(); |
| 613 } | 618 } |
| 614 if (is_tagged) { | 619 if (is_tagged) { |
| 615 TraceAlloc("Fixed reg is tagged at %d\n", pos); | 620 TraceAlloc("Fixed reg is tagged at %d\n", pos); |
| 616 LInstruction* instr = chunk_->instructions()->at(pos); | 621 LInstruction* instr = InstructionAt(pos); |
| 617 if (instr->HasPointerMap()) { | 622 if (instr->HasPointerMap()) { |
| 618 instr->pointer_map()->RecordPointer(operand); | 623 instr->pointer_map()->RecordPointer(operand); |
| 619 } | 624 } |
| 620 } | 625 } |
| 621 return operand; | 626 return operand; |
| 622 } | 627 } |
| 623 | 628 |
| 624 | 629 |
| 625 LiveRange* LAllocator::FixedLiveRangeFor(int index) { | 630 LiveRange* LAllocator::FixedLiveRangeFor(int index) { |
| 626 if (index >= fixed_live_ranges_.length()) { | 631 if (index >= fixed_live_ranges_.length()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 } | 666 } |
| 662 LiveRange* result = live_ranges_[index]; | 667 LiveRange* result = live_ranges_[index]; |
| 663 if (result == NULL) { | 668 if (result == NULL) { |
| 664 result = new LiveRange(index); | 669 result = new LiveRange(index); |
| 665 live_ranges_[index] = result; | 670 live_ranges_[index] = result; |
| 666 } | 671 } |
| 667 return result; | 672 return result; |
| 668 } | 673 } |
| 669 | 674 |
| 670 | 675 |
| 671 LGap* LAllocator::GetLastGap(HBasicBlock* block) const { | 676 LGap* LAllocator::GetLastGap(HBasicBlock* block) { |
| 672 int last_instruction = block->last_instruction_index(); | 677 int last_instruction = block->last_instruction_index(); |
| 673 int index = chunk_->NearestGapPos(last_instruction); | 678 int index = chunk_->NearestGapPos(last_instruction); |
| 674 return chunk_->GetGapAt(index); | 679 return GapAt(index); |
| 675 } | 680 } |
| 676 | 681 |
| 677 | 682 |
| 678 HPhi* LAllocator::LookupPhi(LOperand* operand) const { | 683 HPhi* LAllocator::LookupPhi(LOperand* operand) const { |
| 679 if (!operand->IsUnallocated()) return NULL; | 684 if (!operand->IsUnallocated()) return NULL; |
| 680 int index = operand->VirtualRegister(); | 685 int index = operand->VirtualRegister(); |
| 681 HValue* instr = graph()->LookupValue(index); | 686 HValue* instr = graph_->LookupValue(index); |
| 682 if (instr != NULL && instr->IsPhi()) { | 687 if (instr != NULL && instr->IsPhi()) { |
| 683 return HPhi::cast(instr); | 688 return HPhi::cast(instr); |
| 684 } | 689 } |
| 685 return NULL; | 690 return NULL; |
| 686 } | 691 } |
| 687 | 692 |
| 688 | 693 |
| 689 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { | 694 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { |
| 690 if (operand->IsUnallocated()) { | 695 if (operand->IsUnallocated()) { |
| 691 return LiveRangeFor(LUnallocated::cast(operand)->virtual_register()); | 696 return LiveRangeFor(LUnallocated::cast(operand)->virtual_register()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 LUnallocated* unalloc_operand = LUnallocated::cast(operand); | 735 LUnallocated* unalloc_operand = LUnallocated::cast(operand); |
| 731 range->AddUsePosition(position, unalloc_operand)->set_hint(hint); | 736 range->AddUsePosition(position, unalloc_operand)->set_hint(hint); |
| 732 } | 737 } |
| 733 range->AddUseInterval(block_start, position); | 738 range->AddUseInterval(block_start, position); |
| 734 } | 739 } |
| 735 | 740 |
| 736 | 741 |
| 737 void LAllocator::AddConstraintsGapMove(int index, | 742 void LAllocator::AddConstraintsGapMove(int index, |
| 738 LOperand* from, | 743 LOperand* from, |
| 739 LOperand* to) { | 744 LOperand* to) { |
| 740 LGap* gap = chunk_->GetGapAt(index); | 745 LGap* gap = GapAt(index); |
| 741 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); | 746 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); |
| 742 if (from->IsUnallocated()) { | 747 if (from->IsUnallocated()) { |
| 743 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); | 748 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); |
| 744 for (int i = 0; i < move_operands->length(); ++i) { | 749 for (int i = 0; i < move_operands->length(); ++i) { |
| 745 LMoveOperands cur = move_operands->at(i); | 750 LMoveOperands cur = move_operands->at(i); |
| 746 LOperand* cur_to = cur.destination(); | 751 LOperand* cur_to = cur.destination(); |
| 747 if (cur_to->IsUnallocated()) { | 752 if (cur_to->IsUnallocated()) { |
| 748 if (cur_to->VirtualRegister() == from->VirtualRegister()) { | 753 if (cur_to->VirtualRegister() == from->VirtualRegister()) { |
| 749 move->AddMove(cur.source(), to); | 754 move->AddMove(cur.source(), to); |
| 750 return; | 755 return; |
| 751 } | 756 } |
| 752 } | 757 } |
| 753 } | 758 } |
| 754 } | 759 } |
| 755 move->AddMove(from, to); | 760 move->AddMove(from, to); |
| 756 } | 761 } |
| 757 | 762 |
| 758 | 763 |
| 759 void LAllocator::MeetRegisterConstraints(HBasicBlock* block) { | 764 void LAllocator::MeetRegisterConstraints(HBasicBlock* block) { |
| 760 int start = block->first_instruction_index(); | 765 int start = block->first_instruction_index(); |
| 761 int end = block->last_instruction_index(); | 766 int end = block->last_instruction_index(); |
| 762 for (int i = start; i <= end; ++i) { | 767 for (int i = start; i <= end; ++i) { |
| 763 if (chunk_->IsGapAt(i)) { | 768 if (IsGapAt(i)) { |
| 764 InstructionSummary* summary = NULL; | 769 LInstruction* instr = NULL; |
| 765 InstructionSummary* prev_summary = NULL; | 770 LInstruction* prev_instr = NULL; |
| 766 if (i < end) summary = GetSummary(i + 1); | 771 if (i < end) instr = InstructionAt(i + 1); |
| 767 if (i > start) prev_summary = GetSummary(i - 1); | 772 if (i > start) prev_instr = InstructionAt(i - 1); |
| 768 MeetConstraintsBetween(prev_summary, summary, i); | 773 MeetConstraintsBetween(prev_instr, instr, i); |
| 769 } | 774 } |
| 770 } | 775 } |
| 771 } | 776 } |
| 772 | 777 |
| 773 | 778 |
| 774 void LAllocator::MeetConstraintsBetween(InstructionSummary* first, | 779 void LAllocator::MeetConstraintsBetween(LInstruction* first, |
| 775 InstructionSummary* second, | 780 LInstruction* second, |
| 776 int gap_index) { | 781 int gap_index) { |
| 777 // Handle fixed temporaries. | 782 // Handle fixed temporaries. |
| 778 if (first != NULL) { | 783 if (first != NULL) { |
| 779 for (int i = 0; i < first->TempCount(); ++i) { | 784 for (TempIterator it(first); it.HasNext(); it.Advance()) { |
| 780 LUnallocated* temp = LUnallocated::cast(first->TempAt(i)); | 785 LUnallocated* temp = LUnallocated::cast(it.Next()); |
| 781 if (temp->HasFixedPolicy()) { | 786 if (temp->HasFixedPolicy()) { |
| 782 AllocateFixed(temp, gap_index - 1, false); | 787 AllocateFixed(temp, gap_index - 1, false); |
| 783 } | 788 } |
| 784 } | 789 } |
| 785 } | 790 } |
| 786 | 791 |
| 787 // Handle fixed output operand. | 792 // Handle fixed output operand. |
| 788 if (first != NULL && first->Output() != NULL) { | 793 if (first != NULL && first->Output() != NULL) { |
| 789 LUnallocated* first_output = LUnallocated::cast(first->Output()); | 794 LUnallocated* first_output = LUnallocated::cast(first->Output()); |
| 790 LiveRange* range = LiveRangeFor(first_output->VirtualRegister()); | 795 LiveRange* range = LiveRangeFor(first_output->VirtualRegister()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 803 chunk_->AddGapMove(gap_index, first_output, output_copy); | 808 chunk_->AddGapMove(gap_index, first_output, output_copy); |
| 804 } | 809 } |
| 805 | 810 |
| 806 if (!assigned) { | 811 if (!assigned) { |
| 807 range->SetSpillStartIndex(gap_index); | 812 range->SetSpillStartIndex(gap_index); |
| 808 | 813 |
| 809 // This move to spill operand is not a real use. Liveness analysis | 814 // This move to spill operand is not a real use. Liveness analysis |
| 810 // and splitting of live ranges do not account for it. | 815 // and splitting of live ranges do not account for it. |
| 811 // Thus it should be inserted to a lifetime position corresponding to | 816 // Thus it should be inserted to a lifetime position corresponding to |
| 812 // the instruction end. | 817 // the instruction end. |
| 813 LGap* gap = chunk_->GetGapAt(gap_index); | 818 LGap* gap = GapAt(gap_index); |
| 814 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE); | 819 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE); |
| 815 move->AddMove(first_output, range->GetSpillOperand()); | 820 move->AddMove(first_output, range->GetSpillOperand()); |
| 816 } | 821 } |
| 817 } | 822 } |
| 818 | 823 |
| 819 // Handle fixed input operands of second instruction. | 824 // Handle fixed input operands of second instruction. |
| 820 if (second != NULL) { | 825 if (second != NULL) { |
| 821 for (int i = 0; i < second->InputCount(); ++i) { | 826 for (UseIterator it(second); it.HasNext(); it.Advance()) { |
| 822 LUnallocated* cur_input = LUnallocated::cast(second->InputAt(i)); | 827 LUnallocated* cur_input = LUnallocated::cast(it.Next()); |
| 823 if (cur_input->HasFixedPolicy()) { | 828 if (cur_input->HasFixedPolicy()) { |
| 824 LUnallocated* input_copy = cur_input->CopyUnconstrained(); | 829 LUnallocated* input_copy = cur_input->CopyUnconstrained(); |
| 825 bool is_tagged = HasTaggedValue(cur_input->VirtualRegister()); | 830 bool is_tagged = HasTaggedValue(cur_input->VirtualRegister()); |
| 826 AllocateFixed(cur_input, gap_index + 1, is_tagged); | 831 AllocateFixed(cur_input, gap_index + 1, is_tagged); |
| 827 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 832 AddConstraintsGapMove(gap_index, input_copy, cur_input); |
| 828 } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) { | 833 } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) { |
| 829 // The live range of writable input registers always goes until the end | 834 // The live range of writable input registers always goes until the end |
| 830 // of the instruction. | 835 // of the instruction. |
| 831 ASSERT(!cur_input->IsUsedAtStart()); | 836 ASSERT(!cur_input->IsUsedAtStart()); |
| 832 | 837 |
| 833 LUnallocated* input_copy = cur_input->CopyUnconstrained(); | 838 LUnallocated* input_copy = cur_input->CopyUnconstrained(); |
| 834 cur_input->set_virtual_register(next_virtual_register_++); | 839 cur_input->set_virtual_register(next_virtual_register_++); |
| 835 | 840 |
| 836 if (RequiredRegisterKind(input_copy->virtual_register()) == | 841 if (RequiredRegisterKind(input_copy->virtual_register()) == |
| 837 DOUBLE_REGISTERS) { | 842 DOUBLE_REGISTERS) { |
| 838 double_artificial_registers_.Add( | 843 double_artificial_registers_.Add( |
| 839 cur_input->virtual_register() - first_artificial_register_); | 844 cur_input->virtual_register() - first_artificial_register_); |
| 840 } | 845 } |
| 841 | 846 |
| 842 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 847 AddConstraintsGapMove(gap_index, input_copy, cur_input); |
| 843 } | 848 } |
| 844 } | 849 } |
| 845 } | 850 } |
| 846 | 851 |
| 847 // Handle "output same as input" for second instruction. | 852 // Handle "output same as input" for second instruction. |
| 848 if (second != NULL && second->Output() != NULL) { | 853 if (second != NULL && second->Output() != NULL) { |
| 849 LUnallocated* second_output = LUnallocated::cast(second->Output()); | 854 LUnallocated* second_output = LUnallocated::cast(second->Output()); |
| 850 if (second_output->HasSameAsInputPolicy()) { | 855 if (second_output->HasSameAsInputPolicy()) { |
| 851 LUnallocated* cur_input = LUnallocated::cast(second->InputAt(0)); | 856 LUnallocated* cur_input = LUnallocated::cast(second->FirstInput()); |
| 852 int output_vreg = second_output->VirtualRegister(); | 857 int output_vreg = second_output->VirtualRegister(); |
| 853 int input_vreg = cur_input->VirtualRegister(); | 858 int input_vreg = cur_input->VirtualRegister(); |
| 854 | 859 |
| 855 LUnallocated* input_copy = cur_input->CopyUnconstrained(); | 860 LUnallocated* input_copy = cur_input->CopyUnconstrained(); |
| 856 cur_input->set_virtual_register(second_output->virtual_register()); | 861 cur_input->set_virtual_register(second_output->virtual_register()); |
| 857 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 862 AddConstraintsGapMove(gap_index, input_copy, cur_input); |
| 858 | 863 |
| 859 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { | 864 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { |
| 860 int index = gap_index + 1; | 865 int index = gap_index + 1; |
| 861 LInstruction* instr = chunk_->instructions()->at(index); | 866 LInstruction* instr = InstructionAt(index); |
| 862 if (instr->HasPointerMap()) { | 867 if (instr->HasPointerMap()) { |
| 863 instr->pointer_map()->RecordPointer(input_copy); | 868 instr->pointer_map()->RecordPointer(input_copy); |
| 864 } | 869 } |
| 865 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { | 870 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { |
| 866 // The input is assumed to immediately have a tagged representation, | 871 // The input is assumed to immediately have a tagged representation, |
| 867 // before the pointer map can be used. I.e. the pointer map at the | 872 // before the pointer map can be used. I.e. the pointer map at the |
| 868 // instruction will include the output operand (whose value at the | 873 // instruction will include the output operand (whose value at the |
| 869 // beginning of the instruction is equal to the input operand). If | 874 // beginning of the instruction is equal to the input operand). If |
| 870 // this is not desired, then the pointer map at this instruction needs | 875 // this is not desired, then the pointer map at this instruction needs |
| 871 // to be adjusted manually. | 876 // to be adjusted manually. |
| 872 } | 877 } |
| 873 } | 878 } |
| 874 } | 879 } |
| 875 } | 880 } |
| 876 | 881 |
| 877 | 882 |
| 878 void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) { | 883 void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) { |
| 879 int block_start = block->first_instruction_index(); | 884 int block_start = block->first_instruction_index(); |
| 880 int index = block->last_instruction_index(); | 885 int index = block->last_instruction_index(); |
| 881 | 886 |
| 882 LifetimePosition block_start_position = | 887 LifetimePosition block_start_position = |
| 883 LifetimePosition::FromInstructionIndex(block_start); | 888 LifetimePosition::FromInstructionIndex(block_start); |
| 884 | 889 |
| 885 while (index >= block_start) { | 890 while (index >= block_start) { |
| 886 LifetimePosition curr_position = | 891 LifetimePosition curr_position = |
| 887 LifetimePosition::FromInstructionIndex(index); | 892 LifetimePosition::FromInstructionIndex(index); |
| 888 | 893 |
| 889 if (chunk_->IsGapAt(index)) { | 894 if (IsGapAt(index)) { |
| 890 // We have a gap at this position. | 895 // We have a gap at this position. |
| 891 LGap* gap = chunk_->GetGapAt(index); | 896 LGap* gap = GapAt(index); |
| 892 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); | 897 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); |
| 893 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); | 898 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); |
| 894 for (int i = 0; i < move_operands->length(); ++i) { | 899 for (int i = 0; i < move_operands->length(); ++i) { |
| 895 LMoveOperands* cur = &move_operands->at(i); | 900 LMoveOperands* cur = &move_operands->at(i); |
| 896 if (cur->IsIgnored()) continue; | 901 if (cur->IsIgnored()) continue; |
| 897 LOperand* from = cur->source(); | 902 LOperand* from = cur->source(); |
| 898 LOperand* to = cur->destination(); | 903 LOperand* to = cur->destination(); |
| 899 HPhi* phi = LookupPhi(to); | 904 HPhi* phi = LookupPhi(to); |
| 900 LOperand* hint = to; | 905 LOperand* hint = to; |
| 901 if (phi != NULL) { | 906 if (phi != NULL) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 915 } else { | 920 } else { |
| 916 Define(curr_position, to, from); | 921 Define(curr_position, to, from); |
| 917 } | 922 } |
| 918 } | 923 } |
| 919 Use(block_start_position, curr_position, from, hint); | 924 Use(block_start_position, curr_position, from, hint); |
| 920 if (from->IsUnallocated()) { | 925 if (from->IsUnallocated()) { |
| 921 live->Add(from->VirtualRegister()); | 926 live->Add(from->VirtualRegister()); |
| 922 } | 927 } |
| 923 } | 928 } |
| 924 } else { | 929 } else { |
| 925 ASSERT(!chunk_->IsGapAt(index)); | 930 ASSERT(!IsGapAt(index)); |
| 926 InstructionSummary* summary = GetSummary(index); | 931 LInstruction* instr = InstructionAt(index); |
| 927 | 932 |
| 928 if (summary != NULL) { | 933 if (instr != NULL) { |
| 929 LOperand* output = summary->Output(); | 934 LOperand* output = instr->Output(); |
| 930 if (output != NULL) { | 935 if (output != NULL) { |
| 931 if (output->IsUnallocated()) live->Remove(output->VirtualRegister()); | 936 if (output->IsUnallocated()) live->Remove(output->VirtualRegister()); |
| 932 Define(curr_position, output, NULL); | 937 Define(curr_position, output, NULL); |
| 933 } | 938 } |
| 934 | 939 |
| 935 if (summary->IsCall()) { | 940 if (instr->IsMarkedAsCall()) { |
| 936 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) { | 941 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) { |
| 937 if (output == NULL || !output->IsRegister() || | 942 if (output == NULL || !output->IsRegister() || |
| 938 output->index() != i) { | 943 output->index() != i) { |
| 939 LiveRange* range = FixedLiveRangeFor(i); | 944 LiveRange* range = FixedLiveRangeFor(i); |
| 940 range->AddUseInterval(curr_position, | 945 range->AddUseInterval(curr_position, |
| 941 curr_position.InstructionEnd()); | 946 curr_position.InstructionEnd()); |
| 942 } | 947 } |
| 943 } | 948 } |
| 944 } | 949 } |
| 945 | 950 |
| 946 if (summary->IsCall() || summary->IsSaveDoubles()) { | 951 if (instr->IsMarkedAsCall() || instr->IsMarkedAsSaveDoubles()) { |
| 947 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) { | 952 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) { |
| 948 if (output == NULL || !output->IsDoubleRegister() || | 953 if (output == NULL || !output->IsDoubleRegister() || |
| 949 output->index() != i) { | 954 output->index() != i) { |
| 950 LiveRange* range = FixedDoubleLiveRangeFor(i); | 955 LiveRange* range = FixedDoubleLiveRangeFor(i); |
| 951 range->AddUseInterval(curr_position, | 956 range->AddUseInterval(curr_position, |
| 952 curr_position.InstructionEnd()); | 957 curr_position.InstructionEnd()); |
| 953 } | 958 } |
| 954 } | 959 } |
| 955 } | 960 } |
| 956 | 961 |
| 957 for (int i = 0; i < summary->InputCount(); ++i) { | 962 for (UseIterator it(instr); it.HasNext(); it.Advance()) { |
| 958 LOperand* input = summary->InputAt(i); | 963 LOperand* input = it.Next(); |
| 959 | 964 |
| 960 LifetimePosition use_pos; | 965 LifetimePosition use_pos; |
| 961 if (input->IsUnallocated() && | 966 if (input->IsUnallocated() && |
| 962 LUnallocated::cast(input)->IsUsedAtStart()) { | 967 LUnallocated::cast(input)->IsUsedAtStart()) { |
| 963 use_pos = curr_position; | 968 use_pos = curr_position; |
| 964 } else { | 969 } else { |
| 965 use_pos = curr_position.InstructionEnd(); | 970 use_pos = curr_position.InstructionEnd(); |
| 966 } | 971 } |
| 967 | 972 |
| 968 Use(block_start_position, use_pos, input, NULL); | 973 Use(block_start_position, use_pos, input, NULL); |
| 969 if (input->IsUnallocated()) live->Add(input->VirtualRegister()); | 974 if (input->IsUnallocated()) live->Add(input->VirtualRegister()); |
| 970 } | 975 } |
| 971 | 976 |
| 972 for (int i = 0; i < summary->TempCount(); ++i) { | 977 for (TempIterator it(instr); it.HasNext(); it.Advance()) { |
| 973 LOperand* temp = summary->TempAt(i); | 978 LOperand* temp = it.Next(); |
| 974 if (summary->IsCall()) { | 979 if (instr->IsMarkedAsCall()) { |
| 975 if (temp->IsRegister()) continue; | 980 if (temp->IsRegister()) continue; |
| 976 if (temp->IsUnallocated()) { | 981 if (temp->IsUnallocated()) { |
| 977 LUnallocated* temp_unalloc = LUnallocated::cast(temp); | 982 LUnallocated* temp_unalloc = LUnallocated::cast(temp); |
| 978 if (temp_unalloc->HasFixedPolicy()) { | 983 if (temp_unalloc->HasFixedPolicy()) { |
| 979 continue; | 984 continue; |
| 980 } | 985 } |
| 981 } | 986 } |
| 982 } | 987 } |
| 983 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); | 988 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); |
| 984 Define(curr_position, temp, NULL); | 989 Define(curr_position, temp, NULL); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 AllocateGeneralRegisters(); | 1040 AllocateGeneralRegisters(); |
| 1036 AllocateDoubleRegisters(); | 1041 AllocateDoubleRegisters(); |
| 1037 PopulatePointerMaps(); | 1042 PopulatePointerMaps(); |
| 1038 if (has_osr_entry_) ProcessOsrEntry(); | 1043 if (has_osr_entry_) ProcessOsrEntry(); |
| 1039 ConnectRanges(); | 1044 ConnectRanges(); |
| 1040 ResolveControlFlow(); | 1045 ResolveControlFlow(); |
| 1041 } | 1046 } |
| 1042 | 1047 |
| 1043 | 1048 |
| 1044 void LAllocator::MeetRegisterConstraints() { | 1049 void LAllocator::MeetRegisterConstraints() { |
| 1045 HPhase phase("Register constraints", chunk()); | 1050 HPhase phase("Register constraints", chunk_); |
| 1046 first_artificial_register_ = next_virtual_register_; | 1051 first_artificial_register_ = next_virtual_register_; |
| 1047 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1052 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
| 1048 for (int i = 0; i < blocks->length(); ++i) { | 1053 for (int i = 0; i < blocks->length(); ++i) { |
| 1049 HBasicBlock* block = blocks->at(i); | 1054 HBasicBlock* block = blocks->at(i); |
| 1050 MeetRegisterConstraints(block); | 1055 MeetRegisterConstraints(block); |
| 1051 } | 1056 } |
| 1052 } | 1057 } |
| 1053 | 1058 |
| 1054 | 1059 |
| 1055 void LAllocator::ResolvePhis() { | 1060 void LAllocator::ResolvePhis() { |
| 1056 HPhase phase("Resolve phis", chunk()); | 1061 HPhase phase("Resolve phis", chunk_); |
| 1057 | 1062 |
| 1058 // Process the blocks in reverse order. | 1063 // Process the blocks in reverse order. |
| 1059 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1064 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
| 1060 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { | 1065 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { |
| 1061 HBasicBlock* block = blocks->at(block_id); | 1066 HBasicBlock* block = blocks->at(block_id); |
| 1062 ResolvePhis(block); | 1067 ResolvePhis(block); |
| 1063 } | 1068 } |
| 1064 } | 1069 } |
| 1065 | 1070 |
| 1066 | 1071 |
| 1067 void LAllocator::ResolveControlFlow(LiveRange* range, | 1072 void LAllocator::ResolveControlFlow(LiveRange* range, |
| 1068 HBasicBlock* block, | 1073 HBasicBlock* block, |
| 1069 HBasicBlock* pred) { | 1074 HBasicBlock* pred) { |
| 1070 LifetimePosition pred_end = | 1075 LifetimePosition pred_end = |
| 1071 LifetimePosition::FromInstructionIndex(pred->last_instruction_index()). | 1076 LifetimePosition::FromInstructionIndex(pred->last_instruction_index()); |
| 1072 PrevInstruction(); | |
| 1073 | |
| 1074 LifetimePosition cur_start = | 1077 LifetimePosition cur_start = |
| 1075 LifetimePosition::FromInstructionIndex(block->first_instruction_index()); | 1078 LifetimePosition::FromInstructionIndex(block->first_instruction_index()); |
| 1076 LiveRange* pred_cover = NULL; | 1079 LiveRange* pred_cover = NULL; |
| 1077 LiveRange* cur_cover = NULL; | 1080 LiveRange* cur_cover = NULL; |
| 1078 LiveRange* cur_range = range; | 1081 LiveRange* cur_range = range; |
| 1079 while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) { | 1082 while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) { |
| 1080 if (cur_range->CanCover(cur_start)) { | 1083 if (cur_range->CanCover(cur_start)) { |
| 1081 ASSERT(cur_cover == NULL); | 1084 ASSERT(cur_cover == NULL); |
| 1082 cur_cover = cur_range; | 1085 cur_cover = cur_range; |
| 1083 } | 1086 } |
| 1084 if (cur_range->CanCover(pred_end)) { | 1087 if (cur_range->CanCover(pred_end)) { |
| 1085 ASSERT(pred_cover == NULL); | 1088 ASSERT(pred_cover == NULL); |
| 1086 pred_cover = cur_range; | 1089 pred_cover = cur_range; |
| 1087 } | 1090 } |
| 1088 cur_range = cur_range->next(); | 1091 cur_range = cur_range->next(); |
| 1089 } | 1092 } |
| 1090 | 1093 |
| 1091 if (cur_cover->IsSpilled()) return; | 1094 if (cur_cover->IsSpilled()) return; |
| 1092 ASSERT(pred_cover != NULL && cur_cover != NULL); | 1095 ASSERT(pred_cover != NULL && cur_cover != NULL); |
| 1093 if (pred_cover != cur_cover) { | 1096 if (pred_cover != cur_cover) { |
| 1094 LOperand* pred_op = pred_cover->CreateAssignedOperand(); | 1097 LOperand* pred_op = pred_cover->CreateAssignedOperand(); |
| 1095 LOperand* cur_op = cur_cover->CreateAssignedOperand(); | 1098 LOperand* cur_op = cur_cover->CreateAssignedOperand(); |
| 1096 if (!pred_op->Equals(cur_op)) { | 1099 if (!pred_op->Equals(cur_op)) { |
| 1097 LGap* gap = NULL; | 1100 LGap* gap = NULL; |
| 1098 if (block->predecessors()->length() == 1) { | 1101 if (block->predecessors()->length() == 1) { |
| 1099 gap = chunk_->GetGapAt(block->first_instruction_index()); | 1102 gap = GapAt(block->first_instruction_index()); |
| 1100 } else { | 1103 } else { |
| 1101 ASSERT(pred->end()->SecondSuccessor() == NULL); | 1104 ASSERT(pred->end()->SecondSuccessor() == NULL); |
| 1102 gap = GetLastGap(pred); | 1105 gap = GetLastGap(pred); |
| 1103 } | 1106 } |
| 1104 gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op); | 1107 gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op); |
| 1105 } | 1108 } |
| 1106 } | 1109 } |
| 1107 } | 1110 } |
| 1108 | 1111 |
| 1109 | 1112 |
| 1110 LParallelMove* LAllocator::GetConnectingParallelMove(LifetimePosition pos) { | 1113 LParallelMove* LAllocator::GetConnectingParallelMove(LifetimePosition pos) { |
| 1111 int index = pos.InstructionIndex(); | 1114 int index = pos.InstructionIndex(); |
| 1112 if (chunk_->IsGapAt(index)) { | 1115 if (IsGapAt(index)) { |
| 1113 LGap* gap = chunk_->GetGapAt(index); | 1116 LGap* gap = GapAt(index); |
| 1114 return gap->GetOrCreateParallelMove( | 1117 return gap->GetOrCreateParallelMove( |
| 1115 pos.IsInstructionStart() ? LGap::START : LGap::END); | 1118 pos.IsInstructionStart() ? LGap::START : LGap::END); |
| 1116 } | 1119 } |
| 1117 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1); | 1120 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1); |
| 1118 return chunk_->GetGapAt(gap_pos)->GetOrCreateParallelMove( | 1121 return GapAt(gap_pos)->GetOrCreateParallelMove( |
| 1119 (gap_pos < index) ? LGap::AFTER : LGap::BEFORE); | 1122 (gap_pos < index) ? LGap::AFTER : LGap::BEFORE); |
| 1120 } | 1123 } |
| 1121 | 1124 |
| 1122 | 1125 |
| 1123 HBasicBlock* LAllocator::GetBlock(LifetimePosition pos) { | 1126 HBasicBlock* LAllocator::GetBlock(LifetimePosition pos) { |
| 1124 LGap* gap = chunk_->GetGapAt(chunk_->NearestGapPos(pos.InstructionIndex())); | 1127 LGap* gap = GapAt(chunk_->NearestGapPos(pos.InstructionIndex())); |
| 1125 return gap->block(); | 1128 return gap->block(); |
| 1126 } | 1129 } |
| 1127 | 1130 |
| 1128 | 1131 |
| 1129 void LAllocator::ConnectRanges() { | 1132 void LAllocator::ConnectRanges() { |
| 1130 HPhase phase("Connect ranges", this); | 1133 HPhase phase("Connect ranges", this); |
| 1131 for (int i = 0; i < live_ranges()->length(); ++i) { | 1134 for (int i = 0; i < live_ranges()->length(); ++i) { |
| 1132 LiveRange* first_range = live_ranges()->at(i); | 1135 LiveRange* first_range = live_ranges()->at(i); |
| 1133 if (first_range == NULL || first_range->parent() != NULL) continue; | 1136 if (first_range == NULL || first_range->parent() != NULL) continue; |
| 1134 | 1137 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1161 | 1164 |
| 1162 | 1165 |
| 1163 bool LAllocator::CanEagerlyResolveControlFlow(HBasicBlock* block) const { | 1166 bool LAllocator::CanEagerlyResolveControlFlow(HBasicBlock* block) const { |
| 1164 if (block->predecessors()->length() != 1) return false; | 1167 if (block->predecessors()->length() != 1) return false; |
| 1165 return block->predecessors()->first()->block_id() == block->block_id() - 1; | 1168 return block->predecessors()->first()->block_id() == block->block_id() - 1; |
| 1166 } | 1169 } |
| 1167 | 1170 |
| 1168 | 1171 |
| 1169 void LAllocator::ResolveControlFlow() { | 1172 void LAllocator::ResolveControlFlow() { |
| 1170 HPhase phase("Resolve control flow", this); | 1173 HPhase phase("Resolve control flow", this); |
| 1171 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1174 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
| 1172 for (int block_id = 1; block_id < blocks->length(); ++block_id) { | 1175 for (int block_id = 1; block_id < blocks->length(); ++block_id) { |
| 1173 HBasicBlock* block = blocks->at(block_id); | 1176 HBasicBlock* block = blocks->at(block_id); |
| 1174 if (CanEagerlyResolveControlFlow(block)) continue; | 1177 if (CanEagerlyResolveControlFlow(block)) continue; |
| 1175 BitVector* live = live_in_sets_[block->block_id()]; | 1178 BitVector* live = live_in_sets_[block->block_id()]; |
| 1176 BitVector::Iterator iterator(live); | 1179 BitVector::Iterator iterator(live); |
| 1177 while (!iterator.Done()) { | 1180 while (!iterator.Done()) { |
| 1178 int operand_index = iterator.Current(); | 1181 int operand_index = iterator.Current(); |
| 1179 for (int i = 0; i < block->predecessors()->length(); ++i) { | 1182 for (int i = 0; i < block->predecessors()->length(); ++i) { |
| 1180 HBasicBlock* cur = block->predecessors()->at(i); | 1183 HBasicBlock* cur = block->predecessors()->at(i); |
| 1181 LiveRange* cur_range = LiveRangeFor(operand_index); | 1184 LiveRange* cur_range = LiveRangeFor(operand_index); |
| 1182 ResolveControlFlow(cur_range, block, cur); | 1185 ResolveControlFlow(cur_range, block, cur); |
| 1183 } | 1186 } |
| 1184 iterator.Advance(); | 1187 iterator.Advance(); |
| 1185 } | 1188 } |
| 1186 } | 1189 } |
| 1187 } | 1190 } |
| 1188 | 1191 |
| 1189 | 1192 |
| 1190 void LAllocator::BuildLiveRanges() { | 1193 void LAllocator::BuildLiveRanges() { |
| 1191 HPhase phase("Build live ranges", this); | 1194 HPhase phase("Build live ranges", this); |
| 1192 InitializeLivenessAnalysis(); | 1195 InitializeLivenessAnalysis(); |
| 1193 // Process the blocks in reverse order. | 1196 // Process the blocks in reverse order. |
| 1194 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1197 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
| 1195 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { | 1198 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { |
| 1196 HBasicBlock* block = blocks->at(block_id); | 1199 HBasicBlock* block = blocks->at(block_id); |
| 1197 BitVector* live = ComputeLiveOut(block); | 1200 BitVector* live = ComputeLiveOut(block); |
| 1198 // Initially consider all live_out values live for the entire block. We | 1201 // Initially consider all live_out values live for the entire block. We |
| 1199 // will shorten these intervals if necessary. | 1202 // will shorten these intervals if necessary. |
| 1200 AddInitialIntervals(block, live); | 1203 AddInitialIntervals(block, live); |
| 1201 | 1204 |
| 1202 // Process the instructions in reverse order, generating and killing | 1205 // Process the instructions in reverse order, generating and killing |
| 1203 // live values. | 1206 // live values. |
| 1204 ProcessInstructions(block, live); | 1207 ProcessInstructions(block, live); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1238 if (block->IsLoopHeader()) { | 1241 if (block->IsLoopHeader()) { |
| 1239 // TODO(kmillikin): Need to be able to get the last block of the loop | 1242 // TODO(kmillikin): Need to be able to get the last block of the loop |
| 1240 // in the loop information. Add a live range stretching from the first | 1243 // in the loop information. Add a live range stretching from the first |
| 1241 // loop instruction to the last for each value live on entry to the | 1244 // loop instruction to the last for each value live on entry to the |
| 1242 // header. | 1245 // header. |
| 1243 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); | 1246 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); |
| 1244 BitVector::Iterator iterator(live); | 1247 BitVector::Iterator iterator(live); |
| 1245 LifetimePosition start = LifetimePosition::FromInstructionIndex( | 1248 LifetimePosition start = LifetimePosition::FromInstructionIndex( |
| 1246 block->first_instruction_index()); | 1249 block->first_instruction_index()); |
| 1247 LifetimePosition end = LifetimePosition::FromInstructionIndex( | 1250 LifetimePosition end = LifetimePosition::FromInstructionIndex( |
| 1248 back_edge->last_instruction_index()); | 1251 back_edge->last_instruction_index()).NextInstruction(); |
| 1249 while (!iterator.Done()) { | 1252 while (!iterator.Done()) { |
| 1250 int operand_index = iterator.Current(); | 1253 int operand_index = iterator.Current(); |
| 1251 LiveRange* range = LiveRangeFor(operand_index); | 1254 LiveRange* range = LiveRangeFor(operand_index); |
| 1252 range->EnsureInterval(start, end); | 1255 range->EnsureInterval(start, end); |
| 1253 iterator.Advance(); | 1256 iterator.Advance(); |
| 1254 } | 1257 } |
| 1255 | 1258 |
| 1256 for (int i = block->block_id() + 1; i <= back_edge->block_id(); ++i) { | 1259 for (int i = block->block_id() + 1; i <= back_edge->block_id(); ++i) { |
| 1257 live_in_sets_[i]->Union(*live); | 1260 live_in_sets_[i]->Union(*live); |
| 1258 } | 1261 } |
| 1259 } | 1262 } |
| 1260 | 1263 |
| 1261 #ifdef DEBUG | 1264 #ifdef DEBUG |
| 1262 if (block_id == 0) { | 1265 if (block_id == 0) { |
| 1263 BitVector::Iterator iterator(live); | 1266 BitVector::Iterator iterator(live); |
| 1264 bool found = false; | 1267 bool found = false; |
| 1265 while (!iterator.Done()) { | 1268 while (!iterator.Done()) { |
| 1266 found = true; | 1269 found = true; |
| 1267 int operand_index = iterator.Current(); | 1270 int operand_index = iterator.Current(); |
| 1268 PrintF("Function: %s\n", | 1271 PrintF("Function: %s\n", |
| 1269 *graph()->info()->function()->debug_name()->ToCString()); | 1272 *graph_->info()->function()->debug_name()->ToCString()); |
| 1270 PrintF("Value %d used before first definition!\n", operand_index); | 1273 PrintF("Value %d used before first definition!\n", operand_index); |
| 1271 LiveRange* range = LiveRangeFor(operand_index); | 1274 LiveRange* range = LiveRangeFor(operand_index); |
| 1272 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); | 1275 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); |
| 1273 iterator.Advance(); | 1276 iterator.Advance(); |
| 1274 } | 1277 } |
| 1275 ASSERT(!found); | 1278 ASSERT(!found); |
| 1276 } | 1279 } |
| 1277 #endif | 1280 #endif |
| 1278 } | 1281 } |
| 1279 } | 1282 } |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 LiveRange* current = unhandled_live_ranges_.RemoveLast(); | 1467 LiveRange* current = unhandled_live_ranges_.RemoveLast(); |
| 1465 ASSERT(UnhandledIsSorted()); | 1468 ASSERT(UnhandledIsSorted()); |
| 1466 LifetimePosition position = current->Start(); | 1469 LifetimePosition position = current->Start(); |
| 1467 TraceAlloc("Processing interval %d start=%d\n", | 1470 TraceAlloc("Processing interval %d start=%d\n", |
| 1468 current->id(), | 1471 current->id(), |
| 1469 position.Value()); | 1472 position.Value()); |
| 1470 | 1473 |
| 1471 if (current->HasAllocatedSpillOperand()) { | 1474 if (current->HasAllocatedSpillOperand()) { |
| 1472 TraceAlloc("Live range %d already has a spill operand\n", current->id()); | 1475 TraceAlloc("Live range %d already has a spill operand\n", current->id()); |
| 1473 LifetimePosition next_pos = position; | 1476 LifetimePosition next_pos = position; |
| 1474 if (chunk_->IsGapAt(next_pos.InstructionIndex())) { | 1477 if (IsGapAt(next_pos.InstructionIndex())) { |
| 1475 next_pos = next_pos.NextInstruction(); | 1478 next_pos = next_pos.NextInstruction(); |
| 1476 } | 1479 } |
| 1477 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); | 1480 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); |
| 1478 // If the range already has a spill operand and it doesn't need a | 1481 // If the range already has a spill operand and it doesn't need a |
| 1479 // register immediately, split it and spill the first part of the range. | 1482 // register immediately, split it and spill the first part of the range. |
| 1480 if (pos == NULL) { | 1483 if (pos == NULL) { |
| 1481 Spill(current); | 1484 Spill(current); |
| 1482 continue; | 1485 continue; |
| 1483 } else if (pos->pos().Value() > | 1486 } else if (pos->pos().Value() > |
| 1484 current->Start().NextInstruction().Value()) { | 1487 current->Start().NextInstruction().Value()) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1522 if (current->HasRegisterAssigned()) { | 1525 if (current->HasRegisterAssigned()) { |
| 1523 AddToActive(current); | 1526 AddToActive(current); |
| 1524 } | 1527 } |
| 1525 } | 1528 } |
| 1526 | 1529 |
| 1527 active_live_ranges_.Clear(); | 1530 active_live_ranges_.Clear(); |
| 1528 inactive_live_ranges_.Clear(); | 1531 inactive_live_ranges_.Clear(); |
| 1529 } | 1532 } |
| 1530 | 1533 |
| 1531 | 1534 |
| 1532 void LAllocator::Setup() { | |
| 1533 LConstantOperand::SetupCache(); | |
| 1534 LStackSlot::SetupCache(); | |
| 1535 LDoubleStackSlot::SetupCache(); | |
| 1536 LRegister::SetupCache(); | |
| 1537 LDoubleRegister::SetupCache(); | |
| 1538 } | |
| 1539 | |
| 1540 | |
| 1541 const char* LAllocator::RegisterName(int allocation_index) { | 1535 const char* LAllocator::RegisterName(int allocation_index) { |
| 1542 ASSERT(mode_ != NONE); | 1536 ASSERT(mode_ != NONE); |
| 1543 if (mode_ == GENERAL_REGISTERS) { | 1537 if (mode_ == GENERAL_REGISTERS) { |
| 1544 return Register::AllocationIndexToString(allocation_index); | 1538 return Register::AllocationIndexToString(allocation_index); |
| 1545 } else { | 1539 } else { |
| 1546 return DoubleRegister::AllocationIndexToString(allocation_index); | 1540 return DoubleRegister::AllocationIndexToString(allocation_index); |
| 1547 } | 1541 } |
| 1548 } | 1542 } |
| 1549 | 1543 |
| 1550 | 1544 |
| 1551 void LAllocator::TraceAlloc(const char* msg, ...) { | 1545 void LAllocator::TraceAlloc(const char* msg, ...) { |
| 1552 if (FLAG_trace_alloc) { | 1546 if (FLAG_trace_alloc) { |
| 1553 va_list arguments; | 1547 va_list arguments; |
| 1554 va_start(arguments, msg); | 1548 va_start(arguments, msg); |
| 1555 OS::VPrint(msg, arguments); | 1549 OS::VPrint(msg, arguments); |
| 1556 va_end(arguments); | 1550 va_end(arguments); |
| 1557 } | 1551 } |
| 1558 } | 1552 } |
| 1559 | 1553 |
| 1560 | 1554 |
| 1561 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) { | |
| 1562 operand->set_virtual_register(value->id()); | |
| 1563 current_summary()->AddInput(operand); | |
| 1564 } | |
| 1565 | |
| 1566 | |
| 1567 bool LAllocator::HasTaggedValue(int virtual_register) const { | 1555 bool LAllocator::HasTaggedValue(int virtual_register) const { |
| 1568 HValue* value = graph()->LookupValue(virtual_register); | 1556 HValue* value = graph_->LookupValue(virtual_register); |
| 1569 if (value == NULL) return false; | 1557 if (value == NULL) return false; |
| 1570 return value->representation().IsTagged(); | 1558 return value->representation().IsTagged(); |
| 1571 } | 1559 } |
| 1572 | 1560 |
| 1573 | 1561 |
| 1574 RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const { | 1562 RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const { |
| 1575 if (virtual_register < first_artificial_register_) { | 1563 if (virtual_register < first_artificial_register_) { |
| 1576 HValue* value = graph()->LookupValue(virtual_register); | 1564 HValue* value = graph_->LookupValue(virtual_register); |
| 1577 if (value != NULL && value->representation().IsDouble()) { | 1565 if (value != NULL && value->representation().IsDouble()) { |
| 1578 return DOUBLE_REGISTERS; | 1566 return DOUBLE_REGISTERS; |
| 1579 } | 1567 } |
| 1580 } else if (double_artificial_registers_.Contains( | 1568 } else if (double_artificial_registers_.Contains( |
| 1581 virtual_register - first_artificial_register_)) { | 1569 virtual_register - first_artificial_register_)) { |
| 1582 return DOUBLE_REGISTERS; | 1570 return DOUBLE_REGISTERS; |
| 1583 } | 1571 } |
| 1584 | 1572 |
| 1585 return GENERAL_REGISTERS; | 1573 return GENERAL_REGISTERS; |
| 1586 } | 1574 } |
| 1587 | 1575 |
| 1588 | 1576 |
| 1589 void LAllocator::MarkAsCall() { | |
| 1590 // Call instructions can use only fixed registers as | |
| 1591 // temporaries and outputs because all registers | |
| 1592 // are blocked by the calling convention. | |
| 1593 // Inputs can use either fixed register or have a short lifetime (be | |
| 1594 // used at start of the instruction). | |
| 1595 InstructionSummary* summary = current_summary(); | |
| 1596 #ifdef DEBUG | |
| 1597 ASSERT(summary->Output() == NULL || | |
| 1598 LUnallocated::cast(summary->Output())->HasFixedPolicy() || | |
| 1599 !LUnallocated::cast(summary->Output())->HasRegisterPolicy()); | |
| 1600 for (int i = 0; i < summary->InputCount(); i++) { | |
| 1601 ASSERT(LUnallocated::cast(summary->InputAt(i))->HasFixedPolicy() || | |
| 1602 LUnallocated::cast(summary->InputAt(i))->IsUsedAtStart() || | |
| 1603 !LUnallocated::cast(summary->InputAt(i))->HasRegisterPolicy()); | |
| 1604 } | |
| 1605 for (int i = 0; i < summary->TempCount(); i++) { | |
| 1606 ASSERT(LUnallocated::cast(summary->TempAt(i))->HasFixedPolicy() || | |
| 1607 !LUnallocated::cast(summary->TempAt(i))->HasRegisterPolicy()); | |
| 1608 } | |
| 1609 #endif | |
| 1610 summary->MarkAsCall(); | |
| 1611 } | |
| 1612 | |
| 1613 | |
| 1614 void LAllocator::MarkAsSaveDoubles() { | |
| 1615 current_summary()->MarkAsSaveDoubles(); | |
| 1616 } | |
| 1617 | |
| 1618 | |
| 1619 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) { | 1577 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) { |
| 1620 operand->set_virtual_register(instr->id()); | 1578 operand->set_virtual_register(instr->id()); |
| 1621 current_summary()->SetOutput(operand); | |
| 1622 } | 1579 } |
| 1623 | 1580 |
| 1624 | 1581 |
| 1625 void LAllocator::RecordTemporary(LUnallocated* operand) { | 1582 void LAllocator::RecordTemporary(LUnallocated* operand) { |
| 1626 ASSERT(next_virtual_register_ < LUnallocated::kMaxVirtualRegisters); | 1583 ASSERT(next_virtual_register_ < LUnallocated::kMaxVirtualRegisters); |
| 1627 if (!operand->HasFixedPolicy()) { | 1584 if (!operand->HasFixedPolicy()) { |
| 1628 operand->set_virtual_register(next_virtual_register_++); | 1585 operand->set_virtual_register(next_virtual_register_++); |
| 1629 } | 1586 } |
| 1630 current_summary()->AddTemp(operand); | 1587 } |
| 1588 |
| 1589 |
| 1590 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) { |
| 1591 operand->set_virtual_register(value->id()); |
| 1631 } | 1592 } |
| 1632 | 1593 |
| 1633 | 1594 |
| 1634 int LAllocator::max_initial_value_ids() { | 1595 int LAllocator::max_initial_value_ids() { |
| 1635 return LUnallocated::kMaxVirtualRegisters / 32; | 1596 return LUnallocated::kMaxVirtualRegisters / 32; |
| 1636 } | 1597 } |
| 1637 | 1598 |
| 1638 | 1599 |
| 1639 void LAllocator::BeginInstruction() { | |
| 1640 if (next_summary_ == NULL) { | |
| 1641 next_summary_ = new InstructionSummary(); | |
| 1642 } | |
| 1643 summary_stack_.Add(next_summary_); | |
| 1644 next_summary_ = NULL; | |
| 1645 } | |
| 1646 | |
| 1647 | |
| 1648 void LAllocator::SummarizeInstruction(int index) { | |
| 1649 InstructionSummary* sum = summary_stack_.RemoveLast(); | |
| 1650 if (summaries_.length() <= index) { | |
| 1651 summaries_.AddBlock(NULL, index + 1 - summaries_.length()); | |
| 1652 } | |
| 1653 ASSERT(summaries_[index] == NULL); | |
| 1654 if (sum->Output() != NULL || sum->InputCount() > 0 || sum->TempCount() > 0) { | |
| 1655 summaries_[index] = sum; | |
| 1656 } else { | |
| 1657 next_summary_ = sum; | |
| 1658 } | |
| 1659 } | |
| 1660 | |
| 1661 | |
| 1662 void LAllocator::OmitInstruction() { | |
| 1663 summary_stack_.RemoveLast(); | |
| 1664 } | |
| 1665 | |
| 1666 | |
| 1667 void LAllocator::AddToActive(LiveRange* range) { | 1600 void LAllocator::AddToActive(LiveRange* range) { |
| 1668 TraceAlloc("Add live range %d to active\n", range->id()); | 1601 TraceAlloc("Add live range %d to active\n", range->id()); |
| 1669 active_live_ranges_.Add(range); | 1602 active_live_ranges_.Add(range); |
| 1670 } | 1603 } |
| 1671 | 1604 |
| 1672 | 1605 |
| 1673 void LAllocator::AddToInactive(LiveRange* range) { | 1606 void LAllocator::AddToInactive(LiveRange* range) { |
| 1674 TraceAlloc("Add live range %d to inactive\n", range->id()); | 1607 TraceAlloc("Add live range %d to inactive\n", range->id()); |
| 1675 inactive_live_ranges_.Add(range); | 1608 inactive_live_ranges_.Add(range); |
| 1676 } | 1609 } |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2002 InactiveToHandled(range); | 1935 InactiveToHandled(range); |
| 2003 --i; | 1936 --i; |
| 2004 } | 1937 } |
| 2005 } | 1938 } |
| 2006 } | 1939 } |
| 2007 } | 1940 } |
| 2008 | 1941 |
| 2009 | 1942 |
| 2010 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { | 1943 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { |
| 2011 return pos.IsInstructionStart() && | 1944 return pos.IsInstructionStart() && |
| 2012 chunk_->instructions()->at(pos.InstructionIndex())->IsLabel(); | 1945 InstructionAt(pos.InstructionIndex())->IsLabel(); |
| 2013 } | 1946 } |
| 2014 | 1947 |
| 2015 | 1948 |
| 2016 LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) { | 1949 LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) { |
| 2017 ASSERT(!range->IsFixed()); | 1950 ASSERT(!range->IsFixed()); |
| 2018 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); | 1951 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); |
| 2019 | 1952 |
| 2020 if (pos.Value() <= range->Start().Value()) return range; | 1953 if (pos.Value() <= range->Start().Value()) return range; |
| 2021 | 1954 |
| 1955 // We can't properly connect liveranges if split occured at the end |
| 1956 // of control instruction. |
| 1957 ASSERT(pos.IsInstructionStart() || |
| 1958 !chunk_->instructions()->at(pos.InstructionIndex())->IsControl()); |
| 1959 |
| 2022 LiveRange* result = LiveRangeFor(next_virtual_register_++); | 1960 LiveRange* result = LiveRangeFor(next_virtual_register_++); |
| 2023 range->SplitAt(pos, result); | 1961 range->SplitAt(pos, result); |
| 2024 return result; | 1962 return result; |
| 2025 } | 1963 } |
| 2026 | 1964 |
| 2027 | 1965 |
| 2028 LiveRange* LAllocator::SplitBetween(LiveRange* range, | 1966 LiveRange* LAllocator::SplitBetween(LiveRange* range, |
| 2029 LifetimePosition start, | 1967 LifetimePosition start, |
| 2030 LifetimePosition end) { | 1968 LifetimePosition end) { |
| 2031 ASSERT(!range->IsFixed()); | 1969 ASSERT(!range->IsFixed()); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2132 LiveRange* current = live_ranges()->at(i); | 2070 LiveRange* current = live_ranges()->at(i); |
| 2133 if (current != NULL) current->Verify(); | 2071 if (current != NULL) current->Verify(); |
| 2134 } | 2072 } |
| 2135 } | 2073 } |
| 2136 | 2074 |
| 2137 | 2075 |
| 2138 #endif | 2076 #endif |
| 2139 | 2077 |
| 2140 | 2078 |
| 2141 } } // namespace v8::internal | 2079 } } // namespace v8::internal |
| OLD | NEW |