Fix jsctypes unsigned __int64 conversion on MSVC. b=519235, r=jorendorff
authorDan Witte <dwitte@mozilla.com>
Fri, 02 Oct 2009 22:47:56 -0700
changeset 33417 1d1373e850f04f232e297f877097fc4fe4581a0f
parent 33416 b638150de7fb1cfde42d6dac7aa87047395af043
child 33418 4fae2bb3a717b364d76723e4ca2d6ae29bc85a33
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs519235
milestone1.9.3a1pre
Fix jsctypes unsigned __int64 conversion on MSVC. b=519235, r=jorendorff
js/ctypes/Function.cpp
js/ctypes/tests/unit/test_jsctypes.js.in
--- a/js/ctypes/Function.cpp
+++ b/js/ctypes/Function.cpp
@@ -47,30 +47,50 @@
 namespace mozilla {
 namespace ctypes {
 
 /*******************************************************************************
 ** Static helpers
 *******************************************************************************/
 
 template<class IntegerType>
+static IntegerType
+Convert(jsdouble d)
+{
+  return IntegerType(d);
+}
+
+#ifdef _MSC_VER
+// MSVC can't perform double to unsigned __int64 conversion when the
+// double is greater than 2^63 - 1. Help it along a little.
+template<>
+static PRUint64
+Convert<PRUint64>(jsdouble d)
+{
+  return d > 0x7fffffffffffffffui64 ?
+         PRUint64(d - 0x8000000000000000ui64) + 0x8000000000000000ui64 :
+         PRUint64(d);
+}
+#endif
+
+template<class IntegerType>
 static bool
 jsvalToIntStrict(jsval aValue, IntegerType *aResult)
 {
   if (JSVAL_IS_INT(aValue)) {
     jsint i = JSVAL_TO_INT(aValue);
     *aResult = IntegerType(i);
 
     // Make sure the integer fits in the alotted precision, and has the right sign.
     return jsint(*aResult) == i &&
            (i < 0) == (*aResult < 0);
   }
   if (JSVAL_IS_DOUBLE(aValue)) {
     jsdouble d = *JSVAL_TO_DOUBLE(aValue);
-    *aResult = IntegerType(d);
+    *aResult = Convert<IntegerType>(d);
 
     // Don't silently lose bits here -- check that aValue really is an
     // integer value, and has the right sign.
     return jsdouble(*aResult) == d &&
            (d < 0) == (*aResult < 0);
   }
   if (JSVAL_IS_BOOLEAN(aValue)) {
     // Implicitly promote boolean values to 0 or 1, like C.
--- a/js/ctypes/tests/unit/test_jsctypes.js.in
+++ b/js/ctypes/tests/unit/test_jsctypes.js.in
@@ -217,19 +217,17 @@ function run_int64_tests(library) {
     do_check_throws(function () { test_i64_i64(vals[i]); }, TypeError);
 
   var test_i64_i64_sum = library.declare("test_i64_i64_sum", Types.DEFAULT, Types.INT64, Types.INT64, Types.INT64);
   do_check_eq(test_i64_i64_sum(5, 5), 10);
 
   // test the range of unsigned. (we can reuse the signed C function
   // here, since it's binary-compatible.)
   var test_ui64_ui64 = library.declare("test_i64_i64", Types.DEFAULT, Types.UINT64, Types.UINT64);
-#ifndef XP_WIN
   do_check_eq(test_ui64_ui64(0xfffffffffffff000), 0xfffffffffffff000);
-#endif
   do_check_throws(function () { test_ui64_ui64(0x10000000000000000); }, TypeError);
   do_check_throws(function () { test_ui64_ui64(-1); }, TypeError);
 }
 
 function run_float_tests(library) {
   var test_f = library.declare("test_f", Types.DEFAULT, Types.FLOAT);
   do_check_eq(test_f(), 123456.5);