use of soot.ValueBox in project soot by Sable.
the class ConstantArrayAnalysis method flowThrough.
@Override
protected void flowThrough(ArrayState in, Unit d, ArrayState out) {
out.active.clear();
out.active.or(in.active);
out.state = Arrays.copyOf(in.state, in.state.length);
if (d instanceof DefinitionStmt) {
DefinitionStmt ds = (DefinitionStmt) d;
Value rhs = ds.getRightOp();
Value lhs = ds.getLeftOp();
if (rhs instanceof NewArrayExpr) {
Local l = (Local) lhs;
int varRef = localToInt.get(l);
NewArrayExpr nae = (NewArrayExpr) rhs;
out.active.set(varRef);
if (!(nae.getSize() instanceof IntConstant)) {
out.state[varRef] = null;
} else {
int arraySize = ((IntConstant) nae.getSize()).value;
out.state[varRef] = new ArrayTypesInternal();
out.state[varRef].sizeState.set(sizeToInt.get(arraySize));
out.state[varRef].typeState = new BitSet[arraySize];
out.state[varRef].mustAssign = new BitSet(arraySize);
for (int i = 0; i < arraySize; i++) {
out.state[varRef].typeState[i] = new BitSet(typeSize);
}
}
} else if (lhs instanceof Local && lhs.getType() instanceof ArrayType && rhs instanceof NullConstant) {
int varRef = localToInt.get(lhs);
out.active.clear(varRef);
out.state[varRef] = null;
} else if (lhs instanceof Local && rhs instanceof Local && in.state[localToInt.get(rhs)] != null && in.active.get(localToInt.get(rhs))) {
int lhsRef = localToInt.get(lhs);
int rhsRef = localToInt.get(rhs);
out.active.set(lhsRef);
out.state[lhsRef] = in.state[rhsRef];
out.state[rhsRef] = null;
} else if (lhs instanceof Local && rhs instanceof PhiExpr) {
PhiExpr rPhi = (PhiExpr) rhs;
int lhsRef = localToInt.get(lhs);
out.state[lhsRef] = null;
int i = 0;
List<Value> phiValues = rPhi.getValues();
for (; i < phiValues.size(); i++) {
Value v = phiValues.get(i);
int argRef = localToInt.get(v);
if (!in.active.get(argRef)) {
continue;
}
out.active.set(lhsRef);
// one bottom -> all bottom
if (in.state[argRef] == null) {
out.state[lhsRef] = null;
break;
}
if (out.state[lhsRef] == null) {
out.state[lhsRef] = in.state[argRef];
} else {
out.state[lhsRef] = mergeTypeStates(in.state[argRef], out.state[lhsRef]);
}
out.state[argRef] = null;
}
for (; i < phiValues.size(); i++) {
int argRef = localToInt.get(phiValues.get(i));
out.state[argRef] = null;
}
} else if (lhs instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) lhs;
Value indexVal = ar.getIndex();
int localRef = localToInt.get(ar.getBase());
if (!(indexVal instanceof IntConstant)) {
out.state[localRef] = null;
out.active.set(localRef);
} else if (out.state[localRef] != null) {
Type assignType = rhs.getType();
int index = ((IntConstant) indexVal).value;
assert index < out.state[localRef].typeState.length;
out.deepCloneLocalValueSlot(localRef, index);
assert out.state[localRef].typeState[index] != null : d;
out.state[localRef].typeState[index].set(typeToInt.get(assignType));
out.state[localRef].mustAssign.set(index);
}
} else {
Value leftOp = lhs;
if (leftOp instanceof Local) {
Local defLocal = (Local) leftOp;
int varRef = localToInt.get(defLocal);
out.active.set(varRef);
out.state[varRef] = null;
}
}
for (ValueBox b : rhs.getUseBoxes()) {
if (localToInt.containsKey(b.getValue())) {
int localRef = localToInt.get(b.getValue());
out.state[localRef] = null;
out.active.set(localRef);
}
}
if (localToInt.containsKey(rhs)) {
int localRef = localToInt.get(rhs);
out.state[localRef] = null;
out.active.set(localRef);
}
} else {
for (ValueBox b : d.getUseBoxes()) {
if (localToInt.containsKey(b.getValue())) {
int localRef = localToInt.get(b.getValue());
out.state[localRef] = null;
out.active.set(localRef);
}
}
}
}
use of soot.ValueBox 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.ValueBox in project soot by Sable.
the class Aggregator method internalTransform.
/**
* Traverse the statements in the given body, looking for aggregation
* possibilities; that is, given a def d and a use u, d has no other uses, u
* has no other defs, collapse d and u.
*
* option: only-stack-locals; if this is true, only aggregate variables
* starting with $
*/
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
StmtBody body = (StmtBody) b;
boolean onlyStackVars = PhaseOptions.getBoolean(options, "only-stack-locals");
if (Options.v().time())
Timers.v().aggregationTimer.start();
int aggregateCount = 1;
boolean changed = false;
Map<ValueBox, Zone> boxToZone = new HashMap<ValueBox, Zone>(body.getUnits().size() * 2 + 1, 0.7f);
// Determine the zone of every box
{
Zonation zonation = new Zonation(body);
for (Unit u : body.getUnits()) {
Zone zone = zonation.getZoneOf(u);
for (ValueBox box : u.getUseBoxes()) {
boxToZone.put(box, zone);
}
for (ValueBox box : u.getDefBoxes()) {
boxToZone.put(box, zone);
}
}
}
do {
if (Options.v().verbose())
logger.debug("" + "[" + body.getMethod().getName() + "] Aggregating iteration " + aggregateCount + "...");
// body.printTo(new java.io.PrintWriter(G.v().out, true));
changed = internalAggregate(body, boxToZone, onlyStackVars);
aggregateCount++;
} while (changed);
if (Options.v().time())
Timers.v().aggregationTimer.end();
}
use of soot.ValueBox in project soot by Sable.
the class MethodStaticnessCorrector method canBeMadeStatic.
/**
* Checks whether the given method can be made static, i.e., does not
* reference the "this" object
*
* @param target
* The method to check
* @return True if the given method can be made static, otherwise false
*/
private boolean canBeMadeStatic(SootMethod target) {
if (target.hasActiveBody()) {
Body body = target.getActiveBody();
Value thisLocal = body.getThisLocal();
for (Unit u : body.getUnits()) {
for (ValueBox vb : u.getUseBoxes()) {
if (vb.getValue() == thisLocal)
return false;
}
}
return true;
}
return false;
}
use of soot.ValueBox in project soot by Sable.
the class SiteInliner method inlineSite.
/**
* Inlines the given site. Note that this method does
* not actually check if it's safe (with respect to access modifiers and special invokes)
* for it to be inlined. That functionality is handled by the InlinerSafetyManager.
*/
public static List inlineSite(SootMethod inlinee, Stmt toInline, SootMethod container, Map options) {
boolean enableNullPointerCheckInsertion = PhaseOptions.getBoolean(options, "insert-null-checks");
boolean enableRedundantCastInsertion = PhaseOptions.getBoolean(options, "insert-redundant-casts");
Hierarchy hierarchy = Scene.v().getActiveHierarchy();
JimpleBody containerB = (JimpleBody) container.getActiveBody();
Chain<Unit> containerUnits = containerB.getUnits();
if (!(inlinee.getDeclaringClass().isApplicationClass() || inlinee.getDeclaringClass().isLibraryClass()))
return null;
Body inlineeB = inlinee.getActiveBody();
Chain<Unit> inlineeUnits = inlineeB.getUnits();
InvokeExpr ie = toInline.getInvokeExpr();
Value thisToAdd = null;
if (ie instanceof InstanceInvokeExpr)
thisToAdd = ((InstanceInvokeExpr) ie).getBase();
// Insert casts to please the verifier.
{
boolean targetUsesThis = true;
if (enableRedundantCastInsertion && ie instanceof InstanceInvokeExpr && targetUsesThis) {
// The verifier will complain if targetUsesThis, and:
// the argument passed to the method is not the same type.
// For instance, Bottle.price_static takes a cost.
// Cost is an interface implemented by Bottle.
SootClass localType, parameterType;
localType = ((RefType) ((InstanceInvokeExpr) ie).getBase().getType()).getSootClass();
parameterType = inlinee.getDeclaringClass();
if (localType.isInterface() || hierarchy.isClassSuperclassOf(localType, parameterType)) {
Local castee = Jimple.v().newLocal("__castee", parameterType.getType());
containerB.getLocals().add(castee);
containerB.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, Jimple.v().newCastExpr(((InstanceInvokeExpr) ie).getBase(), parameterType.getType())), toInline);
thisToAdd = castee;
}
}
}
// (If enabled), add a null pointer check.
{
if (enableNullPointerCheckInsertion && ie instanceof InstanceInvokeExpr) {
boolean caught = TrapManager.isExceptionCaughtAt(Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB);
/* Ah ha. Caught again! */
if (caught) {
/* In this case, we don't use throwPoint;
* instead, put the code right there. */
Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), toInline);
containerB.getUnits().insertBefore(insertee, toInline);
// This sucks (but less than before).
((IfStmt) insertee).setTarget(toInline);
ThrowManager.addThrowAfter(containerB, insertee);
} else {
Stmt throwPoint = ThrowManager.getNullPointerExceptionThrower(containerB);
containerB.getUnits().insertBefore(Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr) ie).getBase(), NullConstant.v()), throwPoint), toInline);
}
}
}
// Add synchronizing stuff.
{
if (inlinee.isSynchronized()) {
// Need to get the class object if ie is a static invoke.
if (ie instanceof InstanceInvokeExpr)
SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, (Local) ((InstanceInvokeExpr) ie).getBase());
else {
// synchronization.
if (!container.getDeclaringClass().isInterface()) {
// Whew!
Local l = SynchronizerManager.v().addStmtsToFetchClassBefore(containerB, toInline);
SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, l);
}
}
}
}
Stmt exitPoint = (Stmt) containerUnits.getSuccOf(toInline);
// First, clone all of the inlinee's units & locals.
HashMap<Local, Local> oldLocalsToNew = new HashMap<Local, Local>();
HashMap<Stmt, Stmt> oldUnitsToNew = new HashMap<Stmt, Stmt>();
{
Stmt cursor = toInline;
for (Iterator<Unit> currIt = inlineeUnits.iterator(); currIt.hasNext(); ) {
final Stmt curr = (Stmt) currIt.next();
Stmt currPrime = (Stmt) curr.clone();
if (currPrime == null)
throw new RuntimeException("getting null from clone!");
currPrime.addAllTagsOf(curr);
containerUnits.insertAfter(currPrime, cursor);
cursor = currPrime;
oldUnitsToNew.put(curr, currPrime);
}
for (Iterator<Local> lIt = inlineeB.getLocals().iterator(); lIt.hasNext(); ) {
final Local l = lIt.next();
Local lPrime = (Local) l.clone();
if (lPrime == null)
throw new RuntimeException("getting null from local clone!");
containerB.getLocals().add(lPrime);
oldLocalsToNew.put(l, lPrime);
}
}
// Backpatch the newly-inserted units using newly-constructed maps.
{
Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
while (it.hasNext()) {
Stmt patchee = (Stmt) it.next();
for (ValueBox box : patchee.getUseAndDefBoxes()) {
if (!(box.getValue() instanceof Local))
continue;
Local lPrime = oldLocalsToNew.get(box.getValue());
if (lPrime != null)
box.setValue(lPrime);
else
throw new RuntimeException("local has no clone!");
}
for (UnitBox box : patchee.getUnitBoxes()) {
Unit uPrime = (oldUnitsToNew.get(box.getUnit()));
if (uPrime != null)
box.setUnit(uPrime);
else
throw new RuntimeException("inlined stmt has no clone!");
}
}
}
// Copy & backpatch the traps; preserve their same order.
{
Trap prevTrap = null;
for (Trap t : inlineeB.getTraps()) {
Stmt newBegin = oldUnitsToNew.get(t.getBeginUnit()), newEnd = oldUnitsToNew.get(t.getEndUnit()), newHandler = oldUnitsToNew.get(t.getHandlerUnit());
if (newBegin == null || newEnd == null || newHandler == null)
throw new RuntimeException("couldn't map trap!");
Trap trap = Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler);
if (prevTrap == null)
containerB.getTraps().addFirst(trap);
else
containerB.getTraps().insertAfter(trap, prevTrap);
prevTrap = trap;
}
}
// Handle identity stmt's and returns.
{
Iterator<Unit> it = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint));
ArrayList<Unit> cuCopy = new ArrayList<Unit>();
while (it.hasNext()) {
cuCopy.add(it.next());
}
for (Unit u : cuCopy) {
Stmt s = (Stmt) u;
if (s instanceof IdentityStmt) {
IdentityRef rhs = (IdentityRef) ((IdentityStmt) s).getRightOp();
if (rhs instanceof CaughtExceptionRef)
continue;
else if (rhs instanceof ThisRef) {
if (!(ie instanceof InstanceInvokeExpr))
throw new RuntimeException("thisref with no receiver!");
containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), thisToAdd));
} else if (rhs instanceof ParameterRef) {
ParameterRef pref = (ParameterRef) rhs;
containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt) s).getLeftOp(), ie.getArg(pref.getIndex())));
}
} else if (s instanceof ReturnStmt) {
if (toInline instanceof InvokeStmt) {
// munch, munch.
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
continue;
}
if (!(toInline instanceof AssignStmt))
throw new RuntimeException("invoking stmt neither InvokeStmt nor AssignStmt!??!?!");
Value ro = ((ReturnStmt) s).getOp();
Value lhs = ((AssignStmt) toInline).getLeftOp();
AssignStmt as = Jimple.v().newAssignStmt(lhs, ro);
containerUnits.insertBefore(as, s);
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
} else if (s instanceof ReturnVoidStmt)
containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint));
}
}
List<Unit> newStmts = new ArrayList<Unit>();
for (Iterator<Unit> i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext(); ) {
newStmts.add(i.next());
}
// Remove the original statement toInline.
containerUnits.remove(toInline);
// Resolve name collisions.
LocalNameStandardizer.v().transform(containerB, "ji.lns");
return newStmts;
}
Aggregations