Search in sources :

Example 1 with LCMOptions

use of soot.options.LCMOptions in project soot by Sable.

the class LazyCodeMotion method internalTransform.

/**
 * performs the lazy code motion.
 */
protected void internalTransform(Body b, String phaseName, Map<String, String> opts) {
    LCMOptions options = new LCMOptions(opts);
    HashMap<EquivalentValue, Local> expToHelper = new HashMap<EquivalentValue, Local>();
    Chain<Unit> unitChain = b.getUnits();
    if (Options.v().verbose())
        logger.debug("[" + b.getMethod().getName() + "] Performing Lazy Code Motion...");
    if (options.unroll())
        new LoopConditionUnroller().transform(b, phaseName + ".lcu");
    CriticalEdgeRemover.v().transform(b, phaseName + ".cer");
    UnitGraph graph = new BriefUnitGraph(b);
    /* map each unit to its RHS. only take binary expressions */
    Map<Unit, EquivalentValue> unitToEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {

        protected EquivalentValue mapTo(Unit unit) {
            Value tmp = SootFilter.noInvokeRhs(unit);
            Value tmp2 = SootFilter.binop(tmp);
            if (tmp2 == null)
                tmp2 = SootFilter.concreteRef(tmp);
            return SootFilter.equiVal(tmp2);
        }
    };
    /* same as before, but without exception-throwing expressions */
    Map<Unit, EquivalentValue> unitToNoExceptionEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {

        protected EquivalentValue mapTo(Unit unit) {
            Value tmp = SootFilter.binopRhs(unit);
            tmp = SootFilter.noExceptionThrowing(tmp);
            return SootFilter.equiVal(tmp);
        }
    };
    FlowUniverse<EquivalentValue> universe = new CollectionFlowUniverse<EquivalentValue>(unitToEquivRhs.values());
    BoundedFlowSet<EquivalentValue> set = new ArrayPackedSet<EquivalentValue>(universe);
    /* if a more precise sideeffect-tester comes out, please change it here! */
    SideEffectTester sideEffect;
    if (Scene.v().hasCallGraph() && !options.naive_side_effect()) {
        sideEffect = new PASideEffectTester();
    } else {
        sideEffect = new NaiveSideEffectTester();
    }
    sideEffect.newMethod(b.getMethod());
    UpSafetyAnalysis upSafe;
    DownSafetyAnalysis downSafe;
    EarliestnessComputation earliest;
    DelayabilityAnalysis delay;
    NotIsolatedAnalysis notIsolated;
    LatestComputation latest;
    if (options.safety() == LCMOptions.safety_safe)
        upSafe = new UpSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect, set);
    else
        upSafe = new UpSafetyAnalysis(graph, unitToEquivRhs, sideEffect, set);
    if (options.safety() == LCMOptions.safety_unsafe)
        downSafe = new DownSafetyAnalysis(graph, unitToEquivRhs, sideEffect, set);
    else {
        downSafe = new DownSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect, set);
        /* we include the exception-throwing expressions at their uses */
        Iterator<Unit> unitIt = unitChain.iterator();
        while (unitIt.hasNext()) {
            Unit currentUnit = unitIt.next();
            EquivalentValue rhs = unitToEquivRhs.get(currentUnit);
            if (rhs != null)
                downSafe.getFlowBefore(currentUnit).add(rhs);
        }
    }
    earliest = new EarliestnessComputation(graph, upSafe, downSafe, sideEffect, set);
    delay = new DelayabilityAnalysis(graph, earliest, unitToEquivRhs, set);
    latest = new LatestComputation(graph, delay, unitToEquivRhs, set);
    notIsolated = new NotIsolatedAnalysis(graph, latest, unitToEquivRhs, set);
    LocalCreation localCreation = new LocalCreation(b.getLocals(), PREFIX);
    /* debug */
    /*
		 * { logger.debug("========" + b.getMethod().getName()); Iterator
		 * unitIt = unitChain.iterator(); while (unitIt.hasNext()) { Unit
		 * currentUnit = (Unit) unitIt.next(); Value equiVal =
		 * (Value)unitToEquivRhs.get(currentUnit); FlowSet latestSet =
		 * (FlowSet)latest.getFlowBefore(currentUnit); FlowSet notIsolatedSet =
		 * (FlowSet)notIsolated.getFlowAfter(currentUnit); FlowSet delaySet =
		 * (FlowSet)delay.getFlowBefore(currentUnit); FlowSet earlySet =
		 * ((FlowSet)earliest.getFlowBefore(currentUnit)); FlowSet upSet =
		 * (FlowSet)upSafe.getFlowBefore(currentUnit); FlowSet downSet =
		 * (FlowSet)downSafe.getFlowBefore(currentUnit);
		 * logger.debug(""+currentUnit); logger.debug(" rh: " + equiVal);
		 * logger.debug(" up: " + upSet); logger.debug(" do: " +
		 * downSet); logger.debug(" is: " + notIsolatedSet);
		 * logger.debug(" ea: " + earlySet); logger.debug(" db: " +
		 * delaySet); logger.debug(" la: " + latestSet); } }
		 */
    {
        /* insert the computations */
        for (Iterator<Unit> unitIt = unitChain.snapshotIterator(); unitIt.hasNext(); ) {
            Unit currentUnit = unitIt.next();
            FlowSet<EquivalentValue> latestSet = latest.getFlowBefore(currentUnit);
            FlowSet<EquivalentValue> notIsolatedSet = notIsolated.getFlowAfter(currentUnit);
            FlowSet<EquivalentValue> insertHere = latestSet.clone();
            insertHere.intersection(notIsolatedSet, insertHere);
            for (EquivalentValue equiVal : insertHere) {
                /* get the unic helper-name for this expression */
                Local helper = expToHelper.get(equiVal);
                if (helper == null) {
                    helper = localCreation.newLocal(equiVal.getType());
                    expToHelper.put(equiVal, helper);
                }
                /* insert a new Assignment-stmt before the currentUnit */
                Value insertValue = Jimple.cloneIfNecessary(equiVal.getValue());
                Unit firstComp = Jimple.v().newAssignStmt(helper, insertValue);
                unitChain.insertBefore(firstComp, currentUnit);
            }
        }
    }
    {
        /* replace old computations by the helper-vars */
        Iterator<Unit> unitIt = unitChain.iterator();
        while (unitIt.hasNext()) {
            Unit currentUnit = (Unit) unitIt.next();
            EquivalentValue rhs = (EquivalentValue) unitToEquivRhs.get(currentUnit);
            if (rhs != null) {
                FlowSet<EquivalentValue> latestSet = latest.getFlowBefore(currentUnit);
                FlowSet<EquivalentValue> notIsolatedSet = notIsolated.getFlowAfter(currentUnit);
                if (!latestSet.contains(rhs) && notIsolatedSet.contains(rhs)) {
                    Local helper = expToHelper.get(rhs);
                    try {
                        if (helper != null)
                            ((AssignStmt) currentUnit).setRightOp(helper);
                    } catch (RuntimeException e) {
                        logger.debug("Error on " + b.getMethod().getName());
                        logger.debug("" + currentUnit.toString());
                        logger.debug("" + latestSet);
                        logger.debug("" + notIsolatedSet);
                        throw e;
                    }
                }
            }
        }
    }
    if (Options.v().verbose())
        logger.debug("[" + b.getMethod().getName() + "]     Lazy Code Motion done.");
}
Also used : PASideEffectTester(soot.jimple.toolkits.pointer.PASideEffectTester) PASideEffectTester(soot.jimple.toolkits.pointer.PASideEffectTester) LCMOptions(soot.options.LCMOptions)

Aggregations

PASideEffectTester (soot.jimple.toolkits.pointer.PASideEffectTester)1 LCMOptions (soot.options.LCMOptions)1