Title: [200325] trunk/Source/_javascript_Core
Revision
200325
Author
[email protected]
Date
2016-05-02 10:38:15 -0700 (Mon, 02 May 2016)

Log Message

ToThis should be able to be eliminated in Constant Folding
https://bugs.webkit.org/show_bug.cgi?id=157213

Reviewed by Saam Barati.

This patch enables eliminating the ToThis value when we have abstract interpreter
indicates the node is not needed. Since there are Objects that override their
ToThis behavior we first check if we can eliminate the node by looking at its
speculated type. If the function is in strict mode then we can eliminate ToThis as
long as the speculated type is not SpecObjectOther since that contains objects
that may set OverridesToThis. If the function is not in strict mode then we can
eliminate ToThis as long is the speculated type is an object that is not SpecObjectOther.

If we can't eliminate with type information we can still eliminate the ToThis node with
the proven structure set. When ToThis only sees structures that do not set OverridesToThis
it can be eliminated. Additionally, if the function is in strict mode then we can eliminate
ToThis as long as all only the object structures don't set OverridesToThis.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::isToThisAnIdentity):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupToThis):
* tests/stress/to-this-global-object.js: Added.
(test):
(test2):
(get for):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (200324 => 200325)


--- trunk/Source/_javascript_Core/ChangeLog	2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-05-02 17:38:15 UTC (rev 200325)
@@ -1,3 +1,35 @@
+2016-05-02  Keith Miller  <[email protected]>
+
+        ToThis should be able to be eliminated in Constant Folding
+        https://bugs.webkit.org/show_bug.cgi?id=157213
+
+        Reviewed by Saam Barati.
+
+        This patch enables eliminating the ToThis value when we have abstract interpreter
+        indicates the node is not needed. Since there are Objects that override their
+        ToThis behavior we first check if we can eliminate the node by looking at its
+        speculated type. If the function is in strict mode then we can eliminate ToThis as
+        long as the speculated type is not SpecObjectOther since that contains objects
+        that may set OverridesToThis. If the function is not in strict mode then we can
+        eliminate ToThis as long is the speculated type is an object that is not SpecObjectOther.
+
+        If we can't eliminate with type information we can still eliminate the ToThis node with
+        the proven structure set. When ToThis only sees structures that do not set OverridesToThis
+        it can be eliminated. Additionally, if the function is in strict mode then we can eliminate
+        ToThis as long as all only the object structures don't set OverridesToThis.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::isToThisAnIdentity):
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupToThis):
+        * tests/stress/to-this-global-object.js: Added.
+        (test):
+        (test2):
+        (get for):
+
 2016-05-01  Skachkov Oleksandr  <[email protected]>
 
         Class contructor and methods shouldn't have "arguments" and "caller"

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (200324 => 200325)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-05-02 17:38:15 UTC (rev 200325)
@@ -142,6 +142,36 @@
     DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
 }
 
+inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue& valueForNode)
+{
+    // We look at the type first since that will cover most cases and does not require iterating all the structures.
+    if (isStrictMode) {
+        if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
+            return true;
+    } else {
+        if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
+            return true;
+    }
+
+    if ((isStrictMode || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
+        bool overridesToThis = false;
+        valueForNode.m_structure.forEach([&](Structure* structure) {
+            TypeInfo type = structure->typeInfo();
+            ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
+            if (!isStrictMode)
+                ASSERT(type.isObject());
+            // We don't need to worry about strings/symbols here since either:
+            // 1) We are in strict mode and strings/symbols are not wrapped
+            // 2) The AI has proven that the type of this is a subtype of object
+            if (type.isObject() && type.overridesToThis())
+                overridesToThis = true;
+        });
+        return overridesToThis;
+    }
+
+    return false;
+}
+
 template<typename AbstractStateType>
 bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
 {
@@ -1847,21 +1877,17 @@
     case ToThis: {
         AbstractValue& source = forNode(node->child1());
         AbstractValue& destination = forNode(node);
+        bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();
 
-        if (source.m_type == SpecStringObject) {
+        if (isToThisAnIdentity(strictMode, source)) {
             m_state.setFoundConstants(true);
             destination = source;
             break;
         }
 
-        if (m_graph.executableFor(node->origin.semantic)->isStrictMode()) {
-            if (!(source.m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
-                m_state.setFoundConstants(true);
-                destination = source;
-                break;
-            }
+        if (strictMode)
             destination.makeHeapTop();
-        } else {
+        else {
             destination = source;
             destination.merge(SpecObject);
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (200324 => 200325)


--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2016-05-02 17:38:15 UTC (rev 200325)
@@ -557,6 +557,15 @@
                 break;
             }
 
+            case ToThis: {
+                if (!isToThisAnIdentity(m_graph.executableFor(node->origin.semantic)->isStrictMode(), m_state.forNode(node->child1())))
+                    break;
+
+                node->convertToIdentity();
+                changed = true;
+                break;
+            }
+
             case Check: {
                 alreadyHandled = true;
                 m_interpreter.execute(indexInBlock);

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (200324 => 200325)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-05-02 17:38:15 UTC (rev 200325)
@@ -1728,6 +1728,9 @@
             return;
         }
 
+        // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
+        // however, since we cover all the missing cases in constant folding.
+        // https://bugs.webkit.org/show_bug.cgi?id=157213
         if (node->child1()->shouldSpeculateStringObject()) {
             fixEdge<StringObjectUse>(node->child1());
             node->convertToIdentity();

Added: trunk/Source/_javascript_Core/tests/stress/to-this-global-object.js (0 => 200325)


--- trunk/Source/_javascript_Core/tests/stress/to-this-global-object.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/to-this-global-object.js	2016-05-02 17:38:15 UTC (rev 200325)
@@ -0,0 +1,25 @@
+function test() {
+    return this.f;
+}
+noInline(test);
+
+function test2() {
+    "use strict";
+    return this.f;
+}
+noInline(test2);
+
+f = 42;
+
+let get = eval;
+let global = get("this");
+
+for (var i = 0; i < 10000; ++i) {
+    let result = test.call(global);
+    if (result !== 42)
+        throw new Error("bad this value: " + result);
+
+    result = test2.call(global);
+    if (result !== 42)
+        throw new Error("bad this value: " + result);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to