Title: [183752] trunk/Source/_javascript_Core
Revision
183752
Author
[email protected]
Date
2015-05-04 11:37:58 -0700 (Mon, 04 May 2015)

Log Message

Object allocation not sinking properly through CheckStructure
https://bugs.webkit.org/show_bug.cgi?id=144465

Reviewed by Filip Pizlo.

Currently, sinking an allocation through a CheckStructure will
completely ignore all structure checking, which is obviously wrong.

A CheckStructureImmediate node type was present for that purpose, but
the CheckStructures were not properly replaced.  This ensures that
CheckStructure nodes are replaced by CheckStructureImmediate nodes when
sunk through, and that structure checking happens correctly.

* dfg/DFGNode.h:
(JSC::DFG::Node::convertToCheckStructureImmediate): Added.
(JSC::DFG::Node::hasStructureSet):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::promoteSunkenFields):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileCheckStructure):
(JSC::FTL::LowerDFGToLLVM::compileCheckStructureImmediate):
(JSC::FTL::LowerDFGToLLVM::checkStructure):
* tests/stress/sink_checkstructure.js: Added.
(foo):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (183751 => 183752)


--- trunk/Source/_javascript_Core/ChangeLog	2015-05-04 18:26:00 UTC (rev 183751)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-05-04 18:37:58 UTC (rev 183752)
@@ -1,3 +1,30 @@
+2015-05-04  Basile Clement  <[email protected]>
+
+        Object allocation not sinking properly through CheckStructure
+        https://bugs.webkit.org/show_bug.cgi?id=144465
+
+        Reviewed by Filip Pizlo.
+
+        Currently, sinking an allocation through a CheckStructure will
+        completely ignore all structure checking, which is obviously wrong.
+
+        A CheckStructureImmediate node type was present for that purpose, but
+        the CheckStructures were not properly replaced.  This ensures that
+        CheckStructure nodes are replaced by CheckStructureImmediate nodes when
+        sunk through, and that structure checking happens correctly.
+
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToCheckStructureImmediate): Added.
+        (JSC::DFG::Node::hasStructureSet):
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        (JSC::DFG::ObjectAllocationSinkingPhase::promoteSunkenFields):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileCheckStructure):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckStructureImmediate):
+        (JSC::FTL::LowerDFGToLLVM::checkStructure):
+        * tests/stress/sink_checkstructure.js: Added.
+        (foo):
+
 2015-05-01  Geoffrey Garen  <[email protected]>
 
         REGRESSION(r183570): jslib-traverse-jquery is 22% slower

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (183751 => 183752)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2015-05-04 18:26:00 UTC (rev 183751)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2015-05-04 18:37:58 UTC (rev 183752)
@@ -414,6 +414,13 @@
         setOpAndDefaultFlags(CheckStructure);
         m_opInfo = bitwise_cast<uintptr_t>(set); 
     }
+
+    void convertToCheckStructureImmediate(Node* structure)
+    {
+        ASSERT(op() == CheckStructure);
+        m_op = CheckStructureImmediate;
+        children.setChild1(Edge(structure, CellUse));
+    }
     
     void replaceWith(Node* other)
     {
@@ -1334,6 +1341,7 @@
     {
         switch (op()) {
         case CheckStructure:
+        case CheckStructureImmediate:
             return true;
         default:
             return false;

Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (183751 => 183752)


--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2015-05-04 18:26:00 UTC (rev 183751)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2015-05-04 18:37:58 UTC (rev 183752)
@@ -728,8 +728,17 @@
                             m_localMapping.set(location, value.node());
                     },
                     [&] (PromotedHeapLocation location) {
-                        if (m_sinkCandidates.contains(location.base()))
-                            node->replaceWith(resolve(block, location));
+                        if (m_sinkCandidates.contains(location.base())) {
+                            switch (node->op()) {
+                            case CheckStructure:
+                                node->convertToCheckStructureImmediate(resolve(block, location));
+                                break;
+
+                            default:
+                                node->replaceWith(resolve(block, location));
+                                break;
+                            }
+                        }
                     });
             }
             

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (183751 => 183752)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-05-04 18:26:00 UTC (rev 183751)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2015-05-04 18:37:58 UTC (rev 183752)
@@ -1882,7 +1882,11 @@
         
         LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
         
-        checkStructure(structureID, jsValueValue(cell), exitKind, m_node->structureSet());
+        checkStructure(
+            structureID, jsValueValue(cell), exitKind, m_node->structureSet(),
+            [this] (Structure* structure) {
+                return weakStructureID(structure);
+            });
     }
     
     void compileCheckCell()
@@ -5089,8 +5093,12 @@
     
     void compileCheckStructureImmediate()
     {
-        LValue structureID = lowCell(m_node->child1());
-        checkStructure(structureID, noValue(), BadCache, m_node->structureSet());
+        LValue structure = lowCell(m_node->child1());
+        checkStructure(
+            structure, noValue(), BadCache, m_node->structureSet(),
+            [this] (Structure* structure) {
+                return weakStructure(structure);
+            });
     }
     
     void compileMaterializeNewObject()
@@ -5430,14 +5438,15 @@
         return getArgumentsStart(m_node->origin.semantic.inlineCallFrame);
     }
     
+    template<typename Functor>
     void checkStructure(
-        LValue structureID, const FormattedValue& formattedValue, ExitKind exitKind,
-        const StructureSet& set)
+        LValue structureDiscriminant, const FormattedValue& formattedValue, ExitKind exitKind,
+        const StructureSet& set, const Functor& weakStructureDiscriminant)
     {
         if (set.size() == 1) {
             speculate(
                 exitKind, formattedValue, 0,
-                m_out.notEqual(structureID, weakStructureID(set[0])));
+                m_out.notEqual(structureDiscriminant, weakStructureDiscriminant(set[0])));
             return;
         }
         
@@ -5447,14 +5456,14 @@
         for (unsigned i = 0; i < set.size() - 1; ++i) {
             LBasicBlock nextStructure = FTL_NEW_BLOCK(m_out, ("checkStructure nextStructure"));
             m_out.branch(
-                m_out.equal(structureID, weakStructureID(set[i])),
+                m_out.equal(structureDiscriminant, weakStructureDiscriminant(set[i])),
                 unsure(continuation), unsure(nextStructure));
             m_out.appendTo(nextStructure);
         }
         
         speculate(
             exitKind, formattedValue, 0,
-            m_out.notEqual(structureID, weakStructureID(set.last())));
+            m_out.notEqual(structureDiscriminant, weakStructureDiscriminant(set.last())));
         
         m_out.jump(continuation);
         m_out.appendTo(continuation, lastNext);

Added: trunk/Source/_javascript_Core/tests/stress/sink_checkstructure.js (0 => 183752)


--- trunk/Source/_javascript_Core/tests/stress/sink_checkstructure.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/sink_checkstructure.js	2015-05-04 18:37:58 UTC (rev 183752)
@@ -0,0 +1,17 @@
+function foo(p, q) {
+    var o = {};
+    if (p) o.f = 42;
+    if (q) { o.f++; return o; }
+}
+noInline(foo);
+
+var expected = foo(false, true).f;
+
+for (var i = 0; i < 1000000; i++) {
+    foo(true, true);
+}
+
+var result = foo(false, true).f;
+
+if (!Object.is(result, expected))
+    throw "Error: expected " + expected + "; FTL produced " + result;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to