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/compiler/linkage.h" | 5 #include "src/compiler/linkage.h" |
6 #include "src/compiler/register-allocator.h" | 6 #include "src/compiler/register-allocator.h" |
7 #include "src/string-stream.h" | 7 #include "src/string-stream.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 } else if (operand->HasFixedDoubleRegisterPolicy()) { | 715 } else if (operand->HasFixedDoubleRegisterPolicy()) { |
716 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, | 716 allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER, |
717 operand->fixed_register_index()); | 717 operand->fixed_register_index()); |
718 } else { | 718 } else { |
719 UNREACHABLE(); | 719 UNREACHABLE(); |
720 } | 720 } |
721 InstructionOperand::ReplaceWith(operand, &allocated); | 721 InstructionOperand::ReplaceWith(operand, &allocated); |
722 if (is_tagged) { | 722 if (is_tagged) { |
723 TRACE("Fixed reg is tagged at %d\n", pos); | 723 TRACE("Fixed reg is tagged at %d\n", pos); |
724 auto instr = InstructionAt(pos); | 724 auto instr = InstructionAt(pos); |
725 if (instr->HasPointerMap()) { | 725 if (instr->HasReferenceMap()) { |
726 instr->pointer_map()->RecordPointer(operand, code_zone()); | 726 instr->reference_map()->RecordReference(*operand); |
727 } | 727 } |
728 } | 728 } |
729 return operand; | 729 return operand; |
730 } | 730 } |
731 | 731 |
732 | 732 |
733 LiveRange* RegisterAllocator::NewLiveRange(int index) { | 733 LiveRange* RegisterAllocator::NewLiveRange(int index) { |
734 // The LiveRange object itself can go in the local zone, but the | 734 // The LiveRange object itself can go in the local zone, but the |
735 // InstructionOperand needs to go in the code zone, since it may survive | 735 // InstructionOperand needs to go in the code zone, since it may survive |
736 // register allocation. | 736 // register allocation. |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 if (!second_output->HasSameAsInputPolicy()) continue; | 1219 if (!second_output->HasSameAsInputPolicy()) continue; |
1220 DCHECK(i == 0); // Only valid for first output. | 1220 DCHECK(i == 0); // Only valid for first output. |
1221 UnallocatedOperand* cur_input = | 1221 UnallocatedOperand* cur_input = |
1222 UnallocatedOperand::cast(second->InputAt(0)); | 1222 UnallocatedOperand::cast(second->InputAt(0)); |
1223 int output_vreg = second_output->virtual_register(); | 1223 int output_vreg = second_output->virtual_register(); |
1224 int input_vreg = cur_input->virtual_register(); | 1224 int input_vreg = cur_input->virtual_register(); |
1225 auto input_copy = cur_input->CopyUnconstrained(code_zone()); | 1225 auto input_copy = cur_input->CopyUnconstrained(code_zone()); |
1226 cur_input->set_virtual_register(second_output->virtual_register()); | 1226 cur_input->set_virtual_register(second_output->virtual_register()); |
1227 AddGapMove(instr_index, Instruction::END, input_copy, cur_input); | 1227 AddGapMove(instr_index, Instruction::END, input_copy, cur_input); |
1228 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { | 1228 if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) { |
1229 if (second->HasPointerMap()) { | 1229 if (second->HasReferenceMap()) { |
1230 second->pointer_map()->RecordPointer(input_copy, code_zone()); | 1230 second->reference_map()->RecordReference(*input_copy); |
1231 } | 1231 } |
1232 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { | 1232 } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) { |
1233 // The input is assumed to immediately have a tagged representation, | 1233 // The input is assumed to immediately have a tagged representation, |
1234 // before the pointer map can be used. I.e. the pointer map at the | 1234 // before the pointer map can be used. I.e. the pointer map at the |
1235 // instruction will include the output operand (whose value at the | 1235 // instruction will include the output operand (whose value at the |
1236 // beginning of the instruction is equal to the input operand). If | 1236 // beginning of the instruction is equal to the input operand). If |
1237 // this is not desired, then the pointer map at this instruction needs | 1237 // this is not desired, then the pointer map at this instruction needs |
1238 // to be adjusted manually. | 1238 // to be adjusted manually. |
1239 } | 1239 } |
1240 } | 1240 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1404 auto res = | 1404 auto res = |
1405 phi_map_.insert(std::make_pair(phi_vreg, PhiMapValue(phi, block))); | 1405 phi_map_.insert(std::make_pair(phi_vreg, PhiMapValue(phi, block))); |
1406 DCHECK(res.second); | 1406 DCHECK(res.second); |
1407 USE(res); | 1407 USE(res); |
1408 auto& output = phi->output(); | 1408 auto& output = phi->output(); |
1409 for (size_t i = 0; i < phi->operands().size(); ++i) { | 1409 for (size_t i = 0; i < phi->operands().size(); ++i) { |
1410 InstructionBlock* cur_block = | 1410 InstructionBlock* cur_block = |
1411 code()->InstructionBlockAt(block->predecessors()[i]); | 1411 code()->InstructionBlockAt(block->predecessors()[i]); |
1412 AddGapMove(cur_block->last_instruction_index(), Instruction::END, | 1412 AddGapMove(cur_block->last_instruction_index(), Instruction::END, |
1413 &phi->inputs()[i], &output); | 1413 &phi->inputs()[i], &output); |
1414 DCHECK( | 1414 DCHECK(!InstructionAt(cur_block->last_instruction_index()) |
1415 !InstructionAt(cur_block->last_instruction_index())->HasPointerMap()); | 1415 ->HasReferenceMap()); |
1416 } | 1416 } |
1417 auto live_range = LiveRangeFor(phi_vreg); | 1417 auto live_range = LiveRangeFor(phi_vreg); |
1418 int gap_index = block->first_instruction_index(); | 1418 int gap_index = block->first_instruction_index(); |
1419 live_range->SpillAtDefinition(local_zone(), gap_index, &output); | 1419 live_range->SpillAtDefinition(local_zone(), gap_index, &output); |
1420 live_range->SetSpillStartIndex(gap_index); | 1420 live_range->SetSpillStartIndex(gap_index); |
1421 // We use the phi-ness of some nodes in some later heuristics. | 1421 // We use the phi-ness of some nodes in some later heuristics. |
1422 live_range->set_is_phi(true); | 1422 live_range->set_is_phi(true); |
1423 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); | 1423 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); |
1424 } | 1424 } |
1425 } | 1425 } |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1693 const InstructionBlock* pred, | 1693 const InstructionBlock* pred, |
1694 InstructionOperand* pred_op) { | 1694 InstructionOperand* pred_op) { |
1695 if (pred_op->Equals(cur_op)) return; | 1695 if (pred_op->Equals(cur_op)) return; |
1696 int gap_index; | 1696 int gap_index; |
1697 Instruction::GapPosition position; | 1697 Instruction::GapPosition position; |
1698 if (block->PredecessorCount() == 1) { | 1698 if (block->PredecessorCount() == 1) { |
1699 gap_index = block->first_instruction_index(); | 1699 gap_index = block->first_instruction_index(); |
1700 position = Instruction::START; | 1700 position = Instruction::START; |
1701 } else { | 1701 } else { |
1702 DCHECK(pred->SuccessorCount() == 1); | 1702 DCHECK(pred->SuccessorCount() == 1); |
1703 DCHECK(!InstructionAt(pred->last_instruction_index())->HasPointerMap()); | 1703 DCHECK(!InstructionAt(pred->last_instruction_index())->HasReferenceMap()); |
1704 gap_index = pred->last_instruction_index(); | 1704 gap_index = pred->last_instruction_index(); |
1705 position = Instruction::END; | 1705 position = Instruction::END; |
1706 } | 1706 } |
1707 AddGapMove(gap_index, position, pred_op, cur_op); | 1707 AddGapMove(gap_index, position, pred_op, cur_op); |
1708 } | 1708 } |
1709 | 1709 |
1710 | 1710 |
1711 void RegisterAllocator::BuildLiveRanges() { | 1711 void RegisterAllocator::BuildLiveRanges() { |
1712 // Process the blocks in reverse order. | 1712 // Process the blocks in reverse order. |
1713 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; | 1713 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 PrintF(" (function: %s)\n", debug_name()); | 1815 PrintF(" (function: %s)\n", debug_name()); |
1816 } | 1816 } |
1817 iterator.Advance(); | 1817 iterator.Advance(); |
1818 } | 1818 } |
1819 return found; | 1819 return found; |
1820 } | 1820 } |
1821 | 1821 |
1822 | 1822 |
1823 bool RegisterAllocator::SafePointsAreInOrder() const { | 1823 bool RegisterAllocator::SafePointsAreInOrder() const { |
1824 int safe_point = 0; | 1824 int safe_point = 0; |
1825 for (auto map : *code()->pointer_maps()) { | 1825 for (auto map : *code()->reference_maps()) { |
1826 if (safe_point > map->instruction_position()) return false; | 1826 if (safe_point > map->instruction_position()) return false; |
1827 safe_point = map->instruction_position(); | 1827 safe_point = map->instruction_position(); |
1828 } | 1828 } |
1829 return true; | 1829 return true; |
1830 } | 1830 } |
1831 | 1831 |
1832 | 1832 |
1833 void RegisterAllocator::PopulatePointerMaps() { | 1833 void RegisterAllocator::PopulateReferenceMaps() { |
1834 DCHECK(SafePointsAreInOrder()); | 1834 DCHECK(SafePointsAreInOrder()); |
1835 | 1835 |
1836 // Iterate over all safe point positions and record a pointer | 1836 // Iterate over all safe point positions and record a pointer |
1837 // for all spilled live ranges at this point. | 1837 // for all spilled live ranges at this point. |
1838 int last_range_start = 0; | 1838 int last_range_start = 0; |
1839 auto pointer_maps = code()->pointer_maps(); | 1839 auto reference_maps = code()->reference_maps(); |
1840 PointerMapDeque::const_iterator first_it = pointer_maps->begin(); | 1840 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); |
1841 for (LiveRange* range : live_ranges()) { | 1841 for (LiveRange* range : live_ranges()) { |
1842 if (range == nullptr) continue; | 1842 if (range == nullptr) continue; |
1843 // Iterate over the first parts of multi-part live ranges. | 1843 // Iterate over the first parts of multi-part live ranges. |
1844 if (range->IsChild()) continue; | 1844 if (range->IsChild()) continue; |
1845 // Skip non-reference values. | 1845 // Skip non-reference values. |
1846 if (!HasTaggedValue(range->id())) continue; | 1846 if (!HasTaggedValue(range->id())) continue; |
1847 // Skip empty live ranges. | 1847 // Skip empty live ranges. |
1848 if (range->IsEmpty()) continue; | 1848 if (range->IsEmpty()) continue; |
1849 | 1849 |
1850 // Find the extent of the range and its children. | 1850 // Find the extent of the range and its children. |
1851 int start = range->Start().ToInstructionIndex(); | 1851 int start = range->Start().ToInstructionIndex(); |
1852 int end = 0; | 1852 int end = 0; |
1853 for (auto cur = range; cur != nullptr; cur = cur->next()) { | 1853 for (auto cur = range; cur != nullptr; cur = cur->next()) { |
1854 auto this_end = cur->End(); | 1854 auto this_end = cur->End(); |
1855 if (this_end.ToInstructionIndex() > end) | 1855 if (this_end.ToInstructionIndex() > end) |
1856 end = this_end.ToInstructionIndex(); | 1856 end = this_end.ToInstructionIndex(); |
1857 DCHECK(cur->Start().ToInstructionIndex() >= start); | 1857 DCHECK(cur->Start().ToInstructionIndex() >= start); |
1858 } | 1858 } |
1859 | 1859 |
1860 // Most of the ranges are in order, but not all. Keep an eye on when they | 1860 // Most of the ranges are in order, but not all. Keep an eye on when they |
1861 // step backwards and reset the first_it so we don't miss any safe points. | 1861 // step backwards and reset the first_it so we don't miss any safe points. |
1862 if (start < last_range_start) first_it = pointer_maps->begin(); | 1862 if (start < last_range_start) first_it = reference_maps->begin(); |
1863 last_range_start = start; | 1863 last_range_start = start; |
1864 | 1864 |
1865 // Step across all the safe points that are before the start of this range, | 1865 // Step across all the safe points that are before the start of this range, |
1866 // recording how far we step in order to save doing this for the next range. | 1866 // recording how far we step in order to save doing this for the next range. |
1867 for (; first_it != pointer_maps->end(); ++first_it) { | 1867 for (; first_it != reference_maps->end(); ++first_it) { |
1868 auto map = *first_it; | 1868 auto map = *first_it; |
1869 if (map->instruction_position() >= start) break; | 1869 if (map->instruction_position() >= start) break; |
1870 } | 1870 } |
1871 | 1871 |
1872 // Step through the safe points to see whether they are in the range. | 1872 // Step through the safe points to see whether they are in the range. |
1873 for (auto it = first_it; it != pointer_maps->end(); ++it) { | 1873 for (auto it = first_it; it != reference_maps->end(); ++it) { |
1874 auto map = *it; | 1874 auto map = *it; |
1875 int safe_point = map->instruction_position(); | 1875 int safe_point = map->instruction_position(); |
1876 | 1876 |
1877 // The safe points are sorted so we can stop searching here. | 1877 // The safe points are sorted so we can stop searching here. |
1878 if (safe_point - 1 > end) break; | 1878 if (safe_point - 1 > end) break; |
1879 | 1879 |
1880 // Advance to the next active range that covers the current | 1880 // Advance to the next active range that covers the current |
1881 // safe point position. | 1881 // safe point position. |
1882 auto safe_point_pos = | 1882 auto safe_point_pos = |
1883 LifetimePosition::InstructionFromInstructionIndex(safe_point); | 1883 LifetimePosition::InstructionFromInstructionIndex(safe_point); |
1884 auto cur = range; | 1884 auto cur = range; |
1885 while (cur != nullptr && !cur->Covers(safe_point_pos)) { | 1885 while (cur != nullptr && !cur->Covers(safe_point_pos)) { |
1886 cur = cur->next(); | 1886 cur = cur->next(); |
1887 } | 1887 } |
1888 if (cur == nullptr) continue; | 1888 if (cur == nullptr) continue; |
1889 | 1889 |
1890 // Check if the live range is spilled and the safe point is after | 1890 // Check if the live range is spilled and the safe point is after |
1891 // the spill position. | 1891 // the spill position. |
1892 if (range->HasSpillOperand() && | 1892 if (range->HasSpillOperand() && |
1893 safe_point >= range->spill_start_index() && | 1893 safe_point >= range->spill_start_index() && |
1894 !range->GetSpillOperand()->IsConstant()) { | 1894 !range->GetSpillOperand()->IsConstant()) { |
1895 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", | 1895 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", |
1896 range->id(), range->spill_start_index(), safe_point); | 1896 range->id(), range->spill_start_index(), safe_point); |
1897 map->RecordPointer(range->GetSpillOperand(), code_zone()); | 1897 map->RecordReference(*range->GetSpillOperand()); |
1898 } | 1898 } |
1899 | 1899 |
1900 if (!cur->IsSpilled()) { | 1900 if (!cur->IsSpilled()) { |
1901 TRACE( | 1901 TRACE( |
1902 "Pointer in register for range %d (start at %d) " | 1902 "Pointer in register for range %d (start at %d) " |
1903 "at safe point %d\n", | 1903 "at safe point %d\n", |
1904 cur->id(), cur->Start().Value(), safe_point); | 1904 cur->id(), cur->Start().Value(), safe_point); |
1905 InstructionOperand* operand = cur->GetAssignedOperand(operand_cache()); | 1905 auto operand = cur->GetAssignedOperand(); |
1906 DCHECK(!operand->IsStackSlot()); | 1906 DCHECK(!operand.IsStackSlot()); |
1907 map->RecordPointer(operand, code_zone()); | 1907 map->RecordReference(operand); |
1908 } | 1908 } |
1909 } | 1909 } |
1910 } | 1910 } |
1911 } | 1911 } |
1912 | 1912 |
1913 | 1913 |
1914 void RegisterAllocator::AllocateGeneralRegisters() { | 1914 void RegisterAllocator::AllocateGeneralRegisters() { |
1915 num_registers_ = config()->num_general_registers(); | 1915 num_registers_ = config()->num_general_registers(); |
1916 mode_ = GENERAL_REGISTERS; | 1916 mode_ = GENERAL_REGISTERS; |
1917 AllocateRegisters(); | 1917 AllocateRegisters(); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2533 } else { | 2533 } else { |
2534 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2534 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2535 assigned_registers_->Add(reg); | 2535 assigned_registers_->Add(reg); |
2536 } | 2536 } |
2537 range->set_assigned_register(reg, operand_cache()); | 2537 range->set_assigned_register(reg, operand_cache()); |
2538 } | 2538 } |
2539 | 2539 |
2540 } // namespace compiler | 2540 } // namespace compiler |
2541 } // namespace internal | 2541 } // namespace internal |
2542 } // namespace v8 | 2542 } // namespace v8 |
OLD | NEW |