Changeset 174856 in webkit


Ignore:
Timestamp:
Oct 17, 2014 6:12:46 PM (10 years ago)
Author:
mark.lam@apple.com
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.
  1. 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):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r174821 r174856  
     12014-10-17  Mark Lam  <mark.lam@apple.com>
     2
     3        Web Process crash when starting the web inspector after r174025.
     4        <https://webkit.org/b/137340>
     5
     6        Reviewed by Filip Pizlo.
     7
     8        After r174025, we can generate a bad graph in the DFG fixup phase like so:
     9
     10            102:<!0:-> StoreBarrier(Check:KnownCell:@19, ..., bc#44)
     11            60:<!0:->  PutStructure(Check:KnownCell:@19, ..., bc#44)
     12            103:<!0:-> Check(Check:NotCell:@54, ..., bc#44)
     13                    // ^-- PutByOffset's StoreBarrier has been elided and replaced
     14                    //     with a speculation check which can OSR exit.
     15            61:<!0:->  PutByOffset(Check:KnownCell:@19, ..., bc#44)
     16
     17        As a result, the structure change will get executed even if we end up OSR
     18        exiting before the PutByOffset.  In the baseline JIT code, the structure now
     19        erroneously tells the put operation that there is a value in that property
     20        slot when it is actually uninitialized (hence, the crash).
     21
     22        The fix is to insert the Check at the earliest point possible:
     23
     24        1. If the checked node is in the same bytecode as the PutByOffset, then
     25           the earliest point where we can insert the Check is right after the
     26           checked node.
     27
     28        2. If the checked node is from a preceding bytecode (before the PutByOffset),
     29           then the earliest point where we can insert the Check is at the start
     30           of the current bytecode.
     31
     32        Also reverted the workaround from r174749: https://webkit.org/b/137758.
     33
     34        Benchmark results appear to be a wash on aggregate.
     35
     36        * dfg/DFGFixupPhase.cpp:
     37        (JSC::DFG::FixupPhase::indexOfNode):
     38        (JSC::DFG::FixupPhase::indexOfFirstNodeOfExitOrigin):
     39        (JSC::DFG::FixupPhase::fixupNode):
     40        (JSC::DFG::FixupPhase::insertCheck):
     41        * dfg/DFGInsertionSet.h:
     42        (JSC::DFG::InsertionSet::insertOutOfOrder):
     43        (JSC::DFG::InsertionSet::insertOutOfOrderNode):
     44
    1452014-10-10  Oliver Hunt  <oliver@apple.com>
    246
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r174789 r174856  
    8686        clearPhantomsAtEnd();
    8787        m_insertionSet.execute(block);
     88    }
     89   
     90    inline unsigned indexOfNode(Node* node, unsigned indexToSearchFrom)
     91    {
     92        unsigned index = indexToSearchFrom;
     93        while (index) {
     94            if (m_block->at(index) == node)
     95                break;
     96            index--;
     97        }
     98        ASSERT(m_block->at(index) == node);
     99        return index;
     100    }
     101
     102    inline unsigned indexOfFirstNodeOfExitOrigin(CodeOrigin& originForExit, unsigned indexToSearchFrom)
     103    {
     104        unsigned index = indexToSearchFrom;
     105        ASSERT(m_block->at(index)->origin.forExit == originForExit);
     106        while (index) {
     107            index--;
     108            if (m_block->at(index)->origin.forExit != originForExit) {
     109                index++;
     110                break;
     111            }
     112        }
     113        ASSERT(m_block->at(index)->origin.forExit == originForExit);
     114        return index;
    88115    }
    89116   
     
    944971                fixEdge<KnownCellUse>(node->child1());
    945972            fixEdge<KnownCellUse>(node->child2());
    946             insertStoreBarrier(m_indexInBlock, node->child2());
     973            insertStoreBarrier(m_indexInBlock, node->child2(), node->child3());
    947974            break;
    948975        }
     
    17111738    {
    17121739        observeUseKindOnNode<useKind>(node);
    1713         m_insertionSet.insertNode(
     1740        CodeOrigin& checkedNodeOrigin = node->origin.forExit;
     1741        CodeOrigin& currentNodeOrigin = m_currentNode->origin.forExit;
     1742        if (currentNodeOrigin == checkedNodeOrigin) {
     1743            // The checked node is within the same bytecode. Hence, the earliest
     1744            // position we can insert the check is right after the checked node.
     1745            indexInBlock = indexOfNode(node, indexInBlock);
     1746            indexInBlock++;
     1747        } else {
     1748            // The checked node is from a preceding bytecode. Hence, the earliest
     1749            // position we can insert the check is at the start of the current
     1750            // bytecode.
     1751            indexInBlock = indexOfFirstNodeOfExitOrigin(currentNodeOrigin, indexInBlock);
     1752        }
     1753        m_insertionSet.insertOutOfOrderNode(
    17141754            indexInBlock, SpecNone, Check, m_currentNode->origin, Edge(node, useKind));
    17151755    }
  • trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.h

    r173993 r174856  
    117117    }
    118118
     119    Node* insertOutOfOrder(const Insertion& insertion)
     120    {
     121        size_t targetIndex = insertion.index();
     122        size_t entry = m_insertions.size();
     123        if (entry) {
     124            do {
     125                entry--;
     126                if (m_insertions[entry].index() <= targetIndex) {
     127                    entry++;
     128                    break;
     129                }
     130            } while (entry);
     131        }
     132        m_insertions.insert(entry, insertion);
     133        return insertion.element();
     134    }
     135   
     136    Node* insertOutOfOrder(size_t index, Node* element)
     137    {
     138        return insertOutOfOrder(Insertion(index, element));
     139    }
     140
     141    template<typename... Params>
     142    Node* insertOutOfOrderNode(size_t index, SpeculatedType type, Params... params)
     143    {
     144        return insertOutOfOrder(index, m_graph.addNode(type, params...));
     145    }
     146
    119147    void execute(BasicBlock* block)
    120148    {
Note: See TracChangeset for help on using the changeset viewer.