package soot.jimple.toolkits.thread.synchronization;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import soot.*;
import soot.jimple.Stmt;
import soot.jimple.toolkits.pointer.FullObjectSet;
import soot.jimple.toolkits.pointer.SideEffectAnalysis;
import soot.jimple.toolkits.pointer.RWSet;
import soot.jimple.toolkits.pointer.Union;
import soot.jimple.toolkits.pointer.UnionFactory;
import soot.toolkits.graph.UnitGraph;
import soot.toolkits.scalar.ArraySparseSet;
import soot.toolkits.scalar.FlowSet;
import soot.toolkits.scalar.BackwardFlowAnalysis;
/**
* @author Richard L. Halpert
* StrayRWFinder - Analysis to locate reads/writes to shared data that appear outside synchronization
*/
public class StrayRWFinder extends BackwardFlowAnalysis
{
FlowSet emptySet = new ArraySparseSet();
Map unitToGenerateSet;
Body body;
SideEffectAnalysis sea;
List tns;
StrayRWFinder(UnitGraph graph, Body b, List tns)
{
super(graph);
body = b;
this.tns = tns;
if( G.v().Union_factory == null ) {
G.v().Union_factory = new UnionFactory() {
public Union newUnion() { return FullObjectSet.v(); }
};
}
sea = Scene.v().getSideEffectAnalysis();
sea.findNTRWSets( body.getMethod() );
doAnalysis();
}
/**
* All INs are initialized to the empty set.
**/
protected Object newInitialFlow()
{
return emptySet.clone();
}
/**
* IN(Start) is the empty set
**/
protected Object entryInitialFlow()
{
return emptySet.clone();
}
/**
* OUT is the same as (IN minus killSet) plus the genSet.
**/
protected void flowThrough(Object inValue, Object unit, Object outValue)
{
FlowSet
in = (FlowSet) inValue,
out = (FlowSet) outValue;
RWSet stmtRead = sea.readSet( body.getMethod(), (Stmt) unit );
RWSet stmtWrite = sea.writeSet( body.getMethod(), (Stmt) unit );
Boolean addSelf = Boolean.FALSE;
Iterator tnIt = tns.iterator();
while(tnIt.hasNext())
{
CriticalSection tn = (CriticalSection) tnIt.next();
if(stmtRead.hasNonEmptyIntersection(tn.write) ||
stmtWrite.hasNonEmptyIntersection(tn.read) ||
stmtWrite.hasNonEmptyIntersection(tn.write))
addSelf = Boolean.TRUE;
}
in.copy(out);
if(addSelf.booleanValue())
{
CriticalSection tn = new CriticalSection(false, body.getMethod(), 0);
tn.entermonitor = (Stmt) unit;
tn.units.add((Unit) unit);
tn.read.union(stmtRead);
tn.write.union(stmtWrite);
out.add(tn);
}
}
/**
* union, except for transactions in progress. They get joined
**/
protected void merge(Object in1, Object in2, Object out)
{
FlowSet
inSet1 = ((FlowSet) in1).clone(),
inSet2 = ((FlowSet) in2).clone(),
outSet = (FlowSet) out;
/*
boolean hasANull1 = false;
Transaction tn1 = null;
Iterator inIt1 = inSet1.iterator();
while(inIt1.hasNext())
{
tn1 = (Transaction) inIt1.next();
if(tn1.entermonitor == null)
{
hasANull1 = true;
break;
}
}
boolean hasANull2 = false;
Transaction tn2 = null;
Iterator inIt2 = inSet2.iterator();
while(inIt2.hasNext())
{
tn2 = (Transaction) inIt2.next();
if(tn2.entermonitor == null)
{
hasANull2 = true;
break;
}
}
if(hasANull1 && hasANull2)
{
inSet1.remove(tn1);
Iterator itends = tn1.exitmonitors.iterator();
while(itends.hasNext())
{
Stmt stmt = (Stmt) itends.next();
if(!tn2.exitmonitors.contains(stmt))
tn2.exitmonitors.add(stmt);
}
tn2.read.union(tn1.read);
tn2.write.union(tn1.write);
}
*/
inSet1.union(inSet2, outSet);
}
protected void copy(Object source, Object dest)
{
FlowSet
sourceSet = (FlowSet) source,
destSet = (FlowSet) dest;
sourceSet.copy(destSet);
}
}