Revision: 6909
Author: [email protected]
Date: Wed Feb 23 02:41:13 2011
Log: ARM: Implement DoPower in the lithium code generator.
Review URL: http://codereview.chromium.org/6532020
http://code.google.com/p/v8/source/detail?r=6909
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/assembler.cc
/branches/bleeding_edge/src/v8.cc
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Mon Feb 21 02:30:25 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Feb 23 02:41:13 2011
@@ -1417,8 +1417,19 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Wed Feb 16 00:21:45 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Wed Feb 23 02:41:13 2011
@@ -135,6 +135,7 @@
V(OuterContext) \
V(Parameter) \
V(PixelArrayLength) \
+ V(Power) \
V(PushArgument) \
V(RegExpLiteral) \
V(Return) \
@@ -1058,6 +1059,18 @@
};
+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)
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Feb 22
08:56:57 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Feb 23
02:41:13 2011
@@ -1226,7 +1226,7 @@
__ 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());
@@ -2682,6 +2682,64 @@
ASSERT(ToDoubleRegister(instr->result()).is(input));
__ vsqrt(input, input);
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Feb 21
03:29:45 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Feb 23
02:41:13 2011
@@ -745,6 +745,14 @@
add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2));
}
}
+
+void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
+#if !defined(USE_ARM_EABI)
+ UNREACHABLE();
+#else
+ vmov(dst, r0, r1);
+#endif
+}
void MacroAssembler::InvokePrologue(const ParameterCount& expected,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Feb 21
03:29:45 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Feb 23
02:41:13 2011
@@ -684,6 +684,8 @@
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
=======================================
--- /branches/bleeding_edge/src/assembler.cc Tue Feb 22 04:28:33 2011
+++ /branches/bleeding_edge/src/assembler.cc Wed Feb 23 02:41:13 2011
@@ -852,12 +852,14 @@
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));
}
=======================================
--- /branches/bleeding_edge/src/v8.cc Fri Feb 11 04:25:41 2011
+++ /branches/bleeding_edge/src/v8.cc Wed Feb 23 02:41:13 2011
@@ -54,7 +54,12 @@
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;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev