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

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

Issue 9325019: Allow bailing out of the register allocator when running out of virtual registers. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 8 years, 10 months 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') | src/mips/lithium-mips.cc » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 } else { 539 } else {
540 b = b->next(); 540 b = b->next();
541 } 541 }
542 } 542 }
543 return LifetimePosition::Invalid(); 543 return LifetimePosition::Invalid();
544 } 544 }
545 545
546 546
547 LAllocator::LAllocator(int num_values, HGraph* graph) 547 LAllocator::LAllocator(int num_values, HGraph* graph)
548 : chunk_(NULL), 548 : chunk_(NULL),
549 allocation_ok_(true),
549 live_in_sets_(graph->blocks()->length()), 550 live_in_sets_(graph->blocks()->length()),
550 live_ranges_(num_values * 2), 551 live_ranges_(num_values * 2),
551 fixed_live_ranges_(NULL), 552 fixed_live_ranges_(NULL),
552 fixed_double_live_ranges_(NULL), 553 fixed_double_live_ranges_(NULL),
553 unhandled_live_ranges_(num_values * 2), 554 unhandled_live_ranges_(num_values * 2),
554 active_live_ranges_(8), 555 active_live_ranges_(8),
555 inactive_live_ranges_(8), 556 inactive_live_ranges_(8),
556 reusable_slots_(8), 557 reusable_slots_(8),
557 next_virtual_register_(num_values), 558 next_virtual_register_(num_values),
558 first_artificial_register_(num_values), 559 first_artificial_register_(num_values),
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 void LAllocator::MeetRegisterConstraints(HBasicBlock* block) { 781 void LAllocator::MeetRegisterConstraints(HBasicBlock* block) {
781 int start = block->first_instruction_index(); 782 int start = block->first_instruction_index();
782 int end = block->last_instruction_index(); 783 int end = block->last_instruction_index();
783 for (int i = start; i <= end; ++i) { 784 for (int i = start; i <= end; ++i) {
784 if (IsGapAt(i)) { 785 if (IsGapAt(i)) {
785 LInstruction* instr = NULL; 786 LInstruction* instr = NULL;
786 LInstruction* prev_instr = NULL; 787 LInstruction* prev_instr = NULL;
787 if (i < end) instr = InstructionAt(i + 1); 788 if (i < end) instr = InstructionAt(i + 1);
788 if (i > start) prev_instr = InstructionAt(i - 1); 789 if (i > start) prev_instr = InstructionAt(i - 1);
789 MeetConstraintsBetween(prev_instr, instr, i); 790 MeetConstraintsBetween(prev_instr, instr, i);
791 if (!AllocationOk()) return;
790 } 792 }
791 } 793 }
792 } 794 }
793 795
794 796
795 void LAllocator::MeetConstraintsBetween(LInstruction* first, 797 void LAllocator::MeetConstraintsBetween(LInstruction* first,
796 LInstruction* second, 798 LInstruction* second,
797 int gap_index) { 799 int gap_index) {
798 // Handle fixed temporaries. 800 // Handle fixed temporaries.
799 if (first != NULL) { 801 if (first != NULL) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 LUnallocated* input_copy = cur_input->CopyUnconstrained(); 847 LUnallocated* input_copy = cur_input->CopyUnconstrained();
846 bool is_tagged = HasTaggedValue(cur_input->virtual_register()); 848 bool is_tagged = HasTaggedValue(cur_input->virtual_register());
847 AllocateFixed(cur_input, gap_index + 1, is_tagged); 849 AllocateFixed(cur_input, gap_index + 1, is_tagged);
848 AddConstraintsGapMove(gap_index, input_copy, cur_input); 850 AddConstraintsGapMove(gap_index, input_copy, cur_input);
849 } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) { 851 } else if (cur_input->policy() == LUnallocated::WRITABLE_REGISTER) {
850 // The live range of writable input registers always goes until the end 852 // The live range of writable input registers always goes until the end
851 // of the instruction. 853 // of the instruction.
852 ASSERT(!cur_input->IsUsedAtStart()); 854 ASSERT(!cur_input->IsUsedAtStart());
853 855
854 LUnallocated* input_copy = cur_input->CopyUnconstrained(); 856 LUnallocated* input_copy = cur_input->CopyUnconstrained();
855 cur_input->set_virtual_register(next_virtual_register_++); 857 cur_input->set_virtual_register(GetVirtualRegister());
858 if(!AllocationOk()) return;
856 859
857 if (RequiredRegisterKind(input_copy->virtual_register()) == 860 if (RequiredRegisterKind(input_copy->virtual_register()) ==
858 DOUBLE_REGISTERS) { 861 DOUBLE_REGISTERS) {
859 double_artificial_registers_.Add( 862 double_artificial_registers_.Add(
860 cur_input->virtual_register() - first_artificial_register_); 863 cur_input->virtual_register() - first_artificial_register_);
861 } 864 }
862 865
863 AddConstraintsGapMove(gap_index, input_copy, cur_input); 866 AddConstraintsGapMove(gap_index, input_copy, cur_input);
864 } 867 }
865 } 868 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 1065
1063 LiveRange* live_range = LiveRangeFor(phi->id()); 1066 LiveRange* live_range = LiveRangeFor(phi->id());
1064 LLabel* label = chunk_->GetLabel(phi->block()->block_id()); 1067 LLabel* label = chunk_->GetLabel(phi->block()->block_id());
1065 label->GetOrCreateParallelMove(LGap::START)-> 1068 label->GetOrCreateParallelMove(LGap::START)->
1066 AddMove(phi_operand, live_range->GetSpillOperand()); 1069 AddMove(phi_operand, live_range->GetSpillOperand());
1067 live_range->SetSpillStartIndex(phi->block()->first_instruction_index()); 1070 live_range->SetSpillStartIndex(phi->block()->first_instruction_index());
1068 } 1071 }
1069 } 1072 }
1070 1073
1071 1074
1072 void LAllocator::Allocate(LChunk* chunk) { 1075 bool LAllocator::Allocate(LChunk* chunk) {
1073 ASSERT(chunk_ == NULL); 1076 ASSERT(chunk_ == NULL);
1074 chunk_ = chunk; 1077 chunk_ = chunk;
1075 MeetRegisterConstraints(); 1078 MeetRegisterConstraints();
1079 if (!AllocationOk()) return false;
1076 ResolvePhis(); 1080 ResolvePhis();
1077 BuildLiveRanges(); 1081 BuildLiveRanges();
1078 AllocateGeneralRegisters(); 1082 AllocateGeneralRegisters();
1083 if (!AllocationOk()) return false;
1079 AllocateDoubleRegisters(); 1084 AllocateDoubleRegisters();
1085 if (!AllocationOk()) return false;
1080 PopulatePointerMaps(); 1086 PopulatePointerMaps();
1081 if (has_osr_entry_) ProcessOsrEntry(); 1087 if (has_osr_entry_) ProcessOsrEntry();
1082 ConnectRanges(); 1088 ConnectRanges();
1083 ResolveControlFlow(); 1089 ResolveControlFlow();
1090 return true;
1084 } 1091 }
1085 1092
1086 1093
1087 void LAllocator::MeetRegisterConstraints() { 1094 void LAllocator::MeetRegisterConstraints() {
1088 HPhase phase("Register constraints", chunk_); 1095 HPhase phase("Register constraints", chunk_);
1089 first_artificial_register_ = next_virtual_register_; 1096 first_artificial_register_ = next_virtual_register_;
1090 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); 1097 const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1091 for (int i = 0; i < blocks->length(); ++i) { 1098 for (int i = 0; i < blocks->length(); ++i) {
1092 HBasicBlock* block = blocks->at(i); 1099 HBasicBlock* block = blocks->at(i);
1093 MeetRegisterConstraints(block); 1100 MeetRegisterConstraints(block);
1101 if (!AllocationOk()) return;
1094 } 1102 }
1095 } 1103 }
1096 1104
1097 1105
1098 void LAllocator::ResolvePhis() { 1106 void LAllocator::ResolvePhis() {
1099 HPhase phase("Resolve phis", chunk_); 1107 HPhase phase("Resolve phis", chunk_);
1100 1108
1101 // Process the blocks in reverse order. 1109 // Process the blocks in reverse order.
1102 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); 1110 const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1103 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) { 1111 for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) {
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 // If the range already has a spill operand and it doesn't need a 1545 // If the range already has a spill operand and it doesn't need a
1538 // register immediately, split it and spill the first part of the range. 1546 // register immediately, split it and spill the first part of the range.
1539 if (pos == NULL) { 1547 if (pos == NULL) {
1540 Spill(current); 1548 Spill(current);
1541 continue; 1549 continue;
1542 } else if (pos->pos().Value() > 1550 } else if (pos->pos().Value() >
1543 current->Start().NextInstruction().Value()) { 1551 current->Start().NextInstruction().Value()) {
1544 // Do not spill live range eagerly if use position that can benefit from 1552 // Do not spill live range eagerly if use position that can benefit from
1545 // the register is too close to the start of live range. 1553 // the register is too close to the start of live range.
1546 SpillBetween(current, current->Start(), pos->pos()); 1554 SpillBetween(current, current->Start(), pos->pos());
1555 if (!AllocationOk()) return;
1547 ASSERT(UnhandledIsSorted()); 1556 ASSERT(UnhandledIsSorted());
1548 continue; 1557 continue;
1549 } 1558 }
1550 } 1559 }
1551 1560
1552 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1561 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1553 LiveRange* cur_active = active_live_ranges_.at(i); 1562 LiveRange* cur_active = active_live_ranges_.at(i);
1554 if (cur_active->End().Value() <= position.Value()) { 1563 if (cur_active->End().Value() <= position.Value()) {
1555 ActiveToHandled(cur_active); 1564 ActiveToHandled(cur_active);
1556 --i; // The live range was removed from the list of active live ranges. 1565 --i; // The live range was removed from the list of active live ranges.
(...skipping 10 matching lines...) Expand all
1567 --i; // Live range was removed from the list of inactive live ranges. 1576 --i; // Live range was removed from the list of inactive live ranges.
1568 } else if (cur_inactive->Covers(position)) { 1577 } else if (cur_inactive->Covers(position)) {
1569 InactiveToActive(cur_inactive); 1578 InactiveToActive(cur_inactive);
1570 --i; // Live range was removed from the list of inactive live ranges. 1579 --i; // Live range was removed from the list of inactive live ranges.
1571 } 1580 }
1572 } 1581 }
1573 1582
1574 ASSERT(!current->HasRegisterAssigned() && !current->IsSpilled()); 1583 ASSERT(!current->HasRegisterAssigned() && !current->IsSpilled());
1575 1584
1576 bool result = TryAllocateFreeReg(current); 1585 bool result = TryAllocateFreeReg(current);
1577 if (!result) { 1586 if (!AllocationOk()) return;
1578 AllocateBlockedReg(current); 1587
1579 } 1588 if (!result) AllocateBlockedReg(current);
1589 if (!AllocationOk()) return;
1580 1590
1581 if (current->HasRegisterAssigned()) { 1591 if (current->HasRegisterAssigned()) {
1582 AddToActive(current); 1592 AddToActive(current);
1583 } 1593 }
1584 } 1594 }
1585 1595
1586 reusable_slots_.Rewind(0); 1596 reusable_slots_.Rewind(0);
1587 active_live_ranges_.Rewind(0); 1597 active_live_ranges_.Rewind(0);
1588 inactive_live_ranges_.Rewind(0); 1598 inactive_live_ranges_.Rewind(0);
1589 } 1599 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1623 } 1633 }
1624 } else if (double_artificial_registers_.Contains( 1634 } else if (double_artificial_registers_.Contains(
1625 virtual_register - first_artificial_register_)) { 1635 virtual_register - first_artificial_register_)) {
1626 return DOUBLE_REGISTERS; 1636 return DOUBLE_REGISTERS;
1627 } 1637 }
1628 1638
1629 return GENERAL_REGISTERS; 1639 return GENERAL_REGISTERS;
1630 } 1640 }
1631 1641
1632 1642
1633 void LAllocator::RecordDefinition(HInstruction* instr, LUnallocated* operand) {
1634 operand->set_virtual_register(instr->id());
1635 }
1636
1637
1638 void LAllocator::RecordTemporary(LUnallocated* operand) {
1639 ASSERT(next_virtual_register_ < LUnallocated::kMaxVirtualRegisters);
1640 if (!operand->HasFixedPolicy()) {
1641 operand->set_virtual_register(next_virtual_register_++);
1642 }
1643 }
1644
1645
1646 void LAllocator::RecordUse(HValue* value, LUnallocated* operand) {
1647 operand->set_virtual_register(value->id());
1648 }
1649
1650
1651 int LAllocator::max_initial_value_ids() {
1652 return LUnallocated::kMaxVirtualRegisters / 16;
1653 }
1654
1655
1656 void LAllocator::AddToActive(LiveRange* range) { 1643 void LAllocator::AddToActive(LiveRange* range) {
1657 TraceAlloc("Add live range %d to active\n", range->id()); 1644 TraceAlloc("Add live range %d to active\n", range->id());
1658 active_live_ranges_.Add(range); 1645 active_live_ranges_.Add(range);
1659 } 1646 }
1660 1647
1661 1648
1662 void LAllocator::AddToInactive(LiveRange* range) { 1649 void LAllocator::AddToInactive(LiveRange* range) {
1663 TraceAlloc("Add live range %d to inactive\n", range->id()); 1650 TraceAlloc("Add live range %d to inactive\n", range->id());
1664 inactive_live_ranges_.Add(range); 1651 inactive_live_ranges_.Add(range);
1665 } 1652 }
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1840 LifetimePosition pos = free_until_pos[reg]; 1827 LifetimePosition pos = free_until_pos[reg];
1841 1828
1842 if (pos.Value() <= current->Start().Value()) { 1829 if (pos.Value() <= current->Start().Value()) {
1843 // All registers are blocked. 1830 // All registers are blocked.
1844 return false; 1831 return false;
1845 } 1832 }
1846 1833
1847 if (pos.Value() < current->End().Value()) { 1834 if (pos.Value() < current->End().Value()) {
1848 // Register reg is available at the range start but becomes blocked before 1835 // Register reg is available at the range start but becomes blocked before
1849 // the range end. Split current at position where it becomes blocked. 1836 // the range end. Split current at position where it becomes blocked.
1850 LiveRange* tail = SplitAt(current, pos); 1837 LiveRange* tail = SplitRangeAt(current, pos);
1838 if (!AllocationOk()) return false;
1851 AddToUnhandledSorted(tail); 1839 AddToUnhandledSorted(tail);
1852 } 1840 }
1853 1841
1854 1842
1855 // Register reg is available at the range start and is free until 1843 // Register reg is available at the range start and is free until
1856 // the range end. 1844 // the range end.
1857 ASSERT(pos.Value() >= current->End().Value()); 1845 ASSERT(pos.Value() >= current->End().Value());
1858 TraceAlloc("Assigning free reg %s to live range %d\n", 1846 TraceAlloc("Assigning free reg %s to live range %d\n",
1859 RegisterName(reg), 1847 RegisterName(reg),
1860 current->id()); 1848 current->id());
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 } 1983 }
1996 } 1984 }
1997 1985
1998 1986
1999 bool LAllocator::IsBlockBoundary(LifetimePosition pos) { 1987 bool LAllocator::IsBlockBoundary(LifetimePosition pos) {
2000 return pos.IsInstructionStart() && 1988 return pos.IsInstructionStart() &&
2001 InstructionAt(pos.InstructionIndex())->IsLabel(); 1989 InstructionAt(pos.InstructionIndex())->IsLabel();
2002 } 1990 }
2003 1991
2004 1992
2005 LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) { 1993 LiveRange* LAllocator::SplitRangeAt(LiveRange* range, LifetimePosition pos) {
2006 ASSERT(!range->IsFixed()); 1994 ASSERT(!range->IsFixed());
2007 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value()); 1995 TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value());
2008 1996
2009 if (pos.Value() <= range->Start().Value()) return range; 1997 if (pos.Value() <= range->Start().Value()) return range;
2010 1998
2011 // We can't properly connect liveranges if split occured at the end 1999 // We can't properly connect liveranges if split occured at the end
2012 // of control instruction. 2000 // of control instruction.
2013 ASSERT(pos.IsInstructionStart() || 2001 ASSERT(pos.IsInstructionStart() ||
2014 !chunk_->instructions()->at(pos.InstructionIndex())->IsControl()); 2002 !chunk_->instructions()->at(pos.InstructionIndex())->IsControl());
2015 2003
2016 LiveRange* result = LiveRangeFor(next_virtual_register_++); 2004 LiveRange* result = LiveRangeFor(GetVirtualRegister());
2005 if (!AllocationOk()) return NULL;
2017 range->SplitAt(pos, result); 2006 range->SplitAt(pos, result);
2018 return result; 2007 return result;
2019 } 2008 }
2020 2009
2021 2010
2022 LiveRange* LAllocator::SplitBetween(LiveRange* range, 2011 LiveRange* LAllocator::SplitBetween(LiveRange* range,
2023 LifetimePosition start, 2012 LifetimePosition start,
2024 LifetimePosition end) { 2013 LifetimePosition end) {
2025 ASSERT(!range->IsFixed()); 2014 ASSERT(!range->IsFixed());
2026 TraceAlloc("Splitting live range %d in position between [%d, %d]\n", 2015 TraceAlloc("Splitting live range %d in position between [%d, %d]\n",
2027 range->id(), 2016 range->id(),
2028 start.Value(), 2017 start.Value(),
2029 end.Value()); 2018 end.Value());
2030 2019
2031 LifetimePosition split_pos = FindOptimalSplitPos(start, end); 2020 LifetimePosition split_pos = FindOptimalSplitPos(start, end);
2032 ASSERT(split_pos.Value() >= start.Value()); 2021 ASSERT(split_pos.Value() >= start.Value());
2033 return SplitAt(range, split_pos); 2022 return SplitRangeAt(range, split_pos);
2034 } 2023 }
2035 2024
2036 2025
2037 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start, 2026 LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start,
2038 LifetimePosition end) { 2027 LifetimePosition end) {
2039 int start_instr = start.InstructionIndex(); 2028 int start_instr = start.InstructionIndex();
2040 int end_instr = end.InstructionIndex(); 2029 int end_instr = end.InstructionIndex();
2041 ASSERT(start_instr <= end_instr); 2030 ASSERT(start_instr <= end_instr);
2042 2031
2043 // We have no choice 2032 // We have no choice
(...skipping 18 matching lines...) Expand all
2062 // We did not find any suitable outer loop. Split at the latest possible 2051 // We did not find any suitable outer loop. Split at the latest possible
2063 // position unless end_block is a loop header itself. 2052 // position unless end_block is a loop header itself.
2064 if (block == end_block && !end_block->IsLoopHeader()) return end; 2053 if (block == end_block && !end_block->IsLoopHeader()) return end;
2065 2054
2066 return LifetimePosition::FromInstructionIndex( 2055 return LifetimePosition::FromInstructionIndex(
2067 block->first_instruction_index()); 2056 block->first_instruction_index());
2068 } 2057 }
2069 2058
2070 2059
2071 void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { 2060 void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) {
2072 LiveRange* second_part = SplitAt(range, pos); 2061 LiveRange* second_part = SplitRangeAt(range, pos);
2062 if (!AllocationOk()) return;
2073 Spill(second_part); 2063 Spill(second_part);
2074 } 2064 }
2075 2065
2076 2066
2077 void LAllocator::SpillBetween(LiveRange* range, 2067 void LAllocator::SpillBetween(LiveRange* range,
2078 LifetimePosition start, 2068 LifetimePosition start,
2079 LifetimePosition end) { 2069 LifetimePosition end) {
2080 ASSERT(start.Value() < end.Value()); 2070 ASSERT(start.Value() < end.Value());
2081 LiveRange* second_part = SplitAt(range, start); 2071 LiveRange* second_part = SplitRangeAt(range, start);
2072 if (!AllocationOk()) return;
2082 2073
2083 if (second_part->Start().Value() < end.Value()) { 2074 if (second_part->Start().Value() < end.Value()) {
2084 // The split result intersects with [start, end[. 2075 // The split result intersects with [start, end[.
2085 // Split it at position between ]start+1, end[, spill the middle part 2076 // Split it at position between ]start+1, end[, spill the middle part
2086 // and put the rest to unhandled. 2077 // and put the rest to unhandled.
2087 LiveRange* third_part = SplitBetween( 2078 LiveRange* third_part = SplitBetween(
2088 second_part, 2079 second_part,
2089 second_part->Start().InstructionEnd(), 2080 second_part->Start().InstructionEnd(),
2090 end.PrevInstruction().InstructionEnd()); 2081 end.PrevInstruction().InstructionEnd());
2091 2082
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2128 LiveRange* current = live_ranges()->at(i); 2119 LiveRange* current = live_ranges()->at(i);
2129 if (current != NULL) current->Verify(); 2120 if (current != NULL) current->Verify();
2130 } 2121 }
2131 } 2122 }
2132 2123
2133 2124
2134 #endif 2125 #endif
2135 2126
2136 2127
2137 } } // namespace v8::internal 2128 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/lithium-allocator.h ('k') | src/mips/lithium-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698