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/compiler/linkage.h" | 5 #include "src/compiler/linkage.h" |
| 6 #include "src/compiler/pipeline-statistics.h" | 6 #include "src/compiler/pipeline-statistics.h" |
| 7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
| 8 #include "src/macro-assembler.h" // TODO(dcarney): remove this. | |
| 8 #include "src/string-stream.h" | 9 #include "src/string-stream.h" |
| 9 | 10 |
| 10 namespace v8 { | 11 namespace v8 { |
| 11 namespace internal { | 12 namespace internal { |
| 12 namespace compiler { | 13 namespace compiler { |
| 13 | 14 |
| 14 static inline LifetimePosition Min(LifetimePosition a, LifetimePosition b) { | 15 static inline LifetimePosition Min(LifetimePosition a, LifetimePosition b) { |
| 15 return a.Value() < b.Value() ? a : b; | 16 return a.Value() < b.Value() ? a : b; |
| 16 } | 17 } |
| 17 | 18 |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 if (a == NULL || a->start().Value() > other->End().Value()) break; | 500 if (a == NULL || a->start().Value() > other->End().Value()) break; |
| 500 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); | 501 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); |
| 501 } else { | 502 } else { |
| 502 b = b->next(); | 503 b = b->next(); |
| 503 } | 504 } |
| 504 } | 505 } |
| 505 return LifetimePosition::Invalid(); | 506 return LifetimePosition::Invalid(); |
| 506 } | 507 } |
| 507 | 508 |
| 508 | 509 |
| 509 RegisterAllocator::RegisterAllocator(Zone* local_zone, Frame* frame, | 510 RegisterAllocator::Config RegisterAllocator::PlatformConfig() { |
| 510 InstructionSequence* code, | 511 DCHECK_EQ(Register::kMaxNumAllocatableRegisters, |
| 512 Register::NumAllocatableRegisters()); | |
| 513 Config config; | |
| 514 config.num_general_registers_ = Register::kMaxNumAllocatableRegisters; | |
| 515 config.num_double_registers_ = DoubleRegister::kMaxNumAllocatableRegisters; | |
| 516 config.num_aliased_double_registers_ = | |
| 517 DoubleRegister::NumAllocatableAliasedRegisters(); | |
| 518 config.GeneralRegisterName = Register::AllocationIndexToString; | |
| 519 config.DoubleRegisterName = DoubleRegister::AllocationIndexToString; | |
| 520 return config; | |
| 521 } | |
| 522 | |
| 523 | |
| 524 RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone, | |
| 525 Frame* frame, InstructionSequence* code, | |
| 511 const char* debug_name) | 526 const char* debug_name) |
| 512 : zone_(local_zone), | 527 : zone_(local_zone), |
| 513 frame_(frame), | 528 frame_(frame), |
| 514 code_(code), | 529 code_(code), |
| 515 debug_name_(debug_name), | 530 debug_name_(debug_name), |
| 531 config_(config), | |
| 516 live_in_sets_(code->InstructionBlockCount(), zone()), | 532 live_in_sets_(code->InstructionBlockCount(), zone()), |
| 517 live_ranges_(code->VirtualRegisterCount() * 2, zone()), | 533 live_ranges_(code->VirtualRegisterCount() * 2, zone()), |
| 518 fixed_live_ranges_(NULL), | 534 fixed_live_ranges_(this->config().num_general_registers_, NULL, zone()), |
| 519 fixed_double_live_ranges_(NULL), | 535 fixed_double_live_ranges_(this->config().num_double_registers_, NULL, |
| 536 zone()), | |
| 520 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()), | 537 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()), |
| 521 active_live_ranges_(8, zone()), | 538 active_live_ranges_(8, zone()), |
| 522 inactive_live_ranges_(8, zone()), | 539 inactive_live_ranges_(8, zone()), |
| 523 reusable_slots_(8, zone()), | 540 reusable_slots_(8, zone()), |
| 524 mode_(UNALLOCATED_REGISTERS), | 541 mode_(UNALLOCATED_REGISTERS), |
| 525 num_registers_(-1), | 542 num_registers_(-1), |
| 526 allocation_ok_(true) {} | 543 allocation_ok_(true) {} |
| 527 | 544 |
| 528 | 545 |
| 529 void RegisterAllocator::InitializeLivenessAnalysis() { | 546 void RegisterAllocator::InitializeLivenessAnalysis() { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 while (!iterator.Done()) { | 589 while (!iterator.Done()) { |
| 573 int operand_index = iterator.Current(); | 590 int operand_index = iterator.Current(); |
| 574 LiveRange* range = LiveRangeFor(operand_index); | 591 LiveRange* range = LiveRangeFor(operand_index); |
| 575 range->AddUseInterval(start, end, zone()); | 592 range->AddUseInterval(start, end, zone()); |
| 576 iterator.Advance(); | 593 iterator.Advance(); |
| 577 } | 594 } |
| 578 } | 595 } |
| 579 | 596 |
| 580 | 597 |
| 581 int RegisterAllocator::FixedDoubleLiveRangeID(int index) { | 598 int RegisterAllocator::FixedDoubleLiveRangeID(int index) { |
| 582 return -index - 1 - Register::kMaxNumAllocatableRegisters; | 599 return -index - 1 - config().num_general_registers_; |
| 583 } | 600 } |
| 584 | 601 |
| 585 | 602 |
| 586 InstructionOperand* RegisterAllocator::AllocateFixed( | 603 InstructionOperand* RegisterAllocator::AllocateFixed( |
| 587 UnallocatedOperand* operand, int pos, bool is_tagged) { | 604 UnallocatedOperand* operand, int pos, bool is_tagged) { |
| 588 TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register()); | 605 TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register()); |
| 589 DCHECK(operand->HasFixedPolicy()); | 606 DCHECK(operand->HasFixedPolicy()); |
| 590 if (operand->HasFixedSlotPolicy()) { | 607 if (operand->HasFixedSlotPolicy()) { |
| 591 operand->ConvertTo(InstructionOperand::STACK_SLOT, | 608 operand->ConvertTo(InstructionOperand::STACK_SLOT, |
| 592 operand->fixed_slot_index()); | 609 operand->fixed_slot_index()); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 604 Instruction* instr = InstructionAt(pos); | 621 Instruction* instr = InstructionAt(pos); |
| 605 if (instr->HasPointerMap()) { | 622 if (instr->HasPointerMap()) { |
| 606 instr->pointer_map()->RecordPointer(operand, code_zone()); | 623 instr->pointer_map()->RecordPointer(operand, code_zone()); |
| 607 } | 624 } |
| 608 } | 625 } |
| 609 return operand; | 626 return operand; |
| 610 } | 627 } |
| 611 | 628 |
| 612 | 629 |
| 613 LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) { | 630 LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) { |
| 614 DCHECK(index < Register::kMaxNumAllocatableRegisters); | 631 DCHECK(index < config().num_general_registers_); |
| 615 LiveRange* result = fixed_live_ranges_[index]; | 632 LiveRange* result = fixed_live_ranges_[index]; |
| 616 if (result == NULL) { | 633 if (result == NULL) { |
| 617 // TODO(titzer): add a utility method to allocate a new LiveRange: | 634 // TODO(titzer): add a utility method to allocate a new LiveRange: |
| 618 // The LiveRange object itself can go in this zone, but the | 635 // The LiveRange object itself can go in this zone, but the |
| 619 // InstructionOperand needs | 636 // InstructionOperand needs |
| 620 // to go in the code zone, since it may survive register allocation. | 637 // to go in the code zone, since it may survive register allocation. |
| 621 result = new (zone()) LiveRange(FixedLiveRangeID(index), code_zone()); | 638 result = new (zone()) LiveRange(FixedLiveRangeID(index), code_zone()); |
| 622 DCHECK(result->IsFixed()); | 639 DCHECK(result->IsFixed()); |
| 623 result->kind_ = GENERAL_REGISTERS; | 640 result->kind_ = GENERAL_REGISTERS; |
| 624 SetLiveRangeAssignedRegister(result, index); | 641 SetLiveRangeAssignedRegister(result, index); |
| 625 fixed_live_ranges_[index] = result; | 642 fixed_live_ranges_[index] = result; |
| 626 } | 643 } |
| 627 return result; | 644 return result; |
| 628 } | 645 } |
| 629 | 646 |
| 630 | 647 |
| 631 LiveRange* RegisterAllocator::FixedDoubleLiveRangeFor(int index) { | 648 LiveRange* RegisterAllocator::FixedDoubleLiveRangeFor(int index) { |
| 632 DCHECK(index < DoubleRegister::NumAllocatableAliasedRegisters()); | 649 DCHECK(index < config().num_aliased_double_registers_); |
| 633 LiveRange* result = fixed_double_live_ranges_[index]; | 650 LiveRange* result = fixed_double_live_ranges_[index]; |
| 634 if (result == NULL) { | 651 if (result == NULL) { |
| 635 result = new (zone()) LiveRange(FixedDoubleLiveRangeID(index), code_zone()); | 652 result = new (zone()) LiveRange(FixedDoubleLiveRangeID(index), code_zone()); |
| 636 DCHECK(result->IsFixed()); | 653 DCHECK(result->IsFixed()); |
| 637 result->kind_ = DOUBLE_REGISTERS; | 654 result->kind_ = DOUBLE_REGISTERS; |
| 638 SetLiveRangeAssignedRegister(result, index); | 655 SetLiveRangeAssignedRegister(result, index); |
| 639 fixed_double_live_ranges_[index] = result; | 656 fixed_double_live_ranges_[index] = result; |
| 640 } | 657 } |
| 641 return result; | 658 return result; |
| 642 } | 659 } |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1000 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); | 1017 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); |
| 1001 live->Remove(out_vreg); | 1018 live->Remove(out_vreg); |
| 1002 } else if (output->IsConstant()) { | 1019 } else if (output->IsConstant()) { |
| 1003 int out_vreg = output->index(); | 1020 int out_vreg = output->index(); |
| 1004 live->Remove(out_vreg); | 1021 live->Remove(out_vreg); |
| 1005 } | 1022 } |
| 1006 Define(curr_position, output, NULL); | 1023 Define(curr_position, output, NULL); |
| 1007 } | 1024 } |
| 1008 | 1025 |
| 1009 if (instr->ClobbersRegisters()) { | 1026 if (instr->ClobbersRegisters()) { |
| 1010 for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) { | 1027 for (int i = 0; i < config().num_general_registers_; ++i) { |
| 1011 if (!IsOutputRegisterOf(instr, i)) { | 1028 if (!IsOutputRegisterOf(instr, i)) { |
| 1012 LiveRange* range = FixedLiveRangeFor(i); | 1029 LiveRange* range = FixedLiveRangeFor(i); |
| 1013 range->AddUseInterval(curr_position, curr_position.InstructionEnd(), | 1030 range->AddUseInterval(curr_position, curr_position.InstructionEnd(), |
| 1014 zone()); | 1031 zone()); |
| 1015 } | 1032 } |
| 1016 } | 1033 } |
| 1017 } | 1034 } |
| 1018 | 1035 |
| 1019 if (instr->ClobbersDoubleRegisters()) { | 1036 if (instr->ClobbersDoubleRegisters()) { |
| 1020 for (int i = 0; i < DoubleRegister::NumAllocatableAliasedRegisters(); | 1037 for (int i = 0; i < config().num_aliased_double_registers_; ++i) { |
| 1021 ++i) { | |
| 1022 if (!IsOutputDoubleRegisterOf(instr, i)) { | 1038 if (!IsOutputDoubleRegisterOf(instr, i)) { |
| 1023 LiveRange* range = FixedDoubleLiveRangeFor(i); | 1039 LiveRange* range = FixedDoubleLiveRangeFor(i); |
| 1024 range->AddUseInterval(curr_position, curr_position.InstructionEnd(), | 1040 range->AddUseInterval(curr_position, curr_position.InstructionEnd(), |
| 1025 zone()); | 1041 zone()); |
| 1026 } | 1042 } |
| 1027 } | 1043 } |
| 1028 } | 1044 } |
| 1029 | 1045 |
| 1030 for (size_t i = 0; i < instr->InputCount(); i++) { | 1046 for (size_t i = 0; i < instr->InputCount(); i++) { |
| 1031 InstructionOperand* input = instr->InputAt(i); | 1047 InstructionOperand* input = instr->InputAt(i); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 // We use the phi-ness of some nodes in some later heuristics. | 1112 // We use the phi-ness of some nodes in some later heuristics. |
| 1097 live_range->set_is_phi(true); | 1113 live_range->set_is_phi(true); |
| 1098 if (!block->IsLoopHeader()) { | 1114 if (!block->IsLoopHeader()) { |
| 1099 live_range->set_is_non_loop_phi(true); | 1115 live_range->set_is_non_loop_phi(true); |
| 1100 } | 1116 } |
| 1101 } | 1117 } |
| 1102 } | 1118 } |
| 1103 | 1119 |
| 1104 | 1120 |
| 1105 bool RegisterAllocator::Allocate(PipelineStatistics* stats) { | 1121 bool RegisterAllocator::Allocate(PipelineStatistics* stats) { |
| 1106 assigned_registers_ = new (code_zone()) | 1122 assigned_registers_ = |
| 1107 BitVector(Register::NumAllocatableRegisters(), code_zone()); | 1123 new (code_zone()) BitVector(config().num_general_registers_, code_zone()); |
| 1108 assigned_double_registers_ = new (code_zone()) | 1124 assigned_double_registers_ = new (code_zone()) |
| 1109 BitVector(DoubleRegister::NumAllocatableAliasedRegisters(), code_zone()); | 1125 BitVector(config().num_aliased_double_registers_, code_zone()); |
| 1110 { | 1126 { |
| 1111 PhaseScope phase_scope(stats, "meet register constraints"); | 1127 PhaseScope phase_scope(stats, "meet register constraints"); |
| 1112 MeetRegisterConstraints(); | 1128 MeetRegisterConstraints(); |
| 1113 } | 1129 } |
| 1114 if (!AllocationOk()) return false; | 1130 if (!AllocationOk()) return false; |
| 1115 { | 1131 { |
| 1116 PhaseScope phase_scope(stats, "resolve phis"); | 1132 PhaseScope phase_scope(stats, "resolve phis"); |
| 1117 ResolvePhis(); | 1133 ResolvePhis(); |
| 1118 } | 1134 } |
| 1119 { | 1135 { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1228 } | 1244 } |
| 1229 | 1245 |
| 1230 | 1246 |
| 1231 const InstructionBlock* RegisterAllocator::GetInstructionBlock( | 1247 const InstructionBlock* RegisterAllocator::GetInstructionBlock( |
| 1232 LifetimePosition pos) { | 1248 LifetimePosition pos) { |
| 1233 return code()->GetInstructionBlock(pos.InstructionIndex()); | 1249 return code()->GetInstructionBlock(pos.InstructionIndex()); |
| 1234 } | 1250 } |
| 1235 | 1251 |
| 1236 | 1252 |
| 1237 void RegisterAllocator::ConnectRanges() { | 1253 void RegisterAllocator::ConnectRanges() { |
| 1238 for (int i = 0; i < live_ranges()->length(); ++i) { | 1254 for (int i = 0; i < live_ranges().length(); ++i) { |
| 1239 LiveRange* first_range = live_ranges()->at(i); | 1255 LiveRange* first_range = live_ranges().at(i); |
| 1240 if (first_range == NULL || first_range->parent() != NULL) continue; | 1256 if (first_range == NULL || first_range->parent() != NULL) continue; |
| 1241 | 1257 |
| 1242 LiveRange* second_range = first_range->next(); | 1258 LiveRange* second_range = first_range->next(); |
| 1243 while (second_range != NULL) { | 1259 while (second_range != NULL) { |
| 1244 LifetimePosition pos = second_range->Start(); | 1260 LifetimePosition pos = second_range->Start(); |
| 1245 | 1261 |
| 1246 if (!second_range->IsSpilled()) { | 1262 if (!second_range->IsSpilled()) { |
| 1247 // Add gap move if the two live ranges touch and there is no block | 1263 // Add gap move if the two live ranges touch and there is no block |
| 1248 // boundary. | 1264 // boundary. |
| 1249 if (first_range->End().Value() == pos.Value()) { | 1265 if (first_range->End().Value() == pos.Value()) { |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1430 | 1446 |
| 1431 | 1447 |
| 1432 void RegisterAllocator::PopulatePointerMaps() { | 1448 void RegisterAllocator::PopulatePointerMaps() { |
| 1433 DCHECK(SafePointsAreInOrder()); | 1449 DCHECK(SafePointsAreInOrder()); |
| 1434 | 1450 |
| 1435 // Iterate over all safe point positions and record a pointer | 1451 // Iterate over all safe point positions and record a pointer |
| 1436 // for all spilled live ranges at this point. | 1452 // for all spilled live ranges at this point. |
| 1437 int last_range_start = 0; | 1453 int last_range_start = 0; |
| 1438 const PointerMapDeque* pointer_maps = code()->pointer_maps(); | 1454 const PointerMapDeque* pointer_maps = code()->pointer_maps(); |
| 1439 PointerMapDeque::const_iterator first_it = pointer_maps->begin(); | 1455 PointerMapDeque::const_iterator first_it = pointer_maps->begin(); |
| 1440 for (int range_idx = 0; range_idx < live_ranges()->length(); ++range_idx) { | 1456 for (int range_idx = 0; range_idx < live_ranges().length(); ++range_idx) { |
| 1441 LiveRange* range = live_ranges()->at(range_idx); | 1457 LiveRange* range = live_ranges().at(range_idx); |
| 1442 if (range == NULL) continue; | 1458 if (range == NULL) continue; |
| 1443 // Iterate over the first parts of multi-part live ranges. | 1459 // Iterate over the first parts of multi-part live ranges. |
| 1444 if (range->parent() != NULL) continue; | 1460 if (range->parent() != NULL) continue; |
| 1445 // Skip non-reference values. | 1461 // Skip non-reference values. |
| 1446 if (!HasTaggedValue(range->id())) continue; | 1462 if (!HasTaggedValue(range->id())) continue; |
| 1447 // Skip empty live ranges. | 1463 // Skip empty live ranges. |
| 1448 if (range->IsEmpty()) continue; | 1464 if (range->IsEmpty()) continue; |
| 1449 | 1465 |
| 1450 // Find the extent of the range and its children. | 1466 // Find the extent of the range and its children. |
| 1451 int start = range->Start().InstructionIndex(); | 1467 int start = range->Start().InstructionIndex(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1505 InstructionOperand* operand = cur->CreateAssignedOperand(code_zone()); | 1521 InstructionOperand* operand = cur->CreateAssignedOperand(code_zone()); |
| 1506 DCHECK(!operand->IsStackSlot()); | 1522 DCHECK(!operand->IsStackSlot()); |
| 1507 map->RecordPointer(operand, code_zone()); | 1523 map->RecordPointer(operand, code_zone()); |
| 1508 } | 1524 } |
| 1509 } | 1525 } |
| 1510 } | 1526 } |
| 1511 } | 1527 } |
| 1512 | 1528 |
| 1513 | 1529 |
| 1514 void RegisterAllocator::AllocateGeneralRegisters() { | 1530 void RegisterAllocator::AllocateGeneralRegisters() { |
| 1515 num_registers_ = Register::NumAllocatableRegisters(); | 1531 num_registers_ = config().num_general_registers_; |
| 1516 mode_ = GENERAL_REGISTERS; | 1532 mode_ = GENERAL_REGISTERS; |
| 1517 AllocateRegisters(); | 1533 AllocateRegisters(); |
| 1518 } | 1534 } |
| 1519 | 1535 |
| 1520 | 1536 |
| 1521 void RegisterAllocator::AllocateDoubleRegisters() { | 1537 void RegisterAllocator::AllocateDoubleRegisters() { |
| 1522 num_registers_ = DoubleRegister::NumAllocatableAliasedRegisters(); | 1538 num_registers_ = config().num_aliased_double_registers_; |
| 1523 mode_ = DOUBLE_REGISTERS; | 1539 mode_ = DOUBLE_REGISTERS; |
| 1524 AllocateRegisters(); | 1540 AllocateRegisters(); |
| 1525 } | 1541 } |
| 1526 | 1542 |
| 1527 | 1543 |
| 1528 void RegisterAllocator::AllocateRegisters() { | 1544 void RegisterAllocator::AllocateRegisters() { |
| 1529 DCHECK(unhandled_live_ranges_.is_empty()); | 1545 DCHECK(unhandled_live_ranges_.is_empty()); |
| 1530 | 1546 |
| 1531 for (int i = 0; i < live_ranges_.length(); ++i) { | 1547 for (int i = 0; i < live_ranges_.length(); ++i) { |
| 1532 if (live_ranges_[i] != NULL) { | 1548 if (live_ranges_[i] != NULL) { |
| 1533 if (live_ranges_[i]->Kind() == mode_) { | 1549 if (live_ranges_[i]->Kind() == mode_) { |
| 1534 AddToUnhandledUnsorted(live_ranges_[i]); | 1550 AddToUnhandledUnsorted(live_ranges_[i]); |
| 1535 } | 1551 } |
| 1536 } | 1552 } |
| 1537 } | 1553 } |
| 1538 SortUnhandled(); | 1554 SortUnhandled(); |
| 1539 DCHECK(UnhandledIsSorted()); | 1555 DCHECK(UnhandledIsSorted()); |
| 1540 | 1556 |
| 1541 DCHECK(reusable_slots_.is_empty()); | 1557 DCHECK(reusable_slots_.is_empty()); |
| 1542 DCHECK(active_live_ranges_.is_empty()); | 1558 DCHECK(active_live_ranges_.is_empty()); |
| 1543 DCHECK(inactive_live_ranges_.is_empty()); | 1559 DCHECK(inactive_live_ranges_.is_empty()); |
| 1544 | 1560 |
| 1545 if (mode_ == DOUBLE_REGISTERS) { | 1561 if (mode_ == DOUBLE_REGISTERS) { |
| 1546 for (int i = 0; i < DoubleRegister::NumAllocatableAliasedRegisters(); ++i) { | 1562 for (int i = 0; i < config().num_aliased_double_registers_; ++i) { |
| 1547 LiveRange* current = fixed_double_live_ranges_.at(i); | 1563 LiveRange* current = fixed_double_live_ranges_.at(i); |
| 1548 if (current != NULL) { | 1564 if (current != NULL) { |
| 1549 AddToInactive(current); | 1565 AddToInactive(current); |
| 1550 } | 1566 } |
| 1551 } | 1567 } |
| 1552 } else { | 1568 } else { |
| 1553 DCHECK(mode_ == GENERAL_REGISTERS); | 1569 DCHECK(mode_ == GENERAL_REGISTERS); |
| 1554 for (int i = 0; i < fixed_live_ranges_.length(); ++i) { | 1570 for (auto current : fixed_live_ranges()) { |
| 1555 LiveRange* current = fixed_live_ranges_.at(i); | |
| 1556 if (current != NULL) { | 1571 if (current != NULL) { |
| 1557 AddToInactive(current); | 1572 AddToInactive(current); |
| 1558 } | 1573 } |
| 1559 } | 1574 } |
| 1560 } | 1575 } |
| 1561 | 1576 |
| 1562 while (!unhandled_live_ranges_.is_empty()) { | 1577 while (!unhandled_live_ranges_.is_empty()) { |
| 1563 DCHECK(UnhandledIsSorted()); | 1578 DCHECK(UnhandledIsSorted()); |
| 1564 LiveRange* current = unhandled_live_ranges_.RemoveLast(); | 1579 LiveRange* current = unhandled_live_ranges_.RemoveLast(); |
| 1565 DCHECK(UnhandledIsSorted()); | 1580 DCHECK(UnhandledIsSorted()); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1629 } | 1644 } |
| 1630 | 1645 |
| 1631 reusable_slots_.Rewind(0); | 1646 reusable_slots_.Rewind(0); |
| 1632 active_live_ranges_.Rewind(0); | 1647 active_live_ranges_.Rewind(0); |
| 1633 inactive_live_ranges_.Rewind(0); | 1648 inactive_live_ranges_.Rewind(0); |
| 1634 } | 1649 } |
| 1635 | 1650 |
| 1636 | 1651 |
| 1637 const char* RegisterAllocator::RegisterName(int allocation_index) { | 1652 const char* RegisterAllocator::RegisterName(int allocation_index) { |
| 1638 if (mode_ == GENERAL_REGISTERS) { | 1653 if (mode_ == GENERAL_REGISTERS) { |
| 1639 return Register::AllocationIndexToString(allocation_index); | 1654 return config().GeneralRegisterName(allocation_index); |
| 1640 } else { | 1655 } else { |
| 1641 return DoubleRegister::AllocationIndexToString(allocation_index); | 1656 return config().DoubleRegisterName(allocation_index); |
| 1642 } | 1657 } |
| 1643 } | 1658 } |
| 1644 | 1659 |
| 1645 | 1660 |
| 1646 bool RegisterAllocator::HasTaggedValue(int virtual_register) const { | 1661 bool RegisterAllocator::HasTaggedValue(int virtual_register) const { |
| 1647 return code()->IsReference(virtual_register); | 1662 return code()->IsReference(virtual_register); |
| 1648 } | 1663 } |
| 1649 | 1664 |
| 1650 | 1665 |
| 1651 RegisterKind RegisterAllocator::RequiredRegisterKind( | 1666 RegisterKind RegisterAllocator::RequiredRegisterKind( |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1775 | 1790 |
| 1776 | 1791 |
| 1777 void RegisterAllocator::InactiveToActive(LiveRange* range) { | 1792 void RegisterAllocator::InactiveToActive(LiveRange* range) { |
| 1778 DCHECK(inactive_live_ranges_.Contains(range)); | 1793 DCHECK(inactive_live_ranges_.Contains(range)); |
| 1779 inactive_live_ranges_.RemoveElement(range); | 1794 inactive_live_ranges_.RemoveElement(range); |
| 1780 active_live_ranges_.Add(range, zone()); | 1795 active_live_ranges_.Add(range, zone()); |
| 1781 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); | 1796 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); |
| 1782 } | 1797 } |
| 1783 | 1798 |
| 1784 | 1799 |
| 1785 // TryAllocateFreeReg and AllocateBlockedReg assume this | |
| 1786 // when allocating local arrays. | |
| 1787 STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >= | |
| 1788 Register::kMaxNumAllocatableRegisters); | |
| 1789 | |
| 1790 | |
| 1791 bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) { | 1800 bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) { |
| 1792 LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters]; | 1801 DCHECK(config().num_double_registers_ >= config().num_general_registers_); |
| 1802 // TODO(dcarney): ensure this function in non recursive and allocate space for | |
| 1803 // this in RegisterAllocator. | |
| 1804 LifetimePosition free_until_pos[kMaxDoubleRegisters]; | |
| 1793 | 1805 |
| 1794 for (int i = 0; i < num_registers_; i++) { | 1806 for (int i = 0; i < num_registers_; i++) { |
| 1795 free_until_pos[i] = LifetimePosition::MaxPosition(); | 1807 free_until_pos[i] = LifetimePosition::MaxPosition(); |
| 1796 } | 1808 } |
| 1797 | 1809 |
| 1798 for (int i = 0; i < active_live_ranges_.length(); ++i) { | 1810 for (int i = 0; i < active_live_ranges_.length(); ++i) { |
| 1799 LiveRange* cur_active = active_live_ranges_.at(i); | 1811 LiveRange* cur_active = active_live_ranges_.at(i); |
| 1800 free_until_pos[cur_active->assigned_register()] = | 1812 free_until_pos[cur_active->assigned_register()] = |
| 1801 LifetimePosition::FromInstructionIndex(0); | 1813 LifetimePosition::FromInstructionIndex(0); |
| 1802 } | 1814 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1857 DCHECK(pos.Value() >= current->End().Value()); | 1869 DCHECK(pos.Value() >= current->End().Value()); |
| 1858 TraceAlloc("Assigning free reg %s to live range %d\n", RegisterName(reg), | 1870 TraceAlloc("Assigning free reg %s to live range %d\n", RegisterName(reg), |
| 1859 current->id()); | 1871 current->id()); |
| 1860 SetLiveRangeAssignedRegister(current, reg); | 1872 SetLiveRangeAssignedRegister(current, reg); |
| 1861 | 1873 |
| 1862 return true; | 1874 return true; |
| 1863 } | 1875 } |
| 1864 | 1876 |
| 1865 | 1877 |
| 1866 void RegisterAllocator::AllocateBlockedReg(LiveRange* current) { | 1878 void RegisterAllocator::AllocateBlockedReg(LiveRange* current) { |
| 1879 DCHECK(config().num_double_registers_ >= config().num_general_registers_); | |
| 1867 UsePosition* register_use = current->NextRegisterPosition(current->Start()); | 1880 UsePosition* register_use = current->NextRegisterPosition(current->Start()); |
| 1868 if (register_use == NULL) { | 1881 if (register_use == NULL) { |
| 1869 // There is no use in the current live range that requires a register. | 1882 // There is no use in the current live range that requires a register. |
| 1870 // We can just spill it. | 1883 // We can just spill it. |
| 1871 Spill(current); | 1884 Spill(current); |
| 1872 return; | 1885 return; |
| 1873 } | 1886 } |
| 1874 | 1887 |
| 1875 | 1888 // TODO(dcarney): ensure this function in non recursive and allocate space for |
| 1876 LifetimePosition use_pos[DoubleRegister::kMaxNumAllocatableRegisters]; | 1889 // this in RegisterAllocator. |
|
Jarin
2014/10/29 17:37:43
Why would you want this to be allocated RegisterAl
| |
| 1877 LifetimePosition block_pos[DoubleRegister::kMaxNumAllocatableRegisters]; | 1890 LifetimePosition use_pos[kMaxGeneralRegisters]; |
| 1891 // TODO(dcarney): ensure this function in non recursive and allocate space for | |
| 1892 // this in RegisterAllocator. | |
| 1893 LifetimePosition block_pos[kMaxDoubleRegisters]; | |
| 1878 | 1894 |
| 1879 for (int i = 0; i < num_registers_; i++) { | 1895 for (int i = 0; i < num_registers_; i++) { |
| 1880 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); | 1896 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); |
| 1881 } | 1897 } |
| 1882 | 1898 |
| 1883 for (int i = 0; i < active_live_ranges_.length(); ++i) { | 1899 for (int i = 0; i < active_live_ranges_.length(); ++i) { |
| 1884 LiveRange* range = active_live_ranges_[i]; | 1900 LiveRange* range = active_live_ranges_[i]; |
| 1885 int cur_reg = range->assigned_register(); | 1901 int cur_reg = range->assigned_register(); |
| 1886 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { | 1902 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { |
| 1887 block_pos[cur_reg] = use_pos[cur_reg] = | 1903 block_pos[cur_reg] = use_pos[cur_reg] = |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2180 } | 2196 } |
| 2181 | 2197 |
| 2182 | 2198 |
| 2183 int RegisterAllocator::RegisterCount() const { return num_registers_; } | 2199 int RegisterAllocator::RegisterCount() const { return num_registers_; } |
| 2184 | 2200 |
| 2185 | 2201 |
| 2186 #ifdef DEBUG | 2202 #ifdef DEBUG |
| 2187 | 2203 |
| 2188 | 2204 |
| 2189 void RegisterAllocator::Verify() const { | 2205 void RegisterAllocator::Verify() const { |
| 2190 for (int i = 0; i < live_ranges()->length(); ++i) { | 2206 for (auto current : live_ranges()) { |
| 2191 LiveRange* current = live_ranges()->at(i); | |
| 2192 if (current != NULL) current->Verify(); | 2207 if (current != NULL) current->Verify(); |
| 2193 } | 2208 } |
| 2194 } | 2209 } |
| 2195 | 2210 |
| 2196 | 2211 |
| 2197 #endif | 2212 #endif |
| 2198 | 2213 |
| 2199 | 2214 |
| 2200 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, | 2215 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, |
| 2201 int reg) { | 2216 int reg) { |
| 2202 if (range->Kind() == DOUBLE_REGISTERS) { | 2217 if (range->Kind() == DOUBLE_REGISTERS) { |
| 2203 assigned_double_registers_->Add(reg); | 2218 assigned_double_registers_->Add(reg); |
| 2204 } else { | 2219 } else { |
| 2205 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2220 DCHECK(range->Kind() == GENERAL_REGISTERS); |
| 2206 assigned_registers_->Add(reg); | 2221 assigned_registers_->Add(reg); |
| 2207 } | 2222 } |
| 2208 range->set_assigned_register(reg, code_zone()); | 2223 range->set_assigned_register(reg, code_zone()); |
| 2209 } | 2224 } |
| 2210 | 2225 |
| 2211 } | 2226 } |
| 2212 } | 2227 } |
| 2213 } // namespace v8::internal::compiler | 2228 } // namespace v8::internal::compiler |
| OLD | NEW |