Search in sources :

Example 6 with ExceptionalUnitGraph

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);
}
Also used : ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph)

Example 7 with ExceptionalUnitGraph

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;
}
Also used : FieldRef(soot.jimple.FieldRef) AssignStmt(soot.jimple.AssignStmt) ArrayList(java.util.ArrayList) Local(soot.Local) LocalUses(soot.toolkits.scalar.LocalUses) Unit(soot.Unit) LocalDefs(soot.toolkits.scalar.LocalDefs) MonitorStmt(soot.jimple.MonitorStmt) MonitorStmt(soot.jimple.MonitorStmt) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) DefinitionStmt(soot.jimple.DefinitionStmt) ArrayRef(soot.jimple.ArrayRef) ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) InvokeExpr(soot.jimple.InvokeExpr) ValueBox(soot.ValueBox) Value(soot.Value) UnitValueBoxPair(soot.toolkits.scalar.UnitValueBoxPair)

Example 8 with ExceptionalUnitGraph

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();
}
Also used : HashMap(java.util.HashMap) NullConstant(soot.jimple.NullConstant) Constant(soot.jimple.Constant) LongConstant(soot.jimple.LongConstant) IntConstant(soot.jimple.IntConstant) AssignStmt(soot.jimple.AssignStmt) Unit(soot.Unit) Stmt(soot.jimple.Stmt) AssignStmt(soot.jimple.AssignStmt) DefinitionStmt(soot.jimple.DefinitionStmt) RefLikeType(soot.RefLikeType) ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) Iterator(java.util.Iterator) CastExpr(soot.jimple.CastExpr) IntConstant(soot.jimple.IntConstant) List(java.util.List) LongConstant(soot.jimple.LongConstant) PseudoTopologicalOrderer(soot.toolkits.graph.PseudoTopologicalOrderer) Local(soot.Local) LocalDefs(soot.toolkits.scalar.LocalDefs) ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) UnitGraph(soot.toolkits.graph.UnitGraph) ValueBox(soot.ValueBox) CPOptions(soot.options.CPOptions) NullType(soot.NullType) StmtBody(soot.jimple.StmtBody) DefinitionStmt(soot.jimple.DefinitionStmt)

Example 9 with ExceptionalUnitGraph

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);
        }
    }
}
Also used : ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) Trap(soot.Trap) Unit(soot.Unit) HashSet(java.util.HashSet)

Example 10 with ExceptionalUnitGraph

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;
    }
}
Also used : ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) UnitGraph(soot.toolkits.graph.UnitGraph) ExceptionalUnitGraph(soot.toolkits.graph.ExceptionalUnitGraph) Unit(soot.Unit) IdentityStmt(soot.jimple.IdentityStmt) EnterMonitorStmt(soot.jimple.EnterMonitorStmt)

Aggregations

ExceptionalUnitGraph (soot.toolkits.graph.ExceptionalUnitGraph)22 Unit (soot.Unit)14 Local (soot.Local)10 List (java.util.List)8 ArrayList (java.util.ArrayList)7 Value (soot.Value)7 Stmt (soot.jimple.Stmt)6 ValueBox (soot.ValueBox)5 AssignStmt (soot.jimple.AssignStmt)5 Trap (soot.Trap)4 DefinitionStmt (soot.jimple.DefinitionStmt)4 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 Iterator (java.util.Iterator)3 NullConstant (soot.jimple.NullConstant)3 UnitGraph (soot.toolkits.graph.UnitGraph)3 LocalDefs (soot.toolkits.scalar.LocalDefs)3 BitSet (java.util.BitSet)2 Body (soot.Body)2 NormalUnitPrinter (soot.NormalUnitPrinter)2