From 0acc9e13af976170b10dbf3c15dac617eddcc27e Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Mon, 30 Jul 2012 08:34:26 +0000 Subject: [PATCH] Make sure double to int conversion is correct. R=svenpanne@chromium.org BUG=v8:2260 TEST=test-utils/Utils1 Review URL: https://chromiumcodereview.appspot.com/10820047 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12216 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/conversions.h | 12 ++++++++++-- src/elements.cc | 2 +- src/runtime.cc | 10 +++++----- test/cctest/test-utils.cc | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/conversions.h b/src/conversions.h index 70559c9..e12cf5c 100644 --- a/src/conversions.h +++ b/src/conversions.h @@ -59,11 +59,19 @@ inline double SignedZero(bool negative) { // 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(x); +} + + +// The fast double-to-(unsigned-)int conversion routine does not guarantee +// rounding towards zero. // 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(x); } diff --git a/src/elements.cc b/src/elements.cc index f0e1414..4cb50a4 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -800,7 +800,7 @@ class FastElementsAccessor } } 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); } diff --git a/src/runtime.cc b/src/runtime.cc index f7bd0e4..2aaa249 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -3755,8 +3755,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) { } 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 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { 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 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { 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 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { 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 = diff --git a/test/cctest/test-utils.cc b/test/cctest/test-utils.cc index df8ff72..6cd931d 100644 --- a/test/cctest/test-utils.cc +++ b/test/cctest/test-utils.cc @@ -55,6 +55,22 @@ TEST(Utils1) { CHECK_EQ(-2, -8 >> 2); CHECK_EQ(-2, static_cast(-8) >> 2); CHECK_EQ(-2, static_cast(static_cast(-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)); } -- 2.7.4