use of soot.toolkits.graph.ExceptionalUnitGraph in project soot by Sable.
the class PurityInterproceduralAnalysis method analyseMethod.
@Override
protected void analyseMethod(SootMethod method, PurityGraphBox dst) {
Body body = method.retrieveActiveBody();
ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body);
new PurityIntraproceduralAnalysis(graph, this).copyResult(dst);
}
use of soot.toolkits.graph.ExceptionalUnitGraph in project soot by Sable.
the class Aggregator method internalAggregate.
private static boolean internalAggregate(StmtBody body, Map<ValueBox, Zone> boxToZone, boolean onlyStackVars) {
boolean hadAggregation = false;
Chain<Unit> units = body.getUnits();
ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body);
LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(graph);
LocalUses localUses = LocalUses.Factory.newLocalUses(body, localDefs);
List<Unit> unitList = new PseudoTopologicalOrderer<Unit>().newList(graph, false);
for (Unit u : unitList) {
if (!(u instanceof AssignStmt))
continue;
AssignStmt s = (AssignStmt) u;
Value lhs = s.getLeftOp();
if (!(lhs instanceof Local))
continue;
Local lhsLocal = (Local) lhs;
if (onlyStackVars && !lhsLocal.getName().startsWith("$"))
continue;
List<UnitValueBoxPair> lu = localUses.getUsesOf(s);
if (lu.size() != 1)
continue;
UnitValueBoxPair usepair = lu.get(0);
Unit use = usepair.unit;
ValueBox useBox = usepair.valueBox;
List<Unit> ld = localDefs.getDefsOfAt(lhsLocal, use);
if (ld.size() != 1)
continue;
// Check to make sure aggregation pair in the same zone
if (boxToZone.get(s.getRightOpBox()) != boxToZone.get(usepair.valueBox)) {
continue;
}
/* we need to check the path between def and use */
/* to see if there are any intervening re-defs of RHS */
/* in fact, we should check that this path is unique. */
/*
* if the RHS uses only locals, then we know what to do; if RHS has
* a method invocation f(a, b, c) or field access, we must ban field
* writes, other method calls and (as usual) writes to a, b, c.
*/
boolean cantAggr = false;
boolean propagatingInvokeExpr = false;
boolean propagatingFieldRef = false;
boolean propagatingArrayRef = false;
List<FieldRef> fieldRefList = new ArrayList<FieldRef>();
List<Value> localsUsed = new ArrayList<Value>();
for (ValueBox vb : s.getUseBoxes()) {
Value v = vb.getValue();
if (v instanceof Local) {
localsUsed.add(v);
} else if (v instanceof InvokeExpr) {
propagatingInvokeExpr = true;
} else if (v instanceof ArrayRef) {
propagatingArrayRef = true;
} else if (v instanceof FieldRef) {
propagatingFieldRef = true;
fieldRefList.add((FieldRef) v);
}
}
// look for a path from s to use in graph.
// only look in an extended basic block, though.
List<Unit> path = graph.getExtendedBasicBlockPathBetween(s, use);
if (path == null)
continue;
Iterator<Unit> pathIt = path.iterator();
// skip s.
if (pathIt.hasNext())
pathIt.next();
while (pathIt.hasNext() && !cantAggr) {
Stmt between = (Stmt) (pathIt.next());
if (between != use) {
for (ValueBox vb : between.getDefBoxes()) {
Value v = vb.getValue();
if (localsUsed.contains(v)) {
cantAggr = true;
break;
}
if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) {
if (v instanceof FieldRef) {
if (propagatingInvokeExpr) {
cantAggr = true;
break;
} else if (propagatingFieldRef) {
// aliased
for (FieldRef fieldRef : fieldRefList) {
if (isSameField((FieldRef) v, fieldRef)) {
cantAggr = true;
break;
}
}
}
} else if (v instanceof ArrayRef) {
if (propagatingInvokeExpr) {
// Cannot aggregate an invoke expr past an
// array write
cantAggr = true;
break;
} else if (propagatingArrayRef) {
// cannot aggregate an array read past a
// write
// this is somewhat conservative
// (if types differ they may not be aliased)
cantAggr = true;
break;
}
}
}
}
// Make sure not propagating past a {enter,exit}Monitor
if (propagatingInvokeExpr && between instanceof MonitorStmt)
cantAggr = true;
}
// Check for intervening side effects due to method calls
if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) {
for (final ValueBox box : between.getUseBoxes()) {
if (between == use && box == useBox) {
// side effects
break;
}
Value v = box.getValue();
if (v instanceof InvokeExpr || (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef))) {
cantAggr = true;
break;
}
}
}
}
// we give up: can't aggregate.
if (cantAggr) {
continue;
}
/* assuming that the d-u chains are correct, */
/* we need not check the actual contents of ld */
Value aggregatee = s.getRightOp();
if (usepair.valueBox.canContainValue(aggregatee)) {
boolean wasSimpleCopy = isSimpleCopy(usepair.unit);
usepair.valueBox.setValue(aggregatee);
units.remove(s);
hadAggregation = true;
// followed by an invoke, the invoke gets the tags.
if (wasSimpleCopy) {
// usepair.unit.removeAllTags();
usepair.unit.addAllTagsOf(s);
}
} else {
/*
* if(Options.v().verbose()) {
* logger.debug("[debug] failed aggregation");
* logger.debug("[debug] tried to put "+aggregatee+
* " into "+usepair.stmt +
* ": in particular, "+usepair.valueBox);
* logger.debug("[debug] aggregatee instanceof Expr: "
* +(aggregatee instanceof Expr)); }
*/
}
}
return hadAggregation;
}
use of soot.toolkits.graph.ExceptionalUnitGraph in project soot by Sable.
the class CopyPropagator method internalTransform.
/**
* Cascaded copy propagator.
*
* If it encounters situations of the form: A: a = ...; B: ... x = a; C:...
* use (x); where a has only one definition, and x has only one definition
* (B), then it can propagate immediately without checking between B and C
* for redefinitions of a (namely) A because they cannot occur. In this case
* the propagator is global.
*
* Otherwise, if a has multiple definitions then it only checks for
* redefinitions of Propagates constants and copies in extended basic
* blocks.
*
* Does not propagate stack locals when the "only-regular-locals" option is
* true.
*/
protected void internalTransform(Body b, String phaseName, Map<String, String> opts) {
CPOptions options = new CPOptions(opts);
StmtBody stmtBody = (StmtBody) b;
int fastCopyPropagationCount = 0;
int slowCopyPropagationCount = 0;
if (Options.v().verbose())
logger.debug("[" + stmtBody.getMethod().getName() + "] Propagating copies...");
if (Options.v().time())
Timers.v().propagatorTimer.start();
Chain<Unit> units = stmtBody.getUnits();
Map<Local, Integer> localToDefCount = new HashMap<Local, Integer>();
// Count number of definitions for each local.
for (Unit u : units) {
Stmt s = (Stmt) u;
if (s instanceof DefinitionStmt && ((DefinitionStmt) s).getLeftOp() instanceof Local) {
Local l = (Local) ((DefinitionStmt) s).getLeftOp();
if (!localToDefCount.containsKey(l))
localToDefCount.put(l, new Integer(1));
else
localToDefCount.put(l, new Integer(localToDefCount.get(l).intValue() + 1));
}
}
if (throwAnalysis == null)
throwAnalysis = Scene.v().getDefaultThrowAnalysis();
if (forceOmitExceptingUnitEdges == false)
forceOmitExceptingUnitEdges = Options.v().omit_excepting_unit_edges();
// Go through the definitions, building the webs
UnitGraph graph = new ExceptionalUnitGraph(stmtBody, throwAnalysis, forceOmitExceptingUnitEdges);
LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(graph);
// Perform a local propagation pass.
{
Iterator<Unit> stmtIt = (new PseudoTopologicalOrderer<Unit>()).newList(graph, false).iterator();
while (stmtIt.hasNext()) {
Stmt stmt = (Stmt) stmtIt.next();
for (ValueBox useBox : stmt.getUseBoxes()) {
if (useBox.getValue() instanceof Local) {
Local l = (Local) useBox.getValue();
// null due to typing, we always inline that constant.
if (!(l.getType() instanceof NullType)) {
if (options.only_regular_locals() && l.getName().startsWith("$"))
continue;
if (options.only_stack_locals() && !l.getName().startsWith("$"))
continue;
}
List<Unit> defsOfUse = localDefs.getDefsOfAt(l, stmt);
// We can propagate the definition if we either only
// have
// one definition or all definitions are side-effect
// free
// and equal. For starters, we only support constants in
// the case of multiple definitions.
boolean propagateDef = defsOfUse.size() == 1;
if (!propagateDef && defsOfUse.size() > 0) {
boolean agrees = true;
Constant constVal = null;
for (Unit defUnit : defsOfUse) {
boolean defAgrees = false;
if (defUnit instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) defUnit;
if (assign.getRightOp() instanceof Constant) {
if (constVal == null) {
constVal = (Constant) assign.getRightOp();
defAgrees = true;
} else if (constVal.equals(assign.getRightOp()))
defAgrees = true;
}
}
agrees &= defAgrees;
}
propagateDef = agrees;
}
if (propagateDef) {
DefinitionStmt def = (DefinitionStmt) defsOfUse.get(0);
if (def.getRightOp() instanceof Constant) {
if (useBox.canContainValue(def.getRightOp())) {
useBox.setValue(def.getRightOp());
}
} else if (def.getRightOp() instanceof CastExpr) {
CastExpr ce = (CastExpr) def.getRightOp();
if (ce.getCastType() instanceof RefLikeType) {
boolean isConstNull = ce.getOp() instanceof IntConstant && ((IntConstant) ce.getOp()).value == 0;
isConstNull |= ce.getOp() instanceof LongConstant && ((LongConstant) ce.getOp()).value == 0;
if (isConstNull) {
if (useBox.canContainValue(NullConstant.v())) {
useBox.setValue(NullConstant.v());
}
}
}
} else if (def.getRightOp() instanceof Local) {
Local m = (Local) def.getRightOp();
if (l != m) {
Integer defCount = localToDefCount.get(m);
if (defCount == null || defCount == 0)
throw new RuntimeException("Variable " + m + " used without definition!");
if (defCount == 1) {
useBox.setValue(m);
fastCopyPropagationCount++;
continue;
}
List<Unit> path = graph.getExtendedBasicBlockPathBetween(def, stmt);
if (path == null) {
// no path in the extended basic block
continue;
}
Iterator<Unit> pathIt = path.iterator();
// Skip first node
pathIt.next();
// Make sure that m is not redefined along
// path
{
boolean isRedefined = false;
while (pathIt.hasNext()) {
Stmt s = (Stmt) pathIt.next();
if (stmt == s) {
break;
}
if (s instanceof DefinitionStmt) {
if (((DefinitionStmt) s).getLeftOp() == m) {
isRedefined = true;
break;
}
}
}
if (isRedefined)
continue;
}
useBox.setValue(m);
slowCopyPropagationCount++;
}
}
}
}
}
}
}
if (Options.v().verbose())
logger.debug("[" + stmtBody.getMethod().getName() + "] Propagated: " + fastCopyPropagationCount + " fast copies " + slowCopyPropagationCount + " slow copies");
if (Options.v().time())
Timers.v().propagatorTimer.end();
}
use of soot.toolkits.graph.ExceptionalUnitGraph in project soot by Sable.
the class UnreachableCodeEliminator method internalTransform.
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
if (Options.v().verbose()) {
logger.debug("[" + body.getMethod().getName() + "] Eliminating unreachable code...");
}
// says that none of them can throw the caught exception.
if (this.throwAnalysis == null)
this.throwAnalysis = PhaseOptions.getBoolean(options, "remove-unreachable-traps", true) ? Scene.v().getDefaultThrowAnalysis() : PedanticThrowAnalysis.v();
ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body, throwAnalysis, false);
Chain<Unit> units = body.getUnits();
int numPruned = units.size();
Set<Unit> reachable = units.isEmpty() ? Collections.<Unit>emptySet() : reachable(units.getFirst(), graph);
// source.
for (Iterator<Trap> it = body.getTraps().iterator(); it.hasNext(); ) {
Trap trap = it.next();
if ((trap.getBeginUnit() == trap.getEndUnit()) || !reachable.contains(trap.getHandlerUnit())) {
it.remove();
}
}
// alive are kept in the code
for (Trap t : body.getTraps()) if (t.getEndUnit() == body.getUnits().getLast())
reachable.add(t.getEndUnit());
Set<Unit> notReachable = new HashSet<Unit>();
if (Options.v().verbose()) {
for (Unit u : units) {
if (!reachable.contains(u))
notReachable.add(u);
}
}
units.retainAll(reachable);
numPruned -= units.size();
if (Options.v().verbose()) {
logger.debug("[" + body.getMethod().getName() + "] Removed " + numPruned + " statements: ");
for (Unit u : notReachable) {
logger.debug("[" + body.getMethod().getName() + "] " + u);
}
}
}
use of soot.toolkits.graph.ExceptionalUnitGraph in project soot by Sable.
the class SynchronizedMethodTransformer method internalTransform.
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
if (!b.getMethod().isSynchronized() || b.getMethod().isStatic())
return;
Iterator<Unit> it = b.getUnits().snapshotIterator();
while (it.hasNext()) {
Unit u = it.next();
if (u instanceof IdentityStmt)
continue;
// instruction, we generate one
if (!(u instanceof EnterMonitorStmt)) {
b.getUnits().insertBeforeNoRedirect(Jimple.v().newEnterMonitorStmt(b.getThisLocal()), u);
// We also need to leave the monitor when the method terminates
UnitGraph graph = new ExceptionalUnitGraph(b);
for (Unit tail : graph.getTails()) b.getUnits().insertBefore(Jimple.v().newExitMonitorStmt(b.getThisLocal()), tail);
}
break;
}
}
Aggregations