ARM: Implement DoPower in the lithium code generator.

Review URL: http://codereview.chromium.org/6532020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6909 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
karlklose@chromium.org 2011-02-23 10:41:13 +00:00
parent 337f6a953d
commit 16cc528316
7 changed files with 104 additions and 5 deletions

View File

@ -1417,8 +1417,19 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
LInstruction* LChunkBuilder::DoPower(HPower* instr) {
Abort("LPower instruction not implemented on ARM");
return NULL;
ASSERT(instr->representation().IsDouble());
// We call a C function for double power. It can't trigger a GC.
// We need to use fixed result register for the call.
Representation exponent_type = instr->right()->representation();
ASSERT(instr->left()->representation().IsDouble());
LOperand* left = UseFixedDouble(instr->left(), d1);
LOperand* right = exponent_type.IsDouble() ?
UseFixedDouble(instr->right(), d2) :
UseFixed(instr->right(), r0);
LPower* result = new LPower(left, right);
return MarkAsCall(DefineFixedDouble(result, d3),
instr,
CAN_DEOPTIMIZE_EAGERLY);
}

View File

@ -135,6 +135,7 @@ class LCodeGen;
V(OuterContext) \
V(Parameter) \
V(PixelArrayLength) \
V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
V(Return) \
@ -1058,6 +1059,18 @@ class LAddI: public LTemplateInstruction<1, 2, 0> {
};
class LPower: public LTemplateInstruction<1, 2, 0> {
public:
LPower(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(Power, "power")
DECLARE_HYDROGEN_ACCESSOR(Power)
};
class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
public:
LArithmeticD(Token::Value op, LOperand* left, LOperand* right)

View File

@ -1226,7 +1226,7 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
__ vmov(r2, r3, right);
__ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
// Move the result in the double result register.
__ vmov(ToDoubleRegister(instr->result()), r0, r1);
__ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
// Restore r0-r3.
__ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
@ -2684,6 +2684,64 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
}
void LCodeGen::DoPower(LPower* instr) {
LOperand* left = instr->InputAt(0);
LOperand* right = instr->InputAt(1);
Register scratch = scratch0();
DoubleRegister result_reg = ToDoubleRegister(instr->result());
Representation exponent_type = instr->hydrogen()->right()->representation();
if (exponent_type.IsDouble()) {
// Prepare arguments and call C function.
__ PrepareCallCFunction(4, scratch);
__ vmov(r0, r1, ToDoubleRegister(left));
__ vmov(r2, r3, ToDoubleRegister(right));
__ CallCFunction(ExternalReference::power_double_double_function(), 4);
} else if (exponent_type.IsInteger32()) {
ASSERT(ToRegister(right).is(r0));
// Prepare arguments and call C function.
__ PrepareCallCFunction(4, scratch);
__ mov(r2, ToRegister(right));
__ vmov(r0, r1, ToDoubleRegister(left));
__ CallCFunction(ExternalReference::power_double_int_function(), 4);
} else {
ASSERT(exponent_type.IsTagged());
ASSERT(instr->hydrogen()->left()->representation().IsDouble());
Register right_reg = ToRegister(right);
// Check for smi on the right hand side.
Label non_smi, call;
__ JumpIfNotSmi(right_reg, &non_smi);
// Untag smi and convert it to a double.
__ SmiUntag(right_reg);
SwVfpRegister single_scratch = double_scratch0().low();
__ vmov(single_scratch, right_reg);
__ vcvt_f64_s32(result_reg, single_scratch);
__ jmp(&call);
// Heap number map check.
__ bind(&non_smi);
__ ldr(scratch, FieldMemOperand(right_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(scratch, Operand(ip));
DeoptimizeIf(ne, instr->environment());
int32_t value_offset = HeapNumber::kValueOffset - kHeapObjectTag;
__ add(scratch, right_reg, Operand(value_offset));
__ vldr(result_reg, scratch, 0);
// Prepare arguments and call C function.
__ bind(&call);
__ PrepareCallCFunction(4, scratch);
__ vmov(r0, r1, ToDoubleRegister(left));
__ vmov(r2, r3, result_reg);
__ CallCFunction(ExternalReference::power_double_double_function(), 4);
}
// Store the result in the result register.
__ GetCFunctionDoubleResult(result_reg);
}
void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
switch (instr->op()) {
case kMathAbs:

View File

@ -746,6 +746,14 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
}
}
void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
#if !defined(USE_ARM_EABI)
UNREACHABLE();
#else
vmov(dst, r0, r1);
#endif
}
void MacroAssembler::InvokePrologue(const ParameterCount& expected,
const ParameterCount& actual,

View File

@ -684,6 +684,8 @@ class MacroAssembler: public Assembler {
void CallCFunction(ExternalReference function, int num_arguments);
void CallCFunction(Register function, int num_arguments);
void GetCFunctionDoubleResult(const DoubleRegister dst);
// Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Restores context.
// stack_space - space to be unwound on exit (includes the call js

View File

@ -852,12 +852,14 @@ double power_double_double(double x, double y) {
ExternalReference ExternalReference::power_double_double_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double)));
return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double),
FP_RETURN_CALL));
}
ExternalReference ExternalReference::power_double_int_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int)));
return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int),
FP_RETURN_CALL));
}

View File

@ -54,7 +54,12 @@ bool V8::Initialize(Deserializer* des) {
if (has_been_disposed_ || has_fatal_error_) return false;
if (IsRunning()) return true;
#if defined(V8_TARGET_ARCH_ARM) && !defined(USE_ARM_EABI)
use_crankshaft_ = false;
#else
use_crankshaft_ = FLAG_crankshaft;
#endif
// Peephole optimization might interfere with deoptimization.
FLAG_peephole_optimization = !use_crankshaft_;
is_running_ = true;