Search in sources :

Example 1 with StmtBody

use of soot.jimple.StmtBody 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();
}
Also used : HashMap(java.util.HashMap) ValueBox(soot.ValueBox) StmtBody(soot.jimple.StmtBody) Unit(soot.Unit)

Example 2 with StmtBody

use of soot.jimple.StmtBody 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)

Aggregations

HashMap (java.util.HashMap)2 Unit (soot.Unit)2 ValueBox (soot.ValueBox)2 StmtBody (soot.jimple.StmtBody)2 Iterator (java.util.Iterator)1 List (java.util.List)1 Local (soot.Local)1 NullType (soot.NullType)1 RefLikeType (soot.RefLikeType)1 AssignStmt (soot.jimple.AssignStmt)1 CastExpr (soot.jimple.CastExpr)1 Constant (soot.jimple.Constant)1 DefinitionStmt (soot.jimple.DefinitionStmt)1 IntConstant (soot.jimple.IntConstant)1 LongConstant (soot.jimple.LongConstant)1 NullConstant (soot.jimple.NullConstant)1 Stmt (soot.jimple.Stmt)1 CPOptions (soot.options.CPOptions)1 ExceptionalUnitGraph (soot.toolkits.graph.ExceptionalUnitGraph)1 PseudoTopologicalOrderer (soot.toolkits.graph.PseudoTopologicalOrderer)1