Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Side by Side Diff: src/lithium-allocator.cc

Issue 5862002: Version 3.0.2. (Closed)
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 UsePosition* pos = first_pos_; 240 UsePosition* pos = first_pos_;
241 while (pos != NULL && !pos->HasHint()) pos = pos->next(); 241 while (pos != NULL && !pos->HasHint()) pos = pos->next();
242 return pos; 242 return pos;
243 } 243 }
244 244
245 245
246 LOperand* LiveRange::CreateAssignedOperand() { 246 LOperand* LiveRange::CreateAssignedOperand() {
247 LOperand* op = NULL; 247 LOperand* op = NULL;
248 if (HasRegisterAssigned()) { 248 if (HasRegisterAssigned()) {
249 ASSERT(!IsSpilled()); 249 ASSERT(!IsSpilled());
250 if (IsDouble()) { 250 if (assigned_double_) {
251 op = LDoubleRegister::Create(assigned_register()); 251 op = LDoubleRegister::Create(assigned_register());
252 } else { 252 } else {
253 op = LRegister::Create(assigned_register()); 253 op = LRegister::Create(assigned_register());
254 } 254 }
255 } else if (IsSpilled()) { 255 } else if (IsSpilled()) {
256 ASSERT(!HasRegisterAssigned()); 256 ASSERT(!HasRegisterAssigned());
257 op = TopLevel()->GetSpillOperand(); 257 op = TopLevel()->GetSpillOperand();
258 ASSERT(!op->IsUnallocated()); 258 ASSERT(!op->IsUnallocated());
259 } else { 259 } else {
260 LUnallocated* unalloc = new LUnallocated(LUnallocated::NONE); 260 LUnallocated* unalloc = new LUnallocated(LUnallocated::NONE);
(...skipping 22 matching lines...) Expand all
283 LifetimePosition start = 283 LifetimePosition start =
284 current_interval_ == NULL ? LifetimePosition::Invalid() 284 current_interval_ == NULL ? LifetimePosition::Invalid()
285 : current_interval_->start(); 285 : current_interval_->start();
286 if (to_start_of->start().Value() > start.Value()) { 286 if (to_start_of->start().Value() > start.Value()) {
287 current_interval_ = to_start_of; 287 current_interval_ = to_start_of;
288 } 288 }
289 } 289 }
290 290
291 291
292 void LiveRange::SplitAt(LifetimePosition position, LiveRange* result) { 292 void LiveRange::SplitAt(LifetimePosition position, LiveRange* result) {
293 ASSERT(Start().Value() < position.Value()); 293 ASSERT(Start().Value() <= position.Value());
294 ASSERT(result->IsEmpty()); 294 ASSERT(result->IsEmpty());
295 // Find the last interval that ends before the position. If the 295 // Find the last interval that ends before the position. If the
296 // position is contained in one of the intervals in the chain, we 296 // position is contained in one of the intervals in the chain, we
297 // split that interval and use the first part. 297 // split that interval and use the first part.
298 UseInterval* current = FirstSearchIntervalForPosition(position); 298 UseInterval* current = FirstSearchIntervalForPosition(position);
299 while (current != NULL) { 299 while (current != NULL) {
300 if (current->Contains(position)) { 300 if (current->Contains(position)) {
301 current->SplitAt(position); 301 current->SplitAt(position);
302 break; 302 break;
303 } 303 }
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 LiveRange* LAllocator::FixedLiveRangeFor(int index) { 618 LiveRange* LAllocator::FixedLiveRangeFor(int index) {
619 if (index >= fixed_live_ranges_.length()) { 619 if (index >= fixed_live_ranges_.length()) {
620 fixed_live_ranges_.AddBlock(NULL, 620 fixed_live_ranges_.AddBlock(NULL,
621 index - fixed_live_ranges_.length() + 1); 621 index - fixed_live_ranges_.length() + 1);
622 } 622 }
623 623
624 LiveRange* result = fixed_live_ranges_[index]; 624 LiveRange* result = fixed_live_ranges_[index];
625 if (result == NULL) { 625 if (result == NULL) {
626 result = new LiveRange(FixedLiveRangeID(index)); 626 result = new LiveRange(FixedLiveRangeID(index));
627 ASSERT(result->IsFixed()); 627 ASSERT(result->IsFixed());
628 result->set_assigned_register(index, GENERAL_REGISTERS); 628 result->set_assigned_register(index, false);
629 fixed_live_ranges_[index] = result; 629 fixed_live_ranges_[index] = result;
630 } 630 }
631 return result; 631 return result;
632 } 632 }
633 633
634 634
635 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) { 635 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) {
636 if (index >= fixed_double_live_ranges_.length()) { 636 if (index >= fixed_double_live_ranges_.length()) {
637 fixed_double_live_ranges_.AddBlock(NULL, 637 fixed_double_live_ranges_.AddBlock(NULL,
638 index - fixed_double_live_ranges_.length() + 1); 638 index - fixed_double_live_ranges_.length() + 1);
639 } 639 }
640 640
641 LiveRange* result = fixed_double_live_ranges_[index]; 641 LiveRange* result = fixed_double_live_ranges_[index];
642 if (result == NULL) { 642 if (result == NULL) {
643 result = new LiveRange(FixedDoubleLiveRangeID(index)); 643 result = new LiveRange(FixedDoubleLiveRangeID(index));
644 ASSERT(result->IsFixed()); 644 ASSERT(result->IsFixed());
645 result->set_assigned_register(index, DOUBLE_REGISTERS); 645 result->set_assigned_register(index, true);
646 fixed_double_live_ranges_[index] = result; 646 fixed_double_live_ranges_[index] = result;
647 } 647 }
648 return result; 648 return result;
649 } 649 }
650 650
651 LiveRange* LAllocator::LiveRangeFor(int index) { 651 LiveRange* LAllocator::LiveRangeFor(int index) {
652 if (index >= live_ranges_.length()) { 652 if (index >= live_ranges_.length()) {
653 live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1); 653 live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1);
654 } 654 }
655 LiveRange* result = live_ranges_[index]; 655 LiveRange* result = live_ranges_[index];
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); 1251 PrintF("First use is at %d\n", range->first_pos()->pos().Value());
1252 iterator.Advance(); 1252 iterator.Advance();
1253 } 1253 }
1254 ASSERT(!found); 1254 ASSERT(!found);
1255 } 1255 }
1256 #endif 1256 #endif
1257 } 1257 }
1258 } 1258 }
1259 1259
1260 1260
1261 void LAllocator::AllocateGeneralRegisters() {
1262 HPhase phase("Allocate general registers", this);
1263 num_registers_ = Register::kNumAllocatableRegisters;
1264 mode_ = CPU_REGISTERS;
1265 AllocateRegisters();
1266 }
1267
1268
1261 bool LAllocator::SafePointsAreInOrder() const { 1269 bool LAllocator::SafePointsAreInOrder() const {
1262 const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); 1270 const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps();
1263 int safe_point = 0; 1271 int safe_point = 0;
1264 for (int i = 0; i < pointer_maps->length(); ++i) { 1272 for (int i = 0; i < pointer_maps->length(); ++i) {
1265 LPointerMap* map = pointer_maps->at(i); 1273 LPointerMap* map = pointer_maps->at(i);
1266 if (safe_point > map->lithium_position()) return false; 1274 if (safe_point > map->lithium_position()) return false;
1267 safe_point = map->lithium_position(); 1275 safe_point = map->lithium_position();
1268 } 1276 }
1269 return true; 1277 return true;
1270 } 1278 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 instruction->MarkSpilledDoubleRegister(reg_index, spill_operand); 1390 instruction->MarkSpilledDoubleRegister(reg_index, spill_operand);
1383 } else { 1391 } else {
1384 instruction->MarkSpilledRegister(reg_index, spill_operand); 1392 instruction->MarkSpilledRegister(reg_index, spill_operand);
1385 } 1393 }
1386 } 1394 }
1387 } 1395 }
1388 } 1396 }
1389 } 1397 }
1390 1398
1391 1399
1392 void LAllocator::AllocateGeneralRegisters() {
1393 HPhase phase("Allocate general registers", this);
1394 num_registers_ = Register::kNumAllocatableRegisters;
1395 mode_ = GENERAL_REGISTERS;
1396 AllocateRegisters();
1397 }
1398
1399
1400 void LAllocator::AllocateDoubleRegisters() { 1400 void LAllocator::AllocateDoubleRegisters() {
1401 HPhase phase("Allocate double registers", this); 1401 HPhase phase("Allocate double registers", this);
1402 num_registers_ = DoubleRegister::kNumAllocatableRegisters; 1402 num_registers_ = DoubleRegister::kNumAllocatableRegisters;
1403 mode_ = DOUBLE_REGISTERS; 1403 mode_ = XMM_REGISTERS;
1404 AllocateRegisters(); 1404 AllocateRegisters();
1405 } 1405 }
1406 1406
1407 1407
1408 void LAllocator::AllocateRegisters() { 1408 void LAllocator::AllocateRegisters() {
1409 ASSERT(mode_ != NONE); 1409 ASSERT(mode_ != NONE);
1410 reusable_slots_.Clear(); 1410 reusable_slots_.Clear();
1411 1411
1412 for (int i = 0; i < live_ranges_.length(); ++i) { 1412 for (int i = 0; i < live_ranges_.length(); ++i) {
1413 if (live_ranges_[i] != NULL) { 1413 if (live_ranges_[i] != NULL) {
1414 if (RequiredRegisterKind(live_ranges_[i]->id()) == mode_) { 1414 if (HasDoubleValue(live_ranges_[i]->id()) == (mode_ == XMM_REGISTERS)) {
1415 AddToUnhandledUnsorted(live_ranges_[i]); 1415 AddToUnhandledUnsorted(live_ranges_[i]);
1416 } 1416 }
1417 } 1417 }
1418 } 1418 }
1419 SortUnhandled(); 1419 SortUnhandled();
1420 ASSERT(UnhandledIsSorted()); 1420 ASSERT(UnhandledIsSorted());
1421 1421
1422 ASSERT(active_live_ranges_.is_empty()); 1422 ASSERT(active_live_ranges_.is_empty());
1423 ASSERT(inactive_live_ranges_.is_empty()); 1423 ASSERT(inactive_live_ranges_.is_empty());
1424 1424
1425 if (mode_ == DOUBLE_REGISTERS) { 1425 if (mode_ == XMM_REGISTERS) {
1426 for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) { 1426 for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) {
1427 LiveRange* current = fixed_double_live_ranges_.at(i); 1427 LiveRange* current = fixed_double_live_ranges_.at(i);
1428 if (current != NULL) { 1428 if (current != NULL) {
1429 AddToInactive(current); 1429 AddToInactive(current);
1430 } 1430 }
1431 } 1431 }
1432 } else { 1432 } else {
1433 for (int i = 0; i < fixed_live_ranges_.length(); ++i) { 1433 for (int i = 0; i < fixed_live_ranges_.length(); ++i) {
1434 LiveRange* current = fixed_live_ranges_.at(i); 1434 LiveRange* current = fixed_live_ranges_.at(i);
1435 if (current != NULL) { 1435 if (current != NULL) {
(...skipping 20 matching lines...) Expand all
1456 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos); 1456 UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos);
1457 // If the range already has a spill operand and it doesn't need a 1457 // If the range already has a spill operand and it doesn't need a
1458 // register immediately, split it and spill the first part of the range. 1458 // register immediately, split it and spill the first part of the range.
1459 if (pos == NULL) { 1459 if (pos == NULL) {
1460 Spill(current); 1460 Spill(current);
1461 continue; 1461 continue;
1462 } else if (pos->pos().Value() > 1462 } else if (pos->pos().Value() >
1463 current->Start().NextInstruction().Value()) { 1463 current->Start().NextInstruction().Value()) {
1464 // Do not spill live range eagerly if use position that can benefit from 1464 // Do not spill live range eagerly if use position that can benefit from
1465 // the register is too close to the start of live range. 1465 // the register is too close to the start of live range.
1466 SpillBetween(current, current->Start(), pos->pos()); 1466 LiveRange* part = Split(current,
1467 current->Start().NextInstruction(),
1468 pos->pos());
1469 Spill(current);
1470 AddToUnhandledSorted(part);
1467 ASSERT(UnhandledIsSorted()); 1471 ASSERT(UnhandledIsSorted());
1468 continue; 1472 continue;
1469 } 1473 }
1470 } 1474 }
1471 1475
1472 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1476 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1473 LiveRange* cur_active = active_live_ranges_.at(i); 1477 LiveRange* cur_active = active_live_ranges_.at(i);
1474 if (cur_active->End().Value() <= position.Value()) { 1478 if (cur_active->End().Value() <= position.Value()) {
1475 ActiveToHandled(cur_active); 1479 ActiveToHandled(cur_active);
1476 --i; // The live range was removed from the list of active live ranges. 1480 --i; // The live range was removed from the list of active live ranges.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 1514
1511 void LAllocator::Setup() { 1515 void LAllocator::Setup() {
1512 LConstantOperand::SetupCache(); 1516 LConstantOperand::SetupCache();
1513 LStackSlot::SetupCache(); 1517 LStackSlot::SetupCache();
1514 LDoubleStackSlot::SetupCache(); 1518 LDoubleStackSlot::SetupCache();
1515 LRegister::SetupCache(); 1519 LRegister::SetupCache();
1516 LDoubleRegister::SetupCache(); 1520 LDoubleRegister::SetupCache();
1517 } 1521 }
1518 1522
1519 1523
1520 const char* LAllocator::RegisterName(int allocation_index) {
1521 ASSERT(mode_ != NONE);
1522 if (mode_ == GENERAL_REGISTERS) {
1523 return Register::AllocationIndexToString(allocation_index);
1524 } else {
1525 return DoubleRegister::AllocationIndexToString(allocation_index);
1526 }
1527 }
1528
1529
1530 void LAllocator::TraceAlloc(const char* msg, ...) { 1524 void LAllocator::TraceAlloc(const char* msg, ...) {
1531 if (FLAG_trace_alloc) { 1525 if (FLAG_trace_alloc) {
1532 va_list arguments; 1526 va_list arguments;
1533 va_start(arguments, msg); 1527 va_start(arguments, msg);
1534 OS::VPrint(msg, arguments); 1528 OS::VPrint(msg, arguments);
1535 va_end(arguments); 1529 va_end(arguments);
1536 } 1530 }
1537 } 1531 }
1538 1532
1539 1533
1540 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) { 1534 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) {
1541 operand->set_virtual_register(value->id()); 1535 operand->set_virtual_register(value->id());
1542 current_summary()->AddInput(operand); 1536 current_summary()->AddInput(operand);
1543 } 1537 }
1544 1538
1545 1539
1546 bool LAllocator::HasTaggedValue(int virtual_register) const { 1540 bool LAllocator::HasTaggedValue(int virtual_register) const {
1547 HValue* value = graph()->LookupValue(virtual_register); 1541 HValue* value = graph()->LookupValue(virtual_register);
1548 if (value == NULL) return false; 1542 if (value == NULL) return false;
1549 return value->representation().IsTagged(); 1543 return value->representation().IsTagged();
1550 } 1544 }
1551 1545
1552 1546
1553 RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const { 1547 bool LAllocator::HasDoubleValue(int virtual_register) const {
1554 HValue* value = graph()->LookupValue(virtual_register); 1548 HValue* value = graph()->LookupValue(virtual_register);
1555 if (value != NULL && value->representation().IsDouble()) { 1549 if (value == NULL) return false;
1556 return DOUBLE_REGISTERS; 1550 return value->representation().IsDouble();
1557 }
1558 return GENERAL_REGISTERS;
1559 } 1551 }
1560 1552
1561 1553
1562 void LAllocator::MarkAsCall() { 1554 void LAllocator::MarkAsCall() {
1563 current_summary()->MarkAsCall(); 1555 current_summary()->MarkAsCall();
1564 } 1556 }
1565 1557
1566 1558
1567 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) { 1559 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) {
1568 operand->set_virtual_register(instr->id()); 1560 operand->set_virtual_register(instr->id());
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 1721
1730 1722
1731 void LAllocator::InactiveToActive(LiveRange* range) { 1723 void LAllocator::InactiveToActive(LiveRange* range) {
1732 ASSERT(inactive_live_ranges_.Contains(range)); 1724 ASSERT(inactive_live_ranges_.Contains(range));
1733 inactive_live_ranges_.RemoveElement(range); 1725 inactive_live_ranges_.RemoveElement(range);
1734 active_live_ranges_.Add(range); 1726 active_live_ranges_.Add(range);
1735 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); 1727 TraceAlloc("Moving live range %d from inactive to active\n", range->id());
1736 } 1728 }
1737 1729
1738 1730
1739 // TryAllocateFreeReg and AllocateBlockedReg assume this
1740 // when allocating local arrays.
1741 STATIC_ASSERT(DoubleRegister::kNumAllocatableRegisters >=
1742 Register::kNumAllocatableRegisters);
1743
1744
1745 bool LAllocator::TryAllocateFreeReg(LiveRange* current) { 1731 bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
1746 LifetimePosition free_until_pos[DoubleRegister::kNumAllocatableRegisters]; 1732 LifetimePosition max_pos = LifetimePosition::FromInstructionIndex(
1747 1733 chunk_->instructions()->length() + 1);
1748 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { 1734 ASSERT(DoubleRegister::kNumAllocatableRegisters >=
1749 free_until_pos[i] = LifetimePosition::MaxPosition(); 1735 Register::kNumAllocatableRegisters);
1750 } 1736 EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters>
1751 1737 free_pos(max_pos);
1752 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1738 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1753 LiveRange* cur_active = active_live_ranges_.at(i); 1739 LiveRange* cur_active = active_live_ranges_.at(i);
1754 free_until_pos[cur_active->assigned_register()] = 1740 free_pos[cur_active->assigned_register()] =
1755 LifetimePosition::FromInstructionIndex(0); 1741 LifetimePosition::FromInstructionIndex(0);
1756 } 1742 }
1757 1743
1758 for (int i = 0; i < inactive_live_ranges_.length(); ++i) { 1744 for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1759 LiveRange* cur_inactive = inactive_live_ranges_.at(i); 1745 LiveRange* cur_inactive = inactive_live_ranges_.at(i);
1760 ASSERT(cur_inactive->End().Value() > current->Start().Value()); 1746 ASSERT(cur_inactive->End().Value() > current->Start().Value());
1761 LifetimePosition next_intersection = 1747 LifetimePosition next_intersection =
1762 cur_inactive->FirstIntersection(current); 1748 cur_inactive->FirstIntersection(current);
1763 if (!next_intersection.IsValid()) continue; 1749 if (!next_intersection.IsValid()) continue;
1764 int cur_reg = cur_inactive->assigned_register(); 1750 int cur_reg = cur_inactive->assigned_register();
1765 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection); 1751 free_pos[cur_reg] = Min(free_pos[cur_reg], next_intersection);
1766 } 1752 }
1767 1753
1768 UsePosition* hinted_use = current->FirstPosWithHint(); 1754 UsePosition* pos = current->FirstPosWithHint();
1769 if (hinted_use != NULL) { 1755 if (pos != NULL) {
1770 LOperand* hint = hinted_use->hint(); 1756 LOperand* hint = pos->hint();
1771 if (hint->IsRegister() || hint->IsDoubleRegister()) { 1757 if (hint->IsRegister() || hint->IsDoubleRegister()) {
1772 int register_index = hint->index(); 1758 int register_index = hint->index();
1773 TraceAlloc( 1759 TraceAlloc("Found reg hint %d for live range %d (free [%d, end %d[)\n",
1774 "Found reg hint %s (free until [%d) for live range %d (end %d[).\n", 1760 register_index,
1775 RegisterName(register_index), 1761 current->id(),
1776 free_until_pos[register_index].Value(), 1762 free_pos[register_index].Value(),
1777 current->id(), 1763 current->End().Value());
1778 current->End().Value()); 1764 if (free_pos[register_index].Value() >= current->End().Value()) {
1779 1765 TraceAlloc("Assigning preferred reg %d to live range %d\n",
1780 // The desired register is free until the end of the current live range. 1766 register_index,
1781 if (free_until_pos[register_index].Value() >= current->End().Value()) {
1782 TraceAlloc("Assigning preferred reg %s to live range %d\n",
1783 RegisterName(register_index),
1784 current->id()); 1767 current->id());
1785 current->set_assigned_register(register_index, mode_); 1768 current->set_assigned_register(register_index, mode_ == XMM_REGISTERS);
1786 return true; 1769 return true;
1787 } 1770 }
1788 } 1771 }
1789 } 1772 }
1790 1773
1791 // Find the register which stays free for the longest time. 1774 int max_reg = 0;
1792 int reg = 0;
1793 for (int i = 1; i < RegisterCount(); ++i) { 1775 for (int i = 1; i < RegisterCount(); ++i) {
1794 if (free_until_pos[i].Value() > free_until_pos[reg].Value()) { 1776 if (free_pos[i].Value() > free_pos[max_reg].Value()) {
1795 reg = i; 1777 max_reg = i;
1796 } 1778 }
1797 } 1779 }
1798 1780
1799 LifetimePosition pos = free_until_pos[reg]; 1781 if (free_pos[max_reg].InstructionIndex() == 0) {
1800
1801 if (pos.Value() <= current->Start().Value()) {
1802 // All registers are blocked.
1803 return false; 1782 return false;
1783 } else if (free_pos[max_reg].Value() >= current->End().Value()) {
1784 TraceAlloc("Assigning reg %d to live range %d\n", max_reg, current->id());
1785 current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS);
1786 } else {
1787 // Split the interval at the nearest gap and never split an interval at its
1788 // start position.
1789 LifetimePosition pos =
1790 LifetimePosition::FromInstructionIndex(
1791 chunk_->NearestGapPos(free_pos[max_reg].InstructionIndex()));
1792 if (pos.Value() <= current->Start().Value()) return false;
1793 LiveRange* second_range = Split(current, pos);
1794 AddToUnhandledSorted(second_range);
1795 current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS);
1804 } 1796 }
1805 1797
1806 if (pos.Value() < current->End().Value()) {
1807 // Register reg is available at the range start but becomes blocked before
1808 // the range end. Split current at position where it becomes blocked.
1809 LiveRange* tail = SplitAt(current, pos);
1810 AddToUnhandledSorted(tail);
1811 }
1812
1813
1814 // Register reg is available at the range start and is free until
1815 // the range end.
1816 ASSERT(pos.Value() >= current->End().Value());
1817 TraceAlloc("Assigning reg %s to live range %d\n",
1818 RegisterName(reg),
1819 current->id());
1820 current->set_assigned_register(reg, mode_);
1821
1822 return true; 1798 return true;
1823 } 1799 }
1824 1800
1825 1801
1826 void LAllocator::AllocateBlockedReg(LiveRange* current) { 1802 void LAllocator::AllocateBlockedReg(LiveRange* current) {
1827 UsePosition* register_use = current->NextRegisterPosition(current->Start()); 1803 LifetimePosition max_pos =
1828 if (register_use == NULL) { 1804 LifetimePosition::FromInstructionIndex(
1829 // There is no use in the current live range that requires a register. 1805 chunk_->instructions()->length() + 1);
1830 // We can just spill it. 1806 ASSERT(DoubleRegister::kNumAllocatableRegisters >=
1831 Spill(current); 1807 Register::kNumAllocatableRegisters);
1832 return; 1808 EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters>
1833 } 1809 use_pos(max_pos);
1834 1810 EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters>
1835 1811 block_pos(max_pos);
1836 LifetimePosition use_pos[DoubleRegister::kNumAllocatableRegisters];
1837 LifetimePosition block_pos[DoubleRegister::kNumAllocatableRegisters];
1838
1839 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) {
1840 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
1841 }
1842 1812
1843 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1813 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1844 LiveRange* range = active_live_ranges_[i]; 1814 LiveRange* range = active_live_ranges_[i];
1845 int cur_reg = range->assigned_register(); 1815 int cur_reg = range->assigned_register();
1846 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { 1816 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) {
1847 block_pos[cur_reg] = use_pos[cur_reg] = 1817 block_pos[cur_reg] = use_pos[cur_reg] =
1848 LifetimePosition::FromInstructionIndex(0); 1818 LifetimePosition::FromInstructionIndex(0);
1849 } else { 1819 } else {
1850 UsePosition* next_use = range->NextUsePositionRegisterIsBeneficial( 1820 UsePosition* next_use = range->NextUsePositionRegisterIsBeneficial(
1851 current->Start()); 1821 current->Start());
(...skipping 12 matching lines...) Expand all
1864 if (!next_intersection.IsValid()) continue; 1834 if (!next_intersection.IsValid()) continue;
1865 int cur_reg = range->assigned_register(); 1835 int cur_reg = range->assigned_register();
1866 if (range->IsFixed()) { 1836 if (range->IsFixed()) {
1867 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); 1837 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
1868 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); 1838 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
1869 } else { 1839 } else {
1870 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); 1840 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
1871 } 1841 }
1872 } 1842 }
1873 1843
1874 int reg = 0; 1844 int max_reg = 0;
1875 for (int i = 1; i < RegisterCount(); ++i) { 1845 for (int i = 1; i < RegisterCount(); ++i) {
1876 if (use_pos[i].Value() > use_pos[reg].Value()) { 1846 if (use_pos[i].Value() > use_pos[max_reg].Value()) {
1877 reg = i; 1847 max_reg = i;
1878 } 1848 }
1879 } 1849 }
1880 1850
1881 LifetimePosition pos = use_pos[reg]; 1851 UsePosition* first_usage = current->NextRegisterPosition(current->Start());
1852 if (first_usage == NULL) {
1853 Spill(current);
1854 } else if (use_pos[max_reg].Value() < first_usage->pos().Value()) {
1855 SplitAndSpill(current, current->Start(), first_usage->pos());
1856 } else {
1857 if (block_pos[max_reg].Value() < current->End().Value()) {
1858 // Split current before blocked position.
1859 LiveRange* second_range = Split(current,
1860 current->Start(),
1861 block_pos[max_reg]);
1862 AddToUnhandledSorted(second_range);
1863 }
1882 1864
1883 if (pos.Value() < register_use->pos().Value()) { 1865 current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS);
1884 // All registers are blocked before the first use that requires a register. 1866 SplitAndSpillIntersecting(current);
1885 // Spill starting part of live range up to that use.
1886 //
1887 // Corner case: the first use position is equal to the start of the range.
1888 // In this case we have nothing to spill and SpillBetween will just return
1889 // this range to the list of unhandled ones. This will lead to the infinite
1890 // loop.
1891 ASSERT(current->Start().Value() < register_use->pos().Value());
1892 SpillBetween(current, current->Start(), register_use->pos());
1893 return;
1894 } 1867 }
1895
1896 if (block_pos[reg].Value() < current->End().Value()) {
1897 // Register becomes blocked before the current range end. Split before that
1898 // position.
1899 LiveRange* tail = SplitBetween(current,
1900 current->Start(),
1901 block_pos[reg].InstructionStart());
1902 AddToUnhandledSorted(tail);
1903 }
1904
1905 // Register reg is not blocked for the whole range.
1906 ASSERT(block_pos[reg].Value() >= current->End().Value());
1907 TraceAlloc("Assigning reg %s to live range %d\n",
1908 RegisterName(reg),
1909 current->id());
1910 current->set_assigned_register(reg, mode_);
1911
1912 // This register was not free. Thus we need to find and spill
1913 // parts of active and inactive live regions that use the same register
1914 // at the same lifetime positions as current.
1915 SplitAndSpillIntersecting(current);
1916 } 1868 }
1917 1869
1918 1870
1919 void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { 1871 void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
1920 ASSERT(current->HasRegisterAssigned()); 1872 ASSERT(current->HasRegisterAssigned());
1921 int reg = current->assigned_register(); 1873 int reg = current->assigned_register();
1922 LifetimePosition split_pos = current->Start(); 1874 LifetimePosition split_pos =
1875 LifetimePosition::FromInstructionIndex(
1876 chunk_->NearestGapPos(current->Start().InstructionIndex()));
1923 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1877 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1924 LiveRange* range = active_live_ranges_[i]; 1878 LiveRange* range = active_live_ranges_[i];
1925 if (range->assigned_register() == reg) { 1879 if (range->assigned_register() == reg) {
1926 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 1880 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
1927 if (next_pos == NULL) { 1881 if (next_pos == NULL) {
1928 SpillAfter(range, split_pos); 1882 SplitAndSpill(range, split_pos);
1929 } else { 1883 } else {
1930 SpillBetween(range, split_pos, next_pos->pos()); 1884 SplitAndSpill(range, split_pos, next_pos->pos());
1931 } 1885 }
1932 ActiveToHandled(range); 1886 ActiveToHandled(range);
1933 --i; 1887 --i;
1934 } 1888 }
1935 } 1889 }
1936 1890
1937 for (int i = 0; i < inactive_live_ranges_.length(); ++i) { 1891 for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1938 LiveRange* range = inactive_live_ranges_[i]; 1892 LiveRange* range = inactive_live_ranges_[i];
1939 ASSERT(range->End().Value() > current->Start().Value()); 1893 ASSERT(range->End().Value() > current->Start().Value());
1940 if (range->assigned_register() == reg && !range->IsFixed()) { 1894 if (range->assigned_register() == reg && !range->IsFixed()) {
1941 LifetimePosition next_intersection = range->FirstIntersection(current); 1895 LifetimePosition next_intersection = range->FirstIntersection(current);
1942 if (next_intersection.IsValid()) { 1896 if (next_intersection.IsValid()) {
1943 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 1897 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
1944 if (next_pos == NULL) { 1898 if (next_pos == NULL) {
1945 SpillAfter(range, split_pos); 1899 SplitAndSpill(range, split_pos);
1946 } else { 1900 } else {
1947 next_intersection = Min(next_intersection, next_pos->pos()); 1901 next_intersection = Min(next_intersection, next_pos->pos());
1948 SpillBetween(range, split_pos, next_intersection); 1902 SplitAndSpill(range, split_pos, next_intersection);
1949 } 1903 }
1950 InactiveToHandled(range); 1904 InactiveToHandled(range);
1951 --i; 1905 --i;
1952 } 1906 }
1953 } 1907 }
1954 } 1908 }
1955 } 1909 }
1956 1910
1957 1911
1958 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { 1912 LiveRange* LAllocator::Split(LiveRange* range,
1959 return pos.IsInstructionStart() && 1913 LifetimePosition start,
1960 chunk_->instructions()->at(pos.InstructionIndex())->IsLabel(); 1914 LifetimePosition end) {
1961 }
1962
1963
1964 void LAllocator::AddGapMove(int pos, LiveRange* prev, LiveRange* next) {
1965 UsePosition* prev_pos = prev->AddUsePosition(
1966 LifetimePosition::FromInstructionIndex(pos));
1967 UsePosition* next_pos = next->AddUsePosition(
1968 LifetimePosition::FromInstructionIndex(pos));
1969 LOperand* prev_operand = prev_pos->operand();
1970 LOperand* next_operand = next_pos->operand();
1971 LGap* gap = chunk_->GetGapAt(pos);
1972 gap->GetOrCreateParallelMove(LGap::START)->
1973 AddMove(prev_operand, next_operand);
1974 next_pos->set_hint(prev_operand);
1975 }
1976
1977
1978 LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) {
1979 ASSERT(!range->IsFixed()); 1915 ASSERT(!range->IsFixed());
1980 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); 1916 TraceAlloc("Splitting live range %d in position between [%d, %d[\n",
1981
1982 if (pos.Value() <= range->Start().Value()) return range;
1983
1984 LiveRange* result = LiveRangeFor(next_virtual_register_++);
1985 range->SplitAt(pos, result);
1986 return result;
1987 }
1988
1989
1990 LiveRange* LAllocator::SplitBetween(LiveRange* range,
1991 LifetimePosition start,
1992 LifetimePosition end) {
1993 ASSERT(!range->IsFixed());
1994 TraceAlloc("Splitting live range %d in position between [%d, %d]\n",
1995 range->id(), 1917 range->id(),
1996 start.Value(), 1918 start.Value(),
1997 end.Value()); 1919 end.Value());
1998 1920
1999 LifetimePosition split_pos = FindOptimalSplitPos(start, end); 1921 LifetimePosition split_pos = FindOptimalSplitPos(
1922 start, end.PrevInstruction().InstructionEnd());
2000 ASSERT(split_pos.Value() >= start.Value()); 1923 ASSERT(split_pos.Value() >= start.Value());
2001 return SplitAt(range, split_pos); 1924 return Split(range, split_pos);
2002 } 1925 }
2003 1926
2004 1927
2005 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start, 1928 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start,
2006 LifetimePosition end) { 1929 LifetimePosition end) {
2007 int start_instr = start.InstructionIndex(); 1930 int start_instr = start.InstructionIndex();
2008 int end_instr = end.InstructionIndex(); 1931 int end_instr = end.InstructionIndex();
2009 ASSERT(start_instr <= end_instr); 1932 ASSERT(start_instr <= end_instr);
2010 1933
2011 // We have no choice 1934 // We have no choice
2012 if (start_instr == end_instr) return end; 1935 if (start_instr == end_instr) return end;
2013 1936
2014 HBasicBlock* end_block = GetBlock(start); 1937 HBasicBlock* end_block = GetBlock(start);
2015 HBasicBlock* start_block = GetBlock(end); 1938 HBasicBlock* start_block = GetBlock(end);
2016 1939
2017 if (end_block == start_block) { 1940 if (end_block == start_block) {
2018 // The interval is split in the same basic block. Split at latest possible 1941 // The interval is split in the same basic block. Split at latest possible
2019 // position. 1942 // position.
2020 return end; 1943 return end;
2021 } 1944 }
2022 1945
2023 HBasicBlock* block = end_block; 1946 HBasicBlock* block = end_block;
2024 // Find header of outermost loop. 1947 // Move to the most outside loop header.
2025 while (block->parent_loop_header() != NULL && 1948 while (block->parent_loop_header() != NULL &&
2026 block->parent_loop_header()->block_id() > start_block->block_id()) { 1949 block->parent_loop_header()->block_id() > start_block->block_id()) {
2027 block = block->parent_loop_header(); 1950 block = block->parent_loop_header();
2028 } 1951 }
2029 1952
2030 if (block == end_block) return end; 1953 if (block == end_block) {
1954 return end;
1955 }
2031 1956
2032 return LifetimePosition::FromInstructionIndex( 1957 return LifetimePosition::FromInstructionIndex(
2033 block->first_instruction_index()); 1958 block->first_instruction_index());
2034 } 1959 }
2035 1960
2036 1961
2037 void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { 1962 bool LAllocator::IsBlockBoundary(LifetimePosition pos) {
2038 LiveRange* second_part = SplitAt(range, pos); 1963 return pos.IsInstructionStart() &&
2039 Spill(second_part); 1964 chunk_->instructions()->at(pos.InstructionIndex())->IsLabel();
2040 } 1965 }
2041 1966
2042 1967
2043 void LAllocator::SpillBetween(LiveRange* range, 1968 void LAllocator::AddGapMove(int pos, LiveRange* prev, LiveRange* next) {
2044 LifetimePosition start, 1969 UsePosition* prev_pos = prev->AddUsePosition(
2045 LifetimePosition end) { 1970 LifetimePosition::FromInstructionIndex(pos));
1971 UsePosition* next_pos = next->AddUsePosition(
1972 LifetimePosition::FromInstructionIndex(pos));
1973 LOperand* prev_operand = prev_pos->operand();
1974 LOperand* next_operand = next_pos->operand();
1975 LGap* gap = chunk_->GetGapAt(pos);
1976 gap->GetOrCreateParallelMove(LGap::START)->
1977 AddMove(prev_operand, next_operand);
1978 next_pos->set_hint(prev_operand);
1979 }
1980
1981
1982 LiveRange* LAllocator::Split(LiveRange* range, LifetimePosition pos) {
1983 ASSERT(!range->IsFixed());
1984 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value());
1985 if (pos.Value() <= range->Start().Value()) {
1986 return range;
1987 }
1988 LiveRange* result = LiveRangeFor(next_virtual_register_++);
1989 range->SplitAt(pos, result);
1990 return result;
1991 }
1992
1993
1994 void LAllocator::SplitAndSpill(LiveRange* range,
1995 LifetimePosition start,
1996 LifetimePosition end) {
1997 // We have an interval range and want to make sure that it is
1998 // spilled at start and at most spilled until end.
2046 ASSERT(start.Value() < end.Value()); 1999 ASSERT(start.Value() < end.Value());
2047 LiveRange* second_part = SplitAt(range, start); 2000 LiveRange* tail_part = Split(range, start);
2048 2001 if (tail_part->Start().Value() < end.Value()) {
2049 if (second_part->Start().Value() < end.Value()) { 2002 LiveRange* third_part = Split(tail_part,
2050 // The split result intersects with [start, end[. 2003 tail_part->Start().NextInstruction(),
2051 // Split it at position between ]start+1, end[, spill the middle part 2004 end);
2052 // and put the rest to unhandled. 2005 Spill(tail_part);
2053 LiveRange* third_part = SplitBetween( 2006 ASSERT(third_part != tail_part);
2054 second_part,
2055 second_part->Start().InstructionEnd(),
2056 end.PrevInstruction().InstructionEnd());
2057
2058 ASSERT(third_part != second_part);
2059
2060 Spill(second_part);
2061 AddToUnhandledSorted(third_part); 2007 AddToUnhandledSorted(third_part);
2062 } else { 2008 } else {
2063 // The split result does not intersect with [start, end[. 2009 AddToUnhandledSorted(tail_part);
2064 // Nothing to spill. Just put it to unhandled as whole.
2065 AddToUnhandledSorted(second_part);
2066 } 2010 }
2067 } 2011 }
2068 2012
2069 2013
2014 void LAllocator::SplitAndSpill(LiveRange* range, LifetimePosition at) {
2015 at = LifetimePosition::FromInstructionIndex(
2016 chunk_->NearestGapPos(at.InstructionIndex()));
2017 LiveRange* second_part = Split(range, at);
2018 Spill(second_part);
2019 }
2020
2021
2070 void LAllocator::Spill(LiveRange* range) { 2022 void LAllocator::Spill(LiveRange* range) {
2071 ASSERT(!range->IsSpilled()); 2023 ASSERT(!range->IsSpilled());
2072 TraceAlloc("Spilling live range %d\n", range->id()); 2024 TraceAlloc("Spilling live range %d\n", range->id());
2073 LiveRange* first = range->TopLevel(); 2025 LiveRange* first = range->TopLevel();
2074 2026
2075 if (!first->HasAllocatedSpillOperand()) { 2027 if (!first->HasAllocatedSpillOperand()) {
2076 LOperand* op = TryReuseSpillSlot(range); 2028 LOperand* op = TryReuseSpillSlot(range);
2077 if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == DOUBLE_REGISTERS); 2029 if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == XMM_REGISTERS);
2078 first->SetSpillOperand(op); 2030 first->SetSpillOperand(op);
2079 } 2031 }
2080 range->MakeSpilled(); 2032 range->MakeSpilled();
2081 } 2033 }
2082 2034
2083 2035
2084 int LAllocator::RegisterCount() const { 2036 int LAllocator::RegisterCount() const {
2085 return num_registers_; 2037 return num_registers_;
2086 } 2038 }
2087 2039
2088 2040
2089 #ifdef DEBUG 2041 #ifdef DEBUG
2090 2042
2091 2043
2092 void LAllocator::Verify() const { 2044 void LAllocator::Verify() const {
2093 for (int i = 0; i < live_ranges()->length(); ++i) { 2045 for (int i = 0; i < live_ranges()->length(); ++i) {
2094 LiveRange* current = live_ranges()->at(i); 2046 LiveRange* current = live_ranges()->at(i);
2095 if (current != NULL) current->Verify(); 2047 if (current != NULL) current->Verify();
2096 } 2048 }
2097 } 2049 }
2098 2050
2099 2051
2100 #endif 2052 #endif
2101 2053
2102 2054
2103 } } // namespace v8::internal 2055 } } // namespace v8::internal
OLDNEW
« ChangeLog ('K') | « src/lithium-allocator.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698