Fast path for string.replace that replaces a single character by a string.

BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10412 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2012-01-16 15:21:38 +00:00
parent 7370cf6f9d
commit a97cebe292
4 changed files with 66 additions and 1 deletions

View File

@ -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));

View File

@ -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().

View File

@ -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,

View File

@ -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;