OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 config_(config), | 895 config_(config), |
896 phi_map_(allocation_zone()), | 896 phi_map_(allocation_zone()), |
897 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), | 897 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), |
898 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, | 898 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, |
899 allocation_zone()), | 899 allocation_zone()), |
900 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, | 900 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, |
901 allocation_zone()), | 901 allocation_zone()), |
902 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, | 902 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, |
903 allocation_zone()), | 903 allocation_zone()), |
904 spill_ranges_(allocation_zone()), | 904 spill_ranges_(allocation_zone()), |
| 905 delayed_references_(allocation_zone()), |
905 assigned_registers_(nullptr), | 906 assigned_registers_(nullptr), |
906 assigned_double_registers_(nullptr), | 907 assigned_double_registers_(nullptr), |
907 virtual_register_count_(code->VirtualRegisterCount()) { | 908 virtual_register_count_(code->VirtualRegisterCount()) { |
908 DCHECK(this->config()->num_general_registers() <= | 909 DCHECK(this->config()->num_general_registers() <= |
909 RegisterConfiguration::kMaxGeneralRegisters); | 910 RegisterConfiguration::kMaxGeneralRegisters); |
910 DCHECK(this->config()->num_double_registers() <= | 911 DCHECK(this->config()->num_double_registers() <= |
911 RegisterConfiguration::kMaxDoubleRegisters); | 912 RegisterConfiguration::kMaxDoubleRegisters); |
912 spill_ranges().reserve(8); | 913 spill_ranges().reserve(8); |
913 assigned_registers_ = new (code_zone()) | 914 assigned_registers_ = new (code_zone()) |
914 BitVector(this->config()->num_general_registers(), code_zone()); | 915 BitVector(this->config()->num_general_registers(), code_zone()); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, | 1051 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, |
1051 machine_type, operand->fixed_register_index()); | 1052 machine_type, operand->fixed_register_index()); |
1052 } else { | 1053 } else { |
1053 UNREACHABLE(); | 1054 UNREACHABLE(); |
1054 } | 1055 } |
1055 InstructionOperand::ReplaceWith(operand, &allocated); | 1056 InstructionOperand::ReplaceWith(operand, &allocated); |
1056 if (is_tagged) { | 1057 if (is_tagged) { |
1057 TRACE("Fixed reg is tagged at %d\n", pos); | 1058 TRACE("Fixed reg is tagged at %d\n", pos); |
1058 auto instr = InstructionAt(pos); | 1059 auto instr = InstructionAt(pos); |
1059 if (instr->HasReferenceMap()) { | 1060 if (instr->HasReferenceMap()) { |
1060 instr->reference_map()->RecordReference(*operand); | 1061 instr->reference_map()->RecordReference(*AllocatedOperand::cast(operand)); |
1061 } | 1062 } |
1062 } | 1063 } |
1063 return operand; | 1064 return operand; |
1064 } | 1065 } |
1065 | 1066 |
1066 | 1067 |
1067 void ConstraintBuilder::MeetRegisterConstraints() { | 1068 void ConstraintBuilder::MeetRegisterConstraints() { |
1068 for (auto block : code()->instruction_blocks()) { | 1069 for (auto block : code()->instruction_blocks()) { |
1069 MeetRegisterConstraints(block); | 1070 MeetRegisterConstraints(block); |
1070 } | 1071 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1199 if (!output->IsUnallocated()) continue; | 1200 if (!output->IsUnallocated()) continue; |
1200 auto second_output = UnallocatedOperand::cast(output); | 1201 auto second_output = UnallocatedOperand::cast(output); |
1201 if (!second_output->HasSameAsInputPolicy()) continue; | 1202 if (!second_output->HasSameAsInputPolicy()) continue; |
1202 DCHECK(i == 0); // Only valid for first output. | 1203 DCHECK(i == 0); // Only valid for first output. |
1203 UnallocatedOperand* cur_input = | 1204 UnallocatedOperand* cur_input = |
1204 UnallocatedOperand::cast(second->InputAt(0)); | 1205 UnallocatedOperand::cast(second->InputAt(0)); |
1205 int output_vreg = second_output->virtual_register(); | 1206 int output_vreg = second_output->virtual_register(); |
1206 int input_vreg = cur_input->virtual_register(); | 1207 int input_vreg = cur_input->virtual_register(); |
1207 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); | 1208 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); |
1208 cur_input->set_virtual_register(second_output->virtual_register()); | 1209 cur_input->set_virtual_register(second_output->virtual_register()); |
1209 data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input); | 1210 auto gap_move = data()->AddGapMove(instr_index, Instruction::END, |
| 1211 input_copy, *cur_input); |
1210 if (IsReference(input_vreg) && !IsReference(output_vreg)) { | 1212 if (IsReference(input_vreg) && !IsReference(output_vreg)) { |
1211 if (second->HasReferenceMap()) { | 1213 if (second->HasReferenceMap()) { |
1212 second->reference_map()->RecordReference(input_copy); | 1214 RegisterAllocationData::DelayedReference delayed_reference = { |
| 1215 second->reference_map(), &gap_move->source()}; |
| 1216 data()->delayed_references().push_back(delayed_reference); |
1213 } | 1217 } |
1214 } else if (!IsReference(input_vreg) && IsReference(output_vreg)) { | 1218 } else if (!IsReference(input_vreg) && IsReference(output_vreg)) { |
1215 // The input is assumed to immediately have a tagged representation, | 1219 // The input is assumed to immediately have a tagged representation, |
1216 // before the pointer map can be used. I.e. the pointer map at the | 1220 // before the pointer map can be used. I.e. the pointer map at the |
1217 // instruction will include the output operand (whose value at the | 1221 // instruction will include the output operand (whose value at the |
1218 // beginning of the instruction is equal to the input operand). If | 1222 // beginning of the instruction is equal to the input operand). If |
1219 // this is not desired, then the pointer map at this instruction needs | 1223 // this is not desired, then the pointer map at this instruction needs |
1220 // to be adjusted manually. | 1224 // to be adjusted manually. |
1221 } | 1225 } |
1222 } | 1226 } |
(...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2748 for (auto map : *data()->code()->reference_maps()) { | 2752 for (auto map : *data()->code()->reference_maps()) { |
2749 if (safe_point > map->instruction_position()) return false; | 2753 if (safe_point > map->instruction_position()) return false; |
2750 safe_point = map->instruction_position(); | 2754 safe_point = map->instruction_position(); |
2751 } | 2755 } |
2752 return true; | 2756 return true; |
2753 } | 2757 } |
2754 | 2758 |
2755 | 2759 |
2756 void ReferenceMapPopulator::PopulateReferenceMaps() { | 2760 void ReferenceMapPopulator::PopulateReferenceMaps() { |
2757 DCHECK(SafePointsAreInOrder()); | 2761 DCHECK(SafePointsAreInOrder()); |
2758 | 2762 // Map all delayed references. |
| 2763 for (auto& delayed_reference : data()->delayed_references()) { |
| 2764 delayed_reference.map->RecordReference( |
| 2765 AllocatedOperand::cast(*delayed_reference.operand)); |
| 2766 } |
2759 // Iterate over all safe point positions and record a pointer | 2767 // Iterate over all safe point positions and record a pointer |
2760 // for all spilled live ranges at this point. | 2768 // for all spilled live ranges at this point. |
2761 int last_range_start = 0; | 2769 int last_range_start = 0; |
2762 auto reference_maps = data()->code()->reference_maps(); | 2770 auto reference_maps = data()->code()->reference_maps(); |
2763 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); | 2771 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); |
2764 for (LiveRange* range : data()->live_ranges()) { | 2772 for (LiveRange* range : data()->live_ranges()) { |
2765 if (range == nullptr) continue; | 2773 if (range == nullptr) continue; |
2766 // Iterate over the first parts of multi-part live ranges. | 2774 // Iterate over the first parts of multi-part live ranges. |
2767 if (range->IsChild()) continue; | 2775 if (range->IsChild()) continue; |
2768 // Skip non-reference values. | 2776 // Skip non-reference values. |
(...skipping 16 matching lines...) Expand all Loading... |
2785 if (start < last_range_start) first_it = reference_maps->begin(); | 2793 if (start < last_range_start) first_it = reference_maps->begin(); |
2786 last_range_start = start; | 2794 last_range_start = start; |
2787 | 2795 |
2788 // Step across all the safe points that are before the start of this range, | 2796 // Step across all the safe points that are before the start of this range, |
2789 // recording how far we step in order to save doing this for the next range. | 2797 // recording how far we step in order to save doing this for the next range. |
2790 for (; first_it != reference_maps->end(); ++first_it) { | 2798 for (; first_it != reference_maps->end(); ++first_it) { |
2791 auto map = *first_it; | 2799 auto map = *first_it; |
2792 if (map->instruction_position() >= start) break; | 2800 if (map->instruction_position() >= start) break; |
2793 } | 2801 } |
2794 | 2802 |
| 2803 InstructionOperand spill_operand; |
| 2804 if (((range->HasSpillOperand() && |
| 2805 !range->GetSpillOperand()->IsConstant()) || |
| 2806 range->HasSpillRange())) { |
| 2807 if (range->HasSpillOperand()) { |
| 2808 spill_operand = *range->GetSpillOperand(); |
| 2809 } else { |
| 2810 spill_operand = range->GetSpillRangeOperand(); |
| 2811 } |
| 2812 DCHECK(spill_operand.IsStackSlot()); |
| 2813 DCHECK_EQ(kRepTagged, |
| 2814 AllocatedOperand::cast(spill_operand).machine_type()); |
| 2815 } |
| 2816 |
2795 // Step through the safe points to see whether they are in the range. | 2817 // Step through the safe points to see whether they are in the range. |
2796 for (auto it = first_it; it != reference_maps->end(); ++it) { | 2818 for (auto it = first_it; it != reference_maps->end(); ++it) { |
2797 auto map = *it; | 2819 auto map = *it; |
2798 int safe_point = map->instruction_position(); | 2820 int safe_point = map->instruction_position(); |
2799 | 2821 |
2800 // The safe points are sorted so we can stop searching here. | 2822 // The safe points are sorted so we can stop searching here. |
2801 if (safe_point - 1 > end) break; | 2823 if (safe_point - 1 > end) break; |
2802 | 2824 |
2803 // Advance to the next active range that covers the current | 2825 // Advance to the next active range that covers the current |
2804 // safe point position. | 2826 // safe point position. |
2805 auto safe_point_pos = | 2827 auto safe_point_pos = |
2806 LifetimePosition::InstructionFromInstructionIndex(safe_point); | 2828 LifetimePosition::InstructionFromInstructionIndex(safe_point); |
2807 auto cur = range; | 2829 auto cur = range; |
2808 while (cur != nullptr && !cur->Covers(safe_point_pos)) { | 2830 while (cur != nullptr && !cur->Covers(safe_point_pos)) { |
2809 cur = cur->next(); | 2831 cur = cur->next(); |
2810 } | 2832 } |
2811 if (cur == nullptr) continue; | 2833 if (cur == nullptr) continue; |
2812 | 2834 |
2813 // Check if the live range is spilled and the safe point is after | 2835 // Check if the live range is spilled and the safe point is after |
2814 // the spill position. | 2836 // the spill position. |
2815 if (((range->HasSpillOperand() && | 2837 if (!spill_operand.IsInvalid() && |
2816 !range->GetSpillOperand()->IsConstant()) || | |
2817 range->HasSpillRange()) && | |
2818 safe_point >= range->spill_start_index()) { | 2838 safe_point >= range->spill_start_index()) { |
2819 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", | 2839 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", |
2820 range->id(), range->spill_start_index(), safe_point); | 2840 range->id(), range->spill_start_index(), safe_point); |
2821 InstructionOperand operand; | 2841 map->RecordReference(AllocatedOperand::cast(spill_operand)); |
2822 if (range->HasSpillOperand()) { | |
2823 operand = *range->GetSpillOperand(); | |
2824 } else { | |
2825 operand = range->GetSpillRangeOperand(); | |
2826 } | |
2827 DCHECK(operand.IsStackSlot()); | |
2828 DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type()); | |
2829 map->RecordReference(operand); | |
2830 } | 2842 } |
2831 | 2843 |
2832 if (!cur->spilled()) { | 2844 if (!cur->spilled()) { |
2833 TRACE( | 2845 TRACE( |
2834 "Pointer in register for range %d (start at %d) " | 2846 "Pointer in register for range %d (start at %d) " |
2835 "at safe point %d\n", | 2847 "at safe point %d\n", |
2836 cur->id(), cur->Start().value(), safe_point); | 2848 cur->id(), cur->Start().value(), safe_point); |
2837 auto operand = cur->GetAssignedOperand(); | 2849 auto operand = cur->GetAssignedOperand(); |
2838 DCHECK(!operand.IsStackSlot()); | 2850 DCHECK(!operand.IsStackSlot()); |
2839 DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type()); | 2851 DCHECK_EQ(kRepTagged, AllocatedOperand::cast(operand).machine_type()); |
2840 map->RecordReference(operand); | 2852 map->RecordReference(AllocatedOperand::cast(operand)); |
2841 } | 2853 } |
2842 } | 2854 } |
2843 } | 2855 } |
2844 } | 2856 } |
2845 | 2857 |
2846 | 2858 |
2847 namespace { | 2859 namespace { |
2848 | 2860 |
2849 class LiveRangeBound { | 2861 class LiveRangeBound { |
2850 public: | 2862 public: |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3126 auto eliminate = moves->PrepareInsertAfter(move); | 3138 auto eliminate = moves->PrepareInsertAfter(move); |
3127 to_insert.push_back(move); | 3139 to_insert.push_back(move); |
3128 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3140 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
3129 } | 3141 } |
3130 } | 3142 } |
3131 | 3143 |
3132 | 3144 |
3133 } // namespace compiler | 3145 } // namespace compiler |
3134 } // namespace internal | 3146 } // namespace internal |
3135 } // namespace v8 | 3147 } // namespace v8 |
OLD | NEW |