soot.toolkits.graph.ClassicCompleteUnitGraph Maven / Gradle / Ivy
package soot.toolkits.graph;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2003 John Jorgensen
* %%
* 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.Iterator;
import java.util.List;
import java.util.Map;
import soot.Body;
import soot.Trap;
import soot.Unit;
import soot.toolkits.exceptions.ThrowAnalysis;
/**
*
* Represents a CFG for a Body instance where the nodes are {@link Unit} instances, and where edges are a conservative
* indication of unexceptional and exceptional control flow.
*
*
*
* ClassicCompleteUnitGraph attempts to duplicate the results that would have been produced by Soot's
* CompleteUnitGraph
in releases up to Soot 2.1.0 (the one known discrepancy is that the 2.1.0
* CompleteUnitGraph
would include two edges joining one node to another {@link Unit}s if the first node both
* branched to and fell through to the second). It is included solely for testing purposes, and should not be used in actual
* analyses.
*
*
*
* There are two distinctions between the graphs produced by the ClassicCompleteUnitGraph and
* ExceptionalUnitGraph:
*
*
* - ExceptionalUnitGraph only creates edges to a Trap handler for trapped Units that have the
* potential to throw the particular exception type caught by the handler, according to the {@link ThrowAnalysis} used to
* estimate which exceptions each {@link Unit} may throw. ClassicCompleteUnitGraph creates edges for all trapped
* Units, regardless of the types of exceptions they may throw.
*
* - When ExceptionalUnitGraph creates edges for a trapped Unit that may throw a caught exception, it
* adds edges from each predecessor of the excepting Unit to the handler. If the excepting Unit itself has
* no potential side effects, ExceptionalUnitGraph may omit an edge from it to the handler, depending on the
* parameters passed to the ExceptionalUnitGraph constructor.
* ClassicCompleteUnitGraph, on the other hand, always adds an edge from the excepting Unit itself to the
* handler, and adds edges from the predecessor only of the first Unit covered by a Trap (in this one
* aspect ClassicCompleteUnitGraph is less conservative than ExceptionalUnitGraph, since it ignores the
* possibility of a branch into the middle of a protected area).
*
*
*
*/
public class ClassicCompleteUnitGraph extends TrapUnitGraph {
/**
* Constructs the graph from a given Body instance.
*
* @param the
* Body instance from which the graph is built.
*/
public ClassicCompleteUnitGraph(Body body) {
// The TrapUnitGraph constructor will use our buildExceptionalEdges:
super(body);
}
/**
* Method to compute the edges corresponding to exceptional control flow.
*
* @param unitToSuccs
* A {@link Map} from {@link Unit}s to {@link List}s of {@link Unit}s. This is * an ``out parameter'';
* buildExceptionalEdges will add a mapping for every Unit within the scope of one or more
* {@link Trap}s to a List of the handler units of those Traps.
*
* @param unitToPreds
* A {@link Map} from {@link Unit}s to {@link List}s of {@link Unit}s. This is an ``out parameter'';
* buildExceptionalEdges will add a mapping for every {@link Trap} handler to all the Units
* within the scope of that Trap.
*/
protected void buildExceptionalEdges(Map> unitToSuccs, Map> unitToPreds) {
// First, add the same edges as TrapUnitGraph.
super.buildExceptionalEdges(unitToSuccs, unitToPreds);
// Then add edges from the predecessors of the first
// trapped Unit for each Trap.
for (Iterator trapIt = body.getTraps().iterator(); trapIt.hasNext();) {
Trap trap = trapIt.next();
Unit firstTrapped = trap.getBeginUnit();
Unit catcher = trap.getHandlerUnit();
// Make a copy of firstTrapped's predecessors to iterate over,
// just in case we're about to add new predecessors to this
// very list, though that can only happen if the handler traps
// itself. And to really allow for that
// possibility, we should iterate here until we reach a fixed
// point; but the old UnitGraph that we are attempting to
// duplicate did not do that, so we won't either.
List origPredsOfTrapped = new ArrayList(getPredsOf(firstTrapped));
for (Iterator unitIt = origPredsOfTrapped.iterator(); unitIt.hasNext();) {
Unit pred = unitIt.next();
addEdge(unitToSuccs, unitToPreds, pred, catcher);
}
}
}
}