Author: [email protected]
Date: Tue Jun 16 02:49:29 2009
New Revision: 2182

Modified:
    branches/bleeding_edge/src/arm/codegen-arm.cc
    branches/bleeding_edge/test/mjsunit/date-parse.js
    branches/bleeding_edge/test/mjsunit/toint32.js

Log:
Avoid going into runtime system for round-towards-zero operations on ARM.
Review URL: http://codereview.chromium.org/126192

Modified: branches/bleeding_edge/src/arm/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.cc       (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.cc       Tue Jun 16 02:49:29 2009
@@ -4728,27 +4728,53 @@


  // Tries to get a signed int32 out of a double precision floating point  
heap
-// number.  Rounds towards 0.  Only succeeds for doubles that are in the  
ranges
+// number.  Rounds towards 0.  Fastest for doubles that are in the ranges
  // -0x7fffffff to -0x40000000 or 0x40000000 to 0x7fffffff.  This  
corresponds
  // almost to the range of signed int32 values that are not Smis.  Jumps to  
the
-// label if the double isn't in the range it can cope with.
+// label 'slow' if the double isn't in the range -0x80000000.0 to  
0x80000000.0
+// (excluding the endpoints).
  static void GetInt32(MacroAssembler* masm,
                       Register source,
                       Register dest,
                       Register scratch,
+                     Register scratch2,
                       Label* slow) {
-  Register scratch2 = dest;
+  Label right_exponent, done;
    // Get exponent word.
    __ ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
    // Get exponent alone in scratch2.
    __ and_(scratch2, scratch, Operand(HeapNumber::kExponentMask));
+  // Load dest with zero.  We use this either for the final shift or
+  // for the answer.
+  __ mov(dest, Operand(0));
    // Check whether the exponent matches a 32 bit signed int that is not a  
Smi.
-  // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).
+  // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).   
This is
+  // the exponent that we are fastest at and also the highest exponent we  
can
+  // handle here.
    const uint32_t non_smi_exponent =
        (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
    __ cmp(scratch2, Operand(non_smi_exponent));
-  // If not, then we go slow.
-  __ b(ne, slow);
+  // If we have a match of the int32-but-not-Smi exponent then skip some  
logic.
+  __ b(eq, &right_exponent);
+  // If the exponent is higher than that then go to slow case.  This  
catches
+  // numbers that don't fit in a signed int32, infinities and NaNs.
+  __ b(gt, slow);
+
+  // We know the exponent is smaller than 30 (biased).  If it is less than
+  // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie
+  // it rounds to zero.
+  const uint32_t zero_exponent =
+      (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
+  __ sub(scratch2, scratch2, Operand(zero_exponent), SetCC);
+  // Dest already has a Smi zero.
+  __ b(lt, &done);
+  // We have a shifted exponent between 0 and 30 in scratch2.
+  __ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift));
+  // We now have the exponent in dest.  Subtract from 30 to get
+  // how much to shift down.
+  __ rsb(dest, dest, Operand(30));
+
+  __ bind(&right_exponent);
    // Get the top bits of the mantissa.
    __ and_(scratch2, scratch, Operand(HeapNumber::kMantissaMask));
    // Put back the implicit 1.
@@ -4760,12 +4786,17 @@
    __ mov(scratch2, Operand(scratch2, LSL, shift_distance));
    // Put sign in zero flag.
    __ tst(scratch, Operand(HeapNumber::kSignMask));
-  // Get the second half of the double.
+  // Get the second half of the double.  For some exponents we don't  
actually
+  // need this because the bits get shifted out again, but it's probably  
slower
+  // to test than just to do it.
    __ ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
    // Shift down 22 bits to get the last 10 bits.
-  __ orr(dest, scratch2, Operand(scratch, LSR, 32 - shift_distance));
+  __ orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance));
+  // Move down according to the exponent.
+  __ mov(dest, Operand(scratch, LSR, dest));
    // Fix sign if sign bit was set.
    __ rsb(dest, dest, Operand(0), LeaveCC, ne);
+  __ bind(&done);
  }


@@ -4785,7 +4816,7 @@
    __ b(eq, &r1_is_smi);  // It's a Smi so don't check it's a heap number.
    __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
    __ b(ne, &slow);
-  GetInt32(masm, r1, r3, r4, &slow);
+  GetInt32(masm, r1, r3, r4, r5, &slow);
    __ jmp(&done_checking_r1);
    __ bind(&r1_is_smi);
    __ mov(r3, Operand(r1, ASR, 1));
@@ -4795,7 +4826,7 @@
    __ b(eq, &r0_is_smi);  // It's a Smi so don't check it's a heap number.
    __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
    __ b(ne, &slow);
-  GetInt32(masm, r0, r2, r4, &slow);
+  GetInt32(masm, r0, r2, r4, r5, &slow);
    __ jmp(&done_checking_r0);
    __ bind(&r0_is_smi);
    __ mov(r2, Operand(r0, ASR, 1));

Modified: branches/bleeding_edge/test/mjsunit/date-parse.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/date-parse.js   (original)
+++ branches/bleeding_edge/test/mjsunit/date-parse.js   Tue Jun 16 02:49:29  
2009
@@ -254,7 +254,7 @@
  for (var i = 0; i < 24 * 365 * 100; i += 95) {
    var ms = i * (3600 * 1000);
    var s = (new Date(ms)).toString();
-  assertEquals(ms, Date.parse(s), s);
+  assertEquals(ms, Date.parse(s), "parse own: " + s);
  }

  // Negative tests.

Modified: branches/bleeding_edge/test/mjsunit/toint32.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/toint32.js      (original)
+++ branches/bleeding_edge/test/mjsunit/toint32.js      Tue Jun 16 02:49:29 2009
@@ -29,19 +29,19 @@
    return x | 0;
  }

-assertEquals(0, toInt32(Infinity));
-assertEquals(0, toInt32(-Infinity));
-assertEquals(0, toInt32(NaN));
-assertEquals(0, toInt32(0.0));
-assertEquals(0, toInt32(-0.0));
+assertEquals(0, toInt32(Infinity), "Inf");
+assertEquals(0, toInt32(-Infinity), "-Inf");
+assertEquals(0, toInt32(NaN), "NaN");
+assertEquals(0, toInt32(0.0), "zero");
+assertEquals(0, toInt32(-0.0), "-zero");

  assertEquals(0, toInt32(Number.MIN_VALUE));
  assertEquals(0, toInt32(-Number.MIN_VALUE));
  assertEquals(0, toInt32(0.1));
  assertEquals(0, toInt32(-0.1));
-assertEquals(1, toInt32(1));
-assertEquals(1, toInt32(1.1));
-assertEquals(-1, toInt32(-1));
+assertEquals(1, toInt32(1), "one");
+assertEquals(1, toInt32(1.1), "onepointone");
+assertEquals(-1, toInt32(-1), "-one");
  assertEquals(0, toInt32(0.6), "truncate positive (0.6)");
  assertEquals(1, toInt32(1.6), "truncate positive (1.6)");
  assertEquals(0, toInt32(-0.6), "truncate negative (-0.6)");

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

Reply via email to