use of soot.toolkits.scalar.Pair in project soot by Sable.
the class VirtualCalls method resolveLibrarySignature.
protected void resolveLibrarySignature(Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue<SootMethod> targets, boolean appOnly, RefType base) {
FastHierarchy fastHierachy = Scene.v().getOrMakeFastHierarchy();
assert (declaredType instanceof RefType);
Pair<Type, NumberedString> pair = new Pair<Type, NumberedString>(base, subSig);
{
Set<Pair<Type, NumberedString>> types = baseToPossibleSubTypes.get(pair);
// just retrieve the previous result.
if (types != null) {
for (Pair<Type, NumberedString> tuple : types) {
Type st = tuple.getO1();
if (!fastHierachy.canStoreType(st, declaredType)) {
resolve(st, st, sigType, subSig, container, targets, appOnly);
} else {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
}
}
return;
}
}
Set<Pair<Type, NumberedString>> types = new HashSet<Pair<Type, NumberedString>>();
// get return type; method name; parameter types
String[] split = subSig.getString().replaceAll("(.*) (.*)\\((.*)\\)", "$1;$2;$3").split(";");
Type declaredReturnType = Scene.v().getType(split[0]);
String declaredName = split[1];
List<Type> declaredParamTypes = new ArrayList<Type>();
// separate the parameter types
if (split.length == 3) {
for (String type : split[2].split(",")) {
declaredParamTypes.add(Scene.v().getType(type));
}
}
Chain<SootClass> classes = Scene.v().getClasses();
for (SootClass sc : classes) {
for (SootMethod sm : sc.getMethods()) {
if (sm.isConcrete() || sm.isNative()) {
// method name has to match
if (!sm.getName().equals(declaredName))
continue;
// type or a sub type of it
if (!fastHierachy.canStoreType(sm.getReturnType(), declaredReturnType))
continue;
List<Type> paramTypes = sm.getParameterTypes();
// ones (same type or super type).
if (declaredParamTypes.size() != paramTypes.size())
continue;
boolean check = true;
for (int i = 0; i < paramTypes.size(); i++) {
if (!fastHierachy.canStoreType(declaredParamTypes.get(i), paramTypes.get(i))) {
check = false;
break;
}
}
if (check) {
Type st = sc.getType();
if (!fastHierachy.canStoreType(st, declaredType)) {
// therefore not used in library client
if (!sc.isFinal()) {
NumberedString newSubSig = sm.getNumberedSubSignature();
resolve(st, st, sigType, newSubSig, container, targets, appOnly);
types.add(new Pair<Type, NumberedString>(st, newSubSig));
}
} else {
resolve(st, declaredType, sigType, subSig, container, targets, appOnly);
types.add(new Pair<Type, NumberedString>(st, subSig));
}
}
}
}
}
baseToPossibleSubTypes.putAll(pair, types);
}
use of soot.toolkits.scalar.Pair in project soot by Sable.
the class IFDSPossibleTypes method createFlowFunctionsFactory.
public FlowFunctions<Unit, Pair<Value, Type>, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Pair<Value, Type>, SootMethod>() {
public FlowFunction<Pair<Value, Type>> getNormalFlowFunction(Unit src, Unit dest) {
if (src instanceof DefinitionStmt) {
DefinitionStmt defnStmt = (DefinitionStmt) src;
if (defnStmt.containsInvokeExpr())
return Identity.v();
final Value right = defnStmt.getRightOp();
final Value left = defnStmt.getLeftOp();
// won't track primitive-typed variables
if (right.getType() instanceof PrimType)
return Identity.v();
if (right instanceof Constant || right instanceof NewExpr) {
return new FlowFunction<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
if (source == zeroValue()) {
Set<Pair<Value, Type>> res = new LinkedHashSet<Pair<Value, Type>>();
res.add(new Pair<Value, Type>(left, right.getType()));
res.add(zeroValue());
return res;
} else if (source.getO1() instanceof Local && source.getO1().equivTo(left)) {
// strong update for local variables
return Collections.emptySet();
} else {
return Collections.singleton(source);
}
}
};
} else if (right instanceof Ref || right instanceof Local) {
return new FlowFunction<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(final Pair<Value, Type> source) {
Value value = source.getO1();
if (source.getO1() instanceof Local && source.getO1().equivTo(left)) {
// strong update for local variables
return Collections.emptySet();
} else if (maybeSameLocation(value, right)) {
return new LinkedHashSet<Pair<Value, Type>>() {
{
add(new Pair<Value, Type>(left, source.getO2()));
add(source);
}
};
} else {
return Collections.singleton(source);
}
}
private boolean maybeSameLocation(Value v1, Value v2) {
if (!(v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) && !(v1 instanceof ArrayRef && v2 instanceof ArrayRef)) {
return v1.equivTo(v2);
}
if (v1 instanceof InstanceFieldRef && v2 instanceof InstanceFieldRef) {
InstanceFieldRef ifr1 = (InstanceFieldRef) v1;
InstanceFieldRef ifr2 = (InstanceFieldRef) v2;
if (!ifr1.getField().getName().equals(ifr2.getField().getName()))
return false;
Local base1 = (Local) ifr1.getBase();
Local base2 = (Local) ifr2.getBase();
PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
PointsToSet pts1 = pta.reachingObjects(base1);
PointsToSet pts2 = pta.reachingObjects(base2);
return pts1.hasNonEmptyIntersection(pts2);
} else {
// v1 instanceof ArrayRef && v2 instanceof ArrayRef
ArrayRef ar1 = (ArrayRef) v1;
ArrayRef ar2 = (ArrayRef) v2;
Local base1 = (Local) ar1.getBase();
Local base2 = (Local) ar2.getBase();
PointsToAnalysis pta = Scene.v().getPointsToAnalysis();
PointsToSet pts1 = pta.reachingObjects(base1);
PointsToSet pts2 = pta.reachingObjects(base2);
return pts1.hasNonEmptyIntersection(pts2);
}
}
};
}
}
return Identity.v();
}
public FlowFunction<Pair<Value, Type>> getCallFlowFunction(final Unit src, final SootMethod dest) {
Stmt stmt = (Stmt) src;
InvokeExpr ie = stmt.getInvokeExpr();
final List<Value> callArgs = ie.getArgs();
final List<Local> paramLocals = new ArrayList<Local>();
for (int i = 0; i < dest.getParameterCount(); i++) {
paramLocals.add(dest.getActiveBody().getParameterLocal(i));
}
return new FlowFunction<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
if (!dest.getName().equals("<clinit>") && !dest.getSubSignature().equals("void run()")) {
Value value = source.getO1();
int argIndex = callArgs.indexOf(value);
if (argIndex > -1) {
return Collections.singleton(new Pair<Value, Type>(paramLocals.get(argIndex), source.getO2()));
}
}
return Collections.emptySet();
}
};
}
public FlowFunction<Pair<Value, Type>> getReturnFlowFunction(Unit callSite, SootMethod callee, Unit exitStmt, Unit retSite) {
if (exitStmt instanceof ReturnStmt) {
ReturnStmt returnStmt = (ReturnStmt) exitStmt;
Value op = returnStmt.getOp();
if (op instanceof Local) {
if (callSite instanceof DefinitionStmt) {
DefinitionStmt defnStmt = (DefinitionStmt) callSite;
Value leftOp = defnStmt.getLeftOp();
if (leftOp instanceof Local) {
final Local tgtLocal = (Local) leftOp;
final Local retLocal = (Local) op;
return new FlowFunction<Pair<Value, Type>>() {
public Set<Pair<Value, Type>> computeTargets(Pair<Value, Type> source) {
if (source == retLocal)
return Collections.singleton(new Pair<Value, Type>(tgtLocal, source.getO2()));
return Collections.emptySet();
}
};
}
}
}
}
return KillAll.v();
}
public FlowFunction<Pair<Value, Type>> getCallToReturnFlowFunction(Unit call, Unit returnSite) {
return Identity.v();
}
};
}
use of soot.toolkits.scalar.Pair in project soot by Sable.
the class IFDSReachingDefinitions method createFlowFunctionsFactory.
@Override
public FlowFunctions<Unit, Pair<Value, Set<DefinitionStmt>>, SootMethod> createFlowFunctionsFactory() {
return new FlowFunctions<Unit, Pair<Value, Set<DefinitionStmt>>, SootMethod>() {
@Override
public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getNormalFlowFunction(final Unit curr, Unit succ) {
if (curr instanceof DefinitionStmt) {
final DefinitionStmt assignment = (DefinitionStmt) curr;
return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {
@Override
public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
if (source != zeroValue()) {
if (source.getO1().equivTo(assignment.getLeftOp())) {
return Collections.emptySet();
}
return Collections.singleton(source);
} else {
LinkedHashSet<Pair<Value, Set<DefinitionStmt>>> res = new LinkedHashSet<Pair<Value, Set<DefinitionStmt>>>();
res.add(new Pair<Value, Set<DefinitionStmt>>(assignment.getLeftOp(), Collections.<DefinitionStmt>singleton(assignment)));
return res;
}
}
};
}
return Identity.v();
}
@Override
public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getCallFlowFunction(Unit callStmt, final SootMethod destinationMethod) {
Stmt stmt = (Stmt) callStmt;
InvokeExpr invokeExpr = stmt.getInvokeExpr();
final List<Value> args = invokeExpr.getArgs();
final List<Local> localArguments = new ArrayList<Local>(args.size());
for (Value value : args) {
if (value instanceof Local)
localArguments.add((Local) value);
else
localArguments.add(null);
}
return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {
@Override
public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
if (!destinationMethod.getName().equals("<clinit>") && !destinationMethod.getSubSignature().equals("void run()"))
if (localArguments.contains(source.getO1())) {
int paramIndex = args.indexOf(source.getO1());
Pair<Value, Set<DefinitionStmt>> pair = new Pair<Value, Set<DefinitionStmt>>(new EquivalentValue(Jimple.v().newParameterRef(destinationMethod.getParameterType(paramIndex), paramIndex)), source.getO2());
return Collections.singleton(pair);
}
return Collections.emptySet();
}
};
}
@Override
public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getReturnFlowFunction(final Unit callSite, SootMethod calleeMethod, final Unit exitStmt, Unit returnSite) {
if (!(callSite instanceof DefinitionStmt))
return KillAll.v();
if (exitStmt instanceof ReturnVoidStmt)
return KillAll.v();
return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {
@Override
public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
if (exitStmt instanceof ReturnStmt) {
ReturnStmt returnStmt = (ReturnStmt) exitStmt;
if (returnStmt.getOp().equivTo(source.getO1())) {
DefinitionStmt definitionStmt = (DefinitionStmt) callSite;
Pair<Value, Set<DefinitionStmt>> pair = new Pair<Value, Set<DefinitionStmt>>(definitionStmt.getLeftOp(), source.getO2());
return Collections.singleton(pair);
}
}
return Collections.emptySet();
}
};
}
@Override
public FlowFunction<Pair<Value, Set<DefinitionStmt>>> getCallToReturnFlowFunction(Unit callSite, Unit returnSite) {
if (!(callSite instanceof DefinitionStmt))
return Identity.v();
final DefinitionStmt definitionStmt = (DefinitionStmt) callSite;
return new FlowFunction<Pair<Value, Set<DefinitionStmt>>>() {
@Override
public Set<Pair<Value, Set<DefinitionStmt>>> computeTargets(Pair<Value, Set<DefinitionStmt>> source) {
if (source.getO1().equivTo(definitionStmt.getLeftOp())) {
return Collections.emptySet();
} else {
return Collections.singleton(source);
}
}
};
}
};
}
use of soot.toolkits.scalar.Pair in project soot by Sable.
the class LockAllocationBodyTransformer method internalTransform.
protected void internalTransform(Body b, FlowSet fs, List<CriticalSectionGroup> groups, boolean[] insertedGlobalLock) {
//
JimpleBody j = (JimpleBody) b;
SootMethod thisMethod = b.getMethod();
PatchingChain<Unit> units = b.getUnits();
Iterator<Unit> unitIt = units.iterator();
Unit firstUnit = j.getFirstNonIdentityStmt();
Unit lastUnit = units.getLast();
// Objects of synchronization, plus book keeping
Local[] lockObj = new Local[groups.size()];
boolean[] addedLocalLockObj = new boolean[groups.size()];
SootField[] globalLockObj = new SootField[groups.size()];
for (int i = 1; i < groups.size(); i++) {
lockObj[i] = Jimple.v().newLocal("lockObj" + i, RefType.v("java.lang.Object"));
addedLocalLockObj[i] = false;
globalLockObj[i] = null;
}
// Get references to them if they do already exist.
for (int i = 1; i < groups.size(); i++) {
CriticalSectionGroup tnGroup = groups.get(i);
if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
if (!insertedGlobalLock[i]) {
// use it!
try {
globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
// field already exists
} catch (RuntimeException re) {
// field does not yet exist (or, as a pre-existing
// error, there is more than one field by this name)
globalLockObj[i] = Scene.v().makeSootField("globalLockObj" + i, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
Scene.v().getMainClass().addField(globalLockObj[i]);
}
insertedGlobalLock[i] = true;
} else {
globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
}
}
}
// local lock object into the global lock object for use by other fns.
if (// thisMethod.getSubSignature().equals("void
!addedGlobalLockDefs) // <clinit>()") &&
// thisMethod.getDeclaringClass() ==
// Scene.v().getMainClass())
{
// Either get or add the <clinit> method to the main class
SootClass mainClass = Scene.v().getMainClass();
SootMethod clinitMethod = null;
JimpleBody clinitBody = null;
Stmt firstStmt = null;
boolean addingNewClinit = !mainClass.declaresMethod("void <clinit>()");
if (addingNewClinit) {
clinitMethod = Scene.v().makeSootMethod("<clinit>", new ArrayList(), VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
clinitBody = Jimple.v().newBody(clinitMethod);
clinitMethod.setActiveBody(clinitBody);
mainClass.addMethod(clinitMethod);
} else {
clinitMethod = mainClass.getMethod("void <clinit>()");
clinitBody = (JimpleBody) clinitMethod.getActiveBody();
firstStmt = clinitBody.getFirstNonIdentityStmt();
}
PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
for (int i = 1; i < groups.size(); i++) {
CriticalSectionGroup tnGroup = groups.get(i);
// if( useGlobalLock[i - 1] )
if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
// add local lock obj
// addedLocalLockObj[i] = true;
// TODO: add name
clinitBody.getLocals().add(lockObj[i]);
// conflict
// avoidance code
// assign new object to lock obj
Stmt newStmt = Jimple.v().newAssignStmt(lockObj[i], Jimple.v().newNewExpr(RefType.v("java.lang.Object")));
if (addingNewClinit)
clinitUnits.add(newStmt);
else
clinitUnits.insertBeforeNoRedirect(newStmt, firstStmt);
// initialize new object
SootClass objectClass = Scene.v().loadClassAndSupport("java.lang.Object");
RefType type = RefType.v(objectClass);
SootMethod initMethod = objectClass.getMethod("void <init>()");
Stmt initStmt = Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(lockObj[i], initMethod.makeRef(), Collections.EMPTY_LIST));
if (addingNewClinit)
clinitUnits.add(initStmt);
else
clinitUnits.insertBeforeNoRedirect(initStmt, firstStmt);
// copy new object to global static lock object (for use by
// other fns)
Stmt assignStmt = Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(globalLockObj[i].makeRef()), lockObj[i]);
if (addingNewClinit)
clinitUnits.add(assignStmt);
else
clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
}
}
if (addingNewClinit)
clinitUnits.add(Jimple.v().newReturnVoidStmt());
addedGlobalLockDefs = true;
}
int tempNum = 1;
// Iterate through all of the transactions in the current method
Iterator fsIt = fs.iterator();
Stmt newPrep = null;
while (fsIt.hasNext()) {
CriticalSection tn = ((SynchronizedRegionFlowPair) fsIt.next()).tn;
if (tn.setNumber == -1)
// this tn should be deleted... for now just skip it!
continue;
if (tn.wholeMethod) {
// remove
thisMethod.setModifiers(thisMethod.getModifiers() & ~(Modifier.SYNCHRONIZED));
// synchronized
// modifier
// for
// this
// method
}
// depends on type of locking
Local clo = null;
// current synchronized region
SynchronizedRegion csr = null;
int lockNum = 0;
boolean moreLocks = true;
while (moreLocks) {
// needed for this transaction, then create one.
if (tn.group.useDynamicLock) {
// adds
Value lock = getLockFor((EquivalentValue) tn.lockObject);
// needed
if (lock instanceof Ref) {
if (lock instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) lock;
if (ifr.getBase() instanceof FakeJimpleLocal)
lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
}
if (!b.getLocals().contains(lockObj[tn.setNumber]))
b.getLocals().add(lockObj[tn.setNumber]);
newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], lock);
if (tn.wholeMethod)
units.insertBeforeNoRedirect(newPrep, firstUnit);
else
units.insertBefore(newPrep, tn.entermonitor);
clo = lockObj[tn.setNumber];
} else if (lock instanceof Local)
clo = (Local) lock;
else
throw new RuntimeException("Unknown type of lock (" + lock + "): expected Ref or Local");
csr = tn;
moreLocks = false;
} else if (tn.group.useLocksets) {
// adds
Value lock = getLockFor((EquivalentValue) tn.lockset.get(lockNum));
// needed
if (lock instanceof FieldRef) {
if (lock instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) lock;
if (ifr.getBase() instanceof FakeJimpleLocal)
lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
}
// add a local variable for this lock
Local lockLocal = Jimple.v().newLocal("locksetObj" + tempNum, RefType.v("java.lang.Object"));
tempNum++;
b.getLocals().add(lockLocal);
// make it refer to the right lock object
newPrep = Jimple.v().newAssignStmt(lockLocal, lock);
if (tn.entermonitor != null)
units.insertBefore(newPrep, tn.entermonitor);
else
units.insertBeforeNoRedirect(newPrep, tn.beginning);
// use it as the lock
clo = lockLocal;
} else if (lock instanceof Local)
clo = (Local) lock;
else
throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef or Local");
if (lockNum + 1 >= tn.lockset.size())
moreLocks = false;
else
moreLocks = true;
if (lockNum > 0) {
SynchronizedRegion nsr = new SynchronizedRegion();
nsr.beginning = csr.beginning;
for (Pair earlyEnd : csr.earlyEnds) {
Stmt earlyExitmonitor = (Stmt) earlyEnd.getO2();
// <early
nsr.earlyEnds.add(new Pair(earlyExitmonitor, null));
// exitmonitor,
// null>
}
// last stmt before exception
nsr.last = csr.last;
// handling
if (csr.end != null) {
Stmt endExitmonitor = csr.end.getO2();
nsr.after = endExitmonitor;
}
csr = nsr;
} else
csr = tn;
} else // global lock
{
if (!addedLocalLockObj[tn.setNumber])
b.getLocals().add(lockObj[tn.setNumber]);
addedLocalLockObj[tn.setNumber] = true;
newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], Jimple.v().newStaticFieldRef(globalLockObj[tn.setNumber].makeRef()));
if (tn.wholeMethod)
units.insertBeforeNoRedirect(newPrep, firstUnit);
else
units.insertBefore(newPrep, tn.entermonitor);
clo = lockObj[tn.setNumber];
csr = tn;
moreLocks = false;
}
// monitorenter/monitorexit statements with new ones
if (true) {
// Remove old prep stmt
if (csr.prepStmt != null) {
// units.remove(clr.prepStmt); // seems to trigger bugs
// in code generation?
}
// Reuse old entermonitor or insert new one, and insert prep
Stmt newEntermonitor = Jimple.v().newEnterMonitorStmt(clo);
if (csr.entermonitor != null) {
units.insertBefore(newEntermonitor, csr.entermonitor);
// redirectTraps(b, clr.entermonitor, newEntermonitor);
// // EXPERIMENTAL
units.remove(csr.entermonitor);
csr.entermonitor = newEntermonitor;
// units.insertBefore(newEntermonitor, newPrep); //
// already inserted
// clr.prepStmt = newPrep;
} else {
units.insertBeforeNoRedirect(newEntermonitor, csr.beginning);
csr.entermonitor = newEntermonitor;
// units.insertBefore(newEntermonitor, newPrep); //
// already inserted
// clr.prepStmt = newPrep;
}
// For each early end, reuse or insert exitmonitor stmt
List<Pair<Stmt, Stmt>> newEarlyEnds = new ArrayList<Pair<Stmt, Stmt>>();
for (Pair<Stmt, Stmt> end : csr.earlyEnds) {
Stmt earlyEnd = end.getO1();
Stmt exitmonitor = end.getO2();
Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
if (exitmonitor != null) {
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
// seems
units.insertBefore(tmp, exitmonitor);
// to
// avoid
// code
// generation
// bugs?
}
units.insertBefore(newExitmonitor, exitmonitor);
// redirectTraps(b, exitmonitor, newExitmonitor); //
// EXPERIMENTAL
units.remove(exitmonitor);
newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
} else {
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, earlyEnd);
}
units.insertBefore(newExitmonitor, earlyEnd);
newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
}
}
csr.earlyEnds = newEarlyEnds;
// If fallthrough end, reuse or insert goto and exit
if (csr.after != null) {
Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
if (csr.end != null) {
Stmt exitmonitor = csr.end.getO2();
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, exitmonitor);
}
units.insertBefore(newExitmonitor, exitmonitor);
// redirectTraps(b, exitmonitor, newExitmonitor); //
// EXPERIMENTAL
units.remove(exitmonitor);
csr.end = new Pair<Stmt, Stmt>(csr.end.getO1(), newExitmonitor);
} else {
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, csr.after);
}
// steal
units.insertBefore(newExitmonitor, csr.after);
// jumps
// to
// end,
// send
// them
// to
// monitorexit
Stmt newGotoStmt = Jimple.v().newGotoStmt(csr.after);
units.insertBeforeNoRedirect(newGotoStmt, csr.after);
csr.end = new Pair<Stmt, Stmt>(newGotoStmt, newExitmonitor);
csr.last = newGotoStmt;
}
}
// If exceptional end, reuse it, else insert it and traps
Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
if (csr.exceptionalEnd != null) {
Stmt exitmonitor = csr.exceptionalEnd.getO2();
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, exitmonitor);
}
units.insertBefore(newExitmonitor, exitmonitor);
units.remove(exitmonitor);
csr.exceptionalEnd = new Pair<Stmt, Stmt>(csr.exceptionalEnd.getO1(), newExitmonitor);
} else {
// insert after the last end
// last end stmt (not same as last
Stmt lastEnd = null;
// stmt)
if (csr.end != null) {
lastEnd = csr.end.getO1();
} else {
for (Pair earlyEnd : csr.earlyEnds) {
Stmt end = (Stmt) earlyEnd.getO1();
if (lastEnd == null || (units.contains(lastEnd) && units.contains(end) && units.follows(end, lastEnd)))
lastEnd = end;
}
}
if (// || !units.contains(clr.last))
csr.last == null)
// last stmt and last end are
csr.last = lastEnd;
// the same
if (lastEnd == null)
throw new RuntimeException("Lock Region has no ends! Where should we put the exception handling???");
// Add throwable
Local throwableLocal = Jimple.v().newLocal("throwableLocal" + (throwableNum++), RefType.v("java.lang.Throwable"));
b.getLocals().add(throwableLocal);
// Add stmts
Stmt newCatch = Jimple.v().newIdentityStmt(throwableLocal, Jimple.v().newCaughtExceptionRef());
if (csr.last == null)
throw new RuntimeException("WHY IS clr.last NULL???");
if (newCatch == null)
throw new RuntimeException("WHY IS newCatch NULL???");
units.insertAfter(newCatch, csr.last);
units.insertAfter(newExitmonitor, newCatch);
Stmt newThrow = Jimple.v().newThrowStmt(throwableLocal);
units.insertAfter(newThrow, newExitmonitor);
// Add traps
SootClass throwableClass = Scene.v().loadClassAndSupport("java.lang.Throwable");
b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, newExitmonitor, newThrow, newCatch));
b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, csr.beginning, lastEnd, newCatch));
csr.exceptionalEnd = new Pair<Stmt, Stmt>(newThrow, newExitmonitor);
}
}
lockNum++;
}
// deal with waits and notifys
{
for (Unit uNotify : tn.notifys) {
Stmt sNotify = (Stmt) uNotify;
Stmt newNotify = Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(clo, sNotify.getInvokeExpr().getMethodRef().declaringClass().getMethod("void notifyAll()").makeRef(), Collections.EMPTY_LIST));
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, sNotify);
units.insertBefore(newNotify, tmp);
} else
units.insertBefore(newNotify, sNotify);
redirectTraps(b, sNotify, newNotify);
units.remove(sNotify);
}
// Replace base object of calls to wait with appropriate lockobj
for (Unit uWait : tn.waits) {
Stmt sWait = (Stmt) uWait;
// WHAT
((InstanceInvokeExpr) sWait.getInvokeExpr()).setBase(clo);
// LOCKS???
if (newPrep != null)
units.insertBefore((Stmt) newPrep.clone(), sWait);
}
}
}
}
use of soot.toolkits.scalar.Pair in project soot by Sable.
the class StoreChainOptimizer method internalTransform.
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
// We keep track of all the stored values
Map<Local, Pair<Unit, Unit>> stores = new HashMap<Local, Pair<Unit, Unit>>();
Set<Unit> toRemove = new HashSet<Unit>();
Unit lastPush = null;
for (Unit u : b.getUnits()) {
// If we can jump here from somewhere, do not modify this code
if (!u.getBoxesPointingToThis().isEmpty()) {
stores.clear();
lastPush = null;
} else // Emulate pushing stuff on the stack
if (u instanceof PushInst) {
lastPush = u;
} else if (u instanceof StoreInst && lastPush != null) {
StoreInst si = (StoreInst) u;
Pair<Unit, Unit> pushStorePair = stores.get(si.getLocal());
if (pushStorePair != null) {
// We can remove the push and the store
toRemove.add(pushStorePair.getO1());
toRemove.add(pushStorePair.getO2());
}
stores.put(si.getLocal(), new Pair<Unit, Unit>(lastPush, u));
} else {
// We're outside of the trivial initialization chain
stores.clear();
lastPush = null;
}
}
b.getUnits().removeAll(toRemove);
}
Aggregations