| 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 { | 
| 11 namespace internal { | 11 namespace internal { | 
| 12 namespace compiler { | 12 namespace compiler { | 
| 13 | 13 | 
| 14 #define TRACE(...)                             \ | 14 #define TRACE(...)                             \ | 
| 15   do {                                         \ | 15   do {                                         \ | 
| 16     if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \ | 16     if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \ | 
| 17   } while (false) | 17   } while (false) | 
| 18 | 18 | 
| 19 |  | 
| 20 namespace { | 19 namespace { | 
| 21 | 20 | 
| 22 inline LifetimePosition Min(LifetimePosition a, LifetimePosition b) { | 21 inline LifetimePosition Min(LifetimePosition a, LifetimePosition b) { | 
| 23   return a.Value() < b.Value() ? a : b; | 22   return a.Value() < b.Value() ? a : b; | 
| 24 } | 23 } | 
| 25 | 24 | 
| 26 | 25 | 
| 27 inline LifetimePosition Max(LifetimePosition a, LifetimePosition b) { | 26 inline LifetimePosition Max(LifetimePosition a, LifetimePosition b) { | 
| 28   return a.Value() > b.Value() ? a : b; | 27   return a.Value() > b.Value() ? a : b; | 
| 29 } | 28 } | 
| (...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1458 } | 1457 } | 
| 1459 | 1458 | 
| 1460 | 1459 | 
| 1461 void LiveRangeBuilder::Verify() const { | 1460 void LiveRangeBuilder::Verify() const { | 
| 1462   for (auto current : data()->live_ranges()) { | 1461   for (auto current : data()->live_ranges()) { | 
| 1463     if (current != nullptr) current->Verify(); | 1462     if (current != nullptr) current->Verify(); | 
| 1464   } | 1463   } | 
| 1465 } | 1464 } | 
| 1466 | 1465 | 
| 1467 | 1466 | 
| 1468 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, | 1467 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data) | 
| 1469                                      RegisterKind kind) | 1468     : data_(data) {} | 
| 1470     : data_(data), |  | 
| 1471       mode_(kind), |  | 
| 1472       num_registers_(GetRegisterCount(data->config(), kind)) {} |  | 
| 1473 | 1469 | 
| 1474 | 1470 | 
| 1475 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, | 1471 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, | 
| 1476                                            LifetimePosition pos) { | 1472                                            LifetimePosition pos) { | 
| 1477   DCHECK(!range->IsFixed()); | 1473   DCHECK(!range->IsFixed()); | 
| 1478   TRACE("Splitting live range %d at %d\n", range->id(), pos.Value()); | 1474   TRACE("Splitting live range %d at %d\n", range->id(), pos.Value()); | 
| 1479 | 1475 | 
| 1480   if (pos.Value() <= range->Start().Value()) return range; | 1476   if (pos.Value() <= range->Start().Value()) return range; | 
| 1481 | 1477 | 
| 1482   // We can't properly connect liveranges if splitting occurred at the end | 1478   // We can't properly connect liveranges if splitting occurred at the end | 
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1579   auto first = range->TopLevel(); | 1575   auto first = range->TopLevel(); | 
| 1580   if (first->HasNoSpillType()) { | 1576   if (first->HasNoSpillType()) { | 
| 1581     data()->AssignSpillRangeToLiveRange(first); | 1577     data()->AssignSpillRangeToLiveRange(first); | 
| 1582   } | 1578   } | 
| 1583   range->MakeSpilled(); | 1579   range->MakeSpilled(); | 
| 1584 } | 1580 } | 
| 1585 | 1581 | 
| 1586 | 1582 | 
| 1587 LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, | 1583 LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, | 
| 1588                                          RegisterKind kind, Zone* local_zone) | 1584                                          RegisterKind kind, Zone* local_zone) | 
| 1589     : RegisterAllocator(data, kind), | 1585     : RegisterAllocator(data), | 
|  | 1586       mode_(kind), | 
|  | 1587       num_registers_(GetRegisterCount(data->config(), kind)), | 
| 1590       unhandled_live_ranges_(local_zone), | 1588       unhandled_live_ranges_(local_zone), | 
| 1591       active_live_ranges_(local_zone), | 1589       active_live_ranges_(local_zone), | 
| 1592       inactive_live_ranges_(local_zone) { | 1590       inactive_live_ranges_(local_zone) { | 
| 1593   unhandled_live_ranges().reserve( | 1591   unhandled_live_ranges().reserve( | 
| 1594       static_cast<size_t>(code()->VirtualRegisterCount() * 2)); | 1592       static_cast<size_t>(code()->VirtualRegisterCount() * 2)); | 
| 1595   active_live_ranges().reserve(8); | 1593   active_live_ranges().reserve(8); | 
| 1596   inactive_live_ranges().reserve(8); | 1594   inactive_live_ranges().reserve(8); | 
| 1597   // TryAllocateFreeReg and AllocateBlockedReg assume this | 1595   // TryAllocateFreeReg and AllocateBlockedReg assume this | 
| 1598   // when allocating local arrays. | 1596   // when allocating local arrays. | 
| 1599   DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= | 1597   DCHECK(RegisterConfiguration::kMaxDoubleRegisters >= | 
| 1600          this->data()->config()->num_general_registers()); | 1598          this->data()->config()->num_general_registers()); | 
| 1601 } | 1599 } | 
| 1602 | 1600 | 
| 1603 | 1601 | 
| 1604 void LinearScanAllocator::AllocateRegisters() { | 1602 void LinearScanAllocator::AllocateRegisters() { | 
| 1605   DCHECK(unhandled_live_ranges().empty()); | 1603   DCHECK(unhandled_live_ranges().empty()); | 
| 1606   DCHECK(active_live_ranges().empty()); | 1604   DCHECK(active_live_ranges().empty()); | 
| 1607   DCHECK(inactive_live_ranges().empty()); | 1605   DCHECK(inactive_live_ranges().empty()); | 
| 1608 | 1606 | 
| 1609   for (auto range : data()->live_ranges()) { | 1607   for (auto range : data()->live_ranges()) { | 
| 1610     if (range == nullptr) continue; | 1608     if (range == nullptr) continue; | 
| 1611     if (range->Kind() == mode()) { | 1609     if (range->Kind() == mode_) { | 
| 1612       AddToUnhandledUnsorted(range); | 1610       AddToUnhandledUnsorted(range); | 
| 1613     } | 1611     } | 
| 1614   } | 1612   } | 
| 1615   SortUnhandled(); | 1613   SortUnhandled(); | 
| 1616   DCHECK(UnhandledIsSorted()); | 1614   DCHECK(UnhandledIsSorted()); | 
| 1617 | 1615 | 
| 1618   auto& fixed_ranges = GetFixedRegisters(data(), mode()); | 1616   auto& fixed_ranges = GetFixedRegisters(data(), mode_); | 
| 1619   for (auto current : fixed_ranges) { | 1617   for (auto current : fixed_ranges) { | 
| 1620     if (current != nullptr) { | 1618     if (current != nullptr) { | 
| 1621       DCHECK_EQ(mode(), current->Kind()); | 1619       DCHECK_EQ(mode_, current->Kind()); | 
| 1622       AddToInactive(current); | 1620       AddToInactive(current); | 
| 1623     } | 1621     } | 
| 1624   } | 1622   } | 
| 1625 | 1623 | 
| 1626   while (!unhandled_live_ranges().empty()) { | 1624   while (!unhandled_live_ranges().empty()) { | 
| 1627     DCHECK(UnhandledIsSorted()); | 1625     DCHECK(UnhandledIsSorted()); | 
| 1628     auto current = unhandled_live_ranges().back(); | 1626     auto current = unhandled_live_ranges().back(); | 
| 1629     unhandled_live_ranges().pop_back(); | 1627     unhandled_live_ranges().pop_back(); | 
| 1630     DCHECK(UnhandledIsSorted()); | 1628     DCHECK(UnhandledIsSorted()); | 
| 1631     auto position = current->Start(); | 1629     auto position = current->Start(); | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1684     bool result = TryAllocateFreeReg(current); | 1682     bool result = TryAllocateFreeReg(current); | 
| 1685     if (!result) AllocateBlockedReg(current); | 1683     if (!result) AllocateBlockedReg(current); | 
| 1686     if (current->HasRegisterAssigned()) { | 1684     if (current->HasRegisterAssigned()) { | 
| 1687       AddToActive(current); | 1685       AddToActive(current); | 
| 1688     } | 1686     } | 
| 1689   } | 1687   } | 
| 1690 } | 1688 } | 
| 1691 | 1689 | 
| 1692 | 1690 | 
| 1693 const char* LinearScanAllocator::RegisterName(int allocation_index) const { | 1691 const char* LinearScanAllocator::RegisterName(int allocation_index) const { | 
| 1694   if (mode() == GENERAL_REGISTERS) { | 1692   if (mode_ == GENERAL_REGISTERS) { | 
| 1695     return data()->config()->general_register_name(allocation_index); | 1693     return data()->config()->general_register_name(allocation_index); | 
| 1696   } else { | 1694   } else { | 
| 1697     return data()->config()->double_register_name(allocation_index); | 1695     return data()->config()->double_register_name(allocation_index); | 
| 1698   } | 1696   } | 
| 1699 } | 1697 } | 
| 1700 | 1698 | 
| 1701 | 1699 | 
| 1702 void LinearScanAllocator::AddToActive(LiveRange* range) { | 1700 void LinearScanAllocator::AddToActive(LiveRange* range) { | 
| 1703   TRACE("Add live range %d to active\n", range->id()); | 1701   TRACE("Add live range %d to active\n", range->id()); | 
| 1704   active_live_ranges().push_back(range); | 1702   active_live_ranges().push_back(range); | 
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2114     Spill(second_part); | 2112     Spill(second_part); | 
| 2115     AddToUnhandledSorted(third_part); | 2113     AddToUnhandledSorted(third_part); | 
| 2116   } else { | 2114   } else { | 
| 2117     // The split result does not intersect with [start, end[. | 2115     // The split result does not intersect with [start, end[. | 
| 2118     // Nothing to spill. Just put it to unhandled as whole. | 2116     // Nothing to spill. Just put it to unhandled as whole. | 
| 2119     AddToUnhandledSorted(second_part); | 2117     AddToUnhandledSorted(second_part); | 
| 2120   } | 2118   } | 
| 2121 } | 2119 } | 
| 2122 | 2120 | 
| 2123 | 2121 | 
| 2124 class CoallescedLiveRanges : public ZoneObject { |  | 
| 2125  public: |  | 
| 2126   explicit CoallescedLiveRanges(Zone* zone) : storage_(zone) {} |  | 
| 2127 |  | 
| 2128   LiveRange* Find(UseInterval* query) { |  | 
| 2129     ZoneSplayTree<Config>::Locator locator; |  | 
| 2130 |  | 
| 2131     if (storage_.Find(GetKey(query), &locator)) { |  | 
| 2132       return locator.value(); |  | 
| 2133     } |  | 
| 2134     return nullptr; |  | 
| 2135   } |  | 
| 2136 |  | 
| 2137   // TODO(mtrofin): Change to void returning if we do not care if the interval |  | 
| 2138   // was previously added. |  | 
| 2139   bool Insert(LiveRange* range) { |  | 
| 2140     auto* interval = range->first_interval(); |  | 
| 2141     while (interval != nullptr) { |  | 
| 2142       if (!Insert(interval, range)) return false; |  | 
| 2143       interval = interval->next(); |  | 
| 2144     } |  | 
| 2145     return true; |  | 
| 2146   } |  | 
| 2147 |  | 
| 2148   bool Remove(LiveRange* range) { |  | 
| 2149     bool ret = false; |  | 
| 2150     auto* segment = range->first_interval(); |  | 
| 2151     while (segment != nullptr) { |  | 
| 2152       ret |= Remove(segment); |  | 
| 2153       segment = segment->next(); |  | 
| 2154     } |  | 
| 2155     return ret; |  | 
| 2156   } |  | 
| 2157 |  | 
| 2158   bool IsEmpty() { return storage_.is_empty(); } |  | 
| 2159 |  | 
| 2160  private: |  | 
| 2161   struct Config { |  | 
| 2162     typedef std::pair<int, int> Key; |  | 
| 2163     typedef LiveRange* Value; |  | 
| 2164     static const Key kNoKey; |  | 
| 2165     static Value NoValue() { return nullptr; } |  | 
| 2166     static int Compare(const Key& a, const Key& b) { |  | 
| 2167       if (a.second <= b.first) return -1; |  | 
| 2168       if (a.first >= b.second) return 1; |  | 
| 2169       return 0; |  | 
| 2170     } |  | 
| 2171   }; |  | 
| 2172 |  | 
| 2173   Config::Key GetKey(UseInterval* interval) { |  | 
| 2174     if (interval == nullptr) return std::make_pair(0, 0); |  | 
| 2175     return std::make_pair(interval->start().Value(), interval->end().Value()); |  | 
| 2176   } |  | 
| 2177 |  | 
| 2178   // TODO(mtrofin): Change to void returning if we do not care if the interval |  | 
| 2179   // was previously added. |  | 
| 2180   bool Insert(UseInterval* interval, LiveRange* range) { |  | 
| 2181     ZoneSplayTree<Config>::Locator locator; |  | 
| 2182     bool ret = storage_.Insert(GetKey(interval), &locator); |  | 
| 2183     if (ret) locator.set_value(range); |  | 
| 2184     return ret; |  | 
| 2185   } |  | 
| 2186 |  | 
| 2187   bool Remove(UseInterval* key) { return storage_.Remove(GetKey(key)); } |  | 
| 2188 |  | 
| 2189   ZoneSplayTree<Config> storage_; |  | 
| 2190   DISALLOW_COPY_AND_ASSIGN(CoallescedLiveRanges); |  | 
| 2191 }; |  | 
| 2192 |  | 
| 2193 |  | 
| 2194 const std::pair<int, int> CoallescedLiveRanges::Config::kNoKey = |  | 
| 2195     std::make_pair<int, int>(0, 0); |  | 
| 2196 |  | 
| 2197 |  | 
| 2198 GreedyAllocator::GreedyAllocator(RegisterAllocationData* data, |  | 
| 2199                                  RegisterKind kind, Zone* local_zone) |  | 
| 2200     : RegisterAllocator(data, kind), |  | 
| 2201       allocations_(local_zone), |  | 
| 2202       queue_(local_zone) {} |  | 
| 2203 |  | 
| 2204 |  | 
| 2205 unsigned GreedyAllocator::GetLiveRangeSize(LiveRange* range) { |  | 
| 2206   auto interval = range->first_interval(); |  | 
| 2207   if (interval == nullptr) return 0; |  | 
| 2208 |  | 
| 2209   unsigned size = 0; |  | 
| 2210   while (interval != nullptr) { |  | 
| 2211     size += (interval->end().Value() - interval->start().Value()); |  | 
| 2212     interval = interval->next(); |  | 
| 2213   } |  | 
| 2214 |  | 
| 2215   return size; |  | 
| 2216 } |  | 
| 2217 |  | 
| 2218 |  | 
| 2219 void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) { |  | 
| 2220   allocations_[reg_id]->Insert(range); |  | 
| 2221   if (range->HasRegisterAssigned()) { |  | 
| 2222     DCHECK_EQ(reg_id, range->assigned_register()); |  | 
| 2223     return; |  | 
| 2224   } |  | 
| 2225   range->set_assigned_register(reg_id); |  | 
| 2226 } |  | 
| 2227 |  | 
| 2228 |  | 
| 2229 float GreedyAllocator::CalculateSpillWeight(LiveRange* range) { |  | 
| 2230   if (range->IsFixed()) return std::numeric_limits<float>::max(); |  | 
| 2231 |  | 
| 2232   if (range->FirstHint() != nullptr && range->FirstHint()->IsRegister()) { |  | 
| 2233     return std::numeric_limits<float>::max(); |  | 
| 2234   } |  | 
| 2235 |  | 
| 2236   unsigned use_count = 0; |  | 
| 2237   auto* pos = range->first_pos(); |  | 
| 2238   while (pos != nullptr) { |  | 
| 2239     use_count++; |  | 
| 2240     pos = pos->next(); |  | 
| 2241   } |  | 
| 2242 |  | 
| 2243   // GetLiveRangeSize is DCHECK-ed to not be 0 |  | 
| 2244   unsigned range_size = GetLiveRangeSize(range); |  | 
| 2245   DCHECK_NE(0, range_size); |  | 
| 2246 |  | 
| 2247   return static_cast<float>(use_count) / static_cast<float>(range_size); |  | 
| 2248 } |  | 
| 2249 |  | 
| 2250 |  | 
| 2251 float GreedyAllocator::CalculateMaxSpillWeight( |  | 
| 2252     const ZoneSet<LiveRange*>& ranges) { |  | 
| 2253   float max = 0.0; |  | 
| 2254   for (auto* r : ranges) { |  | 
| 2255     max = std::max(max, CalculateSpillWeight(r)); |  | 
| 2256   } |  | 
| 2257   return max; |  | 
| 2258 } |  | 
| 2259 |  | 
| 2260 |  | 
| 2261 void GreedyAllocator::Evict(LiveRange* range) { |  | 
| 2262   bool removed = allocations_[range->assigned_register()]->Remove(range); |  | 
| 2263   CHECK(removed); |  | 
| 2264 } |  | 
| 2265 |  | 
| 2266 |  | 
| 2267 bool GreedyAllocator::TryAllocatePhysicalRegister( |  | 
| 2268     unsigned reg_id, LiveRange* range, ZoneSet<LiveRange*>* conflicting) { |  | 
| 2269   auto* segment = range->first_interval(); |  | 
| 2270 |  | 
| 2271   auto* alloc_info = allocations_[reg_id]; |  | 
| 2272   while (segment != nullptr) { |  | 
| 2273     if (auto* existing = alloc_info->Find(segment)) { |  | 
| 2274       DCHECK(existing->HasRegisterAssigned()); |  | 
| 2275       conflicting->insert(existing); |  | 
| 2276     } |  | 
| 2277     segment = segment->next(); |  | 
| 2278   } |  | 
| 2279   if (!conflicting->empty()) return false; |  | 
| 2280   // No conflicts means we can safely allocate this register to this range. |  | 
| 2281   AssignRangeToRegister(reg_id, range); |  | 
| 2282   return true; |  | 
| 2283 } |  | 
| 2284 |  | 
| 2285 bool GreedyAllocator::TryAllocate(LiveRange* current, |  | 
| 2286                                   ZoneSet<LiveRange*>* conflicting) { |  | 
| 2287   if (current->HasSpillOperand()) { |  | 
| 2288     Spill(current); |  | 
| 2289     return true; |  | 
| 2290   } |  | 
| 2291   if (current->IsFixed()) { |  | 
| 2292     return TryAllocatePhysicalRegister(current->assigned_register(), current, |  | 
| 2293                                        conflicting); |  | 
| 2294   } |  | 
| 2295 |  | 
| 2296   if (current->HasRegisterAssigned()) { |  | 
| 2297     int reg_id = current->assigned_register(); |  | 
| 2298     return TryAllocatePhysicalRegister(reg_id, current, conflicting); |  | 
| 2299   } |  | 
| 2300 |  | 
| 2301   for (unsigned candidate_reg = 0; candidate_reg < allocations_.size(); |  | 
| 2302        candidate_reg++) { |  | 
| 2303     if (TryAllocatePhysicalRegister(candidate_reg, current, conflicting)) { |  | 
| 2304       conflicting->clear(); |  | 
| 2305       return true; |  | 
| 2306     } |  | 
| 2307   } |  | 
| 2308   return false; |  | 
| 2309 } |  | 
| 2310 |  | 
| 2311 LiveRange* GreedyAllocator::SpillBetweenUntil(LiveRange* range, |  | 
| 2312                                               LifetimePosition start, |  | 
| 2313                                               LifetimePosition until, |  | 
| 2314                                               LifetimePosition end) { |  | 
| 2315   CHECK(start.Value() < end.Value()); |  | 
| 2316   auto second_part = SplitRangeAt(range, start); |  | 
| 2317 |  | 
| 2318   if (second_part->Start().Value() < end.Value()) { |  | 
| 2319     // The split result intersects with [start, end[. |  | 
| 2320     // Split it at position between ]start+1, end[, spill the middle part |  | 
| 2321     // and put the rest to unhandled. |  | 
| 2322     auto third_part_end = end.PrevStart().End(); |  | 
| 2323     if (IsBlockBoundary(code(), end.Start())) { |  | 
| 2324       third_part_end = end.Start(); |  | 
| 2325     } |  | 
| 2326     auto third_part = SplitBetween( |  | 
| 2327         second_part, Max(second_part->Start().End(), until), third_part_end); |  | 
| 2328 |  | 
| 2329     DCHECK(third_part != second_part); |  | 
| 2330 |  | 
| 2331     Spill(second_part); |  | 
| 2332     return third_part; |  | 
| 2333   } else { |  | 
| 2334     // The split result does not intersect with [start, end[. |  | 
| 2335     // Nothing to spill. Just return it for re-processing. |  | 
| 2336     return second_part; |  | 
| 2337   } |  | 
| 2338 } |  | 
| 2339 |  | 
| 2340 |  | 
| 2341 void GreedyAllocator::Enqueue(LiveRange* range) { |  | 
| 2342   if (range == nullptr || range->IsEmpty()) return; |  | 
| 2343   unsigned size = GetLiveRangeSize(range); |  | 
| 2344   queue_.push(std::make_pair(size, range)); |  | 
| 2345 } |  | 
| 2346 |  | 
| 2347 |  | 
| 2348 // TODO(mtrofin): consolidate with identical code segment in |  | 
| 2349 // LinearScanAllocator::AllocateRegisters |  | 
| 2350 bool GreedyAllocator::HandleSpillOperands(LiveRange* range) { |  | 
| 2351   auto position = range->Start(); |  | 
| 2352   TRACE("Processing interval %d start=%d\n", range->id(), position.Value()); |  | 
| 2353 |  | 
| 2354   if (!range->HasNoSpillType()) { |  | 
| 2355     TRACE("Live range %d already has a spill operand\n", range->id()); |  | 
| 2356     auto next_pos = position; |  | 
| 2357     if (next_pos.IsGapPosition()) { |  | 
| 2358       next_pos = next_pos.NextStart(); |  | 
| 2359     } |  | 
| 2360     auto pos = range->NextUsePositionRegisterIsBeneficial(next_pos); |  | 
| 2361     // If the range already has a spill operand and it doesn't need a |  | 
| 2362     // register immediately, split it and spill the first part of the range. |  | 
| 2363     if (pos == nullptr) { |  | 
| 2364       Spill(range); |  | 
| 2365       return true; |  | 
| 2366     } else if (pos->pos().Value() > range->Start().NextStart().Value()) { |  | 
| 2367       // Do not spill live range eagerly if use position that can benefit from |  | 
| 2368       // the register is too close to the start of live range. |  | 
| 2369       auto* reminder = SpillBetweenUntil(range, position, position, pos->pos()); |  | 
| 2370       Enqueue(reminder); |  | 
| 2371       return true; |  | 
| 2372     } |  | 
| 2373   } |  | 
| 2374   return false; |  | 
| 2375   // TODO(mtrofin): Do we need this? |  | 
| 2376   // return (TryReuseSpillForPhi(range)); |  | 
| 2377 } |  | 
| 2378 |  | 
| 2379 |  | 
| 2380 void GreedyAllocator::AllocateRegisters() { |  | 
| 2381   for (auto range : data()->live_ranges()) { |  | 
| 2382     if (range == nullptr) continue; |  | 
| 2383     if (range->Kind() == mode()) { |  | 
| 2384       DCHECK(!range->HasRegisterAssigned() && !range->IsSpilled()); |  | 
| 2385       TRACE("Enqueueing live range %d to priority queue \n", range->id()); |  | 
| 2386       Enqueue(range); |  | 
| 2387     } |  | 
| 2388   } |  | 
| 2389 |  | 
| 2390   allocations_.resize(num_registers()); |  | 
| 2391   auto* zone = data()->allocation_zone(); |  | 
| 2392   for (int i = 0; i < num_registers(); i++) { |  | 
| 2393     allocations_[i] = new (zone) CoallescedLiveRanges(zone); |  | 
| 2394   } |  | 
| 2395 |  | 
| 2396   for (auto* current : GetFixedRegisters(data(), mode())) { |  | 
| 2397     if (current != nullptr) { |  | 
| 2398       DCHECK_EQ(mode(), current->Kind()); |  | 
| 2399       int reg_nr = current->assigned_register(); |  | 
| 2400       bool inserted = allocations_[reg_nr]->Insert(current); |  | 
| 2401       CHECK(inserted); |  | 
| 2402     } |  | 
| 2403   } |  | 
| 2404 |  | 
| 2405   while (!queue_.empty()) { |  | 
| 2406     auto current_pair = queue_.top(); |  | 
| 2407     queue_.pop(); |  | 
| 2408     auto current = current_pair.second; |  | 
| 2409     if (HandleSpillOperands(current)) continue; |  | 
| 2410     ZoneSet<LiveRange*> conflicting(zone); |  | 
| 2411     if (!TryAllocate(current, &conflicting)) { |  | 
| 2412       DCHECK(!conflicting.empty()); |  | 
| 2413       float this_max = CalculateSpillWeight(current); |  | 
| 2414       float max_conflicting = CalculateMaxSpillWeight(conflicting); |  | 
| 2415       if (max_conflicting < this_max) { |  | 
| 2416         for (auto* conflict : conflicting) { |  | 
| 2417           Evict(conflict); |  | 
| 2418           Enqueue(conflict); |  | 
| 2419         } |  | 
| 2420         conflicting.clear(); |  | 
| 2421         bool allocated = TryAllocate(current, &conflicting); |  | 
| 2422         CHECK(allocated); |  | 
| 2423         DCHECK(conflicting.empty()); |  | 
| 2424       } else { |  | 
| 2425         DCHECK(!current->IsFixed() || current->CanBeSpilled(current->Start())); |  | 
| 2426         bool allocated = AllocateBlockedRange(current, conflicting); |  | 
| 2427         CHECK(allocated); |  | 
| 2428       } |  | 
| 2429     } |  | 
| 2430   } |  | 
| 2431 |  | 
| 2432   BitVector* assigned_registers = new (zone) BitVector(num_registers(), zone); |  | 
| 2433   for (size_t i = 0; i < allocations_.size(); ++i) { |  | 
| 2434     if (!allocations_[i]->IsEmpty()) { |  | 
| 2435       assigned_registers->Add(static_cast<int>(i)); |  | 
| 2436     } |  | 
| 2437   } |  | 
| 2438   data()->frame()->SetAllocatedRegisters(assigned_registers); |  | 
| 2439 } |  | 
| 2440 |  | 
| 2441 |  | 
| 2442 bool GreedyAllocator::AllocateBlockedRange( |  | 
| 2443     LiveRange* current, const ZoneSet<LiveRange*>& conflicts) { |  | 
| 2444   auto register_use = current->NextRegisterPosition(current->Start()); |  | 
| 2445   if (register_use == nullptr) { |  | 
| 2446     // There is no use in the current live range that requires a register. |  | 
| 2447     // We can just spill it. |  | 
| 2448     Spill(current); |  | 
| 2449     return true; |  | 
| 2450   } |  | 
| 2451 |  | 
| 2452   auto second_part = SplitRangeAt(current, register_use->pos()); |  | 
| 2453   Spill(second_part); |  | 
| 2454 |  | 
| 2455   return true; |  | 
| 2456 } |  | 
| 2457 |  | 
| 2458 |  | 
| 2459 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} | 2122 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} | 
| 2460 | 2123 | 
| 2461 | 2124 | 
| 2462 void OperandAssigner::AssignSpillSlots() { | 2125 void OperandAssigner::AssignSpillSlots() { | 
| 2463   auto& spill_ranges = data()->spill_ranges(); | 2126   auto& spill_ranges = data()->spill_ranges(); | 
| 2464   // Merge disjoint spill ranges | 2127   // Merge disjoint spill ranges | 
| 2465   for (size_t i = 0; i < spill_ranges.size(); i++) { | 2128   for (size_t i = 0; i < spill_ranges.size(); i++) { | 
| 2466     auto range = spill_ranges[i]; | 2129     auto range = spill_ranges[i]; | 
| 2467     if (range->IsEmpty()) continue; | 2130     if (range->IsEmpty()) continue; | 
| 2468     for (size_t j = i + 1; j < spill_ranges.size(); j++) { | 2131     for (size_t j = i + 1; j < spill_ranges.size(); j++) { | 
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2862       moves = it->first.first; | 2525       moves = it->first.first; | 
| 2863     } | 2526     } | 
| 2864     // Gather all MoveOperands for a single ParallelMove. | 2527     // Gather all MoveOperands for a single ParallelMove. | 
| 2865     auto move = new (code_zone()) MoveOperands(it->first.second, it->second); | 2528     auto move = new (code_zone()) MoveOperands(it->first.second, it->second); | 
| 2866     auto eliminate = moves->PrepareInsertAfter(move); | 2529     auto eliminate = moves->PrepareInsertAfter(move); | 
| 2867     to_insert.push_back(move); | 2530     to_insert.push_back(move); | 
| 2868     if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 2531     if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 
| 2869   } | 2532   } | 
| 2870 } | 2533 } | 
| 2871 | 2534 | 
| 2872 |  | 
| 2873 }  // namespace compiler | 2535 }  // namespace compiler | 
| 2874 }  // namespace internal | 2536 }  // namespace internal | 
| 2875 }  // namespace v8 | 2537 }  // namespace v8 | 
| OLD | NEW | 
|---|