Revision: 6032
Author: [email protected]
Date: Wed Dec 15 07:25:53 2010
Log: Fix deoptimization from %_MathPow. Do not prepare the stack for a C
call and then bailout without performing the call.

In order to not duplicate code, convert both heap number and smi to a
double in an xmm register if possible. Then setup the stack and call
the C function.

BUG=http://code.google.com/p/v8/issues/detail?id=986

Review URL: http://codereview.chromium.org/5900001
http://code.google.com/p/v8/source/detail?r=6032

Modified:
 /branches/bleeding_edge/src/execution.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc

=======================================
--- /branches/bleeding_edge/src/execution.cc    Tue Dec  7 03:31:57 2010
+++ /branches/bleeding_edge/src/execution.cc    Wed Dec 15 07:25:53 2010
@@ -720,7 +720,6 @@
     return Top::TerminateExecution();
   }
   if (StackGuard::IsInterrupted()) {
-    // interrupt
     StackGuard::Continue(INTERRUPT);
     return Top::StackOverflow();
   }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Dec 15 05:56:41 2010 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Dec 15 07:25:53 2010
@@ -2262,47 +2262,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);

     __ 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);
-    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
-
-    __ bind(&done);
+ __ 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);
   }

   // 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));
 }

=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Dec 15 04:32:19 2010 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Dec 15 07:25:53 2010
@@ -1603,7 +1603,7 @@
       UseFixedDouble(instr->right(), xmm2) :
       UseFixed(instr->right(), eax);
   LPower* result = new LPower(left, right);
-  return MarkAsCall(DefineFixedDouble(result, xmm1), instr,
+  return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
                     CAN_DEOPTIMIZE_EAGERLY);
 }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to