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