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 |