Fixed two register allocator bugs (off-by-one error/failure propagation).

Minor cleanups on the way, e.g. making sure that we never use something after an allocation failed. Style question: Should we switch to some kind of MUST_USE_RESULT-style to ensure that we handle failures consistently? Not sure...

BUG=v8:2576

Review URL: https://codereview.chromium.org/12867002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13946 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
svenpanne@chromium.org 2013-03-14 14:42:00 +00:00
parent 9aa25ad1a0
commit aaf6340eb3
7 changed files with 35 additions and 13 deletions

View File

@ -675,8 +675,12 @@ LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
Abort("Out of virtual registers while trying to allocate temp register.");
return NULL;
}
operand->set_virtual_register(vreg);
return operand;
}

View File

@ -725,10 +725,12 @@ LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
Abort("Not enough virtual registers (temps).");
Abort("Out of virtual registers while trying to allocate temp register.");
return NULL;
}
operand->set_virtual_register(vreg);
return operand;
}

View File

@ -839,8 +839,9 @@ void LAllocator::MeetConstraintsBetween(LInstruction* first,
ASSERT(!cur_input->IsUsedAtStart());
LUnallocated* input_copy = cur_input->CopyUnconstrained(zone());
cur_input->set_virtual_register(GetVirtualRegister());
int vreg = GetVirtualRegister();
if (!AllocationOk()) return;
cur_input->set_virtual_register(vreg);
if (RequiredRegisterKind(input_copy->virtual_register()) ==
DOUBLE_REGISTERS) {
@ -1924,6 +1925,7 @@ void LAllocator::AllocateBlockedReg(LiveRange* current) {
LiveRange* tail = SplitBetween(current,
current->Start(),
block_pos[reg].InstructionStart());
if (!AllocationOk()) return;
AddToUnhandledSorted(tail);
}
@ -1954,6 +1956,7 @@ void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
} else {
SpillBetween(range, split_pos, next_pos->pos());
}
if (!AllocationOk()) return;
ActiveToHandled(range);
--i;
}
@ -1972,6 +1975,7 @@ void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
next_intersection = Min(next_intersection, next_pos->pos());
SpillBetween(range, split_pos, next_intersection);
}
if (!AllocationOk()) return;
InactiveToHandled(range);
--i;
}
@ -1997,8 +2001,9 @@ LiveRange* LAllocator::SplitRangeAt(LiveRange* range, LifetimePosition pos) {
ASSERT(pos.IsInstructionStart() ||
!chunk_->instructions()->at(pos.InstructionIndex())->IsControl());
LiveRange* result = LiveRangeFor(GetVirtualRegister());
int vreg = GetVirtualRegister();
if (!AllocationOk()) return NULL;
LiveRange* result = LiveRangeFor(vreg);
range->SplitAt(pos, result, zone_);
return result;
}
@ -2075,6 +2080,7 @@ void LAllocator::SpillBetween(LiveRange* range,
second_part,
second_part->Start().InstructionEnd(),
end.PrevInstruction().InstructionEnd());
if (!AllocationOk()) return;
ASSERT(third_part != second_part);

View File

@ -427,8 +427,10 @@ class LAllocator BASE_EMBEDDED {
Zone* zone() const { return zone_; }
int GetVirtualRegister() {
if (next_virtual_register_ > LUnallocated::kMaxVirtualRegisters) {
if (next_virtual_register_ >= LUnallocated::kMaxVirtualRegisters) {
allocation_ok_ = false;
// Maintain the invariant that we return something below the maximum.
return 0;
}
return next_virtual_register_++;
}

View File

@ -668,8 +668,12 @@ LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
Abort("Out of virtual registers while trying to allocate temp register.");
return NULL;
}
operand->set_virtual_register(vreg);
return operand;
}

View File

@ -683,8 +683,12 @@ LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
Abort("Out of virtual registers while trying to allocate temp register.");
return NULL;
}
operand->set_virtual_register(vreg);
return operand;
}

View File

@ -1731,9 +1731,9 @@ TEST(MapHasDescriptorsAndTransitions) {
TEST(ManyLocalsInSharedContext) {
v8::HandleScope scope;
LocalContext env;
int num_objects = 5000;
int num_objects = 6000;
CompileRun(
"var n = 5000;"
"var n = 6000;"
"var result = [];"
"result.push('(function outer() {');"
"for (var i = 0; i < n; i++) {"