use of soot.EquivalentValue in project soot by Sable.
the class DeadlockDetector method reorderLocksets.
public void reorderLocksets(Map<Value, Integer> lockToLockNum, MutableEdgeLabelledDirectedGraph<Integer, CriticalSection> lockOrder) {
for (CriticalSection tn : criticalSections) {
// Get the portion of the lock order that is visible to tn
HashMutableDirectedGraph<Integer> visibleOrder = new HashMutableDirectedGraph<Integer>();
if (tn.group != null) {
for (CriticalSection otherTn : criticalSections) {
// Check if otherTn and tn share a static lock
boolean tnsShareAStaticLock = false;
for (EquivalentValue tnLockEqVal : tn.lockset) {
Integer tnLockNum = lockToLockNum.get(tnLockEqVal.getValue());
if (tnLockNum < 0) {
// this is a static lock... see if some lock in labelTn has the same #
if (otherTn.group != null) {
for (EquivalentValue otherTnLockEqVal : otherTn.lockset) {
if (Objects.equals(lockToLockNum.get(otherTnLockEqVal.getValue()), tnLockNum)) {
tnsShareAStaticLock = true;
}
}
} else {
// not really... but we want to skip this one
tnsShareAStaticLock = true;
}
}
}
if (// if tns don't share any static lock, or if tns are the same one
!tnsShareAStaticLock || tn == otherTn) {
// add these orderings to tn's visible order
DirectedGraph<Integer> orderings = lockOrder.getEdgesForLabel(otherTn);
for (Integer node1 : orderings) {
if (!visibleOrder.containsNode(node1)) {
visibleOrder.addNode(node1);
}
for (Integer node2 : orderings.getSuccsOf(node1)) {
if (!visibleOrder.containsNode(node2)) {
visibleOrder.addNode(node2);
}
visibleOrder.addEdge(node1, node2);
}
}
}
}
logger.debug("VISIBLE ORDER FOR " + tn.name);
visibleOrder.printGraph();
// Order locks in tn's lockset according to the visible order (insertion sort)
List<EquivalentValue> newLockset = new ArrayList<EquivalentValue>();
for (EquivalentValue lockEqVal : tn.lockset) {
Value lockToInsert = lockEqVal.getValue();
Integer lockNumToInsert = lockToLockNum.get(lockToInsert);
int i = 0;
while (i < newLockset.size()) {
EquivalentValue existingLockEqVal = newLockset.get(i);
Value existingLock = existingLockEqVal.getValue();
Integer existingLockNum = lockToLockNum.get(existingLock);
if (visibleOrder.containsEdge(lockNumToInsert, existingLockNum) || // !visibleOrder.containsEdge(existingLockNum, lockNumToInsert) ) // if(! existing before toinsert )
lockNumToInsert < existingLockNum) {
break;
}
i++;
}
newLockset.add(i, lockEqVal);
}
logger.debug("reordered from " + LockAllocator.locksetToLockNumString(tn.lockset, lockToLockNum) + " to " + LockAllocator.locksetToLockNumString(newLockset, lockToLockNum));
tn.lockset = newLockset;
}
}
}
use of soot.EquivalentValue in project soot by Sable.
the class LockAllocationBodyTransformer method getLockFor.
public static Value getLockFor(EquivalentValue lockEqVal) {
Value lock = lockEqVal.getValue();
if (lock instanceof InstanceFieldRef)
return lock;
if (// it would be better to lock the array
lock instanceof ArrayRef)
// ref for each value of the index!
return ((ArrayRef) lock).getBase();
if (lock instanceof Local)
return lock;
if (lock instanceof StaticFieldRef || lock instanceof NewStaticLock) {
if (lockEqValToLock.containsKey(lockEqVal))
return lockEqValToLock.get(lockEqVal);
SootClass lockClass = null;
if (lock instanceof StaticFieldRef) {
StaticFieldRef sfrLock = (StaticFieldRef) lock;
lockClass = sfrLock.getField().getDeclaringClass();
} else if (lock instanceof NewStaticLock) {
DeadlockAvoidanceEdge dae = (DeadlockAvoidanceEdge) lock;
lockClass = dae.getLockClass();
}
SootMethod clinitMethod = null;
JimpleBody clinitBody = null;
Stmt firstStmt = null;
boolean addingNewClinit = !lockClass.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);
lockClass.addMethod(clinitMethod);
} else {
clinitMethod = lockClass.getMethod("void <clinit>()");
clinitBody = (JimpleBody) clinitMethod.getActiveBody();
firstStmt = clinitBody.getFirstNonIdentityStmt();
}
PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
Local lockLocal = Jimple.v().newLocal("objectLockLocal" + lockNumber, RefType.v("java.lang.Object"));
// lockNumber is increased below
// TODO: add name conflict
clinitBody.getLocals().add(lockLocal);
// avoidance code
// assign new object to lock obj
Stmt newStmt = Jimple.v().newAssignStmt(lockLocal, 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(lockLocal, 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)
SootField actualLockObject = Scene.v().makeSootField("objectLockGlobal" + lockNumber, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
lockNumber++;
lockClass.addField(actualLockObject);
StaticFieldRef actualLockSfr = Jimple.v().newStaticFieldRef(actualLockObject.makeRef());
Stmt assignStmt = Jimple.v().newAssignStmt(actualLockSfr, lockLocal);
if (addingNewClinit)
clinitUnits.add(assignStmt);
else
clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
if (addingNewClinit)
clinitUnits.add(Jimple.v().newReturnVoidStmt());
lockEqValToLock.put(lockEqVal, actualLockSfr);
return actualLockSfr;
}
throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef, ArrayRef, or Local");
}
use of soot.EquivalentValue in project soot by Sable.
the class CachedEquivalentValue method equals.
public boolean equals(Object o) {
if (this.getClass() != o.getClass()) {
return false;
}
EquivalentValue ev = (EquivalentValue) o;
Value v = ev.getValue();
Boolean b = isEquivalent.get(v);
if (b == null) {
b = super.equals(o);
isEquivalent.put(v, b);
}
return b;
}
use of soot.EquivalentValue in project soot by Sable.
the class LocalMustAliasAnalysis method numberOfRhs.
private Integer numberOfRhs(Value rhs) {
EquivalentValue equivValue = new EquivalentValue(rhs);
if (localsAndFieldRefs.contains(equivValue)) {
rhs = equivValue;
}
Integer num = rhsToNumber.get(rhs);
if (num == null) {
num = nextNumber++;
rhsToNumber.put(rhs, num);
}
return num;
}
use of soot.EquivalentValue in project soot by Sable.
the class LocalMustAliasAnalysis method trackableFields.
/**
* Computes the set of {@link EquivalentValue}s of all field references that are used
* in this method but not set by the method or any method transitively called by this method.
*/
private Set<Value> trackableFields() {
Set<Value> usedFieldRefs = new HashSet<Value>();
// add all field references that are in use boxes
for (Unit unit : this.graph) {
Stmt s = (Stmt) unit;
List<ValueBox> useBoxes = s.getUseBoxes();
for (ValueBox useBox : useBoxes) {
Value val = useBox.getValue();
if (val instanceof FieldRef) {
FieldRef fieldRef = (FieldRef) val;
if (fieldRef.getType() instanceof RefLikeType)
usedFieldRefs.add(new EquivalentValue(fieldRef));
}
}
}
// prune all fields that are written to
if (!usedFieldRefs.isEmpty()) {
if (!Scene.v().hasCallGraph()) {
throw new IllegalStateException("No call graph found!");
}
CallGraph cg = Scene.v().getCallGraph();
ReachableMethods reachableMethods = new ReachableMethods(cg, Collections.<MethodOrMethodContext>singletonList(container));
reachableMethods.update();
for (Iterator<MethodOrMethodContext> iterator = reachableMethods.listener(); iterator.hasNext(); ) {
SootMethod m = (SootMethod) iterator.next();
if (m.hasActiveBody() && // exclude static initializer of same class (assume that it has already been executed)
!(m.getName().equals(SootMethod.staticInitializerName) && m.getDeclaringClass().equals(container.getDeclaringClass()))) {
for (Unit u : m.getActiveBody().getUnits()) {
List<ValueBox> defBoxes = u.getDefBoxes();
for (ValueBox defBox : defBoxes) {
Value value = defBox.getValue();
if (value instanceof FieldRef) {
usedFieldRefs.remove(new EquivalentValue(value));
}
}
}
}
}
}
return usedFieldRefs;
}
Aggregations