Reviewers: rossberg,
Message:
Please take a look.
When replacing a single character by a string, instead of flattening the
string
for search and copying the string to replace, we can avoid flattening by
depth-first traversal of the cons-string tree and replace the affected part
by a
cons string consisting of slices of the original string.
Description:
Fast path for string.replace that replaces a single character by a string.
BUG=
TEST=
Please review this at http://codereview.chromium.org/9213002/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/heap.cc
M src/runtime.h
M src/runtime.cc
M src/string.js
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index
6295788f0af9a2f4d1e772143ff684362b568d75..7a8f8668fa5dc330d47967da3a09e977de14eb3e
100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -3011,7 +3011,7 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
int end,
PretenureFlag pretenure) {
int length = end - start;
- if (length == 0) {
+ if (length <= 0) {
return empty_string();
} else if (length == 1) {
return LookupSingleCharacterStringFromCode(buffer->Get(start));
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index
df37174c51a499ea3ca31aca47d09139884b91d6..0dc17c5a9ddd6973f7d826639ea402150ecaf9b9
100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -3233,6 +3233,59 @@ RUNTIME_FUNCTION(MaybeObject*,
Runtime_StringReplaceRegExpWithString) {
}
+Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
+ Handle<String>
subject,
+ Handle<String>
search,
+ Handle<String>
replace,
+ bool* found) {
+ if (subject->IsConsString()) {
+ ConsString* cons = ConsString::cast(*subject);
+ Handle<String> first = Handle<String>(cons->first());
+ Handle<String> second = Handle<String>(cons->second());
+ Handle<String> new_first = StringReplaceOneCharWithString(isolate,
+ first,
+ search,
+ replace,
+ found);
+ if (*found) {
+ return isolate->factory()->NewConsString(new_first, second);
+ } else {
+ Handle<String> new_second = StringReplaceOneCharWithString(isolate,
+ second,
+ search,
+ replace,
+ found);
+ return isolate->factory()->NewConsString(first, new_second);
+ }
+ } else {
+ int index = StringMatch(isolate, subject, search, 0);
+ if (index == -1) return subject;
+ *found = true;
+ Handle<String> first = isolate->factory()->NewSubString(subject, 0,
index);
+ Handle<String> cons1 = isolate->factory()->NewConsString(first,
replace);
+ Handle<String> second =
+ isolate->factory()->NewSubString(subject, index + 1,
subject->length());
+ return isolate->factory()->NewConsString(cons1, second);
+ }
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
+ ASSERT(args.length() == 3);
+ HandleScope scope(isolate);
+ CONVERT_ARG_CHECKED(String, subject, 0);
+ CONVERT_ARG_CHECKED(String, search, 1);
+ CONVERT_ARG_CHECKED(String, replace, 2);
+ bool found = false;
+
+ return *(Runtime::StringReplaceOneCharWithString(isolate,
+ subject,
+ search,
+ replace,
+ &found));
+}
+
+
// Perform string match of pattern on subject, starting at start index.
// Caller must ensure that 0 <= start_index <= sub->length(),
// and should check that pat->length() + start_index <= sub->length().
Index: src/runtime.h
diff --git a/src/runtime.h b/src/runtime.h
index
c915cf38da4f9b1bd0d075d49391aaafb4fcde68..3056217ea6734c4e1575f7b0e0980bb6d660f019
100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -197,6 +197,7 @@ namespace internal {
F(StringLocaleCompare, 2, 1) \
F(SubString, 3, 1) \
F(StringReplaceRegExpWithString, 4, 1) \
+ F(StringReplaceOneCharWithString, 3, 1) \
F(StringMatch, 3, 1) \
F(StringTrim, 3, 1) \
F(StringToArray, 2, 1) \
@@ -629,6 +630,12 @@ class Runtime : public AllStatic {
// Get the intrinsic function with the given FunctionId.
static const Function* FunctionForId(FunctionId id);
+ static Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
+ Handle<String>
subject,
+ Handle<String>
search,
+ Handle<String>
replace,
+ bool* found);
+
// General-purpose helper functions for runtime system.
static int StringMatch(Isolate* isolate,
Handle<String> sub,
Index: src/string.js
diff --git a/src/string.js b/src/string.js
index
3608bac8facc279b0d0c31cd299cec641e58d714..e858b0fd526e7c8b8995981460bf7130b5974228
100644
--- a/src/string.js
+++ b/src/string.js
@@ -244,6 +244,11 @@ function StringReplace(search, replace) {
// Convert the search argument to a string and search for it.
search = TO_STRING_INLINE(search);
+ if (search.length == 1 &&
+ IS_STRING(replace) &&
+ %StringIndexOf(replace, '$', 0) < 0) {
+ return %StringReplaceOneCharWithString(subject, search, replace);
+ }
var start = %StringIndexOf(subject, search, 0);
if (start < 0) return subject;
var end = start + search.length;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev