Title: [207060] trunk
Revision
207060
Author
sbar...@apple.com
Date
2016-10-11 00:28:08 -0700 (Tue, 11 Oct 2016)

Log Message

ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String
https://bugs.webkit.org/show_bug.cgi?id=163182

Reviewed by Filip Pizlo.

JSTests:

* microbenchmarks/string-add-constant-folding.js: Added.
(assert):
(runTests):
(add):
(test):

Source/_javascript_Core:

This code pattern shows up in Dromaeo, so it's worth optimizing for.
This might also show up in real world JS code due to inlining and other
types of constant folding.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGLazyJSValue.cpp:
(JSC::DFG::LazyJSValue::getValue):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (207059 => 207060)


--- trunk/JSTests/ChangeLog	2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/JSTests/ChangeLog	2016-10-11 07:28:08 UTC (rev 207060)
@@ -1,3 +1,16 @@
+2016-10-11  Saam Barati  <sbar...@apple.com>
+
+        ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String
+        https://bugs.webkit.org/show_bug.cgi?id=163182
+
+        Reviewed by Filip Pizlo.
+
+        * microbenchmarks/string-add-constant-folding.js: Added.
+        (assert):
+        (runTests):
+        (add):
+        (test):
+
 2016-10-07  Mark Lam  <mark....@apple.com>
 
         Object.freeze() and seal() should throw if [[PreventExtensions]]() fails.

Added: trunk/JSTests/microbenchmarks/string-add-constant-folding.js (0 => 207060)


--- trunk/JSTests/microbenchmarks/string-add-constant-folding.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/string-add-constant-folding.js	2016-10-11 07:28:08 UTC (rev 207060)
@@ -0,0 +1,68 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad assertion.");
+}
+
+let tests = [];
+function test(f) {
+    noInline(f);
+    tests.push(f);
+}
+
+function runTests() {
+    let start = Date.now();
+    for (let f of tests) {
+        for (let i = 0; i < 40000; i++)
+            f();
+    }
+    const verbose = false;
+    if (verbose)
+        print(Date.now() - start);
+}
+
+function add(a,b) { return a + b; }
+noInline(add);
+
+test(function() {
+    let a = "foo";
+    let b = 20;
+    assert(a + b === add(a, b));
+    assert(b + a === add(b, a));
+});
+
+test(function() {
+    let a = "foo";
+    let b = null;
+    assert(a + b === add(a, b));
+    assert(b + a === add(b, a));
+});
+
+test(function() {
+    let a = "foo";
+    let b = undefined;
+    assert(a + b === add(a, b));
+    assert(b + a === add(b, a));
+});
+
+test(function() {
+    let a = "foo";
+    let b = 20.81239012821;
+    assert(a + b === add(a, b));
+    assert(b + a === add(b, a));
+});
+
+test(function() {
+    let a = "foo";
+    let b = true;
+    assert(a + b === add(a, b));
+    assert(b + a === add(b, a));
+});
+
+test(function() {
+    let a = "foo";
+    let b = false;
+    assert(a + b === add(a, b));
+    assert(b + a === add(b, a));
+});
+
+runTests();

Modified: trunk/Source/_javascript_Core/ChangeLog (207059 => 207060)


--- trunk/Source/_javascript_Core/ChangeLog	2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-10-11 07:28:08 UTC (rev 207060)
@@ -1,3 +1,21 @@
+2016-10-11  Saam Barati  <sbar...@apple.com>
+
+        ValueAdd should be constant folded if the operands are constant String,Primitive or Primitive,String
+        https://bugs.webkit.org/show_bug.cgi?id=163182
+
+        Reviewed by Filip Pizlo.
+
+        This code pattern shows up in Dromaeo, so it's worth optimizing for.
+        This might also show up in real world JS code due to inlining and other
+        types of constant folding.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGLazyJSValue.cpp:
+        (JSC::DFG::LazyJSValue::getValue):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+
 2016-10-10  Zan Dobersek  <zdober...@igalia.com>
 
         Add ENABLE_ENCRYPTED_MEDIA configuration option

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (207059 => 207060)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-10-11 07:28:08 UTC (rev 207060)
@@ -4239,7 +4239,12 @@
                 ByValInfo* byValInfo = m_inlineStackTop->m_byValInfos.get(CodeOrigin(currentCodeOrigin().bytecodeIndex));
                 // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
                 // At that time, there is no information.
-                if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent) && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
+                if (byValInfo 
+                    && byValInfo->stubInfo
+                    && !byValInfo->tookSlowPath
+                    && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
+                    && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
+                    && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
                     compiledAsPutById = true;
                     unsigned identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl());
                     UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];

Modified: trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp (207059 => 207060)


--- trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp	2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp	2016-10-11 07:28:08 UTC (rev 207060)
@@ -51,8 +51,9 @@
     case SingleCharacterString:
         return jsSingleCharacterString(&vm, u.character);
     case KnownStringImpl:
+        return jsString(&vm, u.stringImpl);
     case NewStringImpl:
-        return jsString(&vm, u.stringImpl);
+        return jsString(&vm, AtomicStringImpl::add(u.stringImpl));
     }
     RELEASE_ASSERT_NOT_REACHED();
     return JSValue();

Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (207059 => 207060)


--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2016-10-11 07:14:34 UTC (rev 207059)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2016-10-11 07:28:08 UTC (rev 207060)
@@ -322,8 +322,48 @@
         // move these to the abstract interpreter once AbstractValue can support LazyJSValue.
         // https://bugs.webkit.org/show_bug.cgi?id=155204
 
+        case ValueAdd: {
+            if (m_node->child1()->isConstant()
+                && m_node->child2()->isConstant()
+                && (!!m_node->child1()->tryGetString(m_graph) || !!m_node->child2()->tryGetString(m_graph))) {
+                auto tryGetConstantString = [&] (Node* node) -> String {
+                    String string = node->tryGetString(m_graph);
+                    if (!string.isEmpty())
+                        return string;
+                    JSValue value = node->constant()->value();
+                    if (!value)
+                        return String();
+                    if (value.isInt32())
+                        return String::number(value.asInt32());
+                    if (value.isNumber())
+                        return String::numberToStringECMAScript(value.asNumber());
+                    if (value.isBoolean())
+                        return value.asBoolean() ? ASCIILiteral("true") : ASCIILiteral("false");
+                    if (value.isNull())
+                        return ASCIILiteral("null");
+                    if (value.isUndefined())
+                        return ASCIILiteral("undefined");
+                    return String();
+                };
+
+                String leftString = tryGetConstantString(m_node->child1().node());
+                if (!leftString)
+                    break;
+                String rightString = tryGetConstantString(m_node->child2().node());
+                if (!rightString)
+                    break;
+
+                StringBuilder builder;
+                builder.append(leftString);
+                builder.append(rightString);
+                m_node->convertToLazyJSConstant(
+                    m_graph, LazyJSValue::newString(m_graph, builder.toString()));
+                m_changed = true;
+            }
+            break;
+        }
+
         case MakeRope:
-        case ValueAdd:
         case StrCat: {
             String leftString = m_node->child1()->tryGetString(m_graph);
             if (!leftString)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to