| 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 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 local_zone()), | 540 local_zone()), |
| 541 fixed_double_live_ranges_(this->config()->num_double_registers(), NULL, | 541 fixed_double_live_ranges_(this->config()->num_double_registers(), NULL, |
| 542 local_zone()), | 542 local_zone()), |
| 543 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, local_zone()), | 543 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, local_zone()), |
| 544 active_live_ranges_(8, local_zone()), | 544 active_live_ranges_(8, local_zone()), |
| 545 inactive_live_ranges_(8, local_zone()), | 545 inactive_live_ranges_(8, local_zone()), |
| 546 reusable_slots_(8, local_zone()), | 546 reusable_slots_(8, local_zone()), |
| 547 spill_ranges_(8, local_zone()), | 547 spill_ranges_(8, local_zone()), |
| 548 mode_(UNALLOCATED_REGISTERS), | 548 mode_(UNALLOCATED_REGISTERS), |
| 549 num_registers_(-1), | 549 num_registers_(-1), |
| 550 first_register_to_try_(0), |
| 550 allocation_ok_(true) { | 551 allocation_ok_(true) { |
| 551 DCHECK(this->config()->num_general_registers() <= | 552 DCHECK(this->config()->num_general_registers() <= |
| 552 RegisterConfiguration::kMaxGeneralRegisters); | 553 RegisterConfiguration::kMaxGeneralRegisters); |
| 553 DCHECK(this->config()->num_double_registers() <= | 554 DCHECK(this->config()->num_double_registers() <= |
| 554 RegisterConfiguration::kMaxDoubleRegisters); | 555 RegisterConfiguration::kMaxDoubleRegisters); |
| 555 // TryAllocateFreeReg and AllocateBlockedReg assume this | 556 // TryAllocateFreeReg and AllocateBlockedReg assume this |
| 556 // when allocating local arrays. | 557 // when allocating local arrays. |
| 557 DCHECK(this->config()->num_double_registers() >= | 558 DCHECK(this->config()->num_double_registers() >= |
| 558 this->config()->num_general_registers()); | 559 this->config()->num_general_registers()); |
| 559 assigned_registers_ = | 560 assigned_registers_ = |
| (...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2054 | 2055 |
| 2055 | 2056 |
| 2056 void RegisterAllocator::InactiveToActive(LiveRange* range) { | 2057 void RegisterAllocator::InactiveToActive(LiveRange* range) { |
| 2057 DCHECK(inactive_live_ranges_.Contains(range)); | 2058 DCHECK(inactive_live_ranges_.Contains(range)); |
| 2058 inactive_live_ranges_.RemoveElement(range); | 2059 inactive_live_ranges_.RemoveElement(range); |
| 2059 active_live_ranges_.Add(range, local_zone()); | 2060 active_live_ranges_.Add(range, local_zone()); |
| 2060 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); | 2061 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); |
| 2061 } | 2062 } |
| 2062 | 2063 |
| 2063 | 2064 |
| 2065 // Pick the index of the maximum position, starting at offset start. |
| 2066 static int MaximalIndex(const LifetimePosition* positions, const uint8_t start, |
| 2067 const int count) { |
| 2068 int reg = start % count; |
| 2069 for (int i = 1; i < count; ++i) { |
| 2070 int index = (i + start) % count; |
| 2071 if (positions[index].Value() > positions[reg].Value()) { |
| 2072 reg = index; |
| 2073 } |
| 2074 } |
| 2075 return reg; |
| 2076 } |
| 2077 |
| 2078 |
| 2064 bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) { | 2079 bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) { |
| 2065 LifetimePosition free_until_pos[RegisterConfiguration::kMaxDoubleRegisters]; | 2080 LifetimePosition free_until_pos[RegisterConfiguration::kMaxDoubleRegisters]; |
| 2066 | 2081 |
| 2067 for (int i = 0; i < num_registers_; i++) { | 2082 for (int i = 0; i < num_registers_; i++) { |
| 2068 free_until_pos[i] = LifetimePosition::MaxPosition(); | 2083 free_until_pos[i] = LifetimePosition::MaxPosition(); |
| 2069 } | 2084 } |
| 2070 | 2085 |
| 2071 for (int i = 0; i < active_live_ranges_.length(); ++i) { | 2086 for (int i = 0; i < active_live_ranges_.length(); ++i) { |
| 2072 LiveRange* cur_active = active_live_ranges_.at(i); | 2087 LiveRange* cur_active = active_live_ranges_.at(i); |
| 2073 free_until_pos[cur_active->assigned_register()] = | 2088 free_until_pos[cur_active->assigned_register()] = |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2095 // The desired register is free until the end of the current live range. | 2110 // The desired register is free until the end of the current live range. |
| 2096 if (free_until_pos[register_index].Value() >= current->End().Value()) { | 2111 if (free_until_pos[register_index].Value() >= current->End().Value()) { |
| 2097 TraceAlloc("Assigning preferred reg %s to live range %d\n", | 2112 TraceAlloc("Assigning preferred reg %s to live range %d\n", |
| 2098 RegisterName(register_index), current->id()); | 2113 RegisterName(register_index), current->id()); |
| 2099 SetLiveRangeAssignedRegister(current, register_index); | 2114 SetLiveRangeAssignedRegister(current, register_index); |
| 2100 return true; | 2115 return true; |
| 2101 } | 2116 } |
| 2102 } | 2117 } |
| 2103 | 2118 |
| 2104 // Find the register which stays free for the longest time. | 2119 // Find the register which stays free for the longest time. |
| 2105 int reg = 0; | 2120 int reg = |
| 2106 for (int i = 1; i < RegisterCount(); ++i) { | 2121 MaximalIndex(free_until_pos, first_register_to_try_++, RegisterCount()); |
| 2107 if (free_until_pos[i].Value() > free_until_pos[reg].Value()) { | |
| 2108 reg = i; | |
| 2109 } | |
| 2110 } | |
| 2111 | |
| 2112 LifetimePosition pos = free_until_pos[reg]; | 2122 LifetimePosition pos = free_until_pos[reg]; |
| 2113 | 2123 |
| 2114 if (pos.Value() <= current->Start().Value()) { | 2124 if (pos.Value() <= current->Start().Value()) { |
| 2115 // All registers are blocked. | 2125 // All registers are blocked. |
| 2116 return false; | 2126 return false; |
| 2117 } | 2127 } |
| 2118 | 2128 |
| 2119 if (pos.Value() < current->End().Value()) { | 2129 if (pos.Value() < current->End().Value()) { |
| 2120 // Register reg is available at the range start but becomes blocked before | 2130 // Register reg is available at the range start but becomes blocked before |
| 2121 // the range end. Split current at position where it becomes blocked. | 2131 // the range end. Split current at position where it becomes blocked. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2176 if (!next_intersection.IsValid()) continue; | 2186 if (!next_intersection.IsValid()) continue; |
| 2177 int cur_reg = range->assigned_register(); | 2187 int cur_reg = range->assigned_register(); |
| 2178 if (range->IsFixed()) { | 2188 if (range->IsFixed()) { |
| 2179 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); | 2189 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); |
| 2180 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); | 2190 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); |
| 2181 } else { | 2191 } else { |
| 2182 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); | 2192 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); |
| 2183 } | 2193 } |
| 2184 } | 2194 } |
| 2185 | 2195 |
| 2186 int reg = 0; | 2196 int reg = MaximalIndex(use_pos, first_register_to_try_++, RegisterCount()); |
| 2187 for (int i = 1; i < RegisterCount(); ++i) { | |
| 2188 if (use_pos[i].Value() > use_pos[reg].Value()) { | |
| 2189 reg = i; | |
| 2190 } | |
| 2191 } | |
| 2192 | |
| 2193 LifetimePosition pos = use_pos[reg]; | 2197 LifetimePosition pos = use_pos[reg]; |
| 2194 | 2198 |
| 2195 if (pos.Value() < register_use->pos().Value()) { | 2199 if (pos.Value() < register_use->pos().Value()) { |
| 2196 // All registers are blocked before the first use that requires a register. | 2200 // All registers are blocked before the first use that requires a register. |
| 2197 // Spill starting part of live range up to that use. | 2201 // Spill starting part of live range up to that use. |
| 2198 SpillBetween(current, current->Start(), register_use->pos()); | 2202 SpillBetween(current, current->Start(), register_use->pos()); |
| 2199 return; | 2203 return; |
| 2200 } | 2204 } |
| 2201 | 2205 |
| 2202 if (block_pos[reg].Value() < current->End().Value()) { | 2206 if (block_pos[reg].Value() < current->End().Value()) { |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2479 } else { | 2483 } else { |
| 2480 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2484 DCHECK(range->Kind() == GENERAL_REGISTERS); |
| 2481 assigned_registers_->Add(reg); | 2485 assigned_registers_->Add(reg); |
| 2482 } | 2486 } |
| 2483 range->set_assigned_register(reg, code_zone()); | 2487 range->set_assigned_register(reg, code_zone()); |
| 2484 } | 2488 } |
| 2485 | 2489 |
| 2486 } | 2490 } |
| 2487 } | 2491 } |
| 2488 } // namespace v8::internal::compiler | 2492 } // namespace v8::internal::compiler |
| OLD | NEW |