| 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 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); | 560 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); |
| 561 assigned_double_registers_ = new (code_zone()) | 561 assigned_double_registers_ = new (code_zone()) |
| 562 BitVector(config->num_aliased_double_registers(), code_zone()); | 562 BitVector(config->num_aliased_double_registers(), code_zone()); |
| 563 frame->SetAllocatedRegisters(assigned_registers_); | 563 frame->SetAllocatedRegisters(assigned_registers_); |
| 564 frame->SetAllocatedDoubleRegisters(assigned_double_registers_); | 564 frame->SetAllocatedDoubleRegisters(assigned_double_registers_); |
| 565 } | 565 } |
| 566 | 566 |
| 567 | 567 |
| 568 void RegisterAllocator::InitializeLivenessAnalysis() { | 568 void RegisterAllocator::InitializeLivenessAnalysis() { |
| 569 // Initialize the live_in sets for each block to NULL. | 569 // Initialize the live_in sets for each block to NULL. |
| 570 int block_count = code()->InstructionBlockCount(); | 570 std::fill(live_in_sets_.begin(), live_in_sets_.end(), nullptr); |
| 571 live_in_sets_.Initialize(block_count, local_zone()); | |
| 572 live_in_sets_.AddBlock(NULL, block_count, local_zone()); | |
| 573 } | 571 } |
| 574 | 572 |
| 575 | 573 |
| 576 BitVector* RegisterAllocator::ComputeLiveOut(const InstructionBlock* block) { | 574 BitVector* RegisterAllocator::ComputeLiveOut(const InstructionBlock* block) { |
| 577 // Compute live out for the given block, except not including backward | 575 // Compute live out for the given block, except not including backward |
| 578 // successor edges. | 576 // successor edges. |
| 579 BitVector* live_out = new (local_zone()) | 577 BitVector* live_out = new (local_zone()) |
| 580 BitVector(code()->VirtualRegisterCount(), local_zone()); | 578 BitVector(code()->VirtualRegisterCount(), local_zone()); |
| 581 | 579 |
| 582 // Process all successor blocks. | 580 // Process all successor blocks. |
| 583 for (auto succ : block->successors()) { | 581 for (auto succ : block->successors()) { |
| 584 // Add values live on entry to the successor. Note the successor's | 582 // Add values live on entry to the successor. Note the successor's |
| 585 // live_in will not be computed yet for backwards edges. | 583 // live_in will not be computed yet for backwards edges. |
| 586 BitVector* live_in = live_in_sets_[static_cast<int>(succ.ToSize())]; | 584 BitVector* live_in = live_in_sets_[succ.ToSize()]; |
| 587 if (live_in != NULL) live_out->Union(*live_in); | 585 if (live_in != NULL) live_out->Union(*live_in); |
| 588 | 586 |
| 589 // All phi input operands corresponding to this successor edge are live | 587 // All phi input operands corresponding to this successor edge are live |
| 590 // out from this block. | 588 // out from this block. |
| 591 const InstructionBlock* successor = code()->InstructionBlockAt(succ); | 589 const InstructionBlock* successor = code()->InstructionBlockAt(succ); |
| 592 size_t index = successor->PredecessorIndexOf(block->rpo_number()); | 590 size_t index = successor->PredecessorIndexOf(block->rpo_number()); |
| 593 DCHECK(index < successor->PredecessorCount()); | 591 DCHECK(index < successor->PredecessorCount()); |
| 594 for (auto phi : successor->phis()) { | 592 for (auto phi : successor->phis()) { |
| 595 live_out->Add(phi->operands()[index]); | 593 live_out->Add(phi->operands()[index]); |
| 596 } | 594 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 DCHECK(result->IsFixed()); | 674 DCHECK(result->IsFixed()); |
| 677 result->kind_ = DOUBLE_REGISTERS; | 675 result->kind_ = DOUBLE_REGISTERS; |
| 678 SetLiveRangeAssignedRegister(result, index); | 676 SetLiveRangeAssignedRegister(result, index); |
| 679 fixed_double_live_ranges_[index] = result; | 677 fixed_double_live_ranges_[index] = result; |
| 680 } | 678 } |
| 681 return result; | 679 return result; |
| 682 } | 680 } |
| 683 | 681 |
| 684 | 682 |
| 685 LiveRange* RegisterAllocator::LiveRangeFor(int index) { | 683 LiveRange* RegisterAllocator::LiveRangeFor(int index) { |
| 686 if (index >= live_ranges_.length()) { | 684 if (index >= static_cast<int>(live_ranges_.size())) { |
| 687 live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1, | 685 live_ranges_.resize(index + 1, NULL); |
| 688 local_zone()); | |
| 689 } | 686 } |
| 690 LiveRange* result = live_ranges_[index]; | 687 LiveRange* result = live_ranges_[index]; |
| 691 if (result == NULL) { | 688 if (result == NULL) { |
| 692 result = new (local_zone()) LiveRange(index, code_zone()); | 689 result = new (local_zone()) LiveRange(index, code_zone()); |
| 693 live_ranges_[index] = result; | 690 live_ranges_[index] = result; |
| 694 } | 691 } |
| 695 return result; | 692 return result; |
| 696 } | 693 } |
| 697 | 694 |
| 698 | 695 |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1321 } | 1318 } |
| 1322 | 1319 |
| 1323 | 1320 |
| 1324 const InstructionBlock* RegisterAllocator::GetInstructionBlock( | 1321 const InstructionBlock* RegisterAllocator::GetInstructionBlock( |
| 1325 LifetimePosition pos) { | 1322 LifetimePosition pos) { |
| 1326 return code()->GetInstructionBlock(pos.InstructionIndex()); | 1323 return code()->GetInstructionBlock(pos.InstructionIndex()); |
| 1327 } | 1324 } |
| 1328 | 1325 |
| 1329 | 1326 |
| 1330 void RegisterAllocator::ConnectRanges() { | 1327 void RegisterAllocator::ConnectRanges() { |
| 1331 for (int i = 0; i < live_ranges().length(); ++i) { | 1328 for (size_t i = 0; i < live_ranges().size(); ++i) { |
| 1332 LiveRange* first_range = live_ranges().at(i); | 1329 LiveRange* first_range = live_ranges().at(i); |
| 1333 if (first_range == NULL || first_range->parent() != NULL) continue; | 1330 if (first_range == NULL || first_range->parent() != NULL) continue; |
| 1334 | 1331 |
| 1335 LiveRange* second_range = first_range->next(); | 1332 LiveRange* second_range = first_range->next(); |
| 1336 while (second_range != NULL) { | 1333 while (second_range != NULL) { |
| 1337 LifetimePosition pos = second_range->Start(); | 1334 LifetimePosition pos = second_range->Start(); |
| 1338 | 1335 |
| 1339 if (!second_range->IsSpilled()) { | 1336 if (!second_range->IsSpilled()) { |
| 1340 // Add gap move if the two live ranges touch and there is no block | 1337 // Add gap move if the two live ranges touch and there is no block |
| 1341 // boundary. | 1338 // boundary. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 LiveRangeBound* start_; | 1464 LiveRangeBound* start_; |
| 1468 | 1465 |
| 1469 DISALLOW_COPY_AND_ASSIGN(LiveRangeBoundArray); | 1466 DISALLOW_COPY_AND_ASSIGN(LiveRangeBoundArray); |
| 1470 }; | 1467 }; |
| 1471 | 1468 |
| 1472 | 1469 |
| 1473 class LiveRangeFinder { | 1470 class LiveRangeFinder { |
| 1474 public: | 1471 public: |
| 1475 explicit LiveRangeFinder(const RegisterAllocator& allocator) | 1472 explicit LiveRangeFinder(const RegisterAllocator& allocator) |
| 1476 : allocator_(allocator), | 1473 : allocator_(allocator), |
| 1477 bounds_length_(allocator.live_ranges().length()), | 1474 bounds_length_(static_cast<int>(allocator.live_ranges().size())), |
| 1478 bounds_(allocator.local_zone()->NewArray<LiveRangeBoundArray>( | 1475 bounds_(allocator.local_zone()->NewArray<LiveRangeBoundArray>( |
| 1479 bounds_length_)) { | 1476 bounds_length_)) { |
| 1480 for (int i = 0; i < bounds_length_; ++i) { | 1477 for (int i = 0; i < bounds_length_; ++i) { |
| 1481 new (&bounds_[i]) LiveRangeBoundArray(); | 1478 new (&bounds_[i]) LiveRangeBoundArray(); |
| 1482 } | 1479 } |
| 1483 } | 1480 } |
| 1484 | 1481 |
| 1485 LiveRangeBoundArray* ArrayFor(int operand_index) { | 1482 LiveRangeBoundArray* ArrayFor(int operand_index) { |
| 1486 DCHECK(operand_index < bounds_length_); | 1483 DCHECK(operand_index < bounds_length_); |
| 1487 const LiveRange* range = allocator_.live_ranges()[operand_index]; | 1484 const LiveRange* range = allocator_.live_ranges()[operand_index]; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 } | 1635 } |
| 1639 | 1636 |
| 1640 // Insert all values into the live in sets of all blocks in the loop. | 1637 // Insert all values into the live in sets of all blocks in the loop. |
| 1641 for (int i = block->rpo_number().ToInt() + 1; | 1638 for (int i = block->rpo_number().ToInt() + 1; |
| 1642 i < block->loop_end().ToInt(); ++i) { | 1639 i < block->loop_end().ToInt(); ++i) { |
| 1643 live_in_sets_[i]->Union(*live); | 1640 live_in_sets_[i]->Union(*live); |
| 1644 } | 1641 } |
| 1645 } | 1642 } |
| 1646 } | 1643 } |
| 1647 | 1644 |
| 1648 for (int i = 0; i < live_ranges_.length(); ++i) { | 1645 for (size_t i = 0; i < live_ranges_.size(); ++i) { |
| 1649 if (live_ranges_[i] != NULL) { | 1646 if (live_ranges_[i] != NULL) { |
| 1650 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); | 1647 live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id()); |
| 1651 | 1648 |
| 1652 // TODO(bmeurer): This is a horrible hack to make sure that for constant | 1649 // TODO(bmeurer): This is a horrible hack to make sure that for constant |
| 1653 // live ranges, every use requires the constant to be in a register. | 1650 // live ranges, every use requires the constant to be in a register. |
| 1654 // Without this hack, all uses with "any" policy would get the constant | 1651 // Without this hack, all uses with "any" policy would get the constant |
| 1655 // operand assigned. | 1652 // operand assigned. |
| 1656 LiveRange* range = live_ranges_[i]; | 1653 LiveRange* range = live_ranges_[i]; |
| 1657 if (range->HasAllocatedSpillOperand() && | 1654 if (range->HasAllocatedSpillOperand() && |
| 1658 range->GetSpillOperand()->IsConstant()) { | 1655 range->GetSpillOperand()->IsConstant()) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 | 1705 |
| 1709 | 1706 |
| 1710 void RegisterAllocator::PopulatePointerMaps() { | 1707 void RegisterAllocator::PopulatePointerMaps() { |
| 1711 DCHECK(SafePointsAreInOrder()); | 1708 DCHECK(SafePointsAreInOrder()); |
| 1712 | 1709 |
| 1713 // Iterate over all safe point positions and record a pointer | 1710 // Iterate over all safe point positions and record a pointer |
| 1714 // for all spilled live ranges at this point. | 1711 // for all spilled live ranges at this point. |
| 1715 int last_range_start = 0; | 1712 int last_range_start = 0; |
| 1716 const PointerMapDeque* pointer_maps = code()->pointer_maps(); | 1713 const PointerMapDeque* pointer_maps = code()->pointer_maps(); |
| 1717 PointerMapDeque::const_iterator first_it = pointer_maps->begin(); | 1714 PointerMapDeque::const_iterator first_it = pointer_maps->begin(); |
| 1718 for (int range_idx = 0; range_idx < live_ranges().length(); ++range_idx) { | 1715 for (size_t range_idx = 0; range_idx < live_ranges().size(); ++range_idx) { |
| 1719 LiveRange* range = live_ranges().at(range_idx); | 1716 LiveRange* range = live_ranges().at(range_idx); |
| 1720 if (range == NULL) continue; | 1717 if (range == NULL) continue; |
| 1721 // Iterate over the first parts of multi-part live ranges. | 1718 // Iterate over the first parts of multi-part live ranges. |
| 1722 if (range->parent() != NULL) continue; | 1719 if (range->parent() != NULL) continue; |
| 1723 // Skip non-reference values. | 1720 // Skip non-reference values. |
| 1724 if (!HasTaggedValue(range->id())) continue; | 1721 if (!HasTaggedValue(range->id())) continue; |
| 1725 // Skip empty live ranges. | 1722 // Skip empty live ranges. |
| 1726 if (range->IsEmpty()) continue; | 1723 if (range->IsEmpty()) continue; |
| 1727 | 1724 |
| 1728 // Find the extent of the range and its children. | 1725 // Find the extent of the range and its children. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 void RegisterAllocator::AllocateDoubleRegisters() { | 1796 void RegisterAllocator::AllocateDoubleRegisters() { |
| 1800 num_registers_ = config()->num_aliased_double_registers(); | 1797 num_registers_ = config()->num_aliased_double_registers(); |
| 1801 mode_ = DOUBLE_REGISTERS; | 1798 mode_ = DOUBLE_REGISTERS; |
| 1802 AllocateRegisters(); | 1799 AllocateRegisters(); |
| 1803 } | 1800 } |
| 1804 | 1801 |
| 1805 | 1802 |
| 1806 void RegisterAllocator::AllocateRegisters() { | 1803 void RegisterAllocator::AllocateRegisters() { |
| 1807 DCHECK(unhandled_live_ranges_.is_empty()); | 1804 DCHECK(unhandled_live_ranges_.is_empty()); |
| 1808 | 1805 |
| 1809 for (int i = 0; i < live_ranges_.length(); ++i) { | 1806 for (size_t i = 0; i < live_ranges_.size(); ++i) { |
| 1810 if (live_ranges_[i] != NULL) { | 1807 if (live_ranges_[i] != NULL) { |
| 1811 if (live_ranges_[i]->Kind() == mode_) { | 1808 if (live_ranges_[i]->Kind() == mode_) { |
| 1812 AddToUnhandledUnsorted(live_ranges_[i]); | 1809 AddToUnhandledUnsorted(live_ranges_[i]); |
| 1813 } | 1810 } |
| 1814 } | 1811 } |
| 1815 } | 1812 } |
| 1816 SortUnhandled(); | 1813 SortUnhandled(); |
| 1817 DCHECK(UnhandledIsSorted()); | 1814 DCHECK(UnhandledIsSorted()); |
| 1818 | 1815 |
| 1819 DCHECK(reusable_slots_.is_empty()); | 1816 DCHECK(reusable_slots_.is_empty()); |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2479 } else { | 2476 } else { |
| 2480 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2477 DCHECK(range->Kind() == GENERAL_REGISTERS); |
| 2481 assigned_registers_->Add(reg); | 2478 assigned_registers_->Add(reg); |
| 2482 } | 2479 } |
| 2483 range->set_assigned_register(reg, code_zone()); | 2480 range->set_assigned_register(reg, code_zone()); |
| 2484 } | 2481 } |
| 2485 | 2482 |
| 2486 } // namespace compiler | 2483 } // namespace compiler |
| 2487 } // namespace internal | 2484 } // namespace internal |
| 2488 } // namespace v8 | 2485 } // namespace v8 |
| OLD | NEW |