Title: [197416] trunk
Revision
197416
Author
fpi...@apple.com
Date
2016-03-01 15:35:05 -0800 (Tue, 01 Mar 2016)

Log Message

FTL should simplify StringReplace with an empty replacement string
https://bugs.webkit.org/show_bug.cgi?id=154871

Reviewed by Michael Saboff.

This is a simple and hugely profitable change. If we do a string.replace(/things/, ""), then
this calls directly into StringPrototype's replace-with-empty-string logic instead of going
through stuff that does checks before reaching that same conclusion.

This speeds up Octane/regexp by about 6-10%. It also speeds up the attached microbenchmark by
about 7%.

* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileStringReplace):
* runtime/StringPrototype.cpp:
(JSC::jsSpliceSubstringsWithSeparators):
(JSC::removeUsingRegExpSearch):
(JSC::replaceUsingRegExpSearch):
(JSC::operationStringProtoFuncReplaceRegExpEmptyStr):
(JSC::operationStringProtoFuncReplaceRegExpString):
* runtime/StringPrototype.h:

Modified Paths

Diff

Modified: trunk/LayoutTests/js/regress/script-tests/string-replace.js (197415 => 197416)


--- trunk/LayoutTests/js/regress/script-tests/string-replace.js	2016-03-01 23:33:36 UTC (rev 197415)
+++ trunk/LayoutTests/js/regress/script-tests/string-replace.js	2016-03-01 23:35:05 UTC (rev 197416)
@@ -1,7 +1,7 @@
 (function() {
     var result;
     for (var i = 0; i < 400000; ++i) {
-        result = "foo".replace(/f/, "b");
+        result = "foo".replace(/f/g, "b");
     }
     if (result != "boo")
         throw "Error: bad result: "+ result;

Modified: trunk/Source/_javascript_Core/ChangeLog (197415 => 197416)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-01 23:33:36 UTC (rev 197415)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-01 23:35:05 UTC (rev 197416)
@@ -1,3 +1,27 @@
+2016-03-01  Filip Pizlo  <fpi...@apple.com>
+
+        FTL should simplify StringReplace with an empty replacement string
+        https://bugs.webkit.org/show_bug.cgi?id=154871
+
+        Reviewed by Michael Saboff.
+
+        This is a simple and hugely profitable change. If we do a string.replace(/things/, ""), then
+        this calls directly into StringPrototype's replace-with-empty-string logic instead of going
+        through stuff that does checks before reaching that same conclusion.
+
+        This speeds up Octane/regexp by about 6-10%. It also speeds up the attached microbenchmark by
+        about 7%.
+
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileStringReplace):
+        * runtime/StringPrototype.cpp:
+        (JSC::jsSpliceSubstringsWithSeparators):
+        (JSC::removeUsingRegExpSearch):
+        (JSC::replaceUsingRegExpSearch):
+        (JSC::operationStringProtoFuncReplaceRegExpEmptyStr):
+        (JSC::operationStringProtoFuncReplaceRegExpString):
+        * runtime/StringPrototype.h:
+
 2016-03-01  Alex Christensen  <achristen...@webkit.org>
 
         Reduce size of internal windows build output

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (197415 => 197416)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-03-01 23:33:36 UTC (rev 197415)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-03-01 23:35:05 UTC (rev 197416)
@@ -6467,6 +6467,21 @@
         if (m_node->child1().useKind() == StringUse
             && m_node->child2().useKind() == RegExpObjectUse
             && m_node->child3().useKind() == StringUse) {
+
+            if (JSString* replace = m_node->child3()->dynamicCastConstant<JSString*>()) {
+                if (!replace->length()) {
+                    LValue string = lowString(m_node->child1());
+                    LValue regExp = lowCell(m_node->child2());
+                    speculateRegExpObject(m_node->child2(), regExp);
+
+                    LValue result = vmCall(
+                        Int64, m_out.operation(operationStringProtoFuncReplaceRegExpEmptyStr),
+                        m_callFrame, string, regExp);
+
+                    setJSValue(result);
+                    return;
+                }
+            }
             
             LValue string = lowString(m_node->child1());
             LValue regExp = lowCell(m_node->child2());

Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (197415 => 197416)


--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2016-03-01 23:33:36 UTC (rev 197415)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2016-03-01 23:35:05 UTC (rev 197416)
@@ -446,7 +446,7 @@
     return jsString(exec, impl.release());
 }
 
-static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSString* string, const String& source, RegExp* regExp)
+static ALWAYS_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSString* string, const String& source, RegExp* regExp)
 {
     size_t lastIndex = 0;
     unsigned startPosition = 0;
@@ -506,6 +506,8 @@
             return removeUsingRegExpSearch(exec, string, source, regExp);
     }
 
+    // FIXME: This is wrong because we may be called directly from the FTL.
+    // https://bugs.webkit.org/show_bug.cgi?id=154874
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
 
     size_t lastIndex = 0;
@@ -664,6 +666,24 @@
     return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, string, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()));
 }
 
+EncodedJSValue JIT_OPERATION operationStringProtoFuncReplaceRegExpEmptyStr(
+    ExecState* exec, JSString* thisValue, RegExpObject* searchValue)
+{
+    RegExp* regExp = searchValue->regExp();
+    if (regExp->global()) {
+        // ES5.1 15.5.4.10 step 8.a.
+        searchValue->setLastIndex(exec, 0);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+        return removeUsingRegExpSearch(exec, thisValue, thisValue->value(exec), regExp);
+    }
+
+    CallData callData;
+    String replacementString = emptyString();
+    return replaceUsingRegExpSearch(
+        exec, thisValue, searchValue, callData, CallTypeNone, replacementString, JSValue());
+}
+
 EncodedJSValue JIT_OPERATION operationStringProtoFuncReplaceRegExpString(
     ExecState* exec, JSString* thisValue, RegExpObject* searchValue, JSString* replaceString)
 {

Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.h (197415 => 197416)


--- trunk/Source/_javascript_Core/runtime/StringPrototype.h	2016-03-01 23:33:36 UTC (rev 197415)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.h	2016-03-01 23:35:05 UTC (rev 197416)
@@ -54,11 +54,13 @@
 };
 
 EncodedJSValue JIT_OPERATION operationStringProtoFuncReplaceGeneric(
-    ExecState* exec, EncodedJSValue thisValue, EncodedJSValue searchValue,
-    EncodedJSValue replaceValue);
+    ExecState*, EncodedJSValue thisValue, EncodedJSValue searchValue, EncodedJSValue replaceValue);
 
+EncodedJSValue JIT_OPERATION operationStringProtoFuncReplaceRegExpEmptyStr(
+    ExecState*, JSString* thisValue, RegExpObject* searchValue);
+
 EncodedJSValue JIT_OPERATION operationStringProtoFuncReplaceRegExpString(
-    ExecState* exec, JSString* thisValue, RegExpObject* searchValue, JSString* replaceValue);
+    ExecState*, JSString* thisValue, RegExpObject* searchValue, JSString* replaceValue);
 
 } // namespace JSC
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to