Change MergeTo code for virtual frames to use register indices.

Review URL: http://codereview.chromium.org/99052

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1808 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2009-04-28 13:53:15 +00:00
parent aa04659a82
commit 62c4153442
2 changed files with 62 additions and 71 deletions

View File

@ -310,65 +310,34 @@ void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
// We have already done X-to-memory moves. // We have already done X-to-memory moves.
ASSERT(stack_pointer_ >= expected->stack_pointer_); ASSERT(stack_pointer_ >= expected->stack_pointer_);
// Perform register-to-register moves. for (int i = 0; i < kNumRegisters; i++) {
int start = 0; // Move the right value into register i if it is currently in a register.
int end = elements_.length() - 1; int index = expected->register_locations_[i];
bool any_moves_blocked; // Did we fail to make some moves this iteration? int use_index = register_locations_[i];
bool should_break_cycles = false; // Fast check if register is unused in target or already correct
bool any_moves_made; // Did we make any progress this iteration? if (index != kIllegalIndex
do { && index != use_index
any_moves_blocked = false; && elements_[index].is_register()) {
any_moves_made = false; Register source = elements_[index].reg();
int first_move_blocked = kIllegalIndex; Register target = { i };
int last_move_blocked = kIllegalIndex; if (use_index == kIllegalIndex) { // Target is currently unused.
for (int i = start; i <= end; i++) { // Copy contents of source from source to target.
FrameElement source = elements_[i]; // Set frame element register to target.
FrameElement target = expected->elements_[i]; elements_[index].set_reg(target);
if (source.is_register() && target.is_register()) { Use(target, index);
if (target.reg().is(source.reg())) { Unuse(source);
if (target.is_synced() && !source.is_synced()) { __ mov(target, source);
__ mov(Operand(ebp, fp_relative(i)), source.reg());
}
elements_[i] = target;
} else { } else {
// We need to move source to target. // Exchange contents of registers source and target.
if (is_used(target.reg())) { elements_[use_index].set_reg(source);
// The move is blocked because the target contains valid data. elements_[index].set_reg(target);
// If we are stuck with only cycles remaining, then we spill source. register_locations_[target.code()] = index;
// Otherwise, we just need more iterations. register_locations_[source.code()] = use_index;
if (should_break_cycles) { __ xchg(source, target);
SpillElementAt(i);
should_break_cycles = false;
} else { // Record a blocked move.
if (!any_moves_blocked) {
first_move_blocked = i;
}
last_move_blocked = i;
any_moves_blocked = true;
}
} else {
// The move is not blocked. This frame element can be moved from
// its source register to its target register.
if (target.is_synced() && !source.is_synced()) {
SyncElementAt(i);
}
Use(target.reg(), i);
Unuse(source.reg());
elements_[i] = target;
__ mov(target.reg(), source.reg());
any_moves_made = true;
} }
} }
} }
} }
// Update control flags for next iteration.
should_break_cycles = (any_moves_blocked && !any_moves_made);
if (any_moves_blocked) {
start = first_move_blocked;
end = last_move_blocked;
}
} while (any_moves_blocked);
}
void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
@ -376,19 +345,22 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
// final step and is done from the bottom up so that the backing // final step and is done from the bottom up so that the backing
// elements of copies are in their correct locations when we // elements of copies are in their correct locations when we
// encounter the copies. // encounter the copies.
for (int i = 0; i < elements_.length(); i++) { for (int i = 0; i < kNumRegisters; i++) {
FrameElement source = elements_[i]; int index = expected->register_locations_[i];
FrameElement target = expected->elements_[i]; if (index != kIllegalIndex) {
if (target.is_register() && !source.is_register()) { FrameElement source = elements_[index];
FrameElement target = expected->elements_[index];
switch (source.type()) { switch (source.type()) {
case FrameElement::INVALID: // Fall through. case FrameElement::INVALID: // Fall through.
case FrameElement::REGISTER:
UNREACHABLE(); UNREACHABLE();
break; break;
case FrameElement::REGISTER:
ASSERT(source.reg().is(target.reg()));
continue; // Go to next iteration. Skips Use(target.reg()) below.
break;
case FrameElement::MEMORY: case FrameElement::MEMORY:
ASSERT(i <= stack_pointer_); ASSERT(index <= stack_pointer_);
__ mov(target.reg(), Operand(ebp, fp_relative(i))); __ mov(target.reg(), Operand(ebp, fp_relative(index)));
break; break;
case FrameElement::CONSTANT: case FrameElement::CONSTANT:
@ -400,11 +372,25 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
break; break;
case FrameElement::COPY: { case FrameElement::COPY: {
FrameElement backing = elements_[source.index()]; int backing_index = source.index();
FrameElement backing = elements_[backing_index];
ASSERT(backing.is_memory() || backing.is_register()); ASSERT(backing.is_memory() || backing.is_register());
if (backing.is_memory()) { if (backing.is_memory()) {
ASSERT(source.index() <= stack_pointer_); ASSERT(backing_index <= stack_pointer_);
__ mov(target.reg(), Operand(ebp, fp_relative(source.index()))); // Code optimization if backing store should also move
// to a register: move backing store to its register first.
if (expected->elements_[backing_index].is_register()) {
FrameElement new_backing = expected->elements_[backing_index];
Register new_backing_reg = new_backing.reg();
ASSERT(!is_used(new_backing_reg));
elements_[backing_index] = new_backing;
Use(new_backing_reg, backing_index);
__ mov(new_backing_reg,
Operand(ebp, fp_relative(backing_index)));
__ mov(target.reg(), new_backing_reg);
} else {
__ mov(target.reg(), Operand(ebp, fp_relative(backing_index)));
}
} else { } else {
__ mov(target.reg(), backing.reg()); __ mov(target.reg(), backing.reg());
} }
@ -412,11 +398,11 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
} }
// Ensure the proper sync state. If the source was memory no // Ensure the proper sync state. If the source was memory no
// code needs to be emitted. // code needs to be emitted.
if (target.is_synced() && !source.is_memory()) { if (target.is_synced() && !source.is_synced()) {
SyncElementAt(i); __ mov(Operand(ebp, fp_relative(index)), target.reg());
} }
Use(target.reg(), i); Use(target.reg(), index);
elements_[i] = target; elements_[index] = target;
} }
} }
} }

View File

@ -191,6 +191,11 @@ class FrameElement BASE_EMBEDDED {
data_.index_ = new_index; data_.index_ = new_index;
} }
void set_reg(Register new_reg) {
ASSERT(is_register());
data_.reg_ = new_reg;
}
friend class VirtualFrame; friend class VirtualFrame;
}; };