| 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 |