Improve replaceUsingStringSearch() for case of a single character searchValue
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Apr 2012 02:30:03 +0000 (02:30 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Apr 2012 02:30:03 +0000 (02:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=83738

Patch by Benjamin Poulain <bpoulain@apple.com> on 2012-04-12
Reviewed by Geoffrey Garen.

This patch improves replaceUsingStringSearch() with the following:
-Add a special case for single character search, taking advantage of the faster WTF::find().
-Inline replaceUsingStringSearch().
-Use StringImpl::create() instead of UString::substringSharingImpl() since we know we are in the bounds
 by definition.

This gives less than 1% improvement for the multicharacter replace.
The single character search show about 9% improvement.

* runtime/StringPrototype.cpp:
(JSC::replaceUsingStringSearch):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@114072 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/StringPrototype.cpp

index 6bcc5b3..1874fcb 100644 (file)
@@ -1,3 +1,22 @@
+2012-04-12  Benjamin Poulain  <bpoulain@apple.com>
+
+        Improve replaceUsingStringSearch() for case of a single character searchValue
+        https://bugs.webkit.org/show_bug.cgi?id=83738
+
+        Reviewed by Geoffrey Garen.
+
+        This patch improves replaceUsingStringSearch() with the following:
+        -Add a special case for single character search, taking advantage of the faster WTF::find().
+        -Inline replaceUsingStringSearch().
+        -Use StringImpl::create() instead of UString::substringSharingImpl() since we know we are in the bounds
+         by definition.
+
+        This gives less than 1% improvement for the multicharacter replace.
+        The single character search show about 9% improvement.
+
+        * runtime/StringPrototype.cpp:
+        (JSC::replaceUsingStringSearch):
+
 2012-04-12  Michael Saboff  <msaboff@apple.com>
 
         StructureStubInfo::reset() causes leaks of PolymorphicAccessStructureList and ExecutableMemoryHandle objects
index ebbb748..f11e641 100644 (file)
@@ -625,14 +625,28 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
     return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, string, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()));
 }
 
-static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue, JSValue replaceValue)
+static inline EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue, JSValue replaceValue)
 {
     const UString& string = jsString->value(exec);
-    UString searchString = searchValue.toString(exec)->value(exec);
+    UString searchString = searchValue.toUString(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
-    size_t matchStart = string.find(searchString);
+    size_t searchStringLength = searchString.length();
+
+    size_t matchStart;
+    if (searchStringLength == 1) {
+        StringImpl* searchStringImpl = searchString.impl();
+        UChar searchCharacter;
+        if (searchStringImpl->is8Bit())
+            searchCharacter = searchStringImpl->characters8()[0];
+        else
+            searchCharacter = searchStringImpl->characters16()[0];
+
+        matchStart = string.find(searchCharacter);
+    } else
+        matchStart = string.find(searchString);
+
     if (matchStart == notFound)
         return JSValue::encode(jsString);
 
@@ -640,7 +654,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS
     CallType callType = getCallData(replaceValue, callData);
     if (callType != CallTypeNone) {
         MarkedArgumentBuffer args;
-        args.append(jsSubstring(exec, string, matchStart, searchString.length()));
+        args.append(jsSubstring(exec, string, matchStart, searchStringLength));
         args.append(jsNumber(matchStart));
         args.append(jsString);
         replaceValue = call(exec, replaceValue, callType, callData, jsUndefined(), args);
@@ -648,13 +662,20 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS
             return JSValue::encode(jsUndefined());
     }
 
-    UString replaceString = replaceValue.toString(exec)->value(exec);
+    UString replaceString = replaceValue.toUString(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
-    size_t matchEnd = matchStart + searchString.length();
+    StringImpl* stringImpl = string.impl();
+    UString leftPart(StringImpl::create(stringImpl, 0, matchStart));
+
+    size_t matchEnd = matchStart + searchStringLength;
     int ovector[2] = { matchStart,  matchEnd};
-    return JSValue::encode(JSC::jsString(exec, string.substringSharingImpl(0, matchStart), substituteBackreferences(replaceString, string, ovector, 0), string.substringSharingImpl(matchEnd)));
+    UString middlePart = substituteBackreferences(replaceString, string, ovector, 0);
+
+    size_t leftLength = stringImpl->length() - matchEnd;
+    UString rightPart(StringImpl::create(stringImpl, matchEnd, leftLength));
+    return JSValue::encode(JSC::jsString(exec, leftPart, middlePart, rightPart));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)