Chromium Code Reviews| 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(); | |
|
titzer
2016/03/04 19:43:59
I think you can simplify this code a bit.
E.g. ju
Mircea Trofin
2016/03/04 20:02:00
Done.
| |
| 2345 if (first->next() == nullptr) continue; | |
| 2346 | |
| 2347 for (const UseInterval* i = first; i != nullptr; i = i->next()) { | |
| 2348 if (i != first) { | |
| 2349 // Except for the first interval, the other intevals must start at | |
| 2350 // a block boundary, otherwise data wouldn't flow to them. | |
| 2351 DCHECK(IntervalStartsAtBlockBoundary(i)); | |
| 2352 // The last instruction of the predecessors of the block the interval | |
| 2353 // starts must be covered by the range. | |
| 2354 DCHECK(IntervalPredecessorsCoveredByRange(i, current)); | |
| 2355 } | |
| 2356 if (i->next() != nullptr) { | |
| 2357 // Consecutive intervals should not end and start in the same block, | |
| 2358 // otherwise the intervals should have been joined, because the | |
| 2359 // variable is live throughout that block. | |
| 2360 DCHECK(NextIntervalStartsInDifferenbBlocks(i)); | |
| 2361 } | |
| 2362 } | |
| 2363 } | |
| 2341 } | 2364 } |
| 2342 } | 2365 } |
| 2343 | 2366 |
| 2367 bool LiveRangeBuilder::IntervalStartsAtBlockBoundary( | |
| 2368 const UseInterval* interval) const { | |
| 2369 LifetimePosition start = interval->start(); | |
| 2370 if (!start.IsFullStart()) return false; | |
| 2371 int instruction_index = start.ToInstructionIndex(); | |
| 2372 const InstructionBlock* block = | |
| 2373 data()->code()->GetInstructionBlock(instruction_index); | |
| 2374 return block->first_instruction_index() == instruction_index; | |
| 2375 } | |
| 2376 | |
| 2377 bool LiveRangeBuilder::IntervalPredecessorsCoveredByRange( | |
| 2378 const UseInterval* interval, const TopLevelLiveRange* range) const { | |
| 2379 LifetimePosition start = interval->start(); | |
| 2380 int instruction_index = start.ToInstructionIndex(); | |
| 2381 const InstructionBlock* block = | |
| 2382 data()->code()->GetInstructionBlock(instruction_index); | |
| 2383 for (RpoNumber pred_index : block->predecessors()) { | |
| 2384 const InstructionBlock* predecessor = | |
| 2385 data()->code()->InstructionBlockAt(pred_index); | |
| 2386 LifetimePosition last_pos = LifetimePosition::GapFromInstructionIndex( | |
| 2387 predecessor->last_instruction_index()); | |
| 2388 last_pos = last_pos.NextStart().End(); | |
| 2389 if (!range->Covers(last_pos)) return false; | |
| 2390 } | |
| 2391 return true; | |
| 2392 } | |
| 2393 | |
| 2394 bool LiveRangeBuilder::NextIntervalStartsInDifferenbBlocks( | |
| 2395 const UseInterval* interval) const { | |
| 2396 DCHECK_NOT_NULL(interval->next()); | |
| 2397 LifetimePosition end = interval->end(); | |
| 2398 LifetimePosition next_start = interval->next()->start(); | |
| 2399 const InstructionBlock* block = | |
| 2400 data()->code()->GetInstructionBlock(end.ToInstructionIndex()); | |
| 2401 const InstructionBlock* next_block = | |
| 2402 data()->code()->GetInstructionBlock(next_start.ToInstructionIndex()); | |
| 2403 return block->rpo_number() < next_block->rpo_number(); | |
| 2404 } | |
| 2344 | 2405 |
| 2345 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, | 2406 RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, |
| 2346 RegisterKind kind) | 2407 RegisterKind kind) |
| 2347 : data_(data), | 2408 : data_(data), |
| 2348 mode_(kind), | 2409 mode_(kind), |
| 2349 num_registers_(GetRegisterCount(data->config(), kind)), | 2410 num_registers_(GetRegisterCount(data->config(), kind)), |
| 2350 num_allocatable_registers_( | 2411 num_allocatable_registers_( |
| 2351 GetAllocatableRegisterCount(data->config(), kind)), | 2412 GetAllocatableRegisterCount(data->config(), kind)), |
| 2352 allocatable_register_codes_( | 2413 allocatable_register_codes_( |
| 2353 GetAllocatableRegisterCodes(data->config(), kind)) {} | 2414 GetAllocatableRegisterCodes(data->config(), kind)) {} |
| (...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3594 spill_operand); | 3655 spill_operand); |
| 3595 } | 3656 } |
| 3596 } | 3657 } |
| 3597 } | 3658 } |
| 3598 } | 3659 } |
| 3599 | 3660 |
| 3600 | 3661 |
| 3601 } // namespace compiler | 3662 } // namespace compiler |
| 3602 } // namespace internal | 3663 } // namespace internal |
| 3603 } // namespace v8 | 3664 } // namespace v8 |
| OLD | NEW |