From 3ec0b86495b17bb52f936afd18d8f02df24478f2 Mon Sep 17 00:00:00 2001 From: "vitalyr@chromium.org" Date: Thu, 3 Jun 2010 09:32:07 +0000 Subject: [PATCH] Make StringCharCodeAt runtime function do what it name implies and not 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 | 51 +++++++++++----------- src/runtime.h | 1 - test/mjsunit/string-charat.js | 89 +++++++++++++++++++++------------------ test/mjsunit/string-charcodeat.js | 4 ++ 4 files changed, 75 insertions(+), 70 deletions(-) diff --git a/src/runtime.cc b/src/runtime.cc index d53b13d..80e67cc 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -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(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(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(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); diff --git a/src/runtime.h b/src/runtime.h index c8447cb..c586a4b 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -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) \ diff --git a/test/mjsunit/string-charat.js b/test/mjsunit/string-charat.js index f0b0566..99afb75 100644 --- a/test/mjsunit/string-charat.js +++ b/test/mjsunit/string-charat.js @@ -27,52 +27,56 @@ 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(); } diff --git a/test/mjsunit/string-charcodeat.js b/test/mjsunit/string-charcodeat.js index 3927557..831f688 100644 --- a/test/mjsunit/string-charcodeat.js +++ b/test/mjsunit/string-charcodeat.js @@ -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! -- 2.7.4