| 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 2534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2545 DCHECK(!range->spilled()); | 2545 DCHECK(!range->spilled()); |
| 2546 TopLevelLiveRange* first = range->TopLevel(); | 2546 TopLevelLiveRange* first = range->TopLevel(); |
| 2547 TRACE("Spilling live range %d:%d\n", first->vreg(), range->relative_id()); | 2547 TRACE("Spilling live range %d:%d\n", first->vreg(), range->relative_id()); |
| 2548 | 2548 |
| 2549 if (first->HasNoSpillType()) { | 2549 if (first->HasNoSpillType()) { |
| 2550 data()->AssignSpillRangeToLiveRange(first); | 2550 data()->AssignSpillRangeToLiveRange(first); |
| 2551 } | 2551 } |
| 2552 range->Spill(); | 2552 range->Spill(); |
| 2553 } | 2553 } |
| 2554 | 2554 |
| 2555 | 2555 const char* RegisterAllocator::RegisterName(MachineRepresentation rep, |
| 2556 const ZoneVector<TopLevelLiveRange*>& RegisterAllocator::GetFixedRegisters() | 2556 int code) const { |
| 2557 const { | 2557 switch (rep) { |
| 2558 return mode() == FP_REGISTERS ? data()->fixed_double_live_ranges() | 2558 case MachineRepresentation::kFloat32: |
| 2559 : data()->fixed_live_ranges(); | 2559 return data()->config()->GetFloatRegisterName(code); |
| 2560 case MachineRepresentation::kFloat64: |
| 2561 return data()->config()->GetDoubleRegisterName(code); |
| 2562 default: |
| 2563 break; |
| 2564 } |
| 2565 return data()->config()->GetGeneralRegisterName(code); |
| 2560 } | 2566 } |
| 2561 | 2567 |
| 2562 | 2568 |
| 2563 const char* RegisterAllocator::RegisterName(int register_code) const { | |
| 2564 if (mode() == GENERAL_REGISTERS) { | |
| 2565 return data()->config()->GetGeneralRegisterName(register_code); | |
| 2566 } else { | |
| 2567 return data()->config()->GetDoubleRegisterName(register_code); | |
| 2568 } | |
| 2569 } | |
| 2570 | |
| 2571 | |
| 2572 LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, | 2569 LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, |
| 2573 RegisterKind kind, Zone* local_zone) | 2570 RegisterKind kind, Zone* local_zone) |
| 2574 : RegisterAllocator(data, kind), | 2571 : RegisterAllocator(data, kind), |
| 2575 unhandled_live_ranges_(local_zone), | 2572 unhandled_live_ranges_(local_zone), |
| 2576 active_live_ranges_(local_zone), | 2573 active_live_ranges_(local_zone), |
| 2577 inactive_live_ranges_(local_zone) { | 2574 inactive_live_ranges_(local_zone) { |
| 2578 unhandled_live_ranges().reserve( | 2575 unhandled_live_ranges().reserve( |
| 2579 static_cast<size_t>(code()->VirtualRegisterCount() * 2)); | 2576 static_cast<size_t>(code()->VirtualRegisterCount() * 2)); |
| 2580 active_live_ranges().reserve(8); | 2577 active_live_ranges().reserve(8); |
| 2581 inactive_live_ranges().reserve(8); | 2578 inactive_live_ranges().reserve(8); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2599 for (LiveRange* to_add = range; to_add != nullptr; | 2596 for (LiveRange* to_add = range; to_add != nullptr; |
| 2600 to_add = to_add->next()) { | 2597 to_add = to_add->next()) { |
| 2601 if (!to_add->spilled()) { | 2598 if (!to_add->spilled()) { |
| 2602 AddToUnhandledUnsorted(to_add); | 2599 AddToUnhandledUnsorted(to_add); |
| 2603 } | 2600 } |
| 2604 } | 2601 } |
| 2605 } | 2602 } |
| 2606 SortUnhandled(); | 2603 SortUnhandled(); |
| 2607 DCHECK(UnhandledIsSorted()); | 2604 DCHECK(UnhandledIsSorted()); |
| 2608 | 2605 |
| 2609 auto& fixed_ranges = GetFixedRegisters(); | 2606 if (mode() == GENERAL_REGISTERS) { |
| 2610 for (TopLevelLiveRange* current : fixed_ranges) { | 2607 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { |
| 2611 if (current != nullptr) { | 2608 if (current != nullptr) AddToInactive(current); |
| 2612 DCHECK_EQ(mode(), current->kind()); | 2609 } |
| 2613 AddToInactive(current); | 2610 } else { |
| 2611 DCHECK(mode() == FP_REGISTERS); |
| 2612 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { |
| 2613 if (current != nullptr) AddToInactive(current); |
| 2614 } | 2614 } |
| 2615 } | 2615 } |
| 2616 | 2616 |
| 2617 while (!unhandled_live_ranges().empty()) { | 2617 while (!unhandled_live_ranges().empty()) { |
| 2618 DCHECK(UnhandledIsSorted()); | 2618 DCHECK(UnhandledIsSorted()); |
| 2619 LiveRange* current = unhandled_live_ranges().back(); | 2619 LiveRange* current = unhandled_live_ranges().back(); |
| 2620 unhandled_live_ranges().pop_back(); | 2620 unhandled_live_ranges().pop_back(); |
| 2621 DCHECK(UnhandledIsSorted()); | 2621 DCHECK(UnhandledIsSorted()); |
| 2622 LifetimePosition position = current->Start(); | 2622 LifetimePosition position = current->Start(); |
| 2623 #ifdef DEBUG | 2623 #ifdef DEBUG |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2771 | 2771 |
| 2772 void LinearScanAllocator::InactiveToActive(LiveRange* range) { | 2772 void LinearScanAllocator::InactiveToActive(LiveRange* range) { |
| 2773 RemoveElement(&inactive_live_ranges(), range); | 2773 RemoveElement(&inactive_live_ranges(), range); |
| 2774 active_live_ranges().push_back(range); | 2774 active_live_ranges().push_back(range); |
| 2775 TRACE("Moving live range %d:%d from inactive to active\n", | 2775 TRACE("Moving live range %d:%d from inactive to active\n", |
| 2776 range->TopLevel()->vreg(), range->relative_id()); | 2776 range->TopLevel()->vreg(), range->relative_id()); |
| 2777 } | 2777 } |
| 2778 | 2778 |
| 2779 | 2779 |
| 2780 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) { | 2780 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) { |
| 2781 MachineRepresentation rep = current->representation(); |
| 2781 LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters]; | 2782 LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters]; |
| 2782 | 2783 |
| 2783 for (int i = 0; i < num_registers(); i++) { | 2784 for (int i = 0; i < num_registers(); i++) { |
| 2784 free_until_pos[i] = LifetimePosition::MaxPosition(); | 2785 free_until_pos[i] = LifetimePosition::MaxPosition(); |
| 2785 } | 2786 } |
| 2786 | 2787 |
| 2787 for (LiveRange* cur_active : active_live_ranges()) { | 2788 for (LiveRange* cur_active : active_live_ranges()) { |
| 2788 free_until_pos[cur_active->assigned_register()] = | 2789 int cur_reg = cur_active->assigned_register(); |
| 2789 LifetimePosition::GapFromInstructionIndex(0); | 2790 free_until_pos[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); |
| 2790 TRACE("Register %s is free until pos %d (1)\n", | 2791 TRACE("Register %s is free until pos %d (1)\n", |
| 2791 RegisterName(cur_active->assigned_register()), | 2792 RegisterName(cur_active->representation(), cur_reg), |
| 2792 LifetimePosition::GapFromInstructionIndex(0).value()); | 2793 LifetimePosition::GapFromInstructionIndex(0).value()); |
| 2793 } | 2794 } |
| 2794 | 2795 |
| 2795 for (LiveRange* cur_inactive : inactive_live_ranges()) { | 2796 for (LiveRange* cur_inactive : inactive_live_ranges()) { |
| 2796 DCHECK(cur_inactive->End() > current->Start()); | 2797 DCHECK(cur_inactive->End() > current->Start()); |
| 2797 LifetimePosition next_intersection = | 2798 LifetimePosition next_intersection = |
| 2798 cur_inactive->FirstIntersection(current); | 2799 cur_inactive->FirstIntersection(current); |
| 2799 if (!next_intersection.IsValid()) continue; | 2800 if (!next_intersection.IsValid()) continue; |
| 2800 int cur_reg = cur_inactive->assigned_register(); | 2801 int cur_reg = cur_inactive->assigned_register(); |
| 2801 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); | 2802 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); |
| 2802 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), | 2803 TRACE("Register %s is free until pos %d (2)\n", |
| 2804 RegisterName(cur_inactive->representation(), cur_reg), |
| 2803 Min(free_until_pos[cur_reg], next_intersection).value()); | 2805 Min(free_until_pos[cur_reg], next_intersection).value()); |
| 2804 } | 2806 } |
| 2805 | 2807 |
| 2806 int hint_register; | 2808 int hint_register; |
| 2807 if (current->FirstHintPosition(&hint_register) != nullptr) { | 2809 if (current->FirstHintPosition(&hint_register) != nullptr) { |
| 2808 TRACE( | 2810 TRACE( |
| 2809 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", | 2811 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", |
| 2810 RegisterName(hint_register), free_until_pos[hint_register].value(), | 2812 RegisterName(rep, hint_register), free_until_pos[hint_register].value(), |
| 2811 current->TopLevel()->vreg(), current->relative_id(), | 2813 current->TopLevel()->vreg(), current->relative_id(), |
| 2812 current->End().value()); | 2814 current->End().value()); |
| 2813 | 2815 |
| 2814 // The desired register is free until the end of the current live range. | 2816 // The desired register is free until the end of the current live range. |
| 2815 if (free_until_pos[hint_register] >= current->End()) { | 2817 if (free_until_pos[hint_register] >= current->End()) { |
| 2816 TRACE("Assigning preferred reg %s to live range %d:%d\n", | 2818 TRACE("Assigning preferred reg %s to live range %d:%d\n", |
| 2817 RegisterName(hint_register), current->TopLevel()->vreg(), | 2819 RegisterName(rep, hint_register), current->TopLevel()->vreg(), |
| 2818 current->relative_id()); | 2820 current->relative_id()); |
| 2819 SetLiveRangeAssignedRegister(current, hint_register); | 2821 SetLiveRangeAssignedRegister(current, hint_register); |
| 2820 return true; | 2822 return true; |
| 2821 } | 2823 } |
| 2822 } | 2824 } |
| 2823 | 2825 |
| 2824 // Find the register which stays free for the longest time. | 2826 // Find the register which stays free for the longest time. |
| 2825 int reg = allocatable_register_code(0); | 2827 int reg = allocatable_register_code(0); |
| 2826 for (int i = 1; i < num_allocatable_registers(); ++i) { | 2828 for (int i = 1; i < num_allocatable_registers(); ++i) { |
| 2827 int code = allocatable_register_code(i); | 2829 int code = allocatable_register_code(i); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2840 if (pos < current->End()) { | 2842 if (pos < current->End()) { |
| 2841 // Register reg is available at the range start but becomes blocked before | 2843 // Register reg is available at the range start but becomes blocked before |
| 2842 // the range end. Split current at position where it becomes blocked. | 2844 // the range end. Split current at position where it becomes blocked. |
| 2843 LiveRange* tail = SplitRangeAt(current, pos); | 2845 LiveRange* tail = SplitRangeAt(current, pos); |
| 2844 AddToUnhandledSorted(tail); | 2846 AddToUnhandledSorted(tail); |
| 2845 } | 2847 } |
| 2846 | 2848 |
| 2847 // Register reg is available at the range start and is free until | 2849 // Register reg is available at the range start and is free until |
| 2848 // the range end. | 2850 // the range end. |
| 2849 DCHECK(pos >= current->End()); | 2851 DCHECK(pos >= current->End()); |
| 2850 TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(reg), | 2852 TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(rep, reg), |
| 2851 current->TopLevel()->vreg(), current->relative_id()); | 2853 current->TopLevel()->vreg(), current->relative_id()); |
| 2852 SetLiveRangeAssignedRegister(current, reg); | 2854 SetLiveRangeAssignedRegister(current, reg); |
| 2853 | 2855 |
| 2854 return true; | 2856 return true; |
| 2855 } | 2857 } |
| 2856 | 2858 |
| 2857 | 2859 |
| 2858 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { | 2860 void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { |
| 2859 UsePosition* register_use = current->NextRegisterPosition(current->Start()); | 2861 UsePosition* register_use = current->NextRegisterPosition(current->Start()); |
| 2860 if (register_use == nullptr) { | 2862 if (register_use == nullptr) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2925 if (block_pos[reg] < current->End()) { | 2927 if (block_pos[reg] < current->End()) { |
| 2926 // Register becomes blocked before the current range end. Split before that | 2928 // Register becomes blocked before the current range end. Split before that |
| 2927 // position. | 2929 // position. |
| 2928 LiveRange* tail = | 2930 LiveRange* tail = |
| 2929 SplitBetween(current, current->Start(), block_pos[reg].Start()); | 2931 SplitBetween(current, current->Start(), block_pos[reg].Start()); |
| 2930 AddToUnhandledSorted(tail); | 2932 AddToUnhandledSorted(tail); |
| 2931 } | 2933 } |
| 2932 | 2934 |
| 2933 // Register reg is not blocked for the whole range. | 2935 // Register reg is not blocked for the whole range. |
| 2934 DCHECK(block_pos[reg] >= current->End()); | 2936 DCHECK(block_pos[reg] >= current->End()); |
| 2935 TRACE("Assigning blocked reg %s to live range %d:%d\n", RegisterName(reg), | 2937 TRACE("Assigning blocked reg %s to live range %d:%d\n", |
| 2938 RegisterName(current->representation(), reg), |
| 2936 current->TopLevel()->vreg(), current->relative_id()); | 2939 current->TopLevel()->vreg(), current->relative_id()); |
| 2937 SetLiveRangeAssignedRegister(current, reg); | 2940 SetLiveRangeAssignedRegister(current, reg); |
| 2938 | 2941 |
| 2939 // This register was not free. Thus we need to find and spill | 2942 // This register was not free. Thus we need to find and spill |
| 2940 // parts of active and inactive live regions that use the same register | 2943 // parts of active and inactive live regions that use the same register |
| 2941 // at the same lifetime positions as current. | 2944 // at the same lifetime positions as current. |
| 2942 SplitAndSpillIntersecting(current); | 2945 SplitAndSpillIntersecting(current); |
| 2943 } | 2946 } |
| 2944 | 2947 |
| 2945 | 2948 |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3632 } | 3635 } |
| 3633 } | 3636 } |
| 3634 } | 3637 } |
| 3635 } | 3638 } |
| 3636 } | 3639 } |
| 3637 | 3640 |
| 3638 | 3641 |
| 3639 } // namespace compiler | 3642 } // namespace compiler |
| 3640 } // namespace internal | 3643 } // namespace internal |
| 3641 } // namespace v8 | 3644 } // namespace v8 |
| OLD | NEW |