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 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 for (int instr = first; instr <= last;) { | 1554 for (int instr = first; instr <= last;) { |
1555 const InstructionBlock* block = code()->GetInstructionBlock(instr); | 1555 const InstructionBlock* block = code()->GetInstructionBlock(instr); |
1556 if (!block->IsDeferred()) return false; | 1556 if (!block->IsDeferred()) return false; |
1557 instr = block->last_instruction_index() + 1; | 1557 instr = block->last_instruction_index() + 1; |
1558 } | 1558 } |
1559 } | 1559 } |
1560 } | 1560 } |
1561 return true; | 1561 return true; |
1562 } | 1562 } |
1563 | 1563 |
1564 | |
1565 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( | 1564 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( |
1566 TopLevelLiveRange* range) { | 1565 TopLevelLiveRange* range) { |
1567 DCHECK(!range->HasSpillOperand()); | 1566 DCHECK(!range->HasSpillOperand()); |
1568 | 1567 |
1569 SpillRange* spill_range = range->GetAllocatedSpillRange(); | 1568 SpillRange* spill_range = range->GetAllocatedSpillRange(); |
1570 if (spill_range == nullptr) { | 1569 if (spill_range == nullptr) { |
1571 DCHECK(!range->IsSplinter()); | 1570 DCHECK(!range->IsSplinter()); |
1572 spill_range = new (allocation_zone()) SpillRange(range, allocation_zone()); | 1571 spill_range = new (allocation_zone()) SpillRange(range, allocation_zone()); |
1573 } | 1572 } |
1574 range->set_spill_type(TopLevelLiveRange::SpillType::kSpillRange); | 1573 range->set_spill_type(TopLevelLiveRange::SpillType::kSpillRange); |
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2329 if (it == phi_hints_.end()) return; | 2328 if (it == phi_hints_.end()) return; |
2330 DCHECK(!it->second->IsResolved()); | 2329 DCHECK(!it->second->IsResolved()); |
2331 it->second->ResolveHint(use_pos); | 2330 it->second->ResolveHint(use_pos); |
2332 } | 2331 } |
2333 | 2332 |
2334 | 2333 |
2335 void LiveRangeBuilder::Verify() const { | 2334 void LiveRangeBuilder::Verify() const { |
2336 for (auto& hint : phi_hints_) { | 2335 for (auto& hint : phi_hints_) { |
2337 CHECK(hint.second->IsResolved()); | 2336 CHECK(hint.second->IsResolved()); |
2338 } | 2337 } |
2339 for (TopLevelLiveRange* current : data()->live_ranges()) { | 2338 for (const TopLevelLiveRange* current : data()->live_ranges()) { |
2340 if (current != nullptr && !current->IsEmpty()) current->Verify(); | 2339 if (current != nullptr && !current->IsEmpty()) { |
| 2340 // New LiveRanges should not be split. |
| 2341 CHECK_NULL(current->next()); |
| 2342 // General integrity check. |
| 2343 current->Verify(); |
| 2344 const UseInterval* first = current->first_interval(); |
| 2345 if (first->next() == nullptr) continue; |
| 2346 |
| 2347 // Consecutive intervals should not end and start in the same block, |
| 2348 // otherwise the intervals should have been joined, because the |
| 2349 // variable is live throughout that block. |
| 2350 CHECK(NextIntervalStartsInDifferentBlocks(first)); |
| 2351 |
| 2352 for (const UseInterval* i = first->next(); i != nullptr; i = i->next()) { |
| 2353 // Except for the first interval, the other intevals must start at |
| 2354 // a block boundary, otherwise data wouldn't flow to them. |
| 2355 CHECK(IntervalStartsAtBlockBoundary(i)); |
| 2356 // The last instruction of the predecessors of the block the interval |
| 2357 // starts must be covered by the range. |
| 2358 CHECK(IntervalPredecessorsCoveredByRange(i, current)); |
| 2359 if (i->next() != nullptr) { |
| 2360 // Check the consecutive intervals property, except for the last |
| 2361 // interval, where it doesn't apply. |
| 2362 CHECK(NextIntervalStartsInDifferentBlocks(i)); |
| 2363 } |
| 2364 } |
| 2365 } |
2341 } | 2366 } |
2342 } | 2367 } |
2343 | 2368 |
| 2369 bool LiveRangeBuilder::IntervalStartsAtBlockBoundary( |
| 2370 const UseInterval* interval) const { |
| 2371 LifetimePosition start = interval->start(); |
| 2372 if (!start.IsFullStart()) return false; |
| 2373 int instruction_index = start.ToInstructionIndex(); |
| 2374 const InstructionBlock* block = |
| 2375 data()->code()->GetInstructionBlock(instruction_index); |
| 2376 return block->first_instruction_index() == instruction_index; |
| 2377 } |
| 2378 |
| 2379 bool LiveRangeBuilder::IntervalPredecessorsCoveredByRange( |
| 2380 const UseInterval* interval, const TopLevelLiveRange* range) const { |
| 2381 LifetimePosition start = interval->start(); |
| 2382 int instruction_index = start.ToInstructionIndex(); |
| 2383 const InstructionBlock* block = |
| 2384 data()->code()->GetInstructionBlock(instruction_index); |
| 2385 for (RpoNumber pred_index : block->predecessors()) { |
| 2386 const InstructionBlock* predecessor = |
| 2387 data()->code()->InstructionBlockAt(pred_index); |
| 2388 LifetimePosition last_pos = LifetimePosition::GapFromInstructionIndex( |
| 2389 predecessor->last_instruction_index()); |
| 2390 last_pos = last_pos.NextStart().End(); |
| 2391 if (!range->Covers(last_pos)) return false; |
| 2392 } |
| 2393 return true; |
| 2394 } |
| 2395 |
| 2396 bool LiveRangeBuilder::NextIntervalStartsInDifferentBlocks( |
| 2397 const UseInterval* interval) const { |
| 2398 DCHECK_NOT_NULL(interval->next()); |
| 2399 LifetimePosition end = interval->end(); |
| 2400 LifetimePosition next_start = interval->next()->start(); |
| 2401 // Since end is not covered, but the previous position is, move back a |
| 2402 // position |
| 2403 end = end.IsStart() ? end.PrevStart().End() : end.Start(); |
| 2404 int last_covered_index = end.ToInstructionIndex(); |
| 2405 const InstructionBlock* block = |
| 2406 data()->code()->GetInstructionBlock(last_covered_index); |
| 2407 const InstructionBlock* next_block = |
| 2408 data()->code()->GetInstructionBlock(next_start.ToInstructionIndex()); |
| 2409 return block->rpo_number() < next_block->rpo_number(); |
| 2410 } |
2344 | 2411 |
2345 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, | 2412 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, |
2346 RegisterKind kind) | 2413 RegisterKind kind) |
2347 : data_(data), | 2414 : data_(data), |
2348 mode_(kind), | 2415 mode_(kind), |
2349 num_registers_(GetRegisterCount(data->config(), kind)), | 2416 num_registers_(GetRegisterCount(data->config(), kind)), |
2350 num_allocatable_registers_( | 2417 num_allocatable_registers_( |
2351 GetAllocatableRegisterCount(data->config(), kind)), | 2418 GetAllocatableRegisterCount(data->config(), kind)), |
2352 allocatable_register_codes_( | 2419 allocatable_register_codes_( |
2353 GetAllocatableRegisterCodes(data->config(), kind)) {} | 2420 GetAllocatableRegisterCodes(data->config(), kind)) {} |
(...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3594 spill_operand); | 3661 spill_operand); |
3595 } | 3662 } |
3596 } | 3663 } |
3597 } | 3664 } |
3598 } | 3665 } |
3599 | 3666 |
3600 | 3667 |
3601 } // namespace compiler | 3668 } // namespace compiler |
3602 } // namespace internal | 3669 } // namespace internal |
3603 } // namespace v8 | 3670 } // namespace v8 |
OLD | NEW |