]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGDominators.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGDominators.h
index 8eee3e899e1634a63788b8d5f6207dcab51f8a8e..e218ba792f261c1ad3f3055c7b0486eb1a9caa60 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef DFGDominators_h
 #define DFGDominators_h
 
-#include <wtf/Platform.h>
-
 #if ENABLE(DFG_JIT)
 
+#include "DFGAnalysis.h"
+#include "DFGBasicBlock.h"
+#include "DFGBlockMap.h"
+#include "DFGBlockSet.h"
 #include "DFGCommon.h"
-#include <wtf/FastBitVector.h>
 
 namespace JSC { namespace DFG {
 
 class Graph;
 
-class Dominators {
+class Dominators : public Analysis<Dominators> {
 public:
     Dominators();
     ~Dominators();
     
-    void compute(Graph& graph);
-    void invalidate()
+    void compute(Graph&);
+    
+    bool strictlyDominates(BasicBlock* from, BasicBlock* to) const
     {
-        m_valid = false;
+        ASSERT(isValid());
+        return m_data[to].preNumber > m_data[from].preNumber
+            && m_data[to].postNumber < m_data[from].postNumber;
     }
-    void computeIfNecessary(Graph& graph)
+    
+    bool dominates(BasicBlock* from, BasicBlock* to) const
     {
-        if (m_valid)
-            return;
-        compute(graph);
+        return from == to || strictlyDominates(from, to);
     }
     
-    bool isValid() const { return m_valid; }
+    BasicBlock* immediateDominatorOf(BasicBlock* block) const
+    {
+        return m_data[block].idomParent;
+    }
     
-    bool dominates(BlockIndex from, BlockIndex to) const
+    template<typename Functor>
+    void forAllStrictDominatorsOf(BasicBlock* to, const Functor& functor) const
     {
-        ASSERT(isValid());
-        return m_results[to].get(from);
+        for (BasicBlock* block = m_data[to].idomParent; block; block = m_data[block].idomParent)
+            functor(block);
+    }
+    
+    template<typename Functor>
+    void forAllDominatorsOf(BasicBlock* to, const Functor& functor) const
+    {
+        for (BasicBlock* block = to; block; block = m_data[block].idomParent)
+            functor(block);
+    }
+    
+    template<typename Functor>
+    void forAllBlocksStrictlyDominatedBy(BasicBlock* from, const Functor& functor) const
+    {
+        Vector<BasicBlock*, 16> worklist;
+        worklist.appendVector(m_data[from].idomKids);
+        while (!worklist.isEmpty()) {
+            BasicBlock* block = worklist.takeLast();
+            functor(block);
+            worklist.appendVector(m_data[block].idomKids);
+        }
+    }
+    
+    template<typename Functor>
+    void forAllBlocksDominatedBy(BasicBlock* from, const Functor& functor) const
+    {
+        Vector<BasicBlock*, 16> worklist;
+        worklist.append(from);
+        while (!worklist.isEmpty()) {
+            BasicBlock* block = worklist.takeLast();
+            functor(block);
+            worklist.appendVector(m_data[block].idomKids);
+        }
+    }
+    
+    BlockSet strictDominatorsOf(BasicBlock* to) const;
+    BlockSet dominatorsOf(BasicBlock* to) const;
+    BlockSet blocksStrictlyDominatedBy(BasicBlock* from) const;
+    BlockSet blocksDominatedBy(BasicBlock* from) const;
+    
+    template<typename Functor>
+    void forAllBlocksInDominanceFrontierOf(
+        BasicBlock* from, const Functor& functor) const
+    {
+        BlockSet set;
+        forAllBlocksInDominanceFrontierOfImpl(
+            from,
+            [&] (BasicBlock* block) {
+                if (set.add(block))
+                    functor(block);
+            });
+    }
+    
+    BlockSet dominanceFrontierOf(BasicBlock* from) const;
+    
+    template<typename Functor>
+    void forAllBlocksInIteratedDominanceFrontierOf(
+        const BlockList& from, const Functor& functor)
+    {
+        forAllBlocksInPrunedIteratedDominanceFrontierOf(
+            from,
+            [&] (BasicBlock* block) -> bool {
+                functor(block);
+                return true;
+            });
+    }
+    
+    // This is a close relative of forAllBlocksInIteratedDominanceFrontierOf(), which allows the
+    // given functor to return false to indicate that we don't wish to consider the given block.
+    // Useful for computing pruned SSA form.
+    template<typename Functor>
+    void forAllBlocksInPrunedIteratedDominanceFrontierOf(
+        const BlockList& from, const Functor& functor)
+    {
+        BlockSet set;
+        forAllBlocksInIteratedDominanceFrontierOfImpl(
+            from,
+            [&] (BasicBlock* block) -> bool {
+                if (!set.add(block))
+                    return false;
+                return functor(block);
+            });
     }
     
+    BlockSet iteratedDominanceFrontierOf(const BlockList& from) const;
+    
+    void dump(PrintStream&) const;
+    
 private:
-    bool iterateForBlock(Graph& graph, BlockIndex);
+    bool naiveDominates(BasicBlock* from, BasicBlock* to) const;
+    
+    template<typename Functor>
+    void forAllBlocksInDominanceFrontierOfImpl(
+        BasicBlock* from, const Functor& functor) const
+    {
+        // Paraphrasing from http://en.wikipedia.org/wiki/Dominator_(graph_theory):
+        //     "The dominance frontier of a block 'from' is the set of all blocks 'to' such that
+        //     'from' dominates an immediate predecessor of 'to', but 'from' does not strictly
+        //     dominate 'to'."
+        //
+        // A useful corner case to remember: a block may be in its own dominance frontier if it has
+        // a loop edge to itself, since it dominates itself and so it dominates its own immediate
+        // predecessor, and a block never strictly dominates itself.
+        
+        forAllBlocksDominatedBy(
+            from,
+            [&] (BasicBlock* block) {
+                for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
+                    BasicBlock* to = block->successor(successorIndex);
+                    if (!strictlyDominates(from, to))
+                        functor(to);
+                }
+            });
+    }
+    
+    template<typename Functor>
+    void forAllBlocksInIteratedDominanceFrontierOfImpl(
+        const BlockList& from, const Functor& functor) const
+    {
+        BlockList worklist = from;
+        while (!worklist.isEmpty()) {
+            BasicBlock* block = worklist.takeLast();
+            forAllBlocksInDominanceFrontierOfImpl(
+                block,
+                [&] (BasicBlock* otherBlock) {
+                    if (functor(otherBlock))
+                        worklist.append(otherBlock);
+                });
+        }
+    }
+    
+    struct BlockData {
+        BlockData()
+            : idomParent(nullptr)
+            , preNumber(UINT_MAX)
+            , postNumber(UINT_MAX)
+        {
+        }
+        
+        Vector<BasicBlock*> idomKids;
+        BasicBlock* idomParent;
+        
+        unsigned preNumber;
+        unsigned postNumber;
+    };
     
-    Vector<FastBitVector> m_results;
-    FastBitVector m_scratch;
-    bool m_valid;
+    BlockMap<BlockData> m_data;
 };
 
 } } // namespace JSC::DFG