/* * @(#)SSABlockTree.java */ package org.jf.dexlib.Code.Analysis.ssa; import java.util.LinkedList; import java.util.List; import org.jgrapht.graph.DefaultDirectedGraph; /** * A CDG Tree which contains blocks instead of nodes. * @param <V> type of nodes in the blocks * @author Patrick Kuhn */ public class SSABlockTree<V> extends DefaultDirectedGraph<SSABlockNode<V>, SSAEdge> { private static final long serialVersionUID = 1L; /**CDG on which this tree is based on. */ protected final SSAGraph<V> cdg; /** List to check whether certain nodes were visited already. */ private final List<V> visited; /** * Create a CDG Block Tree. As start node the first node in the vertex set is taken. * @param cdg the CDG */ public SSABlockTree(SSAGraph<V> cdg) { this(cdg, cdg.vertexSet().iterator().next()); } /** * Create a CDG Block Tree. * @param cdg the CDG * @param start the start node */ public SSABlockTree(SSAGraph<V> cdg, V start) { super(SSAEdge.class); this.cdg = cdg; this.visited = new LinkedList<V>(); createTree(null, start); } /** * Create a block tree out of an ordinary cdg. One run of this method creates * a block. In recursive calls it creates further blocks and connects them. * @param before block which came before this one, may be <tt>null</tt> * @param start first node of the block */ private void createTree(SSABlockNode<V> before, V start) { assert start != null; SSABlockNode<V> node = SSABlockNode.getInstance(start); if (!visited.contains(start)) { visited.add(start); this.addVertex(node); if (before != null) { this.addEdge(before, node); } V v = start; while (cdg.outDegreeOf(v) == 1) { v = cdg.getEdgeTarget(cdg.outgoingEdgesOf(v).iterator().next()); if (cdg.inDegreeOf(v) > 1) { break; } node.add(v); } for (SSAEdge e : cdg.outgoingEdgesOf(node.getLast())) { V target = cdg.getEdgeTarget(e); createTree(node, target); } } else { if (before != null && !this.containsEdge(before, node)) { this.addEdge(before, node); } } } /** * Get the block which contains a certain node. * @param v the node to seek * @return the block which contains the node or <tt>null</tt> if unsuccessful. */ public SSABlockNode<V> getBlockContainingNode(V v) { SSABlockNode<V> result = null; for (SSABlockNode<V> block : this.vertexSet()) { if (block.contains(v)) { result = block; break; } } return result; } @Override public String toString() { return "CDG Block Tree"; } }