Revision: 12216
Author:   [email protected]
Date:     Mon Jul 30 01:34:26 2012
Log:      Make sure double to int conversion is correct.

[email protected]
BUG=v8:2260
TEST=test-utils/Utils1

Review URL: https://chromiumcodereview.appspot.com/10820047
http://code.google.com/p/v8/source/detail?r=12216

Modified:
 /branches/bleeding_edge/src/conversions.h
 /branches/bleeding_edge/src/elements.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/test/cctest/test-utils.cc

=======================================
--- /branches/bleeding_edge/src/conversions.h   Tue Nov 29 02:56:11 2011
+++ /branches/bleeding_edge/src/conversions.h   Mon Jul 30 01:34:26 2012
@@ -55,6 +55,16 @@
 inline double SignedZero(bool negative) {
   return negative ? -0.0 : 0.0;
 }
+
+
+// The fast double-to-(unsigned-)int conversion routine does not guarantee
+// rounding towards zero.
+// For NaN and values outside the int range, return INT_MIN or INT_MAX.
+inline int FastD2IChecked(double x) {
+  if (!(x >= INT_MIN)) return INT_MIN;  // Negation to catch NaNs.
+  if (x > INT_MAX) return INT_MAX;
+  return static_cast<int>(x);
+}


 // The fast double-to-(unsigned-)int conversion routine does not guarantee
@@ -62,8 +72,6 @@
 // The result is unspecified if x is infinite or NaN, or if the rounded
 // integer value is outside the range of type int.
 inline int FastD2I(double x) {
-  // The static_cast convertion from double to int used to be slow, but
-  // as new benchmarks show, now it is much faster than lrint().
   return static_cast<int>(x);
 }

=======================================
--- /branches/bleeding_edge/src/elements.cc     Tue Jun 12 08:30:16 2012
+++ /branches/bleeding_edge/src/elements.cc     Mon Jul 30 01:34:26 2012
@@ -800,7 +800,7 @@
         }
       } else {
         // Otherwise, fill the unused tail with holes.
-        int old_length = FastD2I(array->length()->Number());
+        int old_length = FastD2IChecked(array->length()->Number());
         for (int i = length; i < old_length; i++) {
           backing_store->set_the_hole(i);
         }
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Mon Jul 23 07:55:12 2012
+++ /branches/bleeding_edge/src/runtime.cc      Mon Jul 30 01:34:26 2012
@@ -3755,8 +3755,8 @@
   } else {
     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
-    start = FastD2I(from_number);
-    end = FastD2I(to_number);
+    start = FastD2IChecked(from_number);
+    end = FastD2IChecked(to_number);
   }
   RUNTIME_ASSERT(end >= start);
   RUNTIME_ASSERT(start >= 0);
@@ -4224,7 +4224,7 @@
     return *isolate->factory()->infinity_symbol();
   }
   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
-  int f = FastD2I(f_number);
+  int f = FastD2IChecked(f_number);
   RUNTIME_ASSERT(f >= 0);
   char* str = DoubleToFixedCString(value, f);
   MaybeObject* res =
@@ -4249,7 +4249,7 @@
     return *isolate->factory()->infinity_symbol();
   }
   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
-  int f = FastD2I(f_number);
+  int f = FastD2IChecked(f_number);
   RUNTIME_ASSERT(f >= -1 && f <= 20);
   char* str = DoubleToExponentialCString(value, f);
   MaybeObject* res =
@@ -4274,7 +4274,7 @@
     return *isolate->factory()->infinity_symbol();
   }
   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
-  int f = FastD2I(f_number);
+  int f = FastD2IChecked(f_number);
   RUNTIME_ASSERT(f >= 1 && f <= 21);
   char* str = DoubleToPrecisionCString(value, f);
   MaybeObject* res =
=======================================
--- /branches/bleeding_edge/test/cctest/test-utils.cc Fri Jan 13 05:09:52 2012 +++ /branches/bleeding_edge/test/cctest/test-utils.cc Mon Jul 30 01:34:26 2012
@@ -55,6 +55,22 @@
   CHECK_EQ(-2, -8 >> 2);
   CHECK_EQ(-2, static_cast<int8_t>(-8) >> 2);
   CHECK_EQ(-2, static_cast<int>(static_cast<intptr_t>(-8) >> 2));
+
+  CHECK_EQ(-1000000, FastD2IChecked(-1000000.0));
+  CHECK_EQ(-1, FastD2IChecked(-1.0));
+  CHECK_EQ(0, FastD2IChecked(0.0));
+  CHECK_EQ(1, FastD2IChecked(1.0));
+  CHECK_EQ(1000000, FastD2IChecked(1000000.0));
+
+  CHECK_EQ(-1000000, FastD2IChecked(-1000000.123));
+  CHECK_EQ(-1, FastD2IChecked(-1.234));
+  CHECK_EQ(0, FastD2IChecked(0.345));
+  CHECK_EQ(1, FastD2IChecked(1.234));
+  CHECK_EQ(1000000, FastD2IChecked(1000000.123));
+
+  CHECK_EQ(INT_MAX, FastD2IChecked(1.0e100));
+  CHECK_EQ(INT_MIN, FastD2IChecked(-1.0e100));
+  CHECK_EQ(INT_MIN, FastD2IChecked(NAN));
 }


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

Reply via email to