Title: [174856] trunk/Source/_javascript_Core
Revision
174856
Author
[email protected]
Date
2014-10-17 18:12:46 -0700 (Fri, 17 Oct 2014)

Log Message

Web Process crash when starting the web inspector after r174025.
<https://webkit.org/b/137340>

Reviewed by Filip Pizlo.

After r174025, we can generate a bad graph in the DFG fixup phase like so:

    102:<!0:-> StoreBarrier(Check:KnownCell:@19, ..., bc#44)
    60:<!0:->  PutStructure(Check:KnownCell:@19, ..., bc#44)
    103:<!0:-> Check(Check:NotCell:@54, ..., bc#44)
            // ^-- PutByOffset's StoreBarrier has been elided and replaced
            //     with a speculation check which can OSR exit.
    61:<!0:->  PutByOffset(Check:KnownCell:@19, ..., bc#44)

As a result, the structure change will get executed even if we end up OSR
exiting before the PutByOffset.  In the baseline JIT code, the structure now
erroneously tells the put operation that there is a value in that property
slot when it is actually uninitialized (hence, the crash).

The fix is to insert the Check at the earliest point possible:

1. If the checked node is in the same bytecode as the PutByOffset, then
   the earliest point where we can insert the Check is right after the
   checked node.

2. If the checked node is from a preceding bytecode (before the PutByOffset),
   then the earliest point where we can insert the Check is at the start
   of the current bytecode.

Also reverted the workaround from r174749: https://webkit.org/b/137758.

Benchmark results appear to be a wash on aggregate.

* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::indexOfNode):
(JSC::DFG::FixupPhase::indexOfFirstNodeOfExitOrigin):
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::insertCheck):
* dfg/DFGInsertionSet.h:
(JSC::DFG::InsertionSet::insertOutOfOrder):
(JSC::DFG::InsertionSet::insertOutOfOrderNode):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (174855 => 174856)


--- trunk/Source/_javascript_Core/ChangeLog	2014-10-18 00:25:08 UTC (rev 174855)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-10-18 01:12:46 UTC (rev 174856)
@@ -1,3 +1,47 @@
+2014-10-17  Mark Lam  <[email protected]>
+
+        Web Process crash when starting the web inspector after r174025.
+        <https://webkit.org/b/137340>
+
+        Reviewed by Filip Pizlo.
+
+        After r174025, we can generate a bad graph in the DFG fixup phase like so:
+
+            102:<!0:-> StoreBarrier(Check:KnownCell:@19, ..., bc#44)
+            60:<!0:->  PutStructure(Check:KnownCell:@19, ..., bc#44)
+            103:<!0:-> Check(Check:NotCell:@54, ..., bc#44)
+                    // ^-- PutByOffset's StoreBarrier has been elided and replaced
+                    //     with a speculation check which can OSR exit.
+            61:<!0:->  PutByOffset(Check:KnownCell:@19, ..., bc#44)
+
+        As a result, the structure change will get executed even if we end up OSR
+        exiting before the PutByOffset.  In the baseline JIT code, the structure now
+        erroneously tells the put operation that there is a value in that property
+        slot when it is actually uninitialized (hence, the crash).
+
+        The fix is to insert the Check at the earliest point possible:
+
+        1. If the checked node is in the same bytecode as the PutByOffset, then
+           the earliest point where we can insert the Check is right after the
+           checked node.
+
+        2. If the checked node is from a preceding bytecode (before the PutByOffset),
+           then the earliest point where we can insert the Check is at the start
+           of the current bytecode.
+
+        Also reverted the workaround from r174749: https://webkit.org/b/137758.
+
+        Benchmark results appear to be a wash on aggregate.
+
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::indexOfNode):
+        (JSC::DFG::FixupPhase::indexOfFirstNodeOfExitOrigin):
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::insertCheck):
+        * dfg/DFGInsertionSet.h:
+        (JSC::DFG::InsertionSet::insertOutOfOrder):
+        (JSC::DFG::InsertionSet::insertOutOfOrderNode):
+
 2014-10-10  Oliver Hunt  <[email protected]>
 
         Various arguments optimisations in codegen fail to account for arguments being in lexical record

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (174855 => 174856)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2014-10-18 00:25:08 UTC (rev 174855)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2014-10-18 01:12:46 UTC (rev 174856)
@@ -87,6 +87,33 @@
         m_insertionSet.execute(block);
     }
     
+    inline unsigned indexOfNode(Node* node, unsigned indexToSearchFrom)
+    {
+        unsigned index = indexToSearchFrom;
+        while (index) {
+            if (m_block->at(index) == node)
+                break;
+            index--;
+        }
+        ASSERT(m_block->at(index) == node);
+        return index;
+    }
+
+    inline unsigned indexOfFirstNodeOfExitOrigin(CodeOrigin& originForExit, unsigned indexToSearchFrom)
+    {
+        unsigned index = indexToSearchFrom;
+        ASSERT(m_block->at(index)->origin.forExit == originForExit);
+        while (index) {
+            index--;
+            if (m_block->at(index)->origin.forExit != originForExit) {
+                index++;
+                break;
+            }
+        }
+        ASSERT(m_block->at(index)->origin.forExit == originForExit);
+        return index;
+    }
+    
     void fixupNode(Node* node)
     {
         NodeType op = node->op();
@@ -943,7 +970,7 @@
             if (!node->child1()->hasStorageResult())
                 fixEdge<KnownCellUse>(node->child1());
             fixEdge<KnownCellUse>(node->child2());
-            insertStoreBarrier(m_indexInBlock, node->child2());
+            insertStoreBarrier(m_indexInBlock, node->child2(), node->child3());
             break;
         }
             
@@ -1710,7 +1737,20 @@
     void insertCheck(unsigned indexInBlock, Node* node)
     {
         observeUseKindOnNode<useKind>(node);
-        m_insertionSet.insertNode(
+        CodeOrigin& checkedNodeOrigin = node->origin.forExit;
+        CodeOrigin& currentNodeOrigin = m_currentNode->origin.forExit;
+        if (currentNodeOrigin == checkedNodeOrigin) {
+            // The checked node is within the same bytecode. Hence, the earliest
+            // position we can insert the check is right after the checked node.
+            indexInBlock = indexOfNode(node, indexInBlock);
+            indexInBlock++;
+        } else {
+            // The checked node is from a preceding bytecode. Hence, the earliest
+            // position we can insert the check is at the start of the current
+            // bytecode.
+            indexInBlock = indexOfFirstNodeOfExitOrigin(currentNodeOrigin, indexInBlock);
+        }
+        m_insertionSet.insertOutOfOrderNode(
             indexInBlock, SpecNone, Check, m_currentNode->origin, Edge(node, useKind));
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGInsertionSet.h (174855 => 174856)


--- trunk/Source/_javascript_Core/dfg/DFGInsertionSet.h	2014-10-18 00:25:08 UTC (rev 174855)
+++ trunk/Source/_javascript_Core/dfg/DFGInsertionSet.h	2014-10-18 01:12:46 UTC (rev 174856)
@@ -116,6 +116,34 @@
         return insertConstantForUse(index, NodeOrigin(origin), value, useKind);
     }
 
+    Node* insertOutOfOrder(const Insertion& insertion)
+    {
+        size_t targetIndex = insertion.index();
+        size_t entry = m_insertions.size();
+        if (entry) {
+            do {
+                entry--;
+                if (m_insertions[entry].index() <= targetIndex) {
+                    entry++;
+                    break;
+                }
+            } while (entry);
+        }
+        m_insertions.insert(entry, insertion);
+        return insertion.element();
+    }
+    
+    Node* insertOutOfOrder(size_t index, Node* element)
+    {
+        return insertOutOfOrder(Insertion(index, element));
+    }
+
+    template<typename... Params>
+    Node* insertOutOfOrderNode(size_t index, SpeculatedType type, Params... params)
+    {
+        return insertOutOfOrder(index, m_graph.addNode(type, params...));
+    }
+
     void execute(BasicBlock* block)
     {
         executeInsertions(*block, m_insertions);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to