Make StringCharCodeAt runtime function do what it name implies and not
authorvitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 3 Jun 2010 09:32:07 +0000 (09:32 +0000)
committervitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 3 Jun 2010 09:32:07 +0000 (09:32 +0000)
just indexed string access.

The difference is that String.prototype.charCodeAt accepts any number
as an index, whereas string[] only accepts array indices.

Review URL: http://codereview.chromium.org/2467006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4790 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/runtime.cc
src/runtime.h
test/mjsunit/string-charat.js
test/mjsunit/string-charcodeat.js

index d53b13d..80e67cc 100644 (file)
@@ -1638,22 +1638,6 @@ static Object* Runtime_SetCode(Arguments args) {
 }
 
 
-static Object* CharCodeAt(String* subject, Object* index) {
-  uint32_t i = 0;
-  if (!index->ToArrayIndex(&i)) return Heap::nan_value();
-  // Flatten the string.  If someone wants to get a char at an index
-  // in a cons string, it is likely that more indices will be
-  // accessed.
-  Object* flat = subject->TryFlatten();
-  if (flat->IsFailure()) return flat;
-  subject = String::cast(flat);
-  if (i >= static_cast<uint32_t>(subject->length())) {
-    return Heap::nan_value();
-  }
-  return Smi::FromInt(subject->Get(i));
-}
-
-
 static Object* CharFromCode(Object* char_code) {
   uint32_t code;
   if (char_code->ToArrayIndex(&code)) {
@@ -1671,21 +1655,31 @@ static Object* Runtime_StringCharCodeAt(Arguments args) {
 
   CONVERT_CHECKED(String, subject, args[0]);
   Object* index = args[1];
-  return CharCodeAt(subject, index);
-}
+  RUNTIME_ASSERT(index->IsNumber());
 
+  uint32_t i = 0;
+  if (index->IsSmi()) {
+    int value = Smi::cast(index)->value();
+    if (value < 0) return Heap::nan_value();
+    i = value;
+  } else {
+    ASSERT(index->IsHeapNumber());
+    double value = HeapNumber::cast(index)->value();
+    i = static_cast<uint32_t>(value);
+  }
 
-static Object* Runtime_StringCharAt(Arguments args) {
-  NoHandleAllocation ha;
-  ASSERT(args.length() == 2);
+  // Flatten the string.  If someone wants to get a char at an index
+  // in a cons string, it is likely that more indices will be
+  // accessed.
+  Object* flat = subject->TryFlatten();
+  if (flat->IsFailure()) return flat;
+  subject = String::cast(flat);
 
-  CONVERT_CHECKED(String, subject, args[0]);
-  Object* index = args[1];
-  Object* code = CharCodeAt(subject, index);
-  if (code == Heap::nan_value()) {
-    return Heap::undefined_value();
+  if (i >= static_cast<uint32_t>(subject->length())) {
+    return Heap::nan_value();
   }
-  return CharFromCode(code);
+
+  return Smi::FromInt(subject->Get(i));
 }
 
 
@@ -5344,6 +5338,9 @@ static Object* Runtime_NumberToInteger(Arguments args) {
 }
 
 
+
+
+
 static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
index c8447cb..c586a4b 100644 (file)
@@ -162,7 +162,6 @@ namespace internal {
   \
   /* Strings */ \
   F(StringCharCodeAt, 2, 1) \
-  F(StringCharAt, 2, 1) \
   F(StringIndexOf, 3, 1) \
   F(StringLastIndexOf, 3, 1) \
   F(StringLocaleCompare, 2, 1) \
index f0b0566..99afb75 100644 (file)
 
 var s = "test";
 
+function getTwoByteString() { return "\u1234t"; }
+function getCons() { return "testtesttesttest" + getTwoByteString() }
+
 var slowIndex1 = { valueOf: function() { return 1; } };
 var slowIndex2 = { toString: function() { return "2"; } };
 var slowIndexOutOfRange = { valueOf: function() { return -1; } };
 
-function basicTest() {
-  assertEquals("t", s.charAt());
-  assertEquals("t", s.charAt("string"));
-  assertEquals("t", s.charAt(null));
-  assertEquals("t", s.charAt(void 0));
-  assertEquals("t", s.charAt(false));
-  assertEquals("e", s.charAt(true));
-  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));
-  assertEquals("e", s.charAt(slowIndex1));
-  assertEquals("s", s.charAt(slowIndex2));
-  assertEquals("t", s.charAt(3));
-  assertEquals("t", s.charAt(3.4));
-  assertEquals("t", s.charAt(NaN));
-
-  assertEquals(116, s.charCodeAt());
-  assertEquals(116, s.charCodeAt("string"));
-  assertEquals(116, s.charCodeAt(null));
-  assertEquals(116, s.charCodeAt(void 0));
-  assertEquals(116, s.charCodeAt(false));
-  assertEquals(101, s.charCodeAt(true));
-  assertEquals(116, s.charCodeAt(0));
-  assertEquals(116, s.charCodeAt(-0.0));
-  assertEquals(116, s.charCodeAt(0.4));
-  assertEquals(101, s.charCodeAt(slowIndex1));
-  assertEquals(115, s.charCodeAt(slowIndex2));
-  assertEquals(116, s.charCodeAt(3));
-  assertEquals(116, s.charCodeAt(3.4));
-  assertEquals(116, s.charCodeAt(NaN));
-  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)));
+function basicTest(s, len) {
+  assertEquals("t", s().charAt());
+  assertEquals("t", s().charAt("string"));
+  assertEquals("t", s().charAt(null));
+  assertEquals("t", s().charAt(void 0));
+  assertEquals("t", s().charAt(false));
+  assertEquals("e", s().charAt(true));
+  assertEquals("", s().charAt(-1));
+  assertEquals("", s().charAt(len));
+  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));
+  assertEquals("e", s().charAt(slowIndex1));
+  assertEquals("s", s().charAt(slowIndex2));
+  assertEquals("t", s().charAt(3));
+  assertEquals("t", s().charAt(3.4));
+  assertEquals("t", s().charAt(NaN));
+
+  assertEquals(116, s().charCodeAt());
+  assertEquals(116, s().charCodeAt("string"));
+  assertEquals(116, s().charCodeAt(null));
+  assertEquals(116, s().charCodeAt(void 0));
+  assertEquals(116, s().charCodeAt(false));
+  assertEquals(101, s().charCodeAt(true));
+  assertEquals(116, s().charCodeAt(0));
+  assertEquals(116, s().charCodeAt(-0.0));
+  assertEquals(116, s().charCodeAt(0.4));
+  assertEquals(101, s().charCodeAt(slowIndex1));
+  assertEquals(115, s().charCodeAt(slowIndex2));
+  assertEquals(116, s().charCodeAt(3));
+  assertEquals(116, s().charCodeAt(3.4));
+  assertEquals(116, s().charCodeAt(NaN));
+  assertTrue(isNaN(s().charCodeAt(-1)));
+  assertTrue(isNaN(s().charCodeAt(len)));
+  assertTrue(isNaN(s().charCodeAt(slowIndexOutOfRange)));
+  assertTrue(isNaN(s().charCodeAt(1/0)));
+  assertTrue(isNaN(s().charCodeAt(-1/0)));
 }
-basicTest();
+basicTest(function() { return s; }, s.length);
+basicTest(getCons, getCons().length);
 
 // Make sure enough of the one-char string cache is filled.
 var alpha = ['@'];
@@ -122,7 +126,8 @@ stealTest();
 
 // Test custom string IC-s.
 for (var i = 0; i < 20; i++) {
-  basicTest();
+  basicTest(function() { return s; }, s.length);
+  basicTest(getCons, getCons().length);
   stealTest();
 }
 
index 3927557..831f688 100644 (file)
@@ -153,6 +153,10 @@ TestStringType(Slice16End, true);
 TestStringType(Flat16, true);
 TestStringType(NotAString16, true);
 
+for (var i = 0; i != 10; i++) {
+  assertEquals(101, Cons16().charCodeAt(1.1));
+  assertEquals('e', Cons16().charAt(1.1));
+}
 
 function StupidThing() {
   // Doesn't return a string from toString!