Index: src/ia32/lithium-codegen-ia32.cc |
=================================================================== |
--- src/ia32/lithium-codegen-ia32.cc (revision 6029) |
+++ src/ia32/lithium-codegen-ia32.cc (working copy) |
@@ -2255,47 +2255,55 @@ |
void LCodeGen::DoPower(LPower* instr) { |
LOperand* left = instr->left(); |
LOperand* right = instr->right(); |
+ DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
Representation exponent_type = instr->hydrogen()->right()->representation(); |
if (exponent_type.IsDouble()) { |
- // Pass two doubles as arguments on the stack. |
- __ PrepareCallCFunction(4, eax); |
+ // It is safe to use ebx directly since the instruction is marked |
+ // as a call. |
+ __ PrepareCallCFunction(4, ebx); |
__ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
__ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); |
__ CallCFunction(ExternalReference::power_double_double_function(), 4); |
} else if (exponent_type.IsInteger32()) { |
+ // It is safe to use ebx directly since the instruction is marked |
+ // as a call. |
+ ASSERT(!ToRegister(right).is(ebx)); |
__ PrepareCallCFunction(4, ebx); |
__ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
__ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); |
__ CallCFunction(ExternalReference::power_double_int_function(), 4); |
} else { |
ASSERT(exponent_type.IsTagged()); |
- __ PrepareCallCFunction(4, ebx); |
- __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
+ CpuFeatures::Scope scope(SSE2); |
Register right_reg = ToRegister(right); |
- Label non_smi; |
- Label done; |
+ |
+ Label non_smi, call; |
__ test(right_reg, Immediate(kSmiTagMask)); |
__ j(not_zero, &non_smi); |
__ SmiUntag(right_reg); |
- __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); |
- __ CallCFunction(ExternalReference::power_double_int_function(), 4); |
- __ jmp(&done); |
+ __ cvtsi2sd(result_reg, Operand(right_reg)); |
+ __ jmp(&call); |
William Hesse
2010/12/15 14:38:38
Calling power_double_double rather than power_doub
Mads Ager (chromium)
2010/12/15 14:43:20
Good point. I'll check performance. I didn't notic
|
__ bind(&non_smi); |
+ // It is safe to use ebx directly since the instruction is marked |
+ // as a call. |
+ ASSERT(!right_reg.is(ebx)); |
__ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx); |
DeoptimizeIf(not_equal, instr->environment()); |
- __ movdbl(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset)); |
- __ movdbl(Operand(esp, 1 * kDoubleSize), xmm1); |
+ __ movdbl(result_reg, FieldOperand(right_reg, HeapNumber::kValueOffset)); |
+ |
+ __ bind(&call); |
+ __ PrepareCallCFunction(4, ebx); |
+ __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
+ __ movdbl(Operand(esp, 1 * kDoubleSize), result_reg); |
__ CallCFunction(ExternalReference::power_double_double_function(), 4); |
- |
- __ bind(&done); |
} |
// Return value is in st(0) on ia32. |
// Store it into the (fixed) result register. |
__ sub(Operand(esp), Immediate(kDoubleSize)); |
__ fstp_d(Operand(esp, 0)); |
- __ movdbl(ToDoubleRegister(instr->result()), Operand(esp, 0)); |
+ __ movdbl(result_reg, Operand(esp, 0)); |
__ add(Operand(esp), Immediate(kDoubleSize)); |
} |