Ignore:
Timestamp:
May 22, 2015, 10:24:05 AM (10 years ago)
Author:
[email protected]
Message:

Allow DFGClobberize to return non-node constants that must be later created
https://bugs.webkit.org/show_bug.cgi?id=145272

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This adds a new LazyNode class in DFG that represents either a Node*,
or a FrozenValue* with a way to convert it to a Node* provided a block
to insert it into. DFGClobberize is converted to use LazyNode instead
of Node* when def()'ing values, which allows to now define the array's
length as well as the value of its various fields in NewArray and
NewArrayBuffer nodes.

We also introduce a Vector<uint32_t> in DFG::Graph to collect all the
values that can be used as index, in order to avoid def()'ing too many
values at once for big NewArrayBuffers.

HeapLocation had to be updated to use a LazyNode as its index to be
able to define array values.

(JSC::DFG::clobberize):
(JSC::DFG::DefMethodClobberize::operator()):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::freezeFragile):

  • dfg/DFGGraph.h:
  • dfg/DFGHeapLocation.h:

(JSC::DFG::HeapLocation::HeapLocation):
(JSC::DFG::HeapLocation::index):
(JSC::DFG::HeapLocation::hash):

  • dfg/DFGLazyNode.cpp: Added.

(JSC::DFG::LazyNode::dump):

  • dfg/DFGLazyNode.h: Added.

(JSC::DFG::LazyNode::LazyNode):
(JSC::DFG::LazyNode::setNode):
(JSC::DFG::LazyNode::isHashTableDeletedValue):
(JSC::DFG::LazyNode::isNode):
(JSC::DFG::LazyNode::op):
(JSC::DFG::LazyNode::asNode):
(JSC::DFG::LazyNode::asValue):
(JSC::DFG::LazyNode::hash):
(JSC::DFG::LazyNode::operator==):
(JSC::DFG::LazyNode::operator!=):
(JSC::DFG::LazyNode::ensureIsNode):
(JSC::DFG::LazyNode::operator->):
(JSC::DFG::LazyNode::operator*):
(JSC::DFG::LazyNode::operator!):
(JSC::DFG::LazyNode::operator UnspecifiedBoolType*):
(JSC::DFG::LazyNode::setFrozenValue):

  • dfg/DFGPreciseLocalClobberize.h:

(JSC::DFG::PreciseLocalClobberizeAdaptor::def):

  • dfg/DFGPutStackSinkingPhase.cpp:

LayoutTests:

  • js/regress/script-tests/cse-new-array-buffer.js: Added.

(foo):

  • js/regress/script-tests/cse-new-array.js: Added.

(foo):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp

    r183497 r184776  
    149149        }
    150150       
    151         Node* findReplacement(HeapLocation location)
     151        LazyNode findReplacement(HeapLocation location)
    152152        {
    153153            for (unsigned i = m_impureLength; i--;) {
     
    158158        }
    159159   
    160         Node* addImpure(HeapLocation location, Node* node)
    161         {
    162             if (Node* result = findReplacement(location))
     160        LazyNode addImpure(HeapLocation location, LazyNode node)
     161        {
     162            // FIXME: If we are using small maps, we must not def() derived values.
     163            // For now the only derived values we def() are constant-based.
     164            if (location.index() && !location.index().isNode())
     165                return nullptr;
     166            if (LazyNode result = findReplacement(location))
    163167                return result;
    164168            ASSERT(m_impureLength < capacity);
    165             m_impureMap[m_impureLength++] = WTF::KeyValuePair<HeapLocation, Node*>(location, node);
     169            m_impureMap[m_impureLength++] = WTF::KeyValuePair<HeapLocation, LazyNode>(location, node);
    166170            return nullptr;
    167171        }
     
    169173    private:
    170174        WTF::KeyValuePair<PureValue, Node*> m_pureMap[capacity];
    171         WTF::KeyValuePair<HeapLocation, Node*> m_impureMap[capacity];
     175        WTF::KeyValuePair<HeapLocation, LazyNode> m_impureMap[capacity];
    172176        unsigned m_pureLength;
    173177        unsigned m_impureLength;
     
    199203        }
    200204       
    201         Node* findReplacement(HeapLocation location)
     205        LazyNode findReplacement(HeapLocation location)
    202206        {
    203207            return m_impureMap.get(location);
    204208        }
    205209   
    206         Node* addImpure(HeapLocation location, Node* node)
     210        LazyNode addImpure(HeapLocation location, LazyNode node)
    207211        {
    208212            auto result = m_impureMap.add(location, node);
     
    214218    private:
    215219        HashMap<PureValue, Node*> m_pureMap;
    216         HashMap<HeapLocation, Node*> m_impureMap;
     220        HashMap<HeapLocation, LazyNode> m_impureMap;
    217221    };
    218222
     
    222226        BlockCSE(Graph& graph)
    223227            : m_graph(graph)
     228            , m_insertionSet(graph)
    224229        {
    225230        }
     
    229234            m_maps.clear();
    230235            m_changed = false;
     236            m_block = block;
    231237       
    232238            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
     
    298304                }
    299305            }
     306
     307            m_insertionSet.execute(block);
    300308       
    301309            return m_changed;
     
    319327        }
    320328   
    321         void def(HeapLocation location, Node* value)
    322         {
    323             Node* match = m_maps.addImpure(location, value);
     329        void def(HeapLocation location, LazyNode value)
     330        {
     331            LazyNode match = m_maps.addImpure(location, value);
    324332            if (!match)
    325333                return;
     
    344352            }
    345353       
    346             m_node->replaceWith(match);
    347             m_changed = true;
     354            if (value.isNode() && value.asNode() == m_node) {
     355                match.ensureIsNode(m_insertionSet, m_block, 0)->owner = m_block;
     356                ASSERT(match.isNode());
     357                m_node->replaceWith(match.asNode());
     358                m_changed = true;
     359            }
    348360        }
    349361   
     
    353365        bool m_changed;
    354366        Node* m_node;
     367        BasicBlock* m_block;
    355368   
    356369        Maps m_maps;
     370
     371        InsertionSet m_insertionSet;
    357372    };
    358373
     
    366381        : Phase(graph, "global common subexpression elimination")
    367382        , m_impureDataMap(graph)
     383        , m_insertionSet(graph)
    368384    {
    369385    }
     
    430446
    431447            for (unsigned nodeIndex = 0; nodeIndex < m_block->size(); ++nodeIndex) {
     448                m_nodeIndex = nodeIndex;
    432449                m_node = m_block->at(nodeIndex);
    433450                if (verbose)
     
    442459                    clobberize(m_graph, m_node, *this);
    443460            }
     461
     462            m_insertionSet.execute(m_block);
    444463           
    445464            m_impureData->didVisit = true;
     
    487506    }
    488507   
    489     Node* findReplacement(HeapLocation location)
     508    LazyNode findReplacement(HeapLocation location)
    490509    {
    491510        // At this instant, our "availableAtTail" reflects the set of things that are available in
    492511        // this block so far. We check this map to find block-local CSE opportunities before doing
    493512        // a global search.
    494         Node* match = m_impureData->availableAtTail.get(location);
    495         if (match) {
     513        LazyNode match = m_impureData->availableAtTail.get(location);
     514        if (!!match) {
    496515            if (verbose)
    497516                dataLog("      Found local match: ", match, "\n");
     
    576595                if (verbose)
    577596                    dataLog("        Availability: ", match, "\n");
    578                 if (match) {
     597                if (!!match) {
    579598                    // Don't examine the predecessors of a match. At this point we just want to
    580599                    // establish that other blocks on the path from here to there don't clobber
     
    617636    }
    618637   
    619     void def(HeapLocation location, Node* value)
     638    void def(HeapLocation location, LazyNode value)
    620639    {
    621640        if (verbose)
    622641            dataLog("    Got heap location def: ", location, " -> ", value, "\n");
    623642       
    624         Node* match = findReplacement(location);
     643        LazyNode match = findReplacement(location);
    625644       
    626645        if (verbose)
     
    634653            return;
    635654        }
    636        
    637         m_node->replaceWith(match);
    638         m_changed = true;
     655
     656        if (value.isNode() && value.asNode() == m_node) {
     657            if (!match.isNode()) {
     658                // We need to properly record the constant in order to use an existing one if applicable.
     659                // This ensures that re-running GCSE will not find new optimizations.
     660                match.ensureIsNode(m_insertionSet, m_block, m_nodeIndex)->owner = m_block;
     661                auto result = m_pureValues.add(PureValue(match.asNode(), match->constant()), Vector<Node*>());
     662                bool replaced = false;
     663                if (!result.isNewEntry) {
     664                    for (unsigned i = result.iterator->value.size(); i--;) {
     665                        Node* candidate = result.iterator->value[i];
     666                        if (m_graph.m_dominators.dominates(candidate->owner, m_block)) {
     667                            ASSERT(candidate);
     668                            match->replaceWith(candidate);
     669                            match.setNode(candidate);
     670                            replaced = true;
     671                            break;
     672                        }
     673                    }
     674                }
     675                if (!replaced)
     676                    result.iterator->value.append(match.asNode());
     677            }
     678            ASSERT(match.asNode());
     679            m_node->replaceWith(match.asNode());
     680            m_changed = true;
     681        }
    639682    }
    640683   
     
    657700    BasicBlock* m_block;
    658701    Node* m_node;
     702    unsigned m_nodeIndex;
    659703    ImpureBlockData* m_impureData;
    660704    ClobberSet m_writesSoFar;
     705    InsertionSet m_insertionSet;
    661706   
    662707    bool m_changed;
Note: See TracChangeset for help on using the changeset viewer.