Optimize ECMA double to int32 conversion path (patch by mohammad.r.haghighat@intel.com, r=dvander).
 author Andreas Gal Fri, 12 Jun 2009 15:18:10 -0700 changeset 29357 319361b182898684775e8d8fe7227fde4a0af957 parent 29356 9b0e68c238ebb4805d51eda892230c86289d9ed8 child 29358 a30e21c74d2da17f609a133e18b2da208b468161 push id unknown push user unknown push date unknown reviewers dvander milestone 1.9.2a1pre
Optimize ECMA double to int32 conversion path (patch by mohammad.r.haghighat@intel.com, r=dvander).
 js/src/jsnum.cpp file | annotate | diff | comparison | revisions
```--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -960,34 +960,118 @@ 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;
+
+    /*
+     * 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;
+        if (shift_amount < 32) {
+            duh.s.hi = du.s.hi & mask32;
+            duh.s.lo = 0;
+        } else {
+            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);
+        if (shift_amount < 32) {
+            du.s.lo = 0;
+        } else {
+        }
+        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;```