com.dragome.compiler.graph.DominatorTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dragome-bytecode-js-compiler Show documentation
Show all versions of dragome-bytecode-js-compiler Show documentation
Dragome SDK module: bytecode to javascript compiler
package com.dragome.compiler.graph;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import com.dragome.compiler.utils.Log;
public class DominatorTree
{
private ControlFlowGraph graph;
public DominatorTree(ControlFlowGraph theGraph)
{
graph= theGraph;
}
/**
* Sets the pre-order index of a node.
*/
private void visit(Node node, Collection visited)
{
// Establish preorder index.
node.setPreOrderIndex(visited.size());
visited.add(node);
for (Node succ : node.succs())
{
if (!visited.contains(succ))
{
visit(succ, visited);
}
}
}
/**
* Builds the dominator tree and store it in the respective nodes. It will
* remove all unreachable nodes on the way!
*/
public void build()
{
// Construct list of nodes in pre-order order.
ArrayList preOrder= new ArrayList();
visit(graph.getSource(), preOrder);
// Remove unreachable nodes.
for (Node node : new ArrayList(graph.getNodes()))
{
if (!preOrder.contains(node))
{
Log.getLogger().warn("Unreachable code detected and removed");
// Logger.getLogger().info("Removed " + node);
graph.removeInEdges(node);
graph.removeOutEdges(node);
graph.removeNode(node);
}
else if (node.getPreOrderIndex() == -1)
{
throw new RuntimeException("Pre-order not set for " + node);
}
}
int size= graph.size(); // The number of vertices in the cfg
Map snkPreds= new LinkedHashMap(); // The predacessor vertices from the sink
// Determine the predacessors of the cfg's sink node
int rootIndex= graph.getSource().getPreOrderIndex();
if (rootIndex < 0 || rootIndex >= size)
throw new RuntimeException("Root index out of range");
BitSet[] domMatrix= new BitSet[size];
for (int i= 0; i < size; i++)
{
BitSet domVector= new BitSet(size);
if (i == rootIndex)
{
domVector.set(rootIndex);
}
else
{
domVector.set(0, size);
}
domMatrix[i]= domVector;
}
boolean changed;
do
{
changed= false;
Iterator nodes= preOrder.iterator();
while (nodes.hasNext())
{
Node node= (Node) nodes.next();
int i= node.getPreOrderIndex();
if (i < 0 || i >= size)
throw new RuntimeException("Unreachable node " + node);
if (i == rootIndex)
{
continue;
}
BitSet oldSet= domMatrix[i];
BitSet domVector= new BitSet(size);
domVector.or(oldSet);
Collection preds= node.preds();
Iterator e= preds.iterator();
// predacessors.
while (e.hasNext())
{
Node pred= (Node) e.next();
int j= pred.getPreOrderIndex();
if (j == -1)
throw new RuntimeException("Unreachable node " + pred);
domVector.and(domMatrix[j]);
}
// Don't forget to account for the sink node if node is a
preds= (Collection) snkPreds.get(node);
if (preds != null)
{
e= preds.iterator();
while (e.hasNext())
{
Node pred= (Node) e.next();
int j= pred.getPreOrderIndex();
domVector.and(domMatrix[j]);
}
}
domVector.set(i);
if (!domVector.equals(oldSet))
{
changed= true;
domMatrix[i]= domVector;
}
}
}
while (changed);
for (Node node : graph.getNodes())
{
node.setDomParent(null);
node.getDomChildren().clear();
}
// A node's immediate dominator is its closest dominator. So, we
for (Node node : graph.getNodes())
{
int i= node.getPreOrderIndex();
if (i < 0 || i >= size)
throw new RuntimeException("Unreachable node " + node);
if (i == rootIndex)
{
continue;
}
BitSet domVector= domMatrix[i];
BitSet idom= new BitSet(size);
idom.or(domVector);
idom.clear(i);
for (int j= 0; j < size; j++)
{
if (i != j && domVector.get(j))
{
BitSet b= new BitSet(size);
b.or(domMatrix[j]);
b.flip(0, size);
b.set(j);
idom.and(b);
}
}
Node parent= null;
for (int j= 0; j < size; j++)
{
if (idom.get(j))
{
Node p= preOrder.get(j);
if (parent != null)
throw new RuntimeException(node + " has more than one immediate dominator: " + parent + " and " + p);
parent= p;
}
}
if (parent == null)
throw new RuntimeException(node + " has 0 immediate dominators");
node.setDomParent(parent);
}
}
}