checkDeclarationInClass(cd);
for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
MethodDescriptor md = (MethodDescriptor) method_it.next();
- if (ssjava.hasAnnotation(md)) {
+ if (ssjava.needAnnotation(md)) {
checkDeclarationInMethodBody(cd, md);
}
}
checkClass(cd);
for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
MethodDescriptor md = (MethodDescriptor) method_it.next();
- if (ssjava.hasAnnotation(md)) {
+ if (ssjava.needAnnotation(md)) {
checkMethodBody(cd, md);
}
}
BlockNode bn = state.getMethodBody(md);
// parsing returnloc annotation
- if (ssjava.hasAnnotation(md)) {
+ if (ssjava.needAnnotation(md)) {
+
Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
if (methodAnnotations != null) {
for (int i = 0; i < methodAnnotations.size(); i++) {
CompositeLocation expLoc =
checkLocationFromExpressionNode(md, nametable, returnExp, new CompositeLocation());
- // by default, return node has "bottom" location
- CompositeLocation loc = new CompositeLocation();
- loc.addLocation(Location.createBottomLocation(md));
- return loc;
+ // check if return value is equal or higher than RETRUNLOC of method
+ // declaration annotation
+ CompositeLocation returnLocAt = md2ReturnLoc.get(md);
+
+ if (CompositeLattice.isGreaterThan(returnLocAt, expLoc)) {
+ throw new Error(
+ "Return value location is not equal or higher than the declaraed return location at "
+ + md.getClassDesc().getSourceFileName() + "::" + rn.getNumLine());
+ }
+
+ return new CompositeLocation();
}
private boolean hasOnlyLiteralValue(ExpressionNode en) {
SymbolTable nametable, MethodInvokeNode min, CompositeLocation loc) {
checkCalleeConstraints(md, nametable, min);
+
+ CompositeLocation baseLocation = null;
+ if (min.getExpression() != null) {
+ baseLocation =
+ checkLocationFromExpressionNode(md, nametable, min.getExpression(),
+ new CompositeLocation());
+ } else {
+ String thisLocId = ssjava.getMethodLattice(md).getThisLoc();
+ baseLocation = new CompositeLocation(new Location(md, thisLocId));
+ }
+
if (!min.getMethod().getReturnType().isVoid()) {
- CompositeLocation ceilingLoc = computeCeilingLocationForCaller(md, nametable, min);
+ // If method has a return value, compute the highest possible return
+ // location in the caller's perspective
+ CompositeLocation ceilingLoc =
+ computeCeilingLocationForCaller(md, nametable, min, baseLocation);
return ceilingLoc;
}
}
private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor md,
- SymbolTable nametable, MethodInvokeNode min) {
-
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation baseLocation) {
List<CompositeLocation> argList = new ArrayList<CompositeLocation>();
- String thisLocId = ssjava.getMethodLattice(md).getThisLoc();
- CompositeLocation thisLoc = new CompositeLocation(new Location(md, thisLocId));
- argList.add(thisLoc);
+ // by default, method has a THIS parameter
+ argList.add(baseLocation);
for (int i = 0; i < min.numArgs(); i++) {
ExpressionNode en = min.getArg(i);
// currently enforce every field to have corresponding location
if (annotationVec.size() == 0) {
- throw new Error("Location is not assigned to the field " + fd.getSymbol() + " of the class "
- + cd.getSymbol());
+ throw new Error("Location is not assigned to the field '" + fd.getSymbol()
+ + "' of the class " + cd.getSymbol() + " at " + cd.getSourceFileName());
}
if (annotationVec.size() > 1) {
public static int compare(CompositeLocation loc1, CompositeLocation loc2) {
-// System.out.println("compare=" + loc1 + " " + loc2);
+ // System.out.println("compare=" + loc1 + " " + loc2);
int baseCompareResult = compareBaseLocationSet(loc1, loc2);
if (baseCompareResult == ComparisonResult.EQUAL) {
// mapping from the priority loc ID to its full representation by the
// composite location
+ int maxTupleSize = 0;
+ CompositeLocation maxCompLoc = null;
+
for (Iterator iterator = inputSet.iterator(); iterator.hasNext();) {
CompositeLocation compLoc = (CompositeLocation) iterator.next();
+ if (compLoc.getSize() > maxTupleSize) {
+ maxTupleSize = compLoc.getSize();
+ maxCompLoc = compLoc;
+ }
Location priorityLoc = compLoc.get(0);
String priorityLocId = priorityLoc.getLocIdentifier();
priorityLocIdentifierSet.add(priorityLocId);
glbCompLoc.addLocation(new Location(priorityDescriptor, glbOfPriorityLoc));
Set<CompositeLocation> compSet = locId2CompLocSet.get(glbOfPriorityLoc);
+ // here find out composite location that has a maximum length tuple
+ // if we have three input set: [A], [A,B], [A,B,C]
+ // maximum length tuple will be [A,B,C]
+ int max = 0;
+ CompositeLocation maxFromCompSet = null;
+ for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
+ CompositeLocation c = (CompositeLocation) iterator.next();
+ if (c.getSize() > max) {
+ max = c.getSize();
+ maxFromCompSet = c;
+ }
+ }
+
if (compSet == null) {
// when GLB(x1,x2)!=x1 and !=x2 : GLB case 4
// mean that the result is already lower than <x1,y1> and <x2,y2>
// assign TOP to the rest of the location elements
// in this case, do not take care about delta
- CompositeLocation inputComp = inputSet.iterator().next();
+ // CompositeLocation inputComp = inputSet.iterator().next();
+ CompositeLocation inputComp = maxCompLoc;
for (int i = 1; i < inputComp.getSize(); i++) {
glbCompLoc.addLocation(Location.createTopLocation(inputComp.get(i).getDescriptor()));
}
// if more than one location shares the same priority GLB
// need to calculate the rest of GLB loc
- int compositeLocSize = compSet.iterator().next().getSize();
+ // int compositeLocSize = compSet.iterator().next().getSize();
+ int compositeLocSize = maxFromCompSet.getSize();
Set<String> glbInputSet = new HashSet<String>();
Descriptor currentD = null;
for (int i = 1; i < compositeLocSize; i++) {
for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
CompositeLocation compositeLocation = (CompositeLocation) iterator.next();
- Location currentLoc = compositeLocation.get(i);
- currentD = currentLoc.getDescriptor();
- // making set of the current location sharing the same idx
- glbInputSet.add(currentLoc.getLocIdentifier());
+ if (compositeLocation.getSize() > i) {
+ Location currentLoc = compositeLocation.get(i);
+ currentD = currentLoc.getDescriptor();
+ // making set of the current location sharing the same idx
+ glbInputSet.add(currentLoc.getLocIdentifier());
+ }
}
// calculate glb for the current lattice
CompositeLocation argLoc = args.get(i);
if (type == PARAMISHIGHER) {
// return loc is lower than param
- System.out.println("argLoc=" + argLoc);
DeltaLocation delta = new DeltaLocation(argLoc, 1);
inputGLB.add(delta);
} else if (type == PARAMISSAME) {
Object obj = toanalyze.iterator().next();
ClassDescriptor cd = (ClassDescriptor) obj;
toanalyze.remove(cd);
+
if (!cd.isInterface()) {
for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
MethodDescriptor md = (MethodDescriptor) method_it.next();
checkMethodBody(cd, md);
}
}
+
}
for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
MethodDescriptor md = (MethodDescriptor) iterator.next();
- ssjava.putHasAnnotation(md);
+ ssjava.putNeedAnnotation(md);
}
Set<Pair> visited = new HashSet<Pair>();
if (!visited.contains(p)) {
visited.add(p);
tovisit.add(calleeMD);
- ssjava.putHasAnnotation(calleeMD);
+ ssjava.putNeedAnnotation(calleeMD);
}
}
}
MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
if (md.matches(matchmd)) {
if (matchmd.getClassDesc().equals(subCD)) {
- ssjava.putHasAnnotation(matchmd);
+ ssjava.putNeedAnnotation(matchmd);
}
}
}
MethodAnnotationCheck methodAnnotationChecker;
// if a method has annotations, the mapping has true
- Hashtable<MethodDescriptor, Boolean> md2hasAnnotation;
+ Hashtable<MethodDescriptor, Boolean> md2needAnnotation;
// class -> field lattice
Hashtable<ClassDescriptor, SSJavaLattice<String>> cd2lattice;
this.cd2lattice = new Hashtable<ClassDescriptor, SSJavaLattice<String>>();
this.cd2methodDefault = new Hashtable<ClassDescriptor, MethodLattice<String>>();
this.md2lattice = new Hashtable<MethodDescriptor, MethodLattice<String>>();
- this.md2hasAnnotation = new Hashtable<MethodDescriptor, Boolean>();
+ this.md2needAnnotation = new Hashtable<MethodDescriptor, Boolean>();
}
public void doCheck() {
}
public void doSingleReferenceCheck() {
- SingleReferenceCheck checker = new SingleReferenceCheck(state);
+ SingleReferenceCheck checker = new SingleReferenceCheck(this, state);
checker.singleReferenceCheck();
}
MethodDescriptor md = (MethodDescriptor) method_it.next();
// parsing location hierarchy declaration for the method
- if (hasAnnotation(md)) {
+ if (needAnnotation(md)) {
Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
if (methodAnnotations != null) {
for (int i = 0; i < methodAnnotations.size(); i++) {
}
}
- public boolean hasAnnotation(MethodDescriptor md) {
- return md2hasAnnotation.containsKey(md);
+ public boolean needAnnotation(MethodDescriptor md) {
+ return md2needAnnotation.containsKey(md);
}
- public void putHasAnnotation(MethodDescriptor md) {
- md2hasAnnotation.put(md, new Boolean(true));
+ public void putNeedAnnotation(MethodDescriptor md) {
+ md2needAnnotation.put(md, new Boolean(true));
}
public Hashtable<MethodDescriptor, Boolean> getMd2hasAnnotation() {
- return md2hasAnnotation;
+ return md2needAnnotation;
}
}
import IR.Tree.BlockNode;
import IR.Tree.BlockStatementNode;
import IR.Tree.CastNode;
-import IR.Tree.CreateObjectNode;
import IR.Tree.DeclarationNode;
import IR.Tree.ExpressionNode;
import IR.Tree.Kind;
public class SingleReferenceCheck {
static State state;
+ SSJavaAnalysis ssjava;
String needToNullify = null;
- public SingleReferenceCheck(State state) {
+ public SingleReferenceCheck(SSJavaAnalysis ssjava, State state) {
+ this.ssjava = ssjava;
this.state = state;
}
ClassDescriptor cd = (ClassDescriptor) it.next();
for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
MethodDescriptor md = (MethodDescriptor) method_it.next();
- checkMethodBody(cd, md);
+ if (ssjava.needAnnotation(md)) {
+ checkMethodBody(cd, md);
+ }
}
}
}
--- /dev/null
+@LATTICE("V<C, V<O")
+@METHODDEFAULT("O<V,V<C,C<IN,THISLOC=IN,C*")
+public class Integer {
+
+ @LOC("V") private int value;
+
+ public Integer(int value) {
+ this.value = value;
+ }
+
+ // public Integer(String str) {
+ // value=Integer.parseInt(str, 10);
+ // }
+
+ public int intValue() {
+ return value;
+ }
+
+ public double doubleValue() {
+ return (double) value;
+ }
+
+ public float floatValue() {
+ return (float) value;
+ }
+
+ public byte[] intToByteArray() {
+ byte[] b = new byte[4];
+ for (int i = 0; i < 4; i++) {
+ int offset = (b.length - 1 - i) * 8;
+ b[i] = (byte) ((value >> offset) & 0xFF);
+ }
+ return b;
+ }
+
+ public int byteArrayToInt(byte[] b) {
+ int value = 0;
+ for (int i = 0; i < 4; i++) {
+ int shift = (4 - 1 - i) * 8;
+ value += (b[i] & 0x000000FF) << shift;
+ }
+ return value;
+ }
+
+ public static int parseInt(String str) {
+ return Integer.parseInt(str, 10);
+ }
+
+ public static int parseInt(String str, int radix) {
+ int value = 0;
+ boolean isNeg = false;
+ int start = 0;
+ byte[] chars = str.getBytes();
+
+ while (chars[start] == ' ' || chars[start] == '\t')
+ start++;
+
+ if (chars[start] == '-') {
+ isNeg = true;
+ start++;
+ }
+ boolean cont = true;
+ for (int i = start; cont && i < str.length(); i++) {
+ byte b = chars[i];
+ int val;
+ if (b >= '0' && b <= '9')
+ val = b - '0';
+ else if (b >= 'a' && b <= 'z')
+ val = 10 + b - 'a';
+ else if (b >= 'A' && b <= 'Z')
+ val = 10 + b - 'A';
+ else {
+ cont = false;
+ }
+ if (cont) {
+ if (val >= radix)
+ System.error();
+ value = value * radix + val;
+ }
+ }
+ if (isNeg)
+ value = -value;
+ return value;
+ }
+
+ @RETURNLOC("V")
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ @RETURNLOC("V")
+ public static String toString(int i) {
+ Integer I = new Integer(i);
+ return I.toString();
+ }
+
+ @RETURNLOC("V")
+ public int hashCode() {
+ return value;
+ }
+
+ public boolean equals(Object o) {
+ if (o.getType() != getType())
+ return false;
+ Integer s = (Integer) o;
+ if (s.intValue() != this.value)
+ return false;
+ return true;
+ }
+
+ public int compareTo(Integer i) {
+ if (value == i.value)
+ return 0;
+ // Returns just -1 or 1 on inequality; doing math might overflow.
+ return value > i.value ? 1 : -1;
+ }
+}
+import String;
+
@LATTICE("")
-@METHODDEFAULT("THIS<IN,THISLOC=IN")
+@METHODDEFAULT("TH<IN,THISLOC=IN")
public class Object {
-
+
+ @RETURNLOC("TH")
public native int hashCode();
/* DON'T USE THIS METHOD UNLESS NECESSARY */
public native int getType();
public boolean equals(@LOC("IN") Object o) {
- if (o==this)
+ if (o == this)
return true;
return false;
}
+
+ @RETURNLOC("TH")
+ public String toString() {
+ return "Object" + hashCode();
+ }
+
}
-@LATTICE("String_V<String_C, String_V<String_O")
-@METHODDEFAULT("StringDM_O<StringDM_V,StringDM_V<StringDM_C,StringDM_C<StringDM_I,THISLOC=StringDM_O,StringDM_C*")
+import Object;
+import String;
+
+@LATTICE("V<C, V<O")
+@METHODDEFAULT("O<V,V<C,C<IN,THISLOC=O,C*")
public class String {
- @LOC("String_V") char value[];
- @LOC("String_C") int count;
- @LOC("String_O") int offset;
- @LOC("String_V") private int cachedHashcode;
+ @LOC("V") char value[];
+ @LOC("C") int count;
+ @LOC("O") int offset;
+ @LOC("V") private int cachedHashcode;
private String() {
}
+
+ public String(String str) {
+ this.value=str.value;
+ this.count=str.count;
+ this.offset=str.offset;
+ }
- public String(@LOC("StringDM_I") char c) {
- @LOC("StringDM_V") char[] str = new char[1];
+ public String(@LOC("IN") char c) {
+ @LOC("V") char[] str = new char[1];
str[0] = c;
String(str);
}
- public String(@LOC("StringDM_I") char str[]) {
- @LOC("StringDM_V") char charstr[]=new char[str.length];
- for(@LOC("StringDM_C") int i=0; i<str.length; i++)
+ public String(@LOC("IN") char str[]) {
+ @LOC("V") char charstr[]=new char[str.length];
+ for(@LOC("C") int i=0; i<str.length; i++)
charstr[i]=str[i];
this.value=charstr;
charstr=null;
this.offset=0;
}
- @LATTICE("StringM1_O<StringM1_V,StringM1_V<StringM1_C,StringM1_C<StringM1_I,THISLOC=StringM1_I,StringM1_C*")
- public String concat(@LOC("StringM1_I") String str) {
- @LOC("StringM1_O") String newstr=new String(); // create new one, it has OUT location
- @LOC("StringM1_C") int newCount=this.count+str.count;
+ @LATTICE("O<V,V<C,C<IN,THISLOC=IN,C*")
+ public String concat(@LOC("IN") String str) {
+ @LOC("O") String newstr=new String(); // create new one, it has OUT location
+ @LOC("C") int newCount=this.count+str.count;
- @LOC("StringM1_V") char charstr[]=new char[newCount];
+ @LOC("V") char charstr[]=new char[newCount];
// here, for loop introduces indirect flow from [C] to [V]
- for(@LOC("StringM1_C") int i=0; i<count; i++) {
+ for(@LOC("C") int i=0; i<count; i++) {
// value flows from GLB(THISLOC,C,THISLOC.V)=(THISLOC,TOP) to [V]
charstr[i]=value[i+offset];
}
- for(@LOC("StringM1_C") int i=0; i<str.count; i++) {
+ for(@LOC("C") int i=0; i<str.count; i++) {
charstr[i+count]=str.value[i+str.offset];
}
newstr.value=charstr;
charstr=null;
- // LOC(newstr.value)=[O,STRING_V]
+ // LOC(newstr.value)=[O,V]
// LOC(charstr)=[V]
- // [O,STRING_V] < [V]
+ // [O,V] < [V]
return newstr;
}
- public boolean equals(@LOC("StringDM_I") Object o) {
- if (o.getType()!=getType()) // values are coming from [StringDM_I] and [THISLOC]
+ public boolean equals(@LOC("IN") Object o) {
+ if (o.getType()!=getType()) // values are coming from [IN] and [THISLOC]
return false;
- @LOC("StringDM_V") String s=(String)o;
+ @LOC("V") String s=(String)o;
o=null;
if (s.count!=count)
return false;
- for(@LOC("StringDM_C") int i=0; i<count; i++) {
+ for(@LOC("C") int i=0; i<count; i++) {
if (s.value[i+s.offset]!=value[i+offset])
return false;
}
return true;
}
+
+ @RETURNLOC("O")
+ public static String valueOf(@LOC("IN") Object o) {
+ if (o==null)
+ return "null";
+ else
+ return o.toString();
+ }
+
+ public byte[] getBytes() {
+ byte str[]=new byte[count];
+ for(int i=0; i<count; i++)
+ str[i]=(byte)value[i+offset];
+ return str;
+ }
+
+ public int length() {
+ return count;
+ }
+
+ public static native int convertdoubletochar(double val, char [] chararray);
+
}
--- /dev/null
+public class System {
+ public static void printInt(int x) {
+ String s = String.valueOf(x);
+ printString(s);
+ }
+
+ public static native void gc();
+
+ public static native long currentTimeMillis();
+
+ public static native long microTimes();
+
+ public static native long getticks();
+
+ public static native void printString(String s);
+
+ public static void println(String s) {
+ System.printString(s + "\n");
+ }
+
+ public static void println() {
+ System.printString("\n");
+ }
+
+ public static void print(String s) {
+ System.printString(s);
+ }
+
+ public static void error() {
+ System
+ .printString("Error (Use Breakpoint on ___System______error method for more information!)\n");
+ }
+
+ public static native void exit(int status);
+
+ public static native void printI(int status);
+
+ public static native void clearPrefetchCache();
+
+ public static native void rangePrefetch(Object o, short[] offsets);
+
+ public static native void deepArrayCopy(Object dst, Object src);
+
+ public static native void Assert(boolean status);
+
+ /* Only used for microbenchmark testing of SingleTM version */
+ public static native void logevent(int event);
+
+ public static native void logevent();
+
+ /* Only used for microbenchmark testing of SingleTM version */
+ public static native void initLog();
+
+ public static native void flushToFile(int threadid);
+
+ /* Only used for microbenchmark testing of SingleTM version */
+
+ public static native void arraycopy(Object src, int srcPos, Object dst, int destPos, int length);
+
+ // for disjoint reachability analysis
+ public static void genReach();
+}