Inline DoubleToECMAInt32 (512049, r=dmandelin).
authorAndreas Gal <gal@mozilla.com>
Mon, 24 Aug 2009 18:46:21 -0700
changeset 32544 fcd321cd60c1eb57472236f5bad294a5bead6124
parent 32543 9b6b17a275ec4ddc5714d2361e277648067d92db
child 32545 4924c617f85205e19fcca4eeb8c897357008ac16
push idunknown
push userunknown
push dateunknown
reviewersdmandelin
bugs512049
milestone1.9.3a1pre
Inline DoubleToECMAInt32 (512049, r=dmandelin).
js/src/jsnum.cpp
js/src/jsnum.h
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1007,120 +1007,16 @@ js_ValueToECMAInt32(JSContext *cx, jsval
         d = js_ValueToNumber(cx, vp);
         if (JSVAL_IS_NULL(*vp))
             return 0;
         *vp = JSVAL_TRUE;
     }
     return js_DoubleToECMAInt32(d);
 }
 
-/*
- * From the ES3 spec, 9.5
- *  2.  If Result(1) is NaN, +0, -0, +Inf, or -Inf, return +0.
- *  3.  Compute sign(Result(1)) * floor(abs(Result(1))).
- *  4.  Compute Result(3) modulo 2^32; that is, a finite integer value k of Number
- *      type with positive sign and less than 2^32 in magnitude such the mathematical
- *      difference of Result(3) and k is mathematically an integer multiple of 2^32.
- *  5.  If Result(4) is greater than or equal to 2^31, return Result(4)- 2^32,
- *  otherwise return Result(4).
- */
-int32
-js_DoubleToECMAInt32(jsdouble d)
-{
-#ifdef __i386__
-    jsdpun du, duh, two32;
-    uint32 di_h, u_tmp, expon, shift_amount;
-    int32 mask32;
-
-    /*
-     * Algorithm Outline
-     *  Step 1. If d is NaN, +/-Inf or |d|>=2^84 or |d|<1, then return 0
-     *          All of this is implemented based on an exponent comparison.
-     *  Step 2. If |d|<2^31, then return (int)d
-     *          The cast to integer (conversion in RZ mode) returns the correct result.
-     *  Step 3. If |d|>=2^32, d:=fmod(d, 2^32) is taken  -- but without a call
-     *  Step 4. If |d|>=2^31, then the fractional bits are cleared before
-     *          applying the correction by 2^32:  d - sign(d)*2^32
-     *  Step 5. Return (int)d
-     */
-
-    du.d = d;
-    di_h = du.s.hi;
-
-    u_tmp = (di_h & 0x7ff00000) - 0x3ff00000;
-    if (u_tmp >= (0x45300000-0x3ff00000)) {
-        // d is Nan, +/-Inf or +/-0, or |d|>=2^(32+52) or |d|<1, in which case result=0
-        return 0;
-    }
-
-    if (u_tmp < 0x01f00000) {
-        // |d|<2^31
-        return int32_t(d);
-    }
-
-    if (u_tmp > 0x01f00000) {
-        // |d|>=2^32
-        expon = u_tmp >> 20;
-        shift_amount = expon - 21;
-        duh.u64 = du.u64;
-        mask32 = 0x80000000;
-        if (shift_amount < 32) {
-            mask32 >>= shift_amount;
-            duh.s.hi = du.s.hi & mask32;
-            duh.s.lo = 0;
-        } else {
-            mask32 >>= (shift_amount-32);
-            duh.s.hi = du.s.hi;
-            duh.s.lo = du.s.lo & mask32;
-        }
-        du.d -= duh.d;
-    }
-
-    di_h = du.s.hi;
-
-    // eliminate fractional bits
-    u_tmp = (di_h & 0x7ff00000);
-    if (u_tmp >= 0x41e00000) {
-        // |d|>=2^31
-        expon = u_tmp >> 20;
-        shift_amount = expon - (0x3ff - 11);
-        mask32 = 0x80000000;
-        if (shift_amount < 32) {
-            mask32 >>= shift_amount;
-            du.s.hi &= mask32;
-            du.s.lo = 0;
-        } else {
-            mask32 >>= (shift_amount-32);
-            du.s.lo &= mask32;
-        }
-        two32.s.hi = 0x41f00000 ^ (du.s.hi & 0x80000000);
-        two32.s.lo = 0;
-        du.d -= two32.d;
-    }
-
-    return int32(du.d);
-#else
-    int32 i;
-    jsdouble two32, two31;
-
-    if (!JSDOUBLE_IS_FINITE(d))
-        return 0;
-
-    i = (int32) d;
-    if ((jsdouble) i == d)
-        return i;
-
-    two32 = 4294967296.0;
-    two31 = 2147483648.0;
-    d = fmod(d, two32);
-    d = (d >= 0) ? floor(d) : ceil(d) + two32;
-    return (int32) (d >= two31 ? d - two32 : d);
-#endif
-}
-
 uint32
 js_ValueToECMAUint32(JSContext *cx, jsval *vp)
 {
     jsval v;
     jsint i;
     jsdouble d;
 
     v = *vp;
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -218,18 +218,119 @@ extern int32
 js_ValueToECMAInt32(JSContext *cx, jsval *vp);
 
 extern uint32
 js_ValueToECMAUint32(JSContext *cx, jsval *vp);
 
 /*
  * Specialized ToInt32 and ToUint32 converters for doubles.
  */
-extern int32
-js_DoubleToECMAInt32(jsdouble d);
+/*
+ * From the ES3 spec, 9.5
+ *  2.  If Result(1) is NaN, +0, -0, +Inf, or -Inf, return +0.
+ *  3.  Compute sign(Result(1)) * floor(abs(Result(1))).
+ *  4.  Compute Result(3) modulo 2^32; that is, a finite integer value k of Number
+ *      type with positive sign and less than 2^32 in magnitude such the mathematical
+ *      difference of Result(3) and k is mathematically an integer multiple of 2^32.
+ *  5.  If Result(4) is greater than or equal to 2^31, return Result(4)- 2^32,
+ *  otherwise return Result(4).
+ */
+static inline int32
+js_DoubleToECMAInt32(jsdouble d)
+{
+#ifdef __i386__
+    jsdpun du, duh, two32;
+    uint32 di_h, u_tmp, expon, shift_amount;
+    int32 mask32;
+
+    /*
+     * Algorithm Outline
+     *  Step 1. If d is NaN, +/-Inf or |d|>=2^84 or |d|<1, then return 0
+     *          All of this is implemented based on an exponent comparison.
+     *  Step 2. If |d|<2^31, then return (int)d
+     *          The cast to integer (conversion in RZ mode) returns the correct result.
+     *  Step 3. If |d|>=2^32, d:=fmod(d, 2^32) is taken  -- but without a call
+     *  Step 4. If |d|>=2^31, then the fractional bits are cleared before
+     *          applying the correction by 2^32:  d - sign(d)*2^32
+     *  Step 5. Return (int)d
+     */
+
+    du.d = d;
+    di_h = du.s.hi;
+
+    u_tmp = (di_h & 0x7ff00000) - 0x3ff00000;
+    if (u_tmp >= (0x45300000-0x3ff00000)) {
+        // d is Nan, +/-Inf or +/-0, or |d|>=2^(32+52) or |d|<1, in which case result=0
+        return 0;
+    }
+
+    if (u_tmp < 0x01f00000) {
+        // |d|<2^31
+        return int32_t(d);
+    }
+
+    if (u_tmp > 0x01f00000) {
+        // |d|>=2^32
+        expon = u_tmp >> 20;
+        shift_amount = expon - 21;
+        duh.u64 = du.u64;
+        mask32 = 0x80000000;
+        if (shift_amount < 32) {
+            mask32 >>= shift_amount;
+            duh.s.hi = du.s.hi & mask32;
+            duh.s.lo = 0;
+        } else {
+            mask32 >>= (shift_amount-32);
+            duh.s.hi = du.s.hi;
+            duh.s.lo = du.s.lo & mask32;
+        }
+        du.d -= duh.d;
+    }
+
+    di_h = du.s.hi;
+
+    // eliminate fractional bits
+    u_tmp = (di_h & 0x7ff00000);
+    if (u_tmp >= 0x41e00000) {
+        // |d|>=2^31
+        expon = u_tmp >> 20;
+        shift_amount = expon - (0x3ff - 11);
+        mask32 = 0x80000000;
+        if (shift_amount < 32) {
+            mask32 >>= shift_amount;
+            du.s.hi &= mask32;
+            du.s.lo = 0;
+        } else {
+            mask32 >>= (shift_amount-32);
+            du.s.lo &= mask32;
+        }
+        two32.s.hi = 0x41f00000 ^ (du.s.hi & 0x80000000);
+        two32.s.lo = 0;
+        du.d -= two32.d;
+    }
+
+    return int32(du.d);
+#else
+    int32 i;
+    jsdouble two32, two31;
+
+    if (!JSDOUBLE_IS_FINITE(d))
+        return 0;
+
+    i = (int32) d;
+    if ((jsdouble) i == d)
+        return i;
+
+    two32 = 4294967296.0;
+    two31 = 2147483648.0;
+    d = fmod(d, two32);
+    d = (d >= 0) ? floor(d) : ceil(d) + two32;
+    return (int32) (d >= two31 ? d - two32 : d);
+#endif
+}
 
 extern uint32
 js_DoubleToECMAUint32(jsdouble d);
 
 /*
  * Convert a value to a number, then to an int32 if it fits by rounding to
  * nearest; but failing with an error report if the double is out of range
  * or unordered. On exit JSVAL_IS_NULL(*vp) iff there was an error. If on exit