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 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 if (output->IsStackSlot()) { | 1071 if (output->IsStackSlot()) { |
1072 DCHECK(output->index() < 0); | 1072 DCHECK(output->index() < 0); |
1073 range->SetSpillOperand(output); | 1073 range->SetSpillOperand(output); |
1074 range->SetSpillStartIndex(end); | 1074 range->SetSpillStartIndex(end); |
1075 assigned = true; | 1075 assigned = true; |
1076 } | 1076 } |
1077 | 1077 |
1078 for (auto succ : block->successors()) { | 1078 for (auto succ : block->successors()) { |
1079 const InstructionBlock* successor = code()->InstructionBlockAt(succ); | 1079 const InstructionBlock* successor = code()->InstructionBlockAt(succ); |
1080 DCHECK(successor->PredecessorCount() == 1); | 1080 DCHECK(successor->PredecessorCount() == 1); |
1081 int gap_index = successor->first_instruction_index() + 1; | 1081 int gap_index = successor->first_instruction_index(); |
1082 DCHECK(code()->IsGapAt(gap_index)); | 1082 DCHECK(code()->IsGapAt(gap_index)); |
1083 | 1083 |
1084 // Create an unconstrained operand for the same virtual register | 1084 // Create an unconstrained operand for the same virtual register |
1085 // and insert a gap move from the fixed output to the operand. | 1085 // and insert a gap move from the fixed output to the operand. |
1086 UnallocatedOperand* output_copy = | 1086 UnallocatedOperand* output_copy = |
1087 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); | 1087 new (code_zone()) UnallocatedOperand(UnallocatedOperand::ANY); |
1088 output_copy->set_virtual_register(output_vreg); | 1088 output_copy->set_virtual_register(output_vreg); |
1089 | 1089 |
1090 AddGapMove(gap_index, GapInstruction::START, output, output_copy); | 1090 AddGapMove(gap_index, GapInstruction::START, output, output_copy); |
1091 } | 1091 } |
1092 } | 1092 } |
1093 | 1093 |
1094 if (!assigned) { | 1094 if (!assigned) { |
1095 for (auto succ : block->successors()) { | 1095 for (auto succ : block->successors()) { |
1096 const InstructionBlock* successor = code()->InstructionBlockAt(succ); | 1096 const InstructionBlock* successor = code()->InstructionBlockAt(succ); |
1097 DCHECK(successor->PredecessorCount() == 1); | 1097 DCHECK(successor->PredecessorCount() == 1); |
1098 int gap_index = successor->first_instruction_index() + 1; | 1098 int gap_index = successor->first_instruction_index(); |
1099 range->SpillAtDefinition(local_zone(), gap_index, output); | 1099 range->SpillAtDefinition(local_zone(), gap_index, output); |
1100 range->SetSpillStartIndex(gap_index); | 1100 range->SetSpillStartIndex(gap_index); |
1101 } | 1101 } |
1102 } | 1102 } |
1103 } | 1103 } |
1104 } | 1104 } |
1105 | 1105 |
1106 | 1106 |
1107 void RegisterAllocator::MeetConstraintsBetween(Instruction* first, | 1107 void RegisterAllocator::MeetConstraintsBetween(Instruction* first, |
1108 Instruction* second, | 1108 Instruction* second, |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 InactiveToHandled(range); | 2369 InactiveToHandled(range); |
2370 --i; | 2370 --i; |
2371 } | 2371 } |
2372 } | 2372 } |
2373 } | 2373 } |
2374 } | 2374 } |
2375 | 2375 |
2376 | 2376 |
2377 bool RegisterAllocator::IsBlockBoundary(LifetimePosition pos) { | 2377 bool RegisterAllocator::IsBlockBoundary(LifetimePosition pos) { |
2378 return pos.IsInstructionStart() && | 2378 return pos.IsInstructionStart() && |
2379 InstructionAt(pos.InstructionIndex())->IsBlockStart(); | 2379 code()->GetInstructionBlock(pos.InstructionIndex())->code_start() == |
| 2380 pos.InstructionIndex(); |
2380 } | 2381 } |
2381 | 2382 |
2382 | 2383 |
2383 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, | 2384 LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, |
2384 LifetimePosition pos) { | 2385 LifetimePosition pos) { |
2385 DCHECK(!range->IsFixed()); | 2386 DCHECK(!range->IsFixed()); |
2386 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); | 2387 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); |
2387 | 2388 |
2388 if (pos.Value() <= range->Start().Value()) return range; | 2389 if (pos.Value() <= range->Start().Value()) return range; |
2389 | 2390 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2467 LifetimePosition until, | 2468 LifetimePosition until, |
2468 LifetimePosition end) { | 2469 LifetimePosition end) { |
2469 CHECK(start.Value() < end.Value()); | 2470 CHECK(start.Value() < end.Value()); |
2470 auto second_part = SplitRangeAt(range, start); | 2471 auto second_part = SplitRangeAt(range, start); |
2471 if (!AllocationOk()) return; | 2472 if (!AllocationOk()) return; |
2472 | 2473 |
2473 if (second_part->Start().Value() < end.Value()) { | 2474 if (second_part->Start().Value() < end.Value()) { |
2474 // The split result intersects with [start, end[. | 2475 // The split result intersects with [start, end[. |
2475 // Split it at position between ]start+1, end[, spill the middle part | 2476 // Split it at position between ]start+1, end[, spill the middle part |
2476 // and put the rest to unhandled. | 2477 // and put the rest to unhandled. |
| 2478 auto third_part_end = end.PrevInstruction().InstructionEnd(); |
| 2479 if (IsBlockBoundary(end.InstructionStart())) { |
| 2480 third_part_end = end.InstructionStart(); |
| 2481 } |
2477 auto third_part = SplitBetween( | 2482 auto third_part = SplitBetween( |
2478 second_part, Max(second_part->Start().InstructionEnd(), until), | 2483 second_part, Max(second_part->Start().InstructionEnd(), until), |
2479 end.PrevInstruction().InstructionEnd()); | 2484 third_part_end); |
2480 if (!AllocationOk()) return; | 2485 if (!AllocationOk()) return; |
2481 | 2486 |
2482 DCHECK(third_part != second_part); | 2487 DCHECK(third_part != second_part); |
2483 | 2488 |
2484 Spill(second_part); | 2489 Spill(second_part); |
2485 AddToUnhandledSorted(third_part); | 2490 AddToUnhandledSorted(third_part); |
2486 } else { | 2491 } else { |
2487 // The split result does not intersect with [start, end[. | 2492 // The split result does not intersect with [start, end[. |
2488 // Nothing to spill. Just put it to unhandled as whole. | 2493 // Nothing to spill. Just put it to unhandled as whole. |
2489 AddToUnhandledSorted(second_part); | 2494 AddToUnhandledSorted(second_part); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2539 } else { | 2544 } else { |
2540 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2545 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2541 assigned_registers_->Add(reg); | 2546 assigned_registers_->Add(reg); |
2542 } | 2547 } |
2543 range->set_assigned_register(reg, code_zone()); | 2548 range->set_assigned_register(reg, code_zone()); |
2544 } | 2549 } |
2545 | 2550 |
2546 } // namespace compiler | 2551 } // namespace compiler |
2547 } // namespace internal | 2552 } // namespace internal |
2548 } // namespace v8 | 2553 } // namespace v8 |
OLD | NEW |