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:
parent
337f6a953d
commit
16cc528316
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user