Title: [229520] trunk
Revision
229520
Author
utatane....@gmail.com
Date
2018-03-11 20:25:39 -0700 (Sun, 11 Mar 2018)

Log Message

[DFG] AI should convert CreateThis to NewObject if the prototype object is proved
https://bugs.webkit.org/show_bug.cgi?id=183310

Reviewed by Filip Pizlo.

JSTests:

* stress/ai-create-this-to-new-object-fire.js: Added.
(assert):
(test):
(func):
(check):
(test.body.A):
(test.body.B):
(test.body):
* stress/ai-create-this-to-new-object.js: Added.
(assert):
(test):
(func):
(check):
(test.body.A):
(test.body.B):
(test.body):

Source/_javascript_Core:

This patch implements CreateThis -> NewObject conversion in AI if the given function is constant.
This contributes to 6% win in Octane/raytrace.

                                baseline                  patched

    raytrace       x2       1.19915+-0.01862    ^     1.13156+-0.01589       ^ definitely 1.0597x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (229519 => 229520)


--- trunk/JSTests/ChangeLog	2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/JSTests/ChangeLog	2018-03-12 03:25:39 UTC (rev 229520)
@@ -1,3 +1,27 @@
+2018-03-11  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [DFG] AI should convert CreateThis to NewObject if the prototype object is proved
+        https://bugs.webkit.org/show_bug.cgi?id=183310
+
+        Reviewed by Filip Pizlo.
+
+        * stress/ai-create-this-to-new-object-fire.js: Added.
+        (assert):
+        (test):
+        (func):
+        (check):
+        (test.body.A):
+        (test.body.B):
+        (test.body):
+        * stress/ai-create-this-to-new-object.js: Added.
+        (assert):
+        (test):
+        (func):
+        (check):
+        (test.body.A):
+        (test.body.B):
+        (test.body):
+
 2018-03-10  Yusuke Suzuki  <utatane....@gmail.com>
 
         [FTL] Drop NewRegexp for String.prototype.match with RegExp + global flag

Added: trunk/JSTests/stress/ai-create-this-to-new-object-fire.js (0 => 229520)


--- trunk/JSTests/stress/ai-create-this-to-new-object-fire.js	                        (rev 0)
+++ trunk/JSTests/stress/ai-create-this-to-new-object-fire.js	2018-03-12 03:25:39 UTC (rev 229520)
@@ -0,0 +1,61 @@
+function assert(b, m = "Bad!") {
+    if (!b) {
+        throw new Error(m);
+    }
+}
+
+function test(f, iters = 1000) {
+    for (let i = 0; i < iters; i++)
+        f(i);
+}
+
+function func(x) {
+    return x;
+}
+noInline(func);
+
+var n = 2;
+var prototype = {};
+function prep(index, i, A, B)
+{
+    if (index === (n - 1) && i === 5000) {
+        // Fire watchpoint!
+        A.prototype = prototype;
+    }
+}
+
+function check(index, arr, A, B, originalPrototype)
+{
+    if (index === (n - 1)) {
+        assert(originalPrototype !== prototype);
+        for (let i = 0; i < 5000; i++)
+            assert(arr[i].__proto__ === originalPrototype);
+        for (let i = 5000; i < 10000; i++)
+            assert(arr[i].__proto__ === prototype);
+    } else {
+        for (let i = 0; i < 10000; i++)
+            assert(arr[i].__proto__ === originalPrototype);
+    }
+}
+noInline(check);
+
+test(function body(index) {
+    function A(x, f = func) {
+        this._value = x;
+        this._func = f;
+    }
+
+    function B(n)
+    {
+        return new A(n);
+    }
+
+    var originalPrototype = A.prototype;
+    let arr = [];
+    for (let i = 0; i < 10000; i++) {
+        prep(index, i, A, B);
+        arr.push(B(20));
+    }
+
+    check(index, arr, A, B, originalPrototype);
+}, n);

Added: trunk/JSTests/stress/ai-create-this-to-new-object.js (0 => 229520)


--- trunk/JSTests/stress/ai-create-this-to-new-object.js	                        (rev 0)
+++ trunk/JSTests/stress/ai-create-this-to-new-object.js	2018-03-12 03:25:39 UTC (rev 229520)
@@ -0,0 +1,41 @@
+function assert(b, m = "Bad!") {
+    if (!b) {
+        throw new Error(m);
+    }
+}
+
+function test(f, iters = 1000) {
+    for (let i = 0; i < iters; i++)
+        f(i);
+}
+
+function func(x) {
+    return x;
+}
+noInline(func);
+
+function check(index, arr, B)
+{
+    for (let i = 0; i < 1000; i++)
+        assert(arr[i] instanceof B);
+}
+noInline(check);
+
+test(function body(index) {
+    class A {
+        constructor(x, f = func)
+        {
+            this._value = x;
+            this._func = f;
+        }
+    }
+
+    class B extends A {
+    }
+
+    let arr = [];
+    for (let i = 0; i < 1000; i++)
+        arr.push(new B(20));
+
+    check(index, arr, B);
+}, 8);

Modified: trunk/Source/_javascript_Core/ChangeLog (229519 => 229520)


--- trunk/Source/_javascript_Core/ChangeLog	2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-03-12 03:25:39 UTC (rev 229520)
@@ -1,3 +1,22 @@
+2018-03-11  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [DFG] AI should convert CreateThis to NewObject if the prototype object is proved
+        https://bugs.webkit.org/show_bug.cgi?id=183310
+
+        Reviewed by Filip Pizlo.
+
+        This patch implements CreateThis -> NewObject conversion in AI if the given function is constant.
+        This contributes to 6% win in Octane/raytrace.
+
+                                        baseline                  patched
+
+            raytrace       x2       1.19915+-0.01862    ^     1.13156+-0.01589       ^ definitely 1.0597x faster
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+
 2018-03-11  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Disable Sigill crash analyzer on watchOS

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (229519 => 229520)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2018-03-12 03:25:39 UTC (rev 229520)
@@ -2257,7 +2257,23 @@
     }
 
     case CreateThis: {
-        // FIXME: We can fold this to NewObject if the incoming callee is a constant.
+        if (JSValue base = forNode(node->child1()).m_value) {
+            if (auto* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
+                if (FunctionRareData* rareData = function->rareData()) {
+                    if (Structure* structure = rareData->objectAllocationStructure()) {
+                        // FIXME: we should be able to allocate a poly proto object here:
+                        // https://bugs.webkit.org/show_bug.cgi?id=177517
+                        if (structure->hasMonoProto()) {
+                            m_graph.freeze(rareData);
+                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+                            m_state.setFoundConstants(true);
+                            forNode(node).set(m_graph, structure);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
         forNode(node).setType(m_graph, SpecFinalObject);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (229519 => 229520)


--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2018-03-12 03:25:39 UTC (rev 229520)
@@ -636,6 +636,27 @@
                 break;
             }
 
+            case CreateThis: {
+                if (JSValue base = m_state.forNode(node->child1()).m_value) {
+                    if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
+                        if (FunctionRareData* rareData = function->rareData()) {
+                            if (Structure* structure = rareData->objectAllocationStructure()) {
+                                // FIXME: we should be able to allocate a poly proto object here:
+                                // https://bugs.webkit.org/show_bug.cgi?id=177517
+                                if (structure->hasMonoProto()) {
+                                    m_graph.freeze(rareData);
+                                    m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+                                    node->convertToNewObject(m_graph.registerStructure(structure));
+                                    changed = true;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+
             case ToNumber: {
                 if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber)
                     break;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to