Reviewers: Søren Gjesse,

Description:
ARM: Implement inline conversion of heap numbers to int32 values for
bitoperations.

For bit operations, values are truncated and converted to the range -2^31
through 2^31 - 1. This patch provides inlined handling of this conversion for
all heap numbers.

Before, we were calling runtime for every heap number that did not fit into a
signed int32.

Please review this at http://codereview.chromium.org/6658034/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/arm/code-stubs-arm.cc


Index: src/arm/code-stubs-arm.cc
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index bce0c518ab5c690baf1d11a3653b3abbd18eb073..1d429c8fc2650b82f8bc84c20119e416f88c2edb 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -409,6 +409,7 @@ class FloatingPointHelper : public AllStatic {
                                   Register heap_number_map,
                                   Register scratch1,
                                   Register scratch2,
+                                  Register scratch3,
                                   DwVfpRegister double_scratch,
                                   Label* not_int32);

@@ -612,6 +613,7 @@ void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm,
                                               Register heap_number_map,
                                               Register scratch1,
                                               Register scratch2,
+                                              Register scratch3,
                                               DwVfpRegister double_scratch,
                                               Label* not_int32) {
   if (FLAG_debug_code) {
@@ -619,14 +621,88 @@ void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm,
                            Heap::kHeapNumberMapRootIndex,
                            "HeapNumberMap register clobbered.");
   }
-  Label is_smi, done;
+  Label is_smi;
+  Label done;
+  Label not_in_int32_range;
+
   __ JumpIfSmi(object, &is_smi);
   __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
   __ cmp(scratch1, heap_number_map);
   __ b(ne, not_int32);
   __ ConvertToInt32(
-      object, dst, scratch1, scratch2, double_scratch, not_int32);
+ object, dst, scratch1, scratch2, double_scratch, &not_in_int32_range);
   __ jmp(&done);
+
+  __ bind(&not_in_int32_range);
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+ __ vldr(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
+    __ vmov(scratch1, scratch2, double_scratch);
+
+    // Register scratch1 contains mantissa word, scratch2 contains
+    // sign, exponent and mantissa.
+    __ and_(dst, scratch2, Operand(HeapNumber::kExponentMask));
+    __ mov(dst, Operand(dst, LSR, HeapNumber::kExponentShift));
+    __ sub(dst, dst, Operand(1023));
+
+    Label normal_exponent;
+    // Express exponent as delta to 31.
+    // If the delta is larger than 53, all bits would be shifted
+    // away, which means that we can return 0.
+    __ sub(dst, dst, Operand(31));
+    __ cmp(dst, Operand(53));
+    __ b(&normal_exponent, lt);
+    __ mov(dst, Operand(0));
+    __ jmp(&done);
+
+    __ bind(&normal_exponent);
+    const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
+    // Calculate shift.
+    __ add(scratch3, dst, Operand(kShiftBase));
+
+    // Put implicit 1 before the mantissa part in scratch2 and
+    // shift the mantissa bits to the correct position.
+    __ orr(scratch2,
+           scratch2,
+           Operand(1 << HeapNumber::kMantissaBitsInTopWord));
+
+    // Save sign.
+    Register sign = dst;
+    __ and_(sign, scratch2, Operand(HeapNumber::kSignMask));
+
+    //  Shift mantisssa bits in high word.
+    __ mov(scratch2, Operand(scratch2, LSL, scratch3));
+
+    // Replace the shifted bits with bits from the lower mantissa word.
+    Label pos_shift, neg_shift;
+    // scratch3 = 32 - scratch3.
+    __ mvn(scratch3, Operand(scratch3));
+    __ add(scratch3, scratch3, Operand(33));
+    __ cmp(scratch3, Operand(0));
+    __ b(&pos_shift, ge);
+
+    // Negate scratch3.
+    __ mvn(scratch3, Operand(scratch3));
+    __ add(scratch3, scratch3, Operand(1));
+    __ mov(scratch1, Operand(scratch1, LSL, scratch3));
+    __ jmp(&neg_shift);
+
+    __ bind(&pos_shift);
+    __ mov(scratch1, Operand(scratch1, LSR, scratch3));
+
+    __ bind(&neg_shift);
+    __ orr(scratch2, scratch2, Operand(scratch1));
+
+    // Restore sign if necessary.
+    __ tst(sign, sign);
+    __ mvn(scratch2, Operand(scratch2), LeaveCC, ne);
+    __ add(scratch2, scratch2, Operand(1), LeaveCC, ne);
+    __ mov(dst, scratch2);
+    __ jmp(&done);
+  } else {
+    __ jmp(not_int32);
+  }
+
   __ bind(&is_smi);
   __ SmiUntag(dst, object);
   __ bind(&done);
@@ -3024,6 +3100,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
   Register right = r0;
   Register scratch1 = r7;
   Register scratch2 = r9;
+  Register scratch3 = r4;

   ASSERT(smi_operands || (not_numbers != NULL));
   if (smi_operands && FLAG_debug_code) {
@@ -3117,6 +3194,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
                                                  heap_number_map,
                                                  scratch1,
                                                  scratch2,
+                                                 scratch3,
                                                  d0,
                                                  not_numbers);
         FloatingPointHelper::LoadNumberAsInteger(masm,
@@ -3125,6 +3203,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
                                                  heap_number_map,
                                                  scratch1,
                                                  scratch2,
+                                                 scratch3,
                                                  d0,
                                                  not_numbers);
       }
@@ -3572,13 +3651,10 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {


void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
-  Label not_numbers, call_runtime;
+  Label call_runtime;
   ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);

-  GenerateFPOperation(masm, false, &not_numbers, &call_runtime);
-
-  __ bind(&not_numbers);
-  GenerateTypeTransition(masm);
+  GenerateFPOperation(masm, false, &call_runtime, &call_runtime);

   __ bind(&call_runtime);
   GenerateCallRuntime(masm);


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

Reply via email to