soot.jimple.toolkits.scalar.FastAvailableExpressionsAnalysis Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot Show documentation
Show all versions of soot Show documentation
A Java Optimization Framework
package soot.jimple.toolkits.scalar;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2000 Patrick Lam
* %%
* 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.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import soot.SideEffectTester;
import soot.SootMethod;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.jimple.AssignStmt;
import soot.jimple.Expr;
import soot.jimple.FieldRef;
import soot.jimple.InvokeExpr;
import soot.jimple.NewArrayExpr;
import soot.jimple.NewExpr;
import soot.jimple.NewMultiArrayExpr;
import soot.toolkits.graph.DirectedGraph;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.scalar.ArraySparseSet;
import soot.toolkits.scalar.FlowSet;
import soot.toolkits.scalar.ForwardFlowAnalysis;
/**
* Implements an available expressions analysis on local variables. The current implementation is slow but correct. A better
* implementation would use an implicit universe and the kill rule would be computed on-the-fly for each statement.
*/
public class FastAvailableExpressionsAnalysis extends ForwardFlowAnalysis> {
SideEffectTester st;
Map> unitToGenerateSet;
Map> unitToPreserveSet;
Map rhsToContainingStmt;
FlowSet emptySet;
public FastAvailableExpressionsAnalysis(DirectedGraph dg, SootMethod m, SideEffectTester st) {
super(dg);
this.st = st;
ExceptionalUnitGraph g = (ExceptionalUnitGraph) dg;
// LocalDefs ld = new SmartLocalDefs(g, new SimpleLiveLocals(g));
// maps an rhs to its containing stmt. object equality in rhs.
rhsToContainingStmt = new HashMap();
emptySet = new ToppedSet(new ArraySparseSet());
// Create generate sets
{
unitToGenerateSet = new HashMap>(g.size() * 2 + 1, 0.7f);
for (Unit s : g) {
FlowSet genSet = emptySet.clone();
// In Jimple, expressions only occur as the RHS of an
// AssignStmt.
if (s instanceof AssignStmt) {
AssignStmt as = (AssignStmt) s;
if (as.getRightOp() instanceof Expr || as.getRightOp() instanceof FieldRef) {
Value gen = as.getRightOp();
rhsToContainingStmt.put(gen, s);
boolean cantAdd = false;
if (gen instanceof NewExpr || gen instanceof NewArrayExpr || gen instanceof NewMultiArrayExpr) {
cantAdd = true;
}
if (gen instanceof InvokeExpr) {
cantAdd = true;
}
// Whee, double negative!
if (!cantAdd) {
genSet.add(gen, genSet);
}
}
}
unitToGenerateSet.put(s, genSet);
}
}
doAnalysis();
}
protected FlowSet newInitialFlow() {
FlowSet newSet = emptySet.clone();
((ToppedSet) newSet).setTop(true);
return newSet;
}
protected FlowSet entryInitialFlow() {
return emptySet.clone();
}
protected void flowThrough(FlowSet in, Unit u, FlowSet out) {
in.copy(out);
if (((ToppedSet) in).isTop()) {
return;
}
// Perform generation
out.union(unitToGenerateSet.get(u), out);
// Perform kill.
if (((ToppedSet) out).isTop()) {
throw new RuntimeException("trying to kill on topped set!");
}
List l = new LinkedList(out.toList());
// iterate over things (avail) in out set.
for (Value avail : l) {
if (avail instanceof FieldRef) {
if (st.unitCanWriteTo(u, avail)) {
out.remove(avail, out);
}
} else {
for (ValueBox vb : avail.getUseBoxes()) {
Value use = vb.getValue();
if (st.unitCanWriteTo(u, use)) {
out.remove(avail, out);
}
}
}
}
}
protected void merge(FlowSet inSet1, FlowSet inSet2, FlowSet outSet) {
inSet1.intersection(inSet2, outSet);
}
protected void copy(FlowSet sourceSet, FlowSet destSet) {
sourceSet.copy(destSet);
}
}