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" |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 } else { | 525 } else { |
526 b = b->next(); | 526 b = b->next(); |
527 } | 527 } |
528 } | 528 } |
529 return LifetimePosition::Invalid(); | 529 return LifetimePosition::Invalid(); |
530 } | 530 } |
531 | 531 |
532 | 532 |
533 void LAllocator::InitializeLivenessAnalysis() { | 533 void LAllocator::InitializeLivenessAnalysis() { |
534 // Initialize the live_in sets for each block to NULL. | 534 // Initialize the live_in sets for each block to NULL. |
535 int block_count = graph()->blocks()->length(); | 535 int block_count = graph_->blocks()->length(); |
536 live_in_sets_.Initialize(block_count); | 536 live_in_sets_.Initialize(block_count); |
537 live_in_sets_.AddBlock(NULL, block_count); | 537 live_in_sets_.AddBlock(NULL, block_count); |
538 } | 538 } |
539 | 539 |
540 | 540 |
541 BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) { | 541 BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) { |
542 // Compute live out for the given block, except not including backward | 542 // Compute live out for the given block, except not including backward |
543 // successor edges. | 543 // successor edges. |
544 BitVector* live_out = new BitVector(next_virtual_register_); | 544 BitVector* live_out = new BitVector(next_virtual_register_); |
545 | 545 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 int reg_index = operand->fixed_index(); | 606 int reg_index = operand->fixed_index(); |
607 operand->ConvertTo(LOperand::REGISTER, reg_index); | 607 operand->ConvertTo(LOperand::REGISTER, reg_index); |
608 } else if (operand->policy() == LUnallocated::FIXED_DOUBLE_REGISTER) { | 608 } else if (operand->policy() == LUnallocated::FIXED_DOUBLE_REGISTER) { |
609 int reg_index = operand->fixed_index(); | 609 int reg_index = operand->fixed_index(); |
610 operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); | 610 operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index); |
611 } else { | 611 } else { |
612 UNREACHABLE(); | 612 UNREACHABLE(); |
613 } | 613 } |
614 if (is_tagged) { | 614 if (is_tagged) { |
615 TraceAlloc("Fixed reg is tagged at %d\n", pos); | 615 TraceAlloc("Fixed reg is tagged at %d\n", pos); |
616 LInstruction* instr = chunk_->instructions()->at(pos); | 616 LInstruction* instr = InstructionAt(pos); |
617 if (instr->HasPointerMap()) { | 617 if (instr->HasPointerMap()) { |
618 instr->pointer_map()->RecordPointer(operand); | 618 instr->pointer_map()->RecordPointer(operand); |
619 } | 619 } |
620 } | 620 } |
621 return operand; | 621 return operand; |
622 } | 622 } |
623 | 623 |
624 | 624 |
625 LiveRange* LAllocator::FixedLiveRangeFor(int index) { | 625 LiveRange* LAllocator::FixedLiveRangeFor(int index) { |
626 if (index >= fixed_live_ranges_.length()) { | 626 if (index >= fixed_live_ranges_.length()) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 } | 661 } |
662 LiveRange* result = live_ranges_[index]; | 662 LiveRange* result = live_ranges_[index]; |
663 if (result == NULL) { | 663 if (result == NULL) { |
664 result = new LiveRange(index); | 664 result = new LiveRange(index); |
665 live_ranges_[index] = result; | 665 live_ranges_[index] = result; |
666 } | 666 } |
667 return result; | 667 return result; |
668 } | 668 } |
669 | 669 |
670 | 670 |
671 LGap* LAllocator::GetLastGap(HBasicBlock* block) const { | 671 LGap* LAllocator::GetLastGap(HBasicBlock* block) { |
672 int last_instruction = block->last_instruction_index(); | 672 int last_instruction = block->last_instruction_index(); |
673 int index = chunk_->NearestGapPos(last_instruction); | 673 int index = chunk_->NearestGapPos(last_instruction); |
674 return chunk_->GetGapAt(index); | 674 return GapAt(index); |
675 } | 675 } |
676 | 676 |
677 | 677 |
678 HPhi* LAllocator::LookupPhi(LOperand* operand) const { | 678 HPhi* LAllocator::LookupPhi(LOperand* operand) const { |
679 if (!operand->IsUnallocated()) return NULL; | 679 if (!operand->IsUnallocated()) return NULL; |
680 int index = operand->VirtualRegister(); | 680 int index = operand->VirtualRegister(); |
681 HValue* instr = graph()->LookupValue(index); | 681 HValue* instr = graph_->LookupValue(index); |
682 if (instr != NULL && instr->IsPhi()) { | 682 if (instr != NULL && instr->IsPhi()) { |
683 return HPhi::cast(instr); | 683 return HPhi::cast(instr); |
684 } | 684 } |
685 return NULL; | 685 return NULL; |
686 } | 686 } |
687 | 687 |
688 | 688 |
689 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { | 689 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { |
690 if (operand->IsUnallocated()) { | 690 if (operand->IsUnallocated()) { |
691 return LiveRangeFor(LUnallocated::cast(operand)->virtual_register()); | 691 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); | 730 LUnallocated* unalloc_operand = LUnallocated::cast(operand); |
731 range->AddUsePosition(position, unalloc_operand)->set_hint(hint); | 731 range->AddUsePosition(position, unalloc_operand)->set_hint(hint); |
732 } | 732 } |
733 range->AddUseInterval(block_start, position); | 733 range->AddUseInterval(block_start, position); |
734 } | 734 } |
735 | 735 |
736 | 736 |
737 void LAllocator::AddConstraintsGapMove(int index, | 737 void LAllocator::AddConstraintsGapMove(int index, |
738 LOperand* from, | 738 LOperand* from, |
739 LOperand* to) { | 739 LOperand* to) { |
740 LGap* gap = chunk_->GetGapAt(index); | 740 LGap* gap = GapAt(index); |
741 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); | 741 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); |
742 if (from->IsUnallocated()) { | 742 if (from->IsUnallocated()) { |
743 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); | 743 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); |
744 for (int i = 0; i < move_operands->length(); ++i) { | 744 for (int i = 0; i < move_operands->length(); ++i) { |
745 LMoveOperands cur = move_operands->at(i); | 745 LMoveOperands cur = move_operands->at(i); |
746 LOperand* cur_to = cur.destination(); | 746 LOperand* cur_to = cur.destination(); |
747 if (cur_to->IsUnallocated()) { | 747 if (cur_to->IsUnallocated()) { |
748 if (cur_to->VirtualRegister() == from->VirtualRegister()) { | 748 if (cur_to->VirtualRegister() == from->VirtualRegister()) { |
749 move->AddMove(cur.source(), to); | 749 move->AddMove(cur.source(), to); |
750 return; | 750 return; |
751 } | 751 } |
752 } | 752 } |
753 } | 753 } |
754 } | 754 } |
755 move->AddMove(from, to); | 755 move->AddMove(from, to); |
756 } | 756 } |
757 | 757 |
758 | 758 |
759 void LAllocator::MeetRegisterConstraints(HBasicBlock* block) { | 759 void LAllocator::MeetRegisterConstraints(HBasicBlock* block) { |
760 int start = block->first_instruction_index(); | 760 int start = block->first_instruction_index(); |
761 int end = block->last_instruction_index(); | 761 int end = block->last_instruction_index(); |
762 for (int i = start; i <= end; ++i) { | 762 for (int i = start; i <= end; ++i) { |
763 if (chunk_->IsGapAt(i)) { | 763 if (IsGapAt(i)) { |
764 InstructionSummary* summary = NULL; | 764 LInstruction* instr = NULL; |
765 InstructionSummary* prev_summary = NULL; | 765 LInstruction* prev_instr = NULL; |
766 if (i < end) summary = GetSummary(i + 1); | 766 if (i < end) instr = InstructionAt(i + 1); |
767 if (i > start) prev_summary = GetSummary(i - 1); | 767 if (i > start) prev_instr = InstructionAt(i - 1); |
768 MeetConstraintsBetween(prev_summary, summary, i); | 768 MeetConstraintsBetween(prev_instr, instr, i); |
769 } | 769 } |
770 } | 770 } |
771 } | 771 } |
772 | 772 |
773 | 773 |
774 void LAllocator::MeetConstraintsBetween(InstructionSummary* first, | 774 void LAllocator::MeetConstraintsBetween(LInstruction* first, |
775 InstructionSummary* second, | 775 LInstruction* second, |
776 int gap_index) { | 776 int gap_index) { |
777 // Handle fixed temporaries. | 777 // Handle fixed temporaries. |
778 if (first != NULL) { | 778 if (first != NULL) { |
779 for (int i = 0; i < first->TempCount(); ++i) { | 779 for (TempIterator it(first); it.HasNext(); it.Advance()) { |
780 LUnallocated* temp = LUnallocated::cast(first->TempAt(i)); | 780 LUnallocated* temp = LUnallocated::cast(it.Next()); |
781 if (temp->HasFixedPolicy()) { | 781 if (temp->HasFixedPolicy()) { |
782 AllocateFixed(temp, gap_index - 1, false); | 782 AllocateFixed(temp, gap_index - 1, false); |
783 } | 783 } |
784 } | 784 } |
785 } | 785 } |
786 | 786 |
787 // Handle fixed output operand. | 787 // Handle fixed output operand. |
788 if (first != NULL && first->Output() != NULL) { | 788 if (first != NULL && first->Output() != NULL) { |
789 LUnallocated* first_output = LUnallocated::cast(first->Output()); | 789 LUnallocated* first_output = LUnallocated::cast(first->Output()); |
790 LiveRange* range = LiveRangeFor(first_output->VirtualRegister()); | 790 LiveRange* range = LiveRangeFor(first_output->VirtualRegister()); |
(...skipping 12 matching lines...) Expand all Loading... |
803 chunk_->AddGapMove(gap_index, first_output, output_copy); | 803 chunk_->AddGapMove(gap_index, first_output, output_copy); |
804 } | 804 } |
805 | 805 |
806 if (!assigned) { | 806 if (!assigned) { |
807 range->SetSpillStartIndex(gap_index); | 807 range->SetSpillStartIndex(gap_index); |
808 | 808 |
809 // This move to spill operand is not a real use. Liveness analysis | 809 // This move to spill operand is not a real use. Liveness analysis |
810 // and splitting of live ranges do not account for it. | 810 // and splitting of live ranges do not account for it. |
811 // Thus it should be inserted to a lifetime position corresponding to | 811 // Thus it should be inserted to a lifetime position corresponding to |
812 // the instruction end. | 812 // the instruction end. |
813 LGap* gap = chunk_->GetGapAt(gap_index); | 813 LGap* gap = GapAt(gap_index); |
814 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE); | 814 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE); |
815 move->AddMove(first_output, range->GetSpillOperand()); | 815 move->AddMove(first_output, range->GetSpillOperand()); |
816 } | 816 } |
817 } | 817 } |
818 | 818 |
819 // Handle fixed input operands of second instruction. | 819 // Handle fixed input operands of second instruction. |
820 if (second != NULL) { | 820 if (second != NULL) { |
821 for (int i = 0; i < second->InputCount(); ++i) { | 821 for (UseIterator it(second); it.HasNext(); it.Advance()) { |
822 LUnallocated* cur_input = LUnallocated::cast(second->InputAt(i)); | 822 LUnallocated* cur_input = LUnallocated::cast(it.Next()); |
823 if (cur_input->HasFixedPolicy()) { | 823 if (cur_input->HasFixedPolicy()) { |
824 LUnallocated* input_copy = cur_input->CopyUnconstrained(); | 824 LUnallocated* input_copy = cur_input->CopyUnconstrained(); |
825 bool is_tagged = HasTaggedValue(cur_input->VirtualRegister()); | 825 bool is_tagged = HasTaggedValue(cur_input->VirtualRegister()); |
826 AllocateFixed(cur_input, gap_index + 1, is_tagged); | 826 AllocateFixed(cur_input, gap_index + 1, is_tagged); |
827 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 827 AddConstraintsGapMove(gap_index, input_copy, cur_input); |
828 } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) { | 828 } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) { |
829 // The live range of writable input registers always goes until the end | 829 // The live range of writable input registers always goes until the end |
830 // of the instruction. | 830 // of the instruction. |
831 ASSERT(!cur_input->IsUsedAtStart()); | 831 ASSERT(!cur_input->IsUsedAtStart()); |
832 | 832 |
833 LUnallocated* input_copy = cur_input->CopyUnconstrained(); | 833 LUnallocated* input_copy = cur_input->CopyUnconstrained(); |
834 cur_input->set_virtual_register(next_virtual_register_++); | 834 cur_input->set_virtual_register(next_virtual_register_++); |
835 | 835 |
836 if (RequiredRegisterKind(input_copy->virtual_register()) == | 836 if (RequiredRegisterKind(input_copy->virtual_register()) == |
837 DOUBLE_REGISTERS) { | 837 DOUBLE_REGISTERS) { |
838 double_artificial_registers_.Add( | 838 double_artificial_registers_.Add( |
839 cur_input->virtual_register() - first_artificial_register_); | 839 cur_input->virtual_register() - first_artificial_register_); |
840 } | 840 } |
841 | 841 |
842 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 842 AddConstraintsGapMove(gap_index, input_copy, cur_input); |
843 } | 843 } |
844 } | 844 } |
845 } | 845 } |
846 | 846 |
847 // Handle "output same as input" for second instruction. | 847 // Handle "output same as input" for second instruction. |
848 if (second != NULL && second->Output() != NULL) { | 848 if (second != NULL && second->Output() != NULL) { |
849 LUnallocated* second_output = LUnallocated::cast(second->Output()); | 849 LUnallocated* second_output = LUnallocated::cast(second->Output()); |
850 if (second_output->HasSameAsInputPolicy()) { | 850 if (second_output->HasSameAsInputPolicy()) { |
851 LUnallocated* cur_input = LUnallocated::cast(second->InputAt(0)); | 851 LUnallocated* cur_input = LUnallocated::cast(second->FirstInput()); |
852 int output_vreg = second_output->VirtualRegister(); | 852 int output_vreg = second_output->VirtualRegister(); |
853 int input_vreg = cur_input->VirtualRegister(); | 853 int input_vreg = cur_input->VirtualRegister(); |
854 | 854 |
855 LUnallocated* input_copy = cur_input->CopyUnconstrained(); | 855 LUnallocated* input_copy = cur_input->CopyUnconstrained(); |
856 cur_input->set_virtual_register(second_output->virtual_register()); | 856 cur_input->set_virtual_register(second_output->virtual_register()); |
857 AddConstraintsGapMove(gap_index, input_copy, cur_input); | 857 AddConstraintsGapMove(gap_index, input_copy, cur_input); |
858 | 858 |
859 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { | 859 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { |
860 int index = gap_index + 1; | 860 int index = gap_index + 1; |
861 LInstruction* instr = chunk_->instructions()->at(index); | 861 LInstruction* instr = InstructionAt(index); |
862 if (instr->HasPointerMap()) { | 862 if (instr->HasPointerMap()) { |
863 instr->pointer_map()->RecordPointer(input_copy); | 863 instr->pointer_map()->RecordPointer(input_copy); |
864 } | 864 } |
865 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { | 865 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { |
866 // The input is assumed to immediately have a tagged representation, | 866 // 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 | 867 // 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 | 868 // instruction will include the output operand (whose value at the |
869 // beginning of the instruction is equal to the input operand). If | 869 // beginning of the instruction is equal to the input operand). If |
870 // this is not desired, then the pointer map at this instruction needs | 870 // this is not desired, then the pointer map at this instruction needs |
871 // to be adjusted manually. | 871 // to be adjusted manually. |
872 } | 872 } |
873 } | 873 } |
874 } | 874 } |
875 } | 875 } |
876 | 876 |
877 | 877 |
878 void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) { | 878 void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) { |
879 int block_start = block->first_instruction_index(); | 879 int block_start = block->first_instruction_index(); |
880 int index = block->last_instruction_index(); | 880 int index = block->last_instruction_index(); |
881 | 881 |
882 LifetimePosition block_start_position = | 882 LifetimePosition block_start_position = |
883 LifetimePosition::FromInstructionIndex(block_start); | 883 LifetimePosition::FromInstructionIndex(block_start); |
884 | 884 |
885 while (index >= block_start) { | 885 while (index >= block_start) { |
886 LifetimePosition curr_position = | 886 LifetimePosition curr_position = |
887 LifetimePosition::FromInstructionIndex(index); | 887 LifetimePosition::FromInstructionIndex(index); |
888 | 888 |
889 if (chunk_->IsGapAt(index)) { | 889 if (IsGapAt(index)) { |
890 // We have a gap at this position. | 890 // We have a gap at this position. |
891 LGap* gap = chunk_->GetGapAt(index); | 891 LGap* gap = GapAt(index); |
892 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); | 892 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START); |
893 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); | 893 const ZoneList<LMoveOperands>* move_operands = move->move_operands(); |
894 for (int i = 0; i < move_operands->length(); ++i) { | 894 for (int i = 0; i < move_operands->length(); ++i) { |
895 LMoveOperands* cur = &move_operands->at(i); | 895 LMoveOperands* cur = &move_operands->at(i); |
896 if (cur->IsIgnored()) continue; | 896 if (cur->IsIgnored()) continue; |
897 LOperand* from = cur->source(); | 897 LOperand* from = cur->source(); |
898 LOperand* to = cur->destination(); | 898 LOperand* to = cur->destination(); |
899 HPhi* phi = LookupPhi(to); | 899 HPhi* phi = LookupPhi(to); |
900 LOperand* hint = to; | 900 LOperand* hint = to; |
901 if (phi != NULL) { | 901 if (phi != NULL) { |
(...skipping 13 matching lines...) Expand all Loading... |
915 } else { | 915 } else { |
916 Define(curr_position, to, from); | 916 Define(curr_position, to, from); |
917 } | 917 } |
918 } | 918 } |
919 Use(block_start_position, curr_position, from, hint); | 919 Use(block_start_position, curr_position, from, hint); |
920 if (from->IsUnallocated()) { | 920 if (from->IsUnallocated()) { |
921 live->Add(from->VirtualRegister()); | 921 live->Add(from->VirtualRegister()); |
922 } | 922 } |
923 } | 923 } |
924 } else { | 924 } else { |
925 ASSERT(!chunk_->IsGapAt(index)); | 925 ASSERT(!IsGapAt(index)); |
926 InstructionSummary* summary = GetSummary(index); | 926 LInstruction* instr = InstructionAt(index); |
927 | 927 |
928 if (summary != NULL) { | 928 if (instr != NULL) { |
929 LOperand* output = summary->Output(); | 929 LOperand* output = instr->Output(); |
930 if (output != NULL) { | 930 if (output != NULL) { |
931 if (output->IsUnallocated()) live->Remove(output->VirtualRegister()); | 931 if (output->IsUnallocated()) live->Remove(output->VirtualRegister()); |
932 Define(curr_position, output, NULL); | 932 Define(curr_position, output, NULL); |
933 } | 933 } |
934 | 934 |
935 if (summary->IsCall()) { | 935 if (instr->IsMarkedAsCall()) { |
936 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) { | 936 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) { |
937 if (output == NULL || !output->IsRegister() || | 937 if (output == NULL || !output->IsRegister() || |
938 output->index() != i) { | 938 output->index() != i) { |
939 LiveRange* range = FixedLiveRangeFor(i); | 939 LiveRange* range = FixedLiveRangeFor(i); |
940 range->AddUseInterval(curr_position, | 940 range->AddUseInterval(curr_position, |
941 curr_position.InstructionEnd()); | 941 curr_position.InstructionEnd()); |
942 } | 942 } |
943 } | 943 } |
944 } | 944 } |
945 | 945 |
946 if (summary->IsCall() || summary->IsSaveDoubles()) { | 946 if (instr->IsMarkedAsCall() || instr->IsMarkedAsSaveDoubles()) { |
947 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) { | 947 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) { |
948 if (output == NULL || !output->IsDoubleRegister() || | 948 if (output == NULL || !output->IsDoubleRegister() || |
949 output->index() != i) { | 949 output->index() != i) { |
950 LiveRange* range = FixedDoubleLiveRangeFor(i); | 950 LiveRange* range = FixedDoubleLiveRangeFor(i); |
951 range->AddUseInterval(curr_position, | 951 range->AddUseInterval(curr_position, |
952 curr_position.InstructionEnd()); | 952 curr_position.InstructionEnd()); |
953 } | 953 } |
954 } | 954 } |
955 } | 955 } |
956 | 956 |
957 for (int i = 0; i < summary->InputCount(); ++i) { | 957 for (UseIterator it(instr); it.HasNext(); it.Advance()) { |
958 LOperand* input = summary->InputAt(i); | 958 LOperand* input = it.Next(); |
959 | 959 |
960 LifetimePosition use_pos; | 960 LifetimePosition use_pos; |
961 if (input->IsUnallocated() && | 961 if (input->IsUnallocated() && |
962 LUnallocated::cast(input)->IsUsedAtStart()) { | 962 LUnallocated::cast(input)->IsUsedAtStart()) { |
963 use_pos = curr_position; | 963 use_pos = curr_position; |
964 } else { | 964 } else { |
965 use_pos = curr_position.InstructionEnd(); | 965 use_pos = curr_position.InstructionEnd(); |
966 } | 966 } |
967 | 967 |
968 Use(block_start_position, use_pos, input, NULL); | 968 Use(block_start_position, use_pos, input, NULL); |
969 if (input->IsUnallocated()) live->Add(input->VirtualRegister()); | 969 if (input->IsUnallocated()) live->Add(input->VirtualRegister()); |
970 } | 970 } |
971 | 971 |
972 for (int i = 0; i < summary->TempCount(); ++i) { | 972 for (TempIterator it(instr); it.HasNext(); it.Advance()) { |
973 LOperand* temp = summary->TempAt(i); | 973 LOperand* temp = it.Next(); |
974 if (summary->IsCall()) { | 974 if (instr->IsMarkedAsCall()) { |
975 if (temp->IsRegister()) continue; | 975 if (temp->IsRegister()) continue; |
976 if (temp->IsUnallocated()) { | 976 if (temp->IsUnallocated()) { |
977 LUnallocated* temp_unalloc = LUnallocated::cast(temp); | 977 LUnallocated* temp_unalloc = LUnallocated::cast(temp); |
978 if (temp_unalloc->HasFixedPolicy()) { | 978 if (temp_unalloc->HasFixedPolicy()) { |
979 continue; | 979 continue; |
980 } | 980 } |
981 } | 981 } |
982 } | 982 } |
983 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); | 983 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); |
984 Define(curr_position, temp, NULL); | 984 Define(curr_position, temp, NULL); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 AllocateGeneralRegisters(); | 1035 AllocateGeneralRegisters(); |
1036 AllocateDoubleRegisters(); | 1036 AllocateDoubleRegisters(); |
1037 PopulatePointerMaps(); | 1037 PopulatePointerMaps(); |
1038 if (has_osr_entry_) ProcessOsrEntry(); | 1038 if (has_osr_entry_) ProcessOsrEntry(); |
1039 ConnectRanges(); | 1039 ConnectRanges(); |
1040 ResolveControlFlow(); | 1040 ResolveControlFlow(); |
1041 } | 1041 } |
1042 | 1042 |
1043 | 1043 |
1044 void LAllocator::MeetRegisterConstraints() { | 1044 void LAllocator::MeetRegisterConstraints() { |
1045 HPhase phase("Register constraints", chunk()); | 1045 HPhase phase("Register constraints", chunk_); |
1046 first_artificial_register_ = next_virtual_register_; | 1046 first_artificial_register_ = next_virtual_register_; |
1047 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1047 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
1048 for (int i = 0; i < blocks->length(); ++i) { | 1048 for (int i = 0; i < blocks->length(); ++i) { |
1049 HBasicBlock* block = blocks->at(i); | 1049 HBasicBlock* block = blocks->at(i); |
1050 MeetRegisterConstraints(block); | 1050 MeetRegisterConstraints(block); |
1051 } | 1051 } |
1052 } | 1052 } |
1053 | 1053 |
1054 | 1054 |
1055 void LAllocator::ResolvePhis() { | 1055 void LAllocator::ResolvePhis() { |
1056 HPhase phase("Resolve phis", chunk()); | 1056 HPhase phase("Resolve phis", chunk_); |
1057 | 1057 |
1058 // Process the blocks in reverse order. | 1058 // Process the blocks in reverse order. |
1059 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1059 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
1060 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { | 1060 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { |
1061 HBasicBlock* block = blocks->at(block_id); | 1061 HBasicBlock* block = blocks->at(block_id); |
1062 ResolvePhis(block); | 1062 ResolvePhis(block); |
1063 } | 1063 } |
1064 } | 1064 } |
1065 | 1065 |
1066 | 1066 |
1067 void LAllocator::ResolveControlFlow(LiveRange* range, | 1067 void LAllocator::ResolveControlFlow(LiveRange* range, |
1068 HBasicBlock* block, | 1068 HBasicBlock* block, |
1069 HBasicBlock* pred) { | 1069 HBasicBlock* pred) { |
(...skipping 19 matching lines...) Expand all Loading... |
1089 } | 1089 } |
1090 | 1090 |
1091 if (cur_cover->IsSpilled()) return; | 1091 if (cur_cover->IsSpilled()) return; |
1092 ASSERT(pred_cover != NULL && cur_cover != NULL); | 1092 ASSERT(pred_cover != NULL && cur_cover != NULL); |
1093 if (pred_cover != cur_cover) { | 1093 if (pred_cover != cur_cover) { |
1094 LOperand* pred_op = pred_cover->CreateAssignedOperand(); | 1094 LOperand* pred_op = pred_cover->CreateAssignedOperand(); |
1095 LOperand* cur_op = cur_cover->CreateAssignedOperand(); | 1095 LOperand* cur_op = cur_cover->CreateAssignedOperand(); |
1096 if (!pred_op->Equals(cur_op)) { | 1096 if (!pred_op->Equals(cur_op)) { |
1097 LGap* gap = NULL; | 1097 LGap* gap = NULL; |
1098 if (block->predecessors()->length() == 1) { | 1098 if (block->predecessors()->length() == 1) { |
1099 gap = chunk_->GetGapAt(block->first_instruction_index()); | 1099 gap = GapAt(block->first_instruction_index()); |
1100 } else { | 1100 } else { |
1101 ASSERT(pred->end()->SecondSuccessor() == NULL); | 1101 ASSERT(pred->end()->SecondSuccessor() == NULL); |
1102 gap = GetLastGap(pred); | 1102 gap = GetLastGap(pred); |
1103 } | 1103 } |
1104 gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op); | 1104 gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op); |
1105 } | 1105 } |
1106 } | 1106 } |
1107 } | 1107 } |
1108 | 1108 |
1109 | 1109 |
1110 LParallelMove* LAllocator::GetConnectingParallelMove(LifetimePosition pos) { | 1110 LParallelMove* LAllocator::GetConnectingParallelMove(LifetimePosition pos) { |
1111 int index = pos.InstructionIndex(); | 1111 int index = pos.InstructionIndex(); |
1112 if (chunk_->IsGapAt(index)) { | 1112 if (IsGapAt(index)) { |
1113 LGap* gap = chunk_->GetGapAt(index); | 1113 LGap* gap = GapAt(index); |
1114 return gap->GetOrCreateParallelMove( | 1114 return gap->GetOrCreateParallelMove( |
1115 pos.IsInstructionStart() ? LGap::START : LGap::END); | 1115 pos.IsInstructionStart() ? LGap::START : LGap::END); |
1116 } | 1116 } |
1117 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1); | 1117 int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1); |
1118 return chunk_->GetGapAt(gap_pos)->GetOrCreateParallelMove( | 1118 return GapAt(gap_pos)->GetOrCreateParallelMove( |
1119 (gap_pos < index) ? LGap::AFTER : LGap::BEFORE); | 1119 (gap_pos < index) ? LGap::AFTER : LGap::BEFORE); |
1120 } | 1120 } |
1121 | 1121 |
1122 | 1122 |
1123 HBasicBlock* LAllocator::GetBlock(LifetimePosition pos) { | 1123 HBasicBlock* LAllocator::GetBlock(LifetimePosition pos) { |
1124 LGap* gap = chunk_->GetGapAt(chunk_->NearestGapPos(pos.InstructionIndex())); | 1124 LGap* gap = GapAt(chunk_->NearestGapPos(pos.InstructionIndex())); |
1125 return gap->block(); | 1125 return gap->block(); |
1126 } | 1126 } |
1127 | 1127 |
1128 | 1128 |
1129 void LAllocator::ConnectRanges() { | 1129 void LAllocator::ConnectRanges() { |
1130 HPhase phase("Connect ranges", this); | 1130 HPhase phase("Connect ranges", this); |
1131 for (int i = 0; i < live_ranges()->length(); ++i) { | 1131 for (int i = 0; i < live_ranges()->length(); ++i) { |
1132 LiveRange* first_range = live_ranges()->at(i); | 1132 LiveRange* first_range = live_ranges()->at(i); |
1133 if (first_range == NULL || first_range->parent() != NULL) continue; | 1133 if (first_range == NULL || first_range->parent() != NULL) continue; |
1134 | 1134 |
(...skipping 26 matching lines...) Expand all Loading... |
1161 | 1161 |
1162 | 1162 |
1163 bool LAllocator::CanEagerlyResolveControlFlow(HBasicBlock* block) const { | 1163 bool LAllocator::CanEagerlyResolveControlFlow(HBasicBlock* block) const { |
1164 if (block->predecessors()->length() != 1) return false; | 1164 if (block->predecessors()->length() != 1) return false; |
1165 return block->predecessors()->first()->block_id() == block->block_id() - 1; | 1165 return block->predecessors()->first()->block_id() == block->block_id() - 1; |
1166 } | 1166 } |
1167 | 1167 |
1168 | 1168 |
1169 void LAllocator::ResolveControlFlow() { | 1169 void LAllocator::ResolveControlFlow() { |
1170 HPhase phase("Resolve control flow", this); | 1170 HPhase phase("Resolve control flow", this); |
1171 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1171 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
1172 for (int block_id = 1; block_id < blocks->length(); ++block_id) { | 1172 for (int block_id = 1; block_id < blocks->length(); ++block_id) { |
1173 HBasicBlock* block = blocks->at(block_id); | 1173 HBasicBlock* block = blocks->at(block_id); |
1174 if (CanEagerlyResolveControlFlow(block)) continue; | 1174 if (CanEagerlyResolveControlFlow(block)) continue; |
1175 BitVector* live = live_in_sets_[block->block_id()]; | 1175 BitVector* live = live_in_sets_[block->block_id()]; |
1176 BitVector::Iterator iterator(live); | 1176 BitVector::Iterator iterator(live); |
1177 while (!iterator.Done()) { | 1177 while (!iterator.Done()) { |
1178 int operand_index = iterator.Current(); | 1178 int operand_index = iterator.Current(); |
1179 for (int i = 0; i < block->predecessors()->length(); ++i) { | 1179 for (int i = 0; i < block->predecessors()->length(); ++i) { |
1180 HBasicBlock* cur = block->predecessors()->at(i); | 1180 HBasicBlock* cur = block->predecessors()->at(i); |
1181 LiveRange* cur_range = LiveRangeFor(operand_index); | 1181 LiveRange* cur_range = LiveRangeFor(operand_index); |
1182 ResolveControlFlow(cur_range, block, cur); | 1182 ResolveControlFlow(cur_range, block, cur); |
1183 } | 1183 } |
1184 iterator.Advance(); | 1184 iterator.Advance(); |
1185 } | 1185 } |
1186 } | 1186 } |
1187 } | 1187 } |
1188 | 1188 |
1189 | 1189 |
1190 void LAllocator::BuildLiveRanges() { | 1190 void LAllocator::BuildLiveRanges() { |
1191 HPhase phase("Build live ranges", this); | 1191 HPhase phase("Build live ranges", this); |
1192 InitializeLivenessAnalysis(); | 1192 InitializeLivenessAnalysis(); |
1193 // Process the blocks in reverse order. | 1193 // Process the blocks in reverse order. |
1194 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 1194 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
1195 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { | 1195 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { |
1196 HBasicBlock* block = blocks->at(block_id); | 1196 HBasicBlock* block = blocks->at(block_id); |
1197 BitVector* live = ComputeLiveOut(block); | 1197 BitVector* live = ComputeLiveOut(block); |
1198 // Initially consider all live_out values live for the entire block. We | 1198 // Initially consider all live_out values live for the entire block. We |
1199 // will shorten these intervals if necessary. | 1199 // will shorten these intervals if necessary. |
1200 AddInitialIntervals(block, live); | 1200 AddInitialIntervals(block, live); |
1201 | 1201 |
1202 // Process the instructions in reverse order, generating and killing | 1202 // Process the instructions in reverse order, generating and killing |
1203 // live values. | 1203 // live values. |
1204 ProcessInstructions(block, live); | 1204 ProcessInstructions(block, live); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1259 } | 1259 } |
1260 | 1260 |
1261 #ifdef DEBUG | 1261 #ifdef DEBUG |
1262 if (block_id == 0) { | 1262 if (block_id == 0) { |
1263 BitVector::Iterator iterator(live); | 1263 BitVector::Iterator iterator(live); |
1264 bool found = false; | 1264 bool found = false; |
1265 while (!iterator.Done()) { | 1265 while (!iterator.Done()) { |
1266 found = true; | 1266 found = true; |
1267 int operand_index = iterator.Current(); | 1267 int operand_index = iterator.Current(); |
1268 PrintF("Function: %s\n", | 1268 PrintF("Function: %s\n", |
1269 *graph()->info()->function()->debug_name()->ToCString()); | 1269 *graph_->info()->function()->debug_name()->ToCString()); |
1270 PrintF("Value %d used before first definition!\n", operand_index); | 1270 PrintF("Value %d used before first definition!\n", operand_index); |
1271 LiveRange* range = LiveRangeFor(operand_index); | 1271 LiveRange* range = LiveRangeFor(operand_index); |
1272 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); | 1272 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); |
1273 iterator.Advance(); | 1273 iterator.Advance(); |
1274 } | 1274 } |
1275 ASSERT(!found); | 1275 ASSERT(!found); |
1276 } | 1276 } |
1277 #endif | 1277 #endif |
1278 } | 1278 } |
1279 } | 1279 } |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 LiveRange* current = unhandled_live_ranges_.RemoveLast(); | 1464 LiveRange* current = unhandled_live_ranges_.RemoveLast(); |
1465 ASSERT(UnhandledIsSorted()); | 1465 ASSERT(UnhandledIsSorted()); |
1466 LifetimePosition position = current->Start(); | 1466 LifetimePosition position = current->Start(); |
1467 TraceAlloc("Processing interval %d start=%d\n", | 1467 TraceAlloc("Processing interval %d start=%d\n", |
1468 current->id(), | 1468 current->id(), |
1469 position.Value()); | 1469 position.Value()); |
1470 | 1470 |
1471 if (current->HasAllocatedSpillOperand()) { | 1471 if (current->HasAllocatedSpillOperand()) { |
1472 TraceAlloc("Live range %d already has a spill operand\n", current->id()); | 1472 TraceAlloc("Live range %d already has a spill operand\n", current->id()); |
1473 LifetimePosition next_pos = position; | 1473 LifetimePosition next_pos = position; |
1474 if (chunk_->IsGapAt(next_pos.InstructionIndex())) { | 1474 if (IsGapAt(next_pos.InstructionIndex())) { |
1475 next_pos = next_pos.NextInstruction(); | 1475 next_pos = next_pos.NextInstruction(); |
1476 } | 1476 } |
1477 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); | 1477 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); |
1478 // If the range already has a spill operand and it doesn't need a | 1478 // 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. | 1479 // register immediately, split it and spill the first part of the range. |
1480 if (pos == NULL) { | 1480 if (pos == NULL) { |
1481 Spill(current); | 1481 Spill(current); |
1482 continue; | 1482 continue; |
1483 } else if (pos->pos().Value() > | 1483 } else if (pos->pos().Value() > |
1484 current->Start().NextInstruction().Value()) { | 1484 current->Start().NextInstruction().Value()) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1551 void LAllocator::TraceAlloc(const char* msg, ...) { | 1551 void LAllocator::TraceAlloc(const char* msg, ...) { |
1552 if (FLAG_trace_alloc) { | 1552 if (FLAG_trace_alloc) { |
1553 va_list arguments; | 1553 va_list arguments; |
1554 va_start(arguments, msg); | 1554 va_start(arguments, msg); |
1555 OS::VPrint(msg, arguments); | 1555 OS::VPrint(msg, arguments); |
1556 va_end(arguments); | 1556 va_end(arguments); |
1557 } | 1557 } |
1558 } | 1558 } |
1559 | 1559 |
1560 | 1560 |
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 { | 1561 bool LAllocator::HasTaggedValue(int virtual_register) const { |
1568 HValue* value = graph()->LookupValue(virtual_register); | 1562 HValue* value = graph_->LookupValue(virtual_register); |
1569 if (value == NULL) return false; | 1563 if (value == NULL) return false; |
1570 return value->representation().IsTagged(); | 1564 return value->representation().IsTagged(); |
1571 } | 1565 } |
1572 | 1566 |
1573 | 1567 |
1574 RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const { | 1568 RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const { |
1575 if (virtual_register < first_artificial_register_) { | 1569 if (virtual_register < first_artificial_register_) { |
1576 HValue* value = graph()->LookupValue(virtual_register); | 1570 HValue* value = graph_->LookupValue(virtual_register); |
1577 if (value != NULL && value->representation().IsDouble()) { | 1571 if (value != NULL && value->representation().IsDouble()) { |
1578 return DOUBLE_REGISTERS; | 1572 return DOUBLE_REGISTERS; |
1579 } | 1573 } |
1580 } else if (double_artificial_registers_.Contains( | 1574 } else if (double_artificial_registers_.Contains( |
1581 virtual_register - first_artificial_register_)) { | 1575 virtual_register - first_artificial_register_)) { |
1582 return DOUBLE_REGISTERS; | 1576 return DOUBLE_REGISTERS; |
1583 } | 1577 } |
1584 | 1578 |
1585 return GENERAL_REGISTERS; | 1579 return GENERAL_REGISTERS; |
1586 } | 1580 } |
1587 | 1581 |
1588 | 1582 |
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) { | 1583 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) { |
1620 operand->set_virtual_register(instr->id()); | 1584 operand->set_virtual_register(instr->id()); |
1621 current_summary()->SetOutput(operand); | |
1622 } | 1585 } |
1623 | 1586 |
1624 | 1587 |
1625 void LAllocator::RecordTemporary(LUnallocated* operand) { | 1588 void LAllocator::RecordTemporary(LUnallocated* operand) { |
1626 ASSERT(next_virtual_register_ < LUnallocated::kMaxVirtualRegisters); | 1589 ASSERT(next_virtual_register_ < LUnallocated::kMaxVirtualRegisters); |
1627 if (!operand->HasFixedPolicy()) { | 1590 if (!operand->HasFixedPolicy()) { |
1628 operand->set_virtual_register(next_virtual_register_++); | 1591 operand->set_virtual_register(next_virtual_register_++); |
1629 } | 1592 } |
1630 current_summary()->AddTemp(operand); | 1593 } |
| 1594 |
| 1595 |
| 1596 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) { |
| 1597 operand->set_virtual_register(value->id()); |
1631 } | 1598 } |
1632 | 1599 |
1633 | 1600 |
1634 int LAllocator::max_initial_value_ids() { | 1601 int LAllocator::max_initial_value_ids() { |
1635 return LUnallocated::kMaxVirtualRegisters / 32; | 1602 return LUnallocated::kMaxVirtualRegisters / 32; |
1636 } | 1603 } |
1637 | 1604 |
1638 | 1605 |
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) { | 1606 void LAllocator::AddToActive(LiveRange* range) { |
1668 TraceAlloc("Add live range %d to active\n", range->id()); | 1607 TraceAlloc("Add live range %d to active\n", range->id()); |
1669 active_live_ranges_.Add(range); | 1608 active_live_ranges_.Add(range); |
1670 } | 1609 } |
1671 | 1610 |
1672 | 1611 |
1673 void LAllocator::AddToInactive(LiveRange* range) { | 1612 void LAllocator::AddToInactive(LiveRange* range) { |
1674 TraceAlloc("Add live range %d to inactive\n", range->id()); | 1613 TraceAlloc("Add live range %d to inactive\n", range->id()); |
1675 inactive_live_ranges_.Add(range); | 1614 inactive_live_ranges_.Add(range); |
1676 } | 1615 } |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2002 InactiveToHandled(range); | 1941 InactiveToHandled(range); |
2003 --i; | 1942 --i; |
2004 } | 1943 } |
2005 } | 1944 } |
2006 } | 1945 } |
2007 } | 1946 } |
2008 | 1947 |
2009 | 1948 |
2010 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { | 1949 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { |
2011 return pos.IsInstructionStart() && | 1950 return pos.IsInstructionStart() && |
2012 chunk_->instructions()->at(pos.InstructionIndex())->IsLabel(); | 1951 InstructionAt(pos.InstructionIndex())->IsLabel(); |
2013 } | 1952 } |
2014 | 1953 |
2015 | 1954 |
2016 LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) { | 1955 LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) { |
2017 ASSERT(!range->IsFixed()); | 1956 ASSERT(!range->IsFixed()); |
2018 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); | 1957 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); |
2019 | 1958 |
2020 if (pos.Value() <= range->Start().Value()) return range; | 1959 if (pos.Value() <= range->Start().Value()) return range; |
2021 | 1960 |
2022 LiveRange* result = LiveRangeFor(next_virtual_register_++); | 1961 LiveRange* result = LiveRangeFor(next_virtual_register_++); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2132 LiveRange* current = live_ranges()->at(i); | 2071 LiveRange* current = live_ranges()->at(i); |
2133 if (current != NULL) current->Verify(); | 2072 if (current != NULL) current->Verify(); |
2134 } | 2073 } |
2135 } | 2074 } |
2136 | 2075 |
2137 | 2076 |
2138 #endif | 2077 #endif |
2139 | 2078 |
2140 | 2079 |
2141 } } // namespace v8::internal | 2080 } } // namespace v8::internal |
OLD | NEW |