Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package soot.jimple.toolkits.scalar.pre;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2002 Florian Loitsch
* %%
* This program 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 program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.Body;
import soot.BodyTransformer;
import soot.EquivalentValue;
import soot.G;
import soot.Local;
import soot.Scene;
import soot.SideEffectTester;
import soot.Singletons;
import soot.Unit;
import soot.Value;
import soot.jimple.AssignStmt;
import soot.jimple.IdentityStmt;
import soot.jimple.Jimple;
import soot.jimple.NaiveSideEffectTester;
import soot.jimple.toolkits.graph.CriticalEdgeRemover;
import soot.jimple.toolkits.pointer.PASideEffectTester;
import soot.jimple.toolkits.scalar.LocalCreation;
import soot.options.BCMOptions;
import soot.options.Options;
import soot.toolkits.graph.BriefUnitGraph;
import soot.toolkits.graph.UnitGraph;
import soot.util.Chain;
import soot.util.UnitMap;
/**
* Performs a partial redundancy elimination (= code motion). This is done, by moving everycomputation as high as
* possible (it is easy to show, that they are computationally optimal), and then replacing the original computation by a
* reference to this new high computation. This implies, that we introduce many new helper-variables (that can easily
* be eliminated afterwards).
* In order to catch every redundant expression, this transformation must be done on a graph without critical edges.
* Therefore the first thing we do, is removing them. A subsequent pass can then easily remove the synthetic nodes we have
* introduced.
* The term "busy" refers to the fact, that we always move computations as high as possible. Even, if this is not
* necessary.
*
* @see soot.jimple.toolkits.graph.CriticalEdgeRemover
*/
public class BusyCodeMotion extends BodyTransformer {
private static final Logger logger = LoggerFactory.getLogger(BusyCodeMotion.class);
public BusyCodeMotion(Singletons.Global g) {
}
public static BusyCodeMotion v() {
return G.v().soot_jimple_toolkits_scalar_pre_BusyCodeMotion();
}
private static final String PREFIX = "$bcm";
/**
* performs the busy code motion.
*/
protected void internalTransform(Body b, String phaseName, Map opts) {
BCMOptions options = new BCMOptions(opts);
HashMap expToHelper = new HashMap();
Chain unitChain = b.getUnits();
if (Options.v().verbose()) {
logger.debug("[" + b.getMethod().getName() + "] performing Busy Code Motion...");
}
CriticalEdgeRemover.v().transform(b, phaseName + ".cer");
UnitGraph graph = new BriefUnitGraph(b);
/* map each unit to its RHS. only take binary expressions */
Map unitToEquivRhs = new UnitMap(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 unitToNoExceptionEquivRhs = new UnitMap(b, graph.size() + 1, 0.7f) {
protected EquivalentValue mapTo(Unit unit) {
Value tmp = SootFilter.binopRhs(unit);
tmp = SootFilter.noExceptionThrowing(tmp);
return SootFilter.equiVal(tmp);
}
};
/* 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 = new UpSafetyAnalysis(graph, unitToEquivRhs, sideEffect);
DownSafetyAnalysis downSafe = new DownSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect);
EarliestnessComputation earliest = new EarliestnessComputation(graph, upSafe, downSafe, sideEffect);
LocalCreation localCreation = new LocalCreation(b.getLocals(), PREFIX);
Iterator unitIt = unitChain.snapshotIterator();
{ /* insert the computations at the earliest positions */
while (unitIt.hasNext()) {
Unit currentUnit = unitIt.next();
for (EquivalentValue equiVal : earliest.getFlowBefore(currentUnit)) {
// Value exp = equiVal.getValue();
/* get the unic helper-name for this expression */
Local helper = expToHelper.get(equiVal);
// Make sure not to place any stuff inside the identity block at
// the beginning of the method
if (currentUnit instanceof IdentityStmt) {
currentUnit = getFirstNonIdentityStmt(b);
}
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 */
unitIt = unitChain.iterator();
while (unitIt.hasNext()) {
Unit currentUnit = unitIt.next();
EquivalentValue rhs = unitToEquivRhs.get(currentUnit);
if (rhs != null) {
Local helper = expToHelper.get(rhs);
if (helper != null) {
((AssignStmt) currentUnit).setRightOp(helper);
}
}
}
}
if (Options.v().verbose()) {
logger.debug("[" + b.getMethod().getName() + "] Busy Code Motion done!");
}
}
private Unit getFirstNonIdentityStmt(Body b) {
for (Unit u : b.getUnits()) {
if (!(u instanceof IdentityStmt)) {
return u;
}
}
return null;
}
}