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

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

Issue 5720001: Fix issue 962. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed Kevin's comments 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 | Annotate | Revision Log
« no previous file with comments | « src/lithium-allocator.h ('k') | test/mjsunit/regress/regress-962.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 (assigned_double_) { 250 if (IsDouble()) {
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, false); 628 result->set_assigned_register(index, GENERAL_REGISTERS);
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, true); 645 result->set_assigned_register(index, DOUBLE_REGISTERS);
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
1269 bool LAllocator::SafePointsAreInOrder() const { 1261 bool LAllocator::SafePointsAreInOrder() const {
1270 const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps(); 1262 const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps();
1271 int safe_point = 0; 1263 int safe_point = 0;
1272 for (int i = 0; i < pointer_maps->length(); ++i) { 1264 for (int i = 0; i < pointer_maps->length(); ++i) {
1273 LPointerMap* map = pointer_maps->at(i); 1265 LPointerMap* map = pointer_maps->at(i);
1274 if (safe_point > map->lithium_position()) return false; 1266 if (safe_point > map->lithium_position()) return false;
1275 safe_point = map->lithium_position(); 1267 safe_point = map->lithium_position();
1276 } 1268 }
1277 return true; 1269 return true;
1278 } 1270 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1390 instruction->MarkSpilledDoubleRegister(reg_index, spill_operand); 1382 instruction->MarkSpilledDoubleRegister(reg_index, spill_operand);
1391 } else { 1383 } else {
1392 instruction->MarkSpilledRegister(reg_index, spill_operand); 1384 instruction->MarkSpilledRegister(reg_index, spill_operand);
1393 } 1385 }
1394 } 1386 }
1395 } 1387 }
1396 } 1388 }
1397 } 1389 }
1398 1390
1399 1391
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_ = XMM_REGISTERS; 1403 mode_ = DOUBLE_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 (HasDoubleValue(live_ranges_[i]->id()) == (mode_ == XMM_REGISTERS)) { 1414 if (RequiredRegisterKind(live_ranges_[i]->id()) == mode_) {
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_ == XMM_REGISTERS) { 1425 if (mode_ == DOUBLE_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 LiveRange* part = Split(current, 1466 SpillBetween(current, current->Start(), pos->pos());
1467 current->Start().NextInstruction(),
1468 pos->pos());
1469 Spill(current);
1470 AddToUnhandledSorted(part);
1471 ASSERT(UnhandledIsSorted()); 1467 ASSERT(UnhandledIsSorted());
1472 continue; 1468 continue;
1473 } 1469 }
1474 } 1470 }
1475 1471
1476 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1472 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1477 LiveRange* cur_active = active_live_ranges_.at(i); 1473 LiveRange* cur_active = active_live_ranges_.at(i);
1478 if (cur_active->End().Value() <= position.Value()) { 1474 if (cur_active->End().Value() <= position.Value()) {
1479 ActiveToHandled(cur_active); 1475 ActiveToHandled(cur_active);
1480 --i; // The live range was removed from the list of active live ranges. 1476 --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
1514 1510
1515 void LAllocator::Setup() { 1511 void LAllocator::Setup() {
1516 LConstantOperand::SetupCache(); 1512 LConstantOperand::SetupCache();
1517 LStackSlot::SetupCache(); 1513 LStackSlot::SetupCache();
1518 LDoubleStackSlot::SetupCache(); 1514 LDoubleStackSlot::SetupCache();
1519 LRegister::SetupCache(); 1515 LRegister::SetupCache();
1520 LDoubleRegister::SetupCache(); 1516 LDoubleRegister::SetupCache();
1521 } 1517 }
1522 1518
1523 1519
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
1524 void LAllocator::TraceAlloc(const char* msg, ...) { 1530 void LAllocator::TraceAlloc(const char* msg, ...) {
1525 if (FLAG_trace_alloc) { 1531 if (FLAG_trace_alloc) {
1526 va_list arguments; 1532 va_list arguments;
1527 va_start(arguments, msg); 1533 va_start(arguments, msg);
1528 OS::VPrint(msg, arguments); 1534 OS::VPrint(msg, arguments);
1529 va_end(arguments); 1535 va_end(arguments);
1530 } 1536 }
1531 } 1537 }
1532 1538
1533 1539
1534 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) { 1540 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) {
1535 operand->set_virtual_register(value->id()); 1541 operand->set_virtual_register(value->id());
1536 current_summary()->AddInput(operand); 1542 current_summary()->AddInput(operand);
1537 } 1543 }
1538 1544
1539 1545
1540 bool LAllocator::HasTaggedValue(int virtual_register) const { 1546 bool LAllocator::HasTaggedValue(int virtual_register) const {
1541 HValue* value = graph()->LookupValue(virtual_register); 1547 HValue* value = graph()->LookupValue(virtual_register);
1542 if (value == NULL) return false; 1548 if (value == NULL) return false;
1543 return value->representation().IsTagged(); 1549 return value->representation().IsTagged();
1544 } 1550 }
1545 1551
1546 1552
1547 bool LAllocator::HasDoubleValue(int virtual_register) const { 1553 RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const {
1548 HValue* value = graph()->LookupValue(virtual_register); 1554 HValue* value = graph()->LookupValue(virtual_register);
1549 if (value == NULL) return false; 1555 if (value != NULL && value->representation().IsDouble()) {
1550 return value->representation().IsDouble(); 1556 return DOUBLE_REGISTERS;
1557 }
1558 return GENERAL_REGISTERS;
1551 } 1559 }
1552 1560
1553 1561
1554 void LAllocator::MarkAsCall() { 1562 void LAllocator::MarkAsCall() {
1555 current_summary()->MarkAsCall(); 1563 current_summary()->MarkAsCall();
1556 } 1564 }
1557 1565
1558 1566
1559 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) { 1567 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) {
1560 operand->set_virtual_register(instr->id()); 1568 operand->set_virtual_register(instr->id());
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 1729
1722 1730
1723 void LAllocator::InactiveToActive(LiveRange* range) { 1731 void LAllocator::InactiveToActive(LiveRange* range) {
1724 ASSERT(inactive_live_ranges_.Contains(range)); 1732 ASSERT(inactive_live_ranges_.Contains(range));
1725 inactive_live_ranges_.RemoveElement(range); 1733 inactive_live_ranges_.RemoveElement(range);
1726 active_live_ranges_.Add(range); 1734 active_live_ranges_.Add(range);
1727 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); 1735 TraceAlloc("Moving live range %d from inactive to active\n", range->id());
1728 } 1736 }
1729 1737
1730 1738
1739 // TryAllocateFreeReg and AllocateBlockedReg assume this
1740 // when allocating local arrays.
1741 STATIC_ASSERT(DoubleRegister::kNumAllocatableRegisters >=
1742 Register::kNumAllocatableRegisters);
1743
1744
1731 bool LAllocator::TryAllocateFreeReg(LiveRange* current) { 1745 bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
1732 LifetimePosition max_pos = LifetimePosition::FromInstructionIndex( 1746 LifetimePosition free_until_pos[DoubleRegister::kNumAllocatableRegisters];
1733 chunk_->instructions()->length() + 1); 1747
1734 ASSERT(DoubleRegister::kNumAllocatableRegisters >= 1748 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) {
1735 Register::kNumAllocatableRegisters); 1749 free_until_pos[i] = LifetimePosition::MaxPosition();
1736 EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters> 1750 }
1737 free_pos(max_pos); 1751
1738 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1752 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1739 LiveRange* cur_active = active_live_ranges_.at(i); 1753 LiveRange* cur_active = active_live_ranges_.at(i);
1740 free_pos[cur_active->assigned_register()] = 1754 free_until_pos[cur_active->assigned_register()] =
1741 LifetimePosition::FromInstructionIndex(0); 1755 LifetimePosition::FromInstructionIndex(0);
1742 } 1756 }
1743 1757
1744 for (int i = 0; i < inactive_live_ranges_.length(); ++i) { 1758 for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1745 LiveRange* cur_inactive = inactive_live_ranges_.at(i); 1759 LiveRange* cur_inactive = inactive_live_ranges_.at(i);
1746 ASSERT(cur_inactive->End().Value() > current->Start().Value()); 1760 ASSERT(cur_inactive->End().Value() > current->Start().Value());
1747 LifetimePosition next_intersection = 1761 LifetimePosition next_intersection =
1748 cur_inactive->FirstIntersection(current); 1762 cur_inactive->FirstIntersection(current);
1749 if (!next_intersection.IsValid()) continue; 1763 if (!next_intersection.IsValid()) continue;
1750 int cur_reg = cur_inactive->assigned_register(); 1764 int cur_reg = cur_inactive->assigned_register();
1751 free_pos[cur_reg] = Min(free_pos[cur_reg], next_intersection); 1765 free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
1752 } 1766 }
1753 1767
1754 UsePosition* pos = current->FirstPosWithHint(); 1768 UsePosition* hinted_use = current->FirstPosWithHint();
1755 if (pos != NULL) { 1769 if (hinted_use != NULL) {
1756 LOperand* hint = pos->hint(); 1770 LOperand* hint = hinted_use->hint();
1757 if (hint->IsRegister() || hint->IsDoubleRegister()) { 1771 if (hint->IsRegister() || hint->IsDoubleRegister()) {
1758 int register_index = hint->index(); 1772 int register_index = hint->index();
1759 TraceAlloc("Found reg hint %d for live range %d (free [%d, end %d[)\n", 1773 TraceAlloc(
1760 register_index, 1774 "Found reg hint %s (free until [%d) for live range %d (end %d[).\n",
1761 current->id(), 1775 RegisterName(register_index),
1762 free_pos[register_index].Value(), 1776 free_until_pos[register_index].Value(),
1763 current->End().Value()); 1777 current->id(),
1764 if (free_pos[register_index].Value() >= current->End().Value()) { 1778 current->End().Value());
1765 TraceAlloc("Assigning preferred reg %d to live range %d\n", 1779
1766 register_index, 1780 // The desired register is free until the end of the current live range.
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),
1767 current->id()); 1784 current->id());
1768 current->set_assigned_register(register_index, mode_ == XMM_REGISTERS); 1785 current->set_assigned_register(register_index, mode_);
1769 return true; 1786 return true;
1770 } 1787 }
1771 } 1788 }
1772 } 1789 }
1773 1790
1774 int max_reg = 0; 1791 // Find the register which stays free for the longest time.
1792 int reg = 0;
1775 for (int i = 1; i < RegisterCount(); ++i) { 1793 for (int i = 1; i < RegisterCount(); ++i) {
1776 if (free_pos[i].Value() > free_pos[max_reg].Value()) { 1794 if (free_until_pos[i].Value() > free_until_pos[reg].Value()) {
1777 max_reg = i; 1795 reg = i;
1778 } 1796 }
1779 } 1797 }
1780 1798
1781 if (free_pos[max_reg].InstructionIndex() == 0) { 1799 LifetimePosition pos = free_until_pos[reg];
1800
1801 if (pos.Value() <= current->Start().Value()) {
1802 // All registers are blocked.
1782 return false; 1803 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 before first use position of max_reg and never split
1788 // it interval at its start position.
1789 LifetimePosition pos = free_pos[max_reg];
1790 if (pos.Value() <= current->Start().Value()) return false;
1791 LiveRange* second_range = Split(current, pos);
1792 AddToUnhandledSorted(second_range);
1793 current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS);
1794 } 1804 }
1795 1805
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
1796 return true; 1822 return true;
1797 } 1823 }
1798 1824
1799 1825
1800 void LAllocator::AllocateBlockedReg(LiveRange* current) { 1826 void LAllocator::AllocateBlockedReg(LiveRange* current) {
1801 LifetimePosition max_pos = 1827 UsePosition* register_use = current->NextRegisterPosition(current->Start());
1802 LifetimePosition::FromInstructionIndex( 1828 if (register_use == NULL) {
1803 chunk_->instructions()->length() + 1); 1829 // There is no use in the current live range that requires a register.
1804 ASSERT(DoubleRegister::kNumAllocatableRegisters >= 1830 // We can just spill it.
1805 Register::kNumAllocatableRegisters); 1831 Spill(current);
1806 EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters> 1832 return;
1807 use_pos(max_pos); 1833 }
1808 EmbeddedVector<LifetimePosition, DoubleRegister::kNumAllocatableRegisters> 1834
1809 block_pos(max_pos); 1835
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 }
1810 1842
1811 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1843 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1812 LiveRange* range = active_live_ranges_[i]; 1844 LiveRange* range = active_live_ranges_[i];
1813 int cur_reg = range->assigned_register(); 1845 int cur_reg = range->assigned_register();
1814 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) { 1846 if (range->IsFixed() || !range->CanBeSpilled(current->Start())) {
1815 block_pos[cur_reg] = use_pos[cur_reg] = 1847 block_pos[cur_reg] = use_pos[cur_reg] =
1816 LifetimePosition::FromInstructionIndex(0); 1848 LifetimePosition::FromInstructionIndex(0);
1817 } else { 1849 } else {
1818 UsePosition* next_use = range->NextUsePositionRegisterIsBeneficial( 1850 UsePosition* next_use = range->NextUsePositionRegisterIsBeneficial(
1819 current->Start()); 1851 current->Start());
(...skipping 12 matching lines...) Expand all
1832 if (!next_intersection.IsValid()) continue; 1864 if (!next_intersection.IsValid()) continue;
1833 int cur_reg = range->assigned_register(); 1865 int cur_reg = range->assigned_register();
1834 if (range->IsFixed()) { 1866 if (range->IsFixed()) {
1835 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); 1867 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
1836 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); 1868 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
1837 } else { 1869 } else {
1838 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); 1870 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
1839 } 1871 }
1840 } 1872 }
1841 1873
1842 int max_reg = 0; 1874 int reg = 0;
1843 for (int i = 1; i < RegisterCount(); ++i) { 1875 for (int i = 1; i < RegisterCount(); ++i) {
1844 if (use_pos[i].Value() > use_pos[max_reg].Value()) { 1876 if (use_pos[i].Value() > use_pos[reg].Value()) {
1845 max_reg = i; 1877 reg = i;
1846 } 1878 }
1847 } 1879 }
1848 1880
1849 UsePosition* first_usage = current->NextRegisterPosition(current->Start()); 1881 LifetimePosition pos = use_pos[reg];
1850 if (first_usage == NULL) {
1851 Spill(current);
1852 } else if (use_pos[max_reg].Value() < first_usage->pos().Value()) {
1853 SplitAndSpill(current, current->Start(), first_usage->pos());
1854 } else {
1855 if (block_pos[max_reg].Value() < current->End().Value()) {
1856 // Split current before blocked position.
1857 LiveRange* second_range = Split(current,
1858 current->Start(),
1859 block_pos[max_reg]);
1860 AddToUnhandledSorted(second_range);
1861 }
1862 1882
1863 current->set_assigned_register(max_reg, mode_ == XMM_REGISTERS); 1883 if (pos.Value() < register_use->pos().Value()) {
1864 SplitAndSpillIntersecting(current); 1884 // All registers are blocked before the first use that requires a register.
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;
1865 } 1894 }
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);
1866 } 1916 }
1867 1917
1868 1918
1869 void LAllocator::SplitAndSpillIntersecting(LiveRange* current) { 1919 void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
1870 ASSERT(current->HasRegisterAssigned()); 1920 ASSERT(current->HasRegisterAssigned());
1871 int reg = current->assigned_register(); 1921 int reg = current->assigned_register();
1872 LifetimePosition split_pos = current->Start(); 1922 LifetimePosition split_pos = current->Start();
1873 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1923 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1874 LiveRange* range = active_live_ranges_[i]; 1924 LiveRange* range = active_live_ranges_[i];
1875 if (range->assigned_register() == reg) { 1925 if (range->assigned_register() == reg) {
1876 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 1926 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
1877 if (next_pos == NULL) { 1927 if (next_pos == NULL) {
1878 SplitAndSpill(range, split_pos); 1928 SpillAfter(range, split_pos);
1879 } else { 1929 } else {
1880 SplitAndSpill(range, split_pos, next_pos->pos()); 1930 SpillBetween(range, split_pos, next_pos->pos());
1881 } 1931 }
1882 ActiveToHandled(range); 1932 ActiveToHandled(range);
1883 --i; 1933 --i;
1884 } 1934 }
1885 } 1935 }
1886 1936
1887 for (int i = 0; i < inactive_live_ranges_.length(); ++i) { 1937 for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1888 LiveRange* range = inactive_live_ranges_[i]; 1938 LiveRange* range = inactive_live_ranges_[i];
1889 ASSERT(range->End().Value() > current->Start().Value()); 1939 ASSERT(range->End().Value() > current->Start().Value());
1890 if (range->assigned_register() == reg && !range->IsFixed()) { 1940 if (range->assigned_register() == reg && !range->IsFixed()) {
1891 LifetimePosition next_intersection = range->FirstIntersection(current); 1941 LifetimePosition next_intersection = range->FirstIntersection(current);
1892 if (next_intersection.IsValid()) { 1942 if (next_intersection.IsValid()) {
1893 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 1943 UsePosition* next_pos = range->NextRegisterPosition(current->Start());
1894 if (next_pos == NULL) { 1944 if (next_pos == NULL) {
1895 SplitAndSpill(range, split_pos); 1945 SpillAfter(range, split_pos);
1896 } else { 1946 } else {
1897 next_intersection = Min(next_intersection, next_pos->pos()); 1947 next_intersection = Min(next_intersection, next_pos->pos());
1898 SplitAndSpill(range, split_pos, next_intersection); 1948 SpillBetween(range, split_pos, next_intersection);
1899 } 1949 }
1900 InactiveToHandled(range); 1950 InactiveToHandled(range);
1901 --i; 1951 --i;
1902 } 1952 }
1903 } 1953 }
1904 } 1954 }
1905 } 1955 }
1906 1956
1907 1957
1908 LiveRange* LAllocator::Split(LiveRange* range, 1958 bool LAllocator::IsBlockBoundary(LifetimePosition pos) {
1909 LifetimePosition start, 1959 return pos.IsInstructionStart() &&
1910 LifetimePosition end) { 1960 chunk_->instructions()->at(pos.InstructionIndex())->IsLabel();
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) {
1911 ASSERT(!range->IsFixed()); 1979 ASSERT(!range->IsFixed());
1912 TraceAlloc("Splitting live range %d in position between [%d, %d[\n", 1980 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value());
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",
1913 range->id(), 1995 range->id(),
1914 start.Value(), 1996 start.Value(),
1915 end.Value()); 1997 end.Value());
1916 1998
1917 LifetimePosition split_pos = FindOptimalSplitPos( 1999 LifetimePosition split_pos = FindOptimalSplitPos(start, end);
1918 start, end.PrevInstruction().InstructionEnd());
1919 ASSERT(split_pos.Value() >= start.Value()); 2000 ASSERT(split_pos.Value() >= start.Value());
1920 return Split(range, split_pos); 2001 return SplitAt(range, split_pos);
1921 } 2002 }
1922 2003
1923 2004
1924 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start, 2005 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start,
1925 LifetimePosition end) { 2006 LifetimePosition end) {
1926 int start_instr = start.InstructionIndex(); 2007 int start_instr = start.InstructionIndex();
1927 int end_instr = end.InstructionIndex(); 2008 int end_instr = end.InstructionIndex();
1928 ASSERT(start_instr <= end_instr); 2009 ASSERT(start_instr <= end_instr);
1929 2010
1930 // We have no choice 2011 // We have no choice
1931 if (start_instr == end_instr) return end; 2012 if (start_instr == end_instr) return end;
1932 2013
1933 HBasicBlock* end_block = GetBlock(start); 2014 HBasicBlock* end_block = GetBlock(start);
1934 HBasicBlock* start_block = GetBlock(end); 2015 HBasicBlock* start_block = GetBlock(end);
1935 2016
1936 if (end_block == start_block) { 2017 if (end_block == start_block) {
1937 // The interval is split in the same basic block. Split at latest possible 2018 // The interval is split in the same basic block. Split at latest possible
1938 // position. 2019 // position.
1939 return end; 2020 return end;
1940 } 2021 }
1941 2022
1942 HBasicBlock* block = end_block; 2023 HBasicBlock* block = end_block;
1943 // Move to the most outside loop header. 2024 // Find header of outermost loop.
1944 while (block->parent_loop_header() != NULL && 2025 while (block->parent_loop_header() != NULL &&
1945 block->parent_loop_header()->block_id() > start_block->block_id()) { 2026 block->parent_loop_header()->block_id() > start_block->block_id()) {
1946 block = block->parent_loop_header(); 2027 block = block->parent_loop_header();
1947 } 2028 }
1948 2029
1949 if (block == end_block) { 2030 if (block == end_block) return end;
1950 return end;
1951 }
1952 2031
1953 return LifetimePosition::FromInstructionIndex( 2032 return LifetimePosition::FromInstructionIndex(
1954 block->first_instruction_index()); 2033 block->first_instruction_index());
1955 } 2034 }
1956 2035
1957 2036
1958 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { 2037 void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) {
1959 return pos.IsInstructionStart() && 2038 LiveRange* second_part = SplitAt(range, pos);
1960 chunk_->instructions()->at(pos.InstructionIndex())->IsLabel(); 2039 Spill(second_part);
1961 } 2040 }
1962 2041
1963 2042
1964 void LAllocator::AddGapMove(int pos, LiveRange* prev, LiveRange* next) { 2043 void LAllocator::SpillBetween(LiveRange* range,
1965 UsePosition* prev_pos = prev->AddUsePosition( 2044 LifetimePosition start,
1966 LifetimePosition::FromInstructionIndex(pos)); 2045 LifetimePosition end) {
1967 UsePosition* next_pos = next->AddUsePosition( 2046 ASSERT(start.Value() < end.Value());
1968 LifetimePosition::FromInstructionIndex(pos)); 2047 LiveRange* second_part = SplitAt(range, start);
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 2048
2049 if (second_part->Start().Value() < end.Value()) {
2050 // The split result intersects with [start, end[.
2051 // Split it at position between ]start+1, end[, spill the middle part
2052 // and put the rest to unhandled.
2053 LiveRange* third_part = SplitBetween(
2054 second_part,
2055 second_part->Start().InstructionEnd(),
2056 end.PrevInstruction().InstructionEnd());
1977 2057
1978 LiveRange* LAllocator::Split(LiveRange* range, LifetimePosition pos) { 2058 ASSERT(third_part != second_part);
1979 ASSERT(!range->IsFixed());
1980 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value());
1981 if (pos.Value() <= range->Start().Value()) {
1982 return range;
1983 }
1984 LiveRange* result = LiveRangeFor(next_virtual_register_++);
1985 range->SplitAt(pos, result);
1986 return result;
1987 }
1988 2059
1989 2060 Spill(second_part);
1990 void LAllocator::SplitAndSpill(LiveRange* range,
1991 LifetimePosition start,
1992 LifetimePosition end) {
1993 // We have an interval range and want to make sure that it is
1994 // spilled at start and at most spilled until end.
1995 ASSERT(start.Value() < end.Value());
1996 LiveRange* tail_part = Split(range, start);
1997 if (tail_part->Start().Value() < end.Value()) {
1998 LiveRange* third_part = Split(tail_part,
1999 tail_part->Start().NextInstruction(),
2000 end);
2001 Spill(tail_part);
2002 ASSERT(third_part != tail_part);
2003 AddToUnhandledSorted(third_part); 2061 AddToUnhandledSorted(third_part);
2004 } else { 2062 } else {
2005 AddToUnhandledSorted(tail_part); 2063 // The split result does not intersect with [start, end[.
2064 // Nothing to spill. Just put it to unhandled as whole.
2065 AddToUnhandledSorted(second_part);
2006 } 2066 }
2007 } 2067 }
2008 2068
2009 2069
2010 void LAllocator::SplitAndSpill(LiveRange* range, LifetimePosition at) {
2011 LiveRange* second_part = Split(range, at);
2012 Spill(second_part);
2013 }
2014
2015
2016 void LAllocator::Spill(LiveRange* range) { 2070 void LAllocator::Spill(LiveRange* range) {
2017 ASSERT(!range->IsSpilled()); 2071 ASSERT(!range->IsSpilled());
2018 TraceAlloc("Spilling live range %d\n", range->id()); 2072 TraceAlloc("Spilling live range %d\n", range->id());
2019 LiveRange* first = range->TopLevel(); 2073 LiveRange* first = range->TopLevel();
2020 2074
2021 if (!first->HasAllocatedSpillOperand()) { 2075 if (!first->HasAllocatedSpillOperand()) {
2022 LOperand* op = TryReuseSpillSlot(range); 2076 LOperand* op = TryReuseSpillSlot(range);
2023 if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == XMM_REGISTERS); 2077 if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == DOUBLE_REGISTERS);
2024 first->SetSpillOperand(op); 2078 first->SetSpillOperand(op);
2025 } 2079 }
2026 range->MakeSpilled(); 2080 range->MakeSpilled();
2027 } 2081 }
2028 2082
2029 2083
2030 int LAllocator::RegisterCount() const { 2084 int LAllocator::RegisterCount() const {
2031 return num_registers_; 2085 return num_registers_;
2032 } 2086 }
2033 2087
2034 2088
2035 #ifdef DEBUG 2089 #ifdef DEBUG
2036 2090
2037 2091
2038 void LAllocator::Verify() const { 2092 void LAllocator::Verify() const {
2039 for (int i = 0; i < live_ranges()->length(); ++i) { 2093 for (int i = 0; i < live_ranges()->length(); ++i) {
2040 LiveRange* current = live_ranges()->at(i); 2094 LiveRange* current = live_ranges()->at(i);
2041 if (current != NULL) current->Verify(); 2095 if (current != NULL) current->Verify();
2042 } 2096 }
2043 } 2097 }
2044 2098
2045 2099
2046 #endif 2100 #endif
2047 2101
2048 2102
2049 } } // namespace v8::internal 2103 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/lithium-allocator.h ('k') | test/mjsunit/regress/regress-962.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698