Revision: 4734
Author: [email protected]
Date: Wed May 26 09:11:30 2010
Log: Fix: make string indexing work with Infinity.

NumberToUint32 that I was trying to use maps -0 to +0 (as desired) but
also maps +/-Infinity to +0, which made +/-Infinity a valid string
index. I fixed it by introducing a new runtime function with the right
semantics.

TEST=LayoutTests/fast/js/char-at.html,mjsunit/string-charat.js

Review URL: http://codereview.chromium.org/2223003
http://code.google.com/p/v8/source/detail?r=4734

Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/test/mjsunit/string-charat.js

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Wed May 26 07:23:19 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Wed May 26 09:11:30 2010
@@ -9284,11 +9284,7 @@
   __ Push(object_, index_, result_);
   __ push(index_);  // Consumed by runtime conversion function.
   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    // Strictly speaking, NumberToInteger should be called here, but
-    // our string lengths don't exceed 32 bits and using ToUint32 maps
-    // -0 to 0, which is what is required by the spec when accessing
-    // strings.
-    __ CallRuntime(Runtime::kNumberToJSUint32, 1);
+    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
   } else {
     ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
     // NumberToSmi discards numbers that are not exact integers.
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed May 26 07:23:19 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed May 26 09:11:30 2010
@@ -12655,11 +12655,7 @@
   __ push(result_);
   __ push(index_);  // Consumed by runtime conversion function.
   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    // Strictly speaking, NumberToInteger should be called here, but
-    // our string lengths don't exceed 32 bits and using ToUint32 maps
-    // -0 to 0, which is what is required by the spec when accessing
-    // strings.
-    __ CallRuntime(Runtime::kNumberToJSUint32, 1);
+    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
   } else {
     ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
     // NumberToSmi discards numbers that are not exact integers.
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Wed May 26 02:24:44 2010
+++ /branches/bleeding_edge/src/runtime.cc      Wed May 26 09:11:30 2010
@@ -5285,6 +5285,25 @@
   }
   return Heap::NumberFromDouble(DoubleToInteger(number));
 }
+
+
+static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
+  NoHandleAllocation ha;
+  ASSERT(args.length() == 1);
+
+  CONVERT_DOUBLE_CHECKED(number, args[0]);
+
+  // We do not include 0 so that we don't have to treat +0 / -0 cases.
+  if (number > 0 && number <= Smi::kMaxValue) {
+    return Smi::FromInt(static_cast<int>(number));
+  }
+
+  double double_value = DoubleToInteger(number);
+  // Map both -0 and +0 to +0.
+  if (double_value == 0) double_value = 0;
+
+  return Heap::NumberFromDouble(double_value);
+}


 static Object* Runtime_NumberToJSUint32(Arguments args) {
=======================================
--- /branches/bleeding_edge/src/runtime.h       Thu Apr 29 08:14:39 2010
+++ /branches/bleeding_edge/src/runtime.h       Wed May 26 09:11:30 2010
@@ -102,6 +102,7 @@
   F(NumberToString, 1, 1) \
   F(NumberToStringSkipCache, 1, 1) \
   F(NumberToInteger, 1, 1) \
+  F(NumberToIntegerMapMinusZero, 1, 1) \
   F(NumberToJSUint32, 1, 1) \
   F(NumberToJSInt32, 1, 1) \
   F(NumberToSmi, 1, 1) \
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed May 26 07:23:19 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed May 26 09:11:30 2010
@@ -10935,11 +10935,7 @@
   __ push(result_);
   __ push(index_);  // Consumed by runtime conversion function.
   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    // Strictly speaking, NumberToInteger should be called here, but
-    // our string lengths don't exceed 32 bits and using ToUint32 maps
-    // -0 to 0, which is what is required by the spec when accessing
-    // strings.
-    __ CallRuntime(Runtime::kNumberToJSUint32, 1);
+    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
   } else {
     ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
     // NumberToSmi discards numbers that are not exact integers.
=======================================
--- /branches/bleeding_edge/test/mjsunit/string-charat.js Wed May 26 07:23:19 2010 +++ /branches/bleeding_edge/test/mjsunit/string-charat.js Wed May 26 09:11:30 2010
@@ -41,6 +41,8 @@
   assertEquals("", s.charAt(-1));
   assertEquals("", s.charAt(4));
   assertEquals("", s.charAt(slowIndexOutOfRange));
+  assertEquals("", s.charAt(1/0));
+  assertEquals("", s.charAt(-1/0));
   assertEquals("t", s.charAt(0));
   assertEquals("t", s.charAt(-0.0));
   assertEquals("t", s.charAt(0.4));
@@ -67,6 +69,8 @@
   assertTrue(isNaN(s.charCodeAt(-1)));
   assertTrue(isNaN(s.charCodeAt(4)));
   assertTrue(isNaN(s.charCodeAt(slowIndexOutOfRange)));
+  assertTrue(isNaN(s.charCodeAt(1/0)));
+  assertTrue(isNaN(s.charCodeAt(-1/0)));
 }
 basicTest();

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

Reply via email to