Index: src/ia32/virtual-frame-ia32.cc |
=================================================================== |
--- src/ia32/virtual-frame-ia32.cc (revision 3954) |
+++ src/ia32/virtual-frame-ia32.cc (working copy) |
@@ -895,30 +895,39 @@ |
} |
+// This function assumes that the only results that could be in a_reg or b_reg |
+// are a and b. Other results can be live, but must not be in a_reg or b_reg. |
+void VirtualFrame::MoveResultsToRegisters(Result* a, |
+ Result* b, |
+ Register a_reg, |
+ Register b_reg) { |
+ if (a->is_register() && a->reg().is(a_reg)) { |
+ b->ToRegister(b_reg); |
+ } else if (!cgen()->allocator()->is_used(a_reg)) { |
+ a->ToRegister(a_reg); |
+ b->ToRegister(b_reg); |
+ } else if (cgen()->allocator()->is_used(b_reg)) { |
+ // a must be in b_reg, b in a_reg. |
+ __ xchg(a_reg, b_reg); |
+ // Results a and b will be invalidated, so it is ok if they are switched. |
+ } else { |
+ b->ToRegister(b_reg); |
+ a->ToRegister(a_reg); |
+ } |
+ a->Unuse(); |
+ b->Unuse(); |
+} |
+ |
+ |
Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { |
// Name and receiver are on the top of the frame. The IC expects |
// name in ecx and receiver in eax. |
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
Result name = Pop(); |
Result receiver = Pop(); |
PrepareForCall(0, 0); // No stack arguments. |
- // Move results to the right registers: |
- if (name.is_register() && name.reg().is(eax)) { |
- if (receiver.is_register() && receiver.reg().is(ecx)) { |
- // Wrong registers. |
- __ xchg(eax, ecx); |
- } else { |
- // Register ecx is free for name, which frees eax for receiver. |
- name.ToRegister(ecx); |
- receiver.ToRegister(eax); |
- } |
- } else { |
- // Register eax is free for receiver, which frees ecx for name. |
- receiver.ToRegister(eax); |
- name.ToRegister(ecx); |
- } |
- name.Unuse(); |
- receiver.Unuse(); |
+ MoveResultsToRegisters(&name, &receiver, ecx, eax); |
+ |
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
return RawCallCodeObject(ic, mode); |
} |
@@ -928,21 +937,8 @@ |
Result key = Pop(); |
Result receiver = Pop(); |
PrepareForCall(0, 0); |
+ MoveResultsToRegisters(&key, &receiver, eax, edx); |
- if (!key.is_register() || !key.reg().is(edx)) { |
- // Register edx is available for receiver. |
- receiver.ToRegister(edx); |
- key.ToRegister(eax); |
- } else if (!receiver.is_register() || !receiver.reg().is(eax)) { |
- // Register eax is available for key. |
- key.ToRegister(eax); |
- receiver.ToRegister(edx); |
- } else { |
- __ xchg(edx, eax); |
- } |
- key.Unuse(); |
- receiver.Unuse(); |
- |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
return RawCallCodeObject(ic, mode); |
} |
@@ -958,41 +954,57 @@ |
value.ToRegister(eax); |
__ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
__ mov(ecx, name); |
+ value.Unuse(); |
} else { |
Result receiver = Pop(); |
PrepareForCall(0, 0); |
- |
- if (value.is_register() && value.reg().is(edx)) { |
- if (receiver.is_register() && receiver.reg().is(eax)) { |
- // Wrong registers. |
- __ xchg(eax, edx); |
- } else { |
- // Register eax is free for value, which frees edx for receiver. |
- value.ToRegister(eax); |
- receiver.ToRegister(edx); |
- } |
- } else { |
- // Register edx is free for receiver, which guarantees eax is free for |
- // value. |
- receiver.ToRegister(edx); |
- value.ToRegister(eax); |
- } |
+ MoveResultsToRegisters(&value, &receiver, eax, edx); |
} |
__ mov(ecx, name); |
- value.Unuse(); |
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); |
} |
Result VirtualFrame::CallKeyedStoreIC() { |
// Value, key, and receiver are on the top of the frame. The IC |
- // expects value in eax and key and receiver on the stack. It does |
- // not drop the key and receiver. |
+ // expects value in eax, key in ecx, and receiver in edx. |
+ Result value = Pop(); |
+ Result key = Pop(); |
+ Result receiver = Pop(); |
+ PrepareForCall(0, 0); |
+ if (!cgen()->allocator()->is_used(eax) || |
+ (value.is_register() && value.reg().is(eax))) { |
+ value.ToRegister(eax); // No effect if value is in eax already. |
+ MoveResultsToRegisters(&key, &receiver, ecx, edx); |
+ value.Unuse(); |
+ } else if (!cgen()->allocator()->is_used(ecx) || |
+ (key.is_register() && key.reg().is(ecx))) { |
+ // Receiver and/or key are in eax. |
+ key.ToRegister(ecx); |
+ MoveResultsToRegisters(&value, &receiver, eax, edx); |
+ key.Unuse(); |
+ } else if (!cgen()->allocator()->is_used(edx) || |
+ (receiver.is_register() && receiver.reg().is(edx))) { |
+ receiver.ToRegister(edx); |
+ MoveResultsToRegisters(&key, &value, ecx, eax); |
+ receiver.Unuse(); |
+ } else { |
+ // All three registers are used, and no value is in the correct place. |
+ // We have one of the two circular permutations of eax, ecx, edx. |
+ ASSERT(value.is_register()); |
+ if (value.reg().is(ecx)) { |
+ __ xchg(eax, edx); |
+ __ xchg(eax, ecx); |
+ } else { |
+ __ xchg(eax, ecx); |
+ __ xchg(eax, edx); |
+ } |
+ value.Unuse(); |
+ key.Unuse(); |
+ receiver.Unuse(); |
+ } |
+ |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
- Result value = Pop(); |
- PrepareForCall(2, 0); // Two stack args, neither callee-dropped. |
- value.ToRegister(eax); |
- value.Unuse(); |
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); |
} |