package Analysis.Disjoint;
-import Analysis.OwnershipAnalysis.EffectsKey;
-import IR.FieldDescriptor;
-import IR.Flat.TempDescriptor;
+import java.util.*;
+
+import IR.*;
+import IR.Flat.*;
public class Effect {
// operation type
public static final int read = 1;
public static final int write = 2;
- public static final int strongupdate = 3;
-
- // identify a parameter index
- protected Integer paramIndex;
-
- // identify an inset var
- protected TempDescriptor insetVar;
-
- // identify an allocation site of inset var
- protected AllocSite insetAllocSite;
+ public static final int strongupdate = 4;
// identify an allocation site of affected object
- protected AllocSite affectedAllocSite;
+ protected Alloc affectedAllocSite;
// identify operation type
protected int type;
// identify a field
protected FieldDescriptor field;
- public Effect(Integer pi, AllocSite insetAS, AllocSite affectedAS, int type, FieldDescriptor field) {
- this.paramIndex = pi;
- this.insetAllocSite = insetAS;
+ // for debugging purposes, keep the compilation
+ // unit and line number of this effect--only if state
+ // is non-null later
+ protected int lineNumber;
+ protected ClassDescriptor compilationUnit;
+ protected static Hashtable<FlatNode, ClassDescriptor> fn2cd =
+ new Hashtable<FlatNode, ClassDescriptor>();
+
+
+ public Effect(Alloc affectedAS, int type, FieldDescriptor field, FlatNode currentProgramPoint) {
this.affectedAllocSite = affectedAS;
this.type = type;
this.field = field;
- }
- public Integer getParamIndex() {
- return paramIndex;
- }
- public void setParamIndex(Integer paramIndex) {
- this.paramIndex = paramIndex;
- }
+ // NOTE: this line number+compilation unit is collected for debugging,
+ // so we don't want to spend time on this unless OOODEBUG or some new
+ // option controls it. Disjoint and Pointer analysis use this currently.
+ lineNumber = -1;
+ compilationUnit = null;
+
+ // find the class the current program point belongs to
+ if( currentProgramPoint == null ) {
+ return;
+ }
+ Set<FlatNode> visited = new HashSet<FlatNode>();
+ Set<FlatNode> toVisit = new HashSet<FlatNode>();
+ toVisit.add( currentProgramPoint );
+
+ while( !toVisit.isEmpty() ) {
+ FlatNode fn = toVisit.iterator().next();
+ toVisit.remove( fn );
+ visited.add( fn );
+
+ // when we find a flat method, remember every node we visited
+ // belongs to that compilation unit
+ if( fn instanceof FlatMethod ) {
+ MethodDescriptor md = ((FlatMethod)fn).getMethod();
+ if( md != null ) {
+ ClassDescriptor cd = md.getClassDesc();
+ if( cd != null ) {
+ fn2cd.put( fn, cd );
+ }
+ }
+ }
+
+ if( fn2cd.containsKey( fn ) ) {
+ compilationUnit = fn2cd.get( fn );
+
+ for( FlatNode fnKnown: visited ) {
+ fn2cd.put( fnKnown, compilationUnit );
+ }
+
+ lineNumber = currentProgramPoint.getNumLine();
+ break;
+ }
- public TempDescriptor getInsetVar() {
- return insetVar;
+ for( int i = 0; i < fn.numPrev(); ++i ) {
+ FlatNode prev = fn.getPrev( i );
+ if( !visited.contains( prev ) ) {
+ toVisit.add( prev );
+ }
+ }
+ }
}
- public void setInsetVar(TempDescriptor insetVar) {
- this.insetVar = insetVar;
+ public static boolean isWrite(int effect) {
+ return (effect & Effect.write)==Effect.write;
}
- public AllocSite getInsetAllocSite() {
- return insetAllocSite;
+ public boolean isWrite() {
+ return type==write;
}
- public void setInsetAllocSite(AllocSite insetAllocSite) {
- this.insetAllocSite = insetAllocSite;
+ public boolean isRead() {
+ return type==read;
}
- public AllocSite getAffectedAllocSite() {
+ public Alloc getAffectedAllocSite() {
return affectedAllocSite;
}
- public void setAffectedAllocSite(AllocSite affectedAllocSite) {
+ public void setAffectedAllocSite(Alloc affectedAllocSite) {
this.affectedAllocSite = affectedAllocSite;
}
Effect in = (Effect) o;
- if (paramIndex != null) {
- if (!paramIndex.equals(in.getParamIndex())) {
- return false;
- }
- } else {
- if (!insetVar.equals(in.getInsetVar())
- && !insetAllocSite.equals(in.getInsetAllocSite())) {
- return false;
- }
- }
-
- if (affectedAllocSite.equals(in.getAffectedAllocSite())
- && type == in.getType()
- && field.equals(in.getField())) {
+ if (affectedAllocSite.equals(in.getAffectedAllocSite())
+ && type == in.getType()
+ && ((field!=null&&field.equals(in.getField()))||
+ (field==null&&in.getField()==null))) {
return true;
} else {
return false;
int hash = affectedAllocSite.hashCode();
- if (paramIndex != null) {
- hash = hash ^ paramIndex.hashCode();
- } else if (insetAllocSite != null) {
- hash = hash ^ insetAllocSite.hashCode();
- }
-
hash = hash + type;
if (field != null) {
public String toString() {
String s = "(";
- if (paramIndex != null) {
- s += "param" + paramIndex;
- } else {
- s += insetVar;
- s += ", " + insetAllocSite.toStringBrief();
- }
-
- s += ", " + affectedAllocSite.toStringBrief();
+ s += affectedAllocSite.toStringBrief();
s += ", ";
if (type == read) {
s += "read";
s += "SU";
}
- s += ", " + field.toStringBrief();
+ if (field==null) {
+ s += ", []";
+ } else {
+ s += ", " + field.toStringBrief();
+ }
+ if( compilationUnit != null ) {
+ s += ", "+compilationUnit.getSymbol()+":"+lineNumber;
+ }
+
return s + ")";
}