use of soot.jimple.toolkits.pointer.CodeBlockRWSet in project soot by Sable.
the class CriticalSectionInterferenceGraph method calculateGroups.
public void calculateGroups() {
nextGroup = 1;
groups = new ArrayList<CriticalSectionGroup>();
// dummy group
groups.add(new CriticalSectionGroup(0));
if (// use one group for all transactions
optionOneGlobalLock) {
CriticalSectionGroup onlyGroup = new CriticalSectionGroup(nextGroup);
Iterator<CriticalSection> tnIt1 = criticalSections.iterator();
while (tnIt1.hasNext()) {
CriticalSection tn1 = tnIt1.next();
onlyGroup.add(tn1);
}
nextGroup++;
groups.add(onlyGroup);
} else // calculate separate groups for transactions
{
Iterator<CriticalSection> tnIt1 = criticalSections.iterator();
while (tnIt1.hasNext()) {
CriticalSection tn1 = tnIt1.next();
// if this transaction has somehow already been marked for deletion
if (tn1.setNumber == -1)
continue;
// if this transaction is empty
if (tn1.read.size() == 0 && tn1.write.size() == 0 && !optionLeaveOriginalLocks) {
// this transaction has no effect except on locals... we don't need it!
// AKA delete the transactional region (but don't really so long as we are using
tn1.setNumber = -1;
// the synchronized keyword in our language... because java guarantees memory
// barriers at certain points in synchronized blocks)
} else {
Iterator<CriticalSection> tnIt2 = criticalSections.iterator();
while (tnIt2.hasNext()) {
CriticalSection tn2 = tnIt2.next();
// check if this transactional region is going to be deleted
if (tn2.setNumber == -1)
continue;
// check if these two transactions can't ever be in parallel
if (!mayHappenInParallel(tn1, tn2))
continue;
// check for RW or WW data dependencies.
// or, for optionLeaveOriginalLocks, check type compatibility
SootClass classOne = null;
SootClass classTwo = null;
boolean typeCompatible = false;
boolean emptyEdge = false;
if (tn1.origLock != null && tn2.origLock != null) {
// Check if edge is empty
if (tn1.origLock == null || tn2.origLock == null)
emptyEdge = true;
else if (!(tn1.origLock instanceof Local) || !(tn2.origLock instanceof Local))
emptyEdge = !tn1.origLock.equals(tn2.origLock);
else
emptyEdge = !pta.reachingObjects((Local) tn1.origLock).hasNonEmptyIntersection(pta.reachingObjects((Local) tn2.origLock));
// Check if types are compatible
RefLikeType typeOne = (RefLikeType) tn1.origLock.getType();
RefLikeType typeTwo = (RefLikeType) tn2.origLock.getType();
classOne = (typeOne instanceof RefType) ? ((RefType) typeOne).getSootClass() : null;
classTwo = (typeTwo instanceof RefType) ? ((RefType) typeTwo).getSootClass() : null;
if (classOne != null && classTwo != null) {
Hierarchy h = Scene.v().getActiveHierarchy();
if (classOne.isInterface()) {
if (classTwo.isInterface()) {
typeCompatible = h.getSubinterfacesOfIncluding(classOne).contains(classTwo) || h.getSubinterfacesOfIncluding(classTwo).contains(classOne);
} else {
typeCompatible = h.getImplementersOf(classOne).contains(classTwo);
}
} else {
if (classTwo.isInterface()) {
typeCompatible = h.getImplementersOf(classTwo).contains(classOne);
} else {
typeCompatible = (classOne != null && Scene.v().getActiveHierarchy().getSubclassesOfIncluding(classOne).contains(classTwo) || classTwo != null && Scene.v().getActiveHierarchy().getSubclassesOfIncluding(classTwo).contains(classOne));
}
}
}
}
if ((!optionLeaveOriginalLocks && (tn1.write.hasNonEmptyIntersection(tn2.write) || tn1.write.hasNonEmptyIntersection(tn2.read) || tn1.read.hasNonEmptyIntersection(tn2.write))) || (optionLeaveOriginalLocks && typeCompatible && (optionIncludeEmptyPossibleEdges || !emptyEdge))) {
// Determine the size of the intersection for GraphViz output
CodeBlockRWSet rw = null;
int size;
if (optionLeaveOriginalLocks) {
rw = new CodeBlockRWSet();
size = emptyEdge ? 0 : 1;
} else {
rw = tn1.write.intersection(tn2.write);
rw.union(tn1.write.intersection(tn2.read));
rw.union(tn1.read.intersection(tn2.write));
size = rw.size();
}
// Record this
tn1.edges.add(new CriticalSectionDataDependency(tn2, size, rw));
if (size > 0) {
// if tn1 already is in a group
if (tn1.setNumber > 0) {
// if tn2 is NOT already in a group
if (tn2.setNumber == 0) {
tn1.group.add(tn2);
} else // if tn2 is already in a group
if (tn2.setNumber > 0) {
if (// if they are equal, then they are already in the same group!
tn1.setNumber != tn2.setNumber) {
tn1.group.mergeGroups(tn2.group);
}
}
} else // if tn1 is NOT already in a group
if (tn1.setNumber == 0) {
// if tn2 is NOT already in a group
if (tn2.setNumber == 0) {
CriticalSectionGroup newGroup = new CriticalSectionGroup(nextGroup);
newGroup.add(tn1);
newGroup.add(tn2);
groups.add(newGroup);
nextGroup++;
} else // if tn2 is already in a group
if (tn2.setNumber > 0) {
tn2.group.add(tn1);
}
}
}
}
}
// If, after comparing to all other transactions, we have no group:
if (tn1.setNumber == 0) {
// delete transactional region
tn1.setNumber = -1;
}
}
}
}
}
Aggregations