All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.toolkits.graph.DominatorTree Maven / Gradle / Ivy

package soot.toolkits.graph;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 2003 Navindra Umanee 
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Constructs a dominator tree structure from the given DominatorsFinder. The nodes in DominatorTree are of type
 * DominatorNode.
 *
 * 

* * Note: DominatorTree does not currently implement DirectedGraph since it provides 4 methods of navigating the nodes where * the meaning of getPredsOf and getSuccsOf diverge from the usual meaning in a DirectedGraph implementation. * *

* * If you need a DirectedGraph implementation, see DominatorTreeAdapter. * * @author Navindra Umanee **/ public class DominatorTree implements Iterable> { private static final Logger logger = LoggerFactory.getLogger(DominatorTree.class); protected DominatorsFinder dominators; protected DirectedGraph graph; protected List> heads; protected List> tails; /** * "gode" is a node in the original graph, "dode" is a node in the dominator tree. **/ protected Map> godeToDode; public DominatorTree(DominatorsFinder dominators) { // if(Options.v().verbose()) // logger.debug("[" + graph.getBody().getMethod().getName() + // "] Constructing DominatorTree..."); this.dominators = dominators; this.graph = dominators.getGraph(); heads = new ArrayList>(); tails = new ArrayList>(); godeToDode = new HashMap>(); buildTree(); } /** * @return the original graph to which the DominatorTree pertains **/ public DirectedGraph getGraph() { return dominators.getGraph(); } /** * @return the root of the dominator tree. **/ public List> getHeads() { return new ArrayList>(heads); } /** * Gets the first head of the dominator tree. This function is implemented for single-headed trees and mainly for backwards * compatibility. * * @return The first head of the dominator tree */ public DominatorNode getHead() { return heads.isEmpty() ? null : heads.get(0); } /** * @return list of the tails of the dominator tree. **/ public List> getTails() { return new ArrayList>(tails); } /** * @return the parent of {@code node} in the tree, null if the node is at the root. **/ public DominatorNode getParentOf(DominatorNode node) { return node.getParent(); } /** * @return the children of node in the tree. **/ public List> getChildrenOf(DominatorNode node) { return new ArrayList>(node.getChildren()); } /** * @return list of the DominatorNodes corresponding to the predecessors of {@code node} in the original DirectedGraph **/ public List> getPredsOf(DominatorNode node) { List preds = graph.getPredsOf(node.getGode()); List> predNodes = new ArrayList>(); for (N pred : preds) { predNodes.add(getDode(pred)); } return predNodes; } /** * @return list of the DominatorNodes corresponding to the successors of {@code node} in the original DirectedGraph **/ public List> getSuccsOf(DominatorNode node) { List succs = graph.getSuccsOf(node.getGode()); List> succNodes = new ArrayList>(); for (N succ : succs) { succNodes.add(getDode(succ)); } return succNodes; } /** * @return true if idom immediately dominates node. **/ public boolean isImmediateDominatorOf(DominatorNode idom, DominatorNode node) { // node.getParent() could be null return (node.getParent() == idom); } /** * @return true if dom dominates node. **/ public boolean isDominatorOf(DominatorNode dom, DominatorNode node) { return dominators.isDominatedBy(node.getGode(), dom.getGode()); } /** * @return DominatorNode for a given node in the original DirectedGraph. **/ public DominatorNode getDode(N gode) { DominatorNode dode = godeToDode.get(gode); if (dode == null) { throw new RuntimeException( "Assertion failed: Dominator tree does not have a corresponding dode for gode (" + gode + ")"); } return dode; } /** * @return iterator over the nodes in the tree. No ordering is implied. **/ public Iterator> iterator() { return godeToDode.values().iterator(); } /** * @return the number of nodes in the tree **/ public int size() { return godeToDode.size(); } /** * Add all the necessary links between nodes to form a meaningful tree structure. **/ protected void buildTree() { // hook up children with parents and vice-versa for (N gode : graph) { DominatorNode dode = fetchDode(gode); DominatorNode parent = fetchParent(gode); if (parent == null) { heads.add(dode); } else { parent.addChild(dode); dode.setParent(parent); } } // identify the tail nodes for (DominatorNode dode : this) { if (dode.isTail()) { tails.add(dode); } } } /** * Convenience method, ensures we don't create more than one DominatorNode for a given block. **/ protected DominatorNode fetchDode(N gode) { DominatorNode dode; if (godeToDode.containsKey(gode)) { dode = godeToDode.get(gode); } else { dode = new DominatorNode(gode); godeToDode.put(gode, dode); } return dode; } protected DominatorNode fetchParent(N gode) { N immediateDominator = dominators.getImmediateDominator(gode); if (immediateDominator == null) { return null; } return fetchDode(immediateDominator); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy