Commit 06a684d3 authored by ager@chromium.org's avatar ager@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6032 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 655b3085
...@@ -720,7 +720,6 @@ MaybeObject* Execution::HandleStackGuardInterrupt() { ...@@ -720,7 +720,6 @@ MaybeObject* Execution::HandleStackGuardInterrupt() {
return Top::TerminateExecution(); return Top::TerminateExecution();
} }
if (StackGuard::IsInterrupted()) { if (StackGuard::IsInterrupted()) {
// interrupt
StackGuard::Continue(INTERRUPT); StackGuard::Continue(INTERRUPT);
return Top::StackOverflow(); return Top::StackOverflow();
} }
......
...@@ -2262,47 +2262,55 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { ...@@ -2262,47 +2262,55 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
void LCodeGen::DoPower(LPower* instr) { void LCodeGen::DoPower(LPower* instr) {
LOperand* left = instr->left(); LOperand* left = instr->left();
LOperand* right = instr->right(); LOperand* right = instr->right();
DoubleRegister result_reg = ToDoubleRegister(instr->result());
Representation exponent_type = instr->hydrogen()->right()->representation(); Representation exponent_type = instr->hydrogen()->right()->representation();
if (exponent_type.IsDouble()) { if (exponent_type.IsDouble()) {
// Pass two doubles as arguments on the stack. // It is safe to use ebx directly since the instruction is marked
__ PrepareCallCFunction(4, eax); // as a call.
__ PrepareCallCFunction(4, ebx);
__ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
__ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right));
__ CallCFunction(ExternalReference::power_double_double_function(), 4); __ CallCFunction(ExternalReference::power_double_double_function(), 4);
} else if (exponent_type.IsInteger32()) { } 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); __ PrepareCallCFunction(4, ebx);
__ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
__ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right));
__ CallCFunction(ExternalReference::power_double_int_function(), 4); __ CallCFunction(ExternalReference::power_double_int_function(), 4);
} else { } else {
ASSERT(exponent_type.IsTagged()); ASSERT(exponent_type.IsTagged());
__ PrepareCallCFunction(4, ebx); CpuFeatures::Scope scope(SSE2);
__ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
Register right_reg = ToRegister(right); Register right_reg = ToRegister(right);
Label non_smi;
Label done; Label non_smi, call;
__ test(right_reg, Immediate(kSmiTagMask)); __ test(right_reg, Immediate(kSmiTagMask));
__ j(not_zero, &non_smi); __ j(not_zero, &non_smi);
__ SmiUntag(right_reg); __ SmiUntag(right_reg);
__ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); __ cvtsi2sd(result_reg, Operand(right_reg));
__ CallCFunction(ExternalReference::power_double_int_function(), 4); __ jmp(&call);
__ jmp(&done);
__ bind(&non_smi); __ 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); __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx);
DeoptimizeIf(not_equal, instr->environment()); DeoptimizeIf(not_equal, instr->environment());
__ movdbl(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset)); __ movdbl(result_reg, FieldOperand(right_reg, HeapNumber::kValueOffset));
__ movdbl(Operand(esp, 1 * kDoubleSize), xmm1);
__ CallCFunction(ExternalReference::power_double_double_function(), 4);
__ bind(&done); __ 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. // Return value is in st(0) on ia32.
// Store it into the (fixed) result register. // Store it into the (fixed) result register.
__ sub(Operand(esp), Immediate(kDoubleSize)); __ sub(Operand(esp), Immediate(kDoubleSize));
__ fstp_d(Operand(esp, 0)); __ fstp_d(Operand(esp, 0));
__ movdbl(ToDoubleRegister(instr->result()), Operand(esp, 0)); __ movdbl(result_reg, Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize)); __ add(Operand(esp), Immediate(kDoubleSize));
} }
......
...@@ -1603,7 +1603,7 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { ...@@ -1603,7 +1603,7 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
UseFixedDouble(instr->right(), xmm2) : UseFixedDouble(instr->right(), xmm2) :
UseFixed(instr->right(), eax); UseFixed(instr->right(), eax);
LPower* result = new LPower(left, right); LPower* result = new LPower(left, right);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr, return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
CAN_DEOPTIMIZE_EAGERLY); CAN_DEOPTIMIZE_EAGERLY);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment