soot.toolkits.graph.SimpleDominatorsFinder 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.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.toolkits.scalar.ArrayPackedSet;
import soot.toolkits.scalar.BoundedFlowSet;
import soot.toolkits.scalar.CollectionFlowUniverse;
import soot.toolkits.scalar.FlowSet;
import soot.toolkits.scalar.FlowUniverse;
import soot.toolkits.scalar.ForwardFlowAnalysis;
/**
* Wrapper class for a simple dominators analysis based on a simple flow analysis algorithm. Works with any DirectedGraph
* with a single head.
*
* @author Navindra Umanee
**/
public class SimpleDominatorsFinder implements DominatorsFinder {
private static final Logger logger = LoggerFactory.getLogger(SimpleDominatorsFinder.class);
protected DirectedGraph graph;
protected Map> nodeToDominators;
/**
* Compute dominators for provided singled-headed directed graph.
**/
public SimpleDominatorsFinder(DirectedGraph graph) {
// if(Options.v().verbose())
// logger.debug("[" + graph.getBody().getMethod().getName() +
// "] Finding Dominators...");
this.graph = graph;
SimpleDominatorsAnalysis analysis = new SimpleDominatorsAnalysis(graph);
// build node to dominators map
{
nodeToDominators = new HashMap>(graph.size() * 2 + 1, 0.7f);
for (Iterator nodeIt = graph.iterator(); nodeIt.hasNext();) {
N node = nodeIt.next();
FlowSet set = analysis.getFlowAfter(node);
nodeToDominators.put(node, set);
}
}
}
public DirectedGraph getGraph() {
return graph;
}
public List getDominators(N node) {
// non-backed list since FlowSet is an ArrayPackedFlowSet
return nodeToDominators.get(node).toList();
}
public N getImmediateDominator(N node) {
// root node
if (getGraph().getHeads().contains(node)) {
return null;
}
// avoid the creation of temp-lists
FlowSet head = (FlowSet) nodeToDominators.get(node).clone();
head.remove(node);
for (N dominator : head) {
if (nodeToDominators.get(dominator).isSubSet(head)) {
return dominator;
}
}
return null;
}
public boolean isDominatedBy(N node, N dominator) {
// avoid the creation of temp-lists
return nodeToDominators.get(node).contains(dominator);
}
public boolean isDominatedByAll(N node, Collection dominators) {
FlowSet f = nodeToDominators.get(node);
for (N n : dominators) {
if (!f.contains(n)) {
return false;
}
}
return true;
}
}
/**
* Calculate dominators for basic blocks.
*
* Uses the algorithm contained in Dragon book, pg. 670-1.
*
*
* D(n0) := { n0 }
* for n in N - { n0 } do D(n) := N;
* while changes to any D(n) occur do
* for n in N - {n0} do
* D(n) := {n} U (intersect of D(p) over all predecessors p of n)
*
**/
class SimpleDominatorsAnalysis extends ForwardFlowAnalysis> {
private FlowSet emptySet;
private BoundedFlowSet fullSet;
SimpleDominatorsAnalysis(DirectedGraph graph) {
super(graph);
// define empty set, with proper universe for complementation
List nodes = new ArrayList(graph.size());
for (N n : graph) {
nodes.add(n);
}
FlowUniverse nodeUniverse = new CollectionFlowUniverse(nodes);
emptySet = new ArrayPackedSet(nodeUniverse);
fullSet = (BoundedFlowSet) emptySet.clone();
fullSet.complement();
doAnalysis();
}
/**
* All OUTs are initialized to the full set of definitions OUT(Start) is tweaked in customizeInitialFlowGraph.
**/
@Override
protected FlowSet newInitialFlow() {
return (FlowSet) fullSet.clone();
}
/**
* OUT(Start) contains all head nodes at initialization time.
**/
@Override
protected FlowSet entryInitialFlow() {
FlowSet initSet = (FlowSet) emptySet.clone();
for (N h : graph.getHeads()) {
initSet.add(h);
}
return initSet;
}
/**
* We compute out straightforwardly.
**/
@Override
protected void flowThrough(FlowSet in, N block, FlowSet out) {
// Perform generation
in.copy(out);
out.add(block);
}
/**
* All paths == Intersection.
**/
@Override
protected void merge(FlowSet in1, FlowSet in2, FlowSet out) {
in1.intersection(in2, out);
}
@Override
protected void mergeInto(N block, FlowSet inout, FlowSet in) {
inout.intersection(in);
}
@Override
protected void copy(FlowSet source, FlowSet dest) {
source.copy(dest);
}
}