soot.jimple.toolkits.scalar.SlowAvailableExpressionsAnalysis Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of robovm-soot Show documentation
Show all versions of robovm-soot Show documentation
RoboVM fork of Soot - A Java optimization framework
/* Soot - a J*va Optimization Framework
* Copyright (C) 2000 Patrick Lam
*
* This library 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 library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.jimple.toolkits.scalar;
import soot.*;
import soot.toolkits.scalar.*;
import soot.toolkits.graph.*;
import soot.jimple.*;
import java.util.*;
import soot.util.*;
// future work: fieldrefs.
/** 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 SlowAvailableExpressionsAnalysis extends ForwardFlowAnalysis
{
Map unitToGenerateSet;
Map unitToPreserveSet;
Map rhsToContainingStmt;
private final HashMap valueToEquivValue;
FlowSet emptySet;
public SlowAvailableExpressionsAnalysis(DirectedGraph dg)
{
super(dg);
UnitGraph g = (UnitGraph)dg;
/* we need a universe of all of the expressions. */
Iterator unitsIt = g.getBody().getUnits().iterator();
ArrayList exprs = new ArrayList();
// Consider "a + b". containingExprs maps a and b (object equality) both to "a + b" (equivalence).
HashMap containingExprs = new HashMap();
// maps a Value to its EquivalentValue.
valueToEquivValue = new HashMap();
// maps an rhs to its containing stmt. object equality in rhs.
rhsToContainingStmt = new HashMap();
HashMap equivValToSiblingList = new HashMap();
// Create the set of all expressions, and a map from values to their containing expressions.
while (unitsIt.hasNext())
{
Stmt s = (Stmt)unitsIt.next();
if (s instanceof AssignStmt)
{
Value v = ((AssignStmt)s).getRightOp();
rhsToContainingStmt.put(v, s);
EquivalentValue ev = valueToEquivValue.get(v);
if (ev == null)
{
ev = new EquivalentValue(v);
valueToEquivValue.put(v, ev);
}
Chain sibList = null;
if (equivValToSiblingList.get(ev) == null)
{ sibList = new HashChain(); equivValToSiblingList.put(ev, sibList); }
else
sibList = equivValToSiblingList.get(ev);
if (!sibList.contains(v)) sibList.add(v);
if (!(v instanceof Expr))
continue;
if (!exprs.contains(v))
{
exprs.add(v);
// Add map values for contained objects.
Iterator it = v.getUseBoxes().iterator();
while (it.hasNext())
{
Value o = ((ValueBox)it.next()).getValue();
EquivalentValue eo = valueToEquivValue.get(o);
if (eo == null)
{
eo = new EquivalentValue(o);
valueToEquivValue.put(o, eo);
}
if (equivValToSiblingList.get(eo) == null)
{ sibList = new HashChain(); equivValToSiblingList.put(eo, sibList); }
else
sibList = equivValToSiblingList.get(eo);
if (!sibList.contains(o)) sibList.add(o);
Chain l = null;
if (containingExprs.containsKey(eo))
l = containingExprs.get(eo);
else
{
l = new HashChain();
containingExprs.put(eo, l);
}
if (!l.contains(ev))
l.add(ev);
}
}
}
}
FlowUniverse exprUniv = new ArrayFlowUniverse(exprs.toArray());
emptySet = new ArrayPackedSet(exprUniv);
// Create preserve sets.
{
unitToPreserveSet = new HashMap(g.size() * 2 + 1, 0.7f);
Iterator unitIt = g.iterator();
while(unitIt.hasNext())
{
BoundedFlowSet killSet = new ArrayPackedSet(exprUniv);
Unit s = (Unit) unitIt.next();
// We need to do more! In particular handle invokeExprs, etc.
// For each def (say of x), kill the set of exprs containing x.
Iterator boxIt = s.getDefBoxes().iterator();
while(boxIt.hasNext())
{
ValueBox box = (ValueBox) boxIt.next();
Value v = box.getValue();
EquivalentValue ev = valueToEquivValue.get(v);
HashChain c = (HashChain)containingExprs.get(ev);
if (c != null)
{
Iterator it = c.iterator();
while (it.hasNext())
{
// Add all siblings of it.next().
EquivalentValue container = (EquivalentValue)it.next();
Iterator sibListIt = equivValToSiblingList.get(container).iterator();
while (sibListIt.hasNext())
killSet.add(sibListIt.next(), killSet);
}
}
}
// Store complement
killSet.complement(killSet);
unitToPreserveSet.put(s, killSet);
}
}
// Create generate sets
{
unitToGenerateSet = new HashMap(g.size() * 2 + 1, 0.7f);
Iterator unitIt = g.iterator();
while(unitIt.hasNext())
{
Unit s = (Unit) unitIt.next();
BoundedFlowSet genSet = new ArrayPackedSet(exprUniv);
// In Jimple, expressions only occur as the RHS of an AssignStmt.
if (s instanceof AssignStmt)
{
AssignStmt as = (AssignStmt)s;
if (as.getRightOp() instanceof Expr)
{
// canonical rep of as.getRightOp();
Value gen = as.getRightOp();
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);
}
}
// remove the kill set
genSet.intersection(unitToPreserveSet.get(s), genSet);
unitToGenerateSet.put(s, genSet);
}
}
doAnalysis();
}
protected Object newInitialFlow()
{
BoundedFlowSet out = (BoundedFlowSet)emptySet.clone();
out.complement(out);
return out;
}
protected Object entryInitialFlow()
{
return emptySet.clone();
}
protected void flowThrough(Object inValue, Object unit, Object outValue)
{
FlowSet in = (FlowSet) inValue, out = (FlowSet) outValue;
// Perform kill
in.intersection(unitToPreserveSet.get(unit), out);
// Perform generation
out.union(unitToGenerateSet.get(unit), out);
}
protected void merge(Object in1, Object in2, Object out)
{
FlowSet inSet1 = (FlowSet) in1,
inSet2 = (FlowSet) in2;
FlowSet outSet = (FlowSet) out;
inSet1.intersection(inSet2, outSet);
}
protected void copy(Object source, Object dest)
{
FlowSet sourceSet = (FlowSet) source,
destSet = (FlowSet) dest;
sourceSet.copy(destSet);
}
}