having a new check that verifies the single reference constraint: only allows a singl...
[IRC.git] / Robust / src / Analysis / SSJava / SSJavaAnalysis.java
1 package Analysis.SSJava;
2
3 import java.util.Hashtable;
4 import java.util.Iterator;
5 import java.util.Set;
6 import java.util.StringTokenizer;
7 import java.util.Vector;
8
9 import IR.AnnotationDescriptor;
10 import IR.ClassDescriptor;
11 import IR.MethodDescriptor;
12 import IR.State;
13
14 public class SSJavaAnalysis {
15
16   public static final String LATTICE = "LATTICE";
17   public static final String METHODDEFAULT = "METHODDEFAULT";
18   public static final String THISLOC = "THISLOC";
19   public static final String GLOBALLOC = "GLOBALLOC";
20   public static final String LOC = "LOC";
21   public static final String DELTA = "DELTA";
22   State state;
23   FlowDownCheck flowDownChecker;
24
25   // class -> field lattice
26   Hashtable<ClassDescriptor, SSJavaLattice<String>> cd2lattice;
27
28   // class -> default local variable lattice
29   Hashtable<ClassDescriptor, MethodLattice<String>> cd2methodDefault;
30
31   // method -> local variable lattice
32   Hashtable<MethodDescriptor, MethodLattice<String>> md2lattice;
33
34   public SSJavaAnalysis(State state) {
35     this.state = state;
36     cd2lattice = new Hashtable<ClassDescriptor, SSJavaLattice<String>>();
37     cd2methodDefault = new Hashtable<ClassDescriptor, MethodLattice<String>>();
38     md2lattice = new Hashtable<MethodDescriptor, MethodLattice<String>>();
39   }
40
41   public void doCheck() {
42     parseLocationAnnotation();
43     doFlowDownCheck();
44     doLoopCheck();
45     doSingleReferenceCheck();
46   }
47
48   public void doFlowDownCheck() {
49     flowDownChecker = new FlowDownCheck(this, state);
50     flowDownChecker.flowDownCheck();
51   }
52
53   public void doLoopCheck() {
54     DefinitelyWrittenCheck checker = new DefinitelyWrittenCheck(state);
55     checker.definitelyWrittenCheck();
56   }
57
58   public void doSingleReferenceCheck() {
59     SingleReferenceCheck checker = new SingleReferenceCheck(state);
60     checker.singleReferenceCheck();
61   }
62
63   private void parseLocationAnnotation() {
64     Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
65     while (it.hasNext()) {
66       ClassDescriptor cd = (ClassDescriptor) it.next();
67       // parsing location hierarchy declaration for the class
68       Vector<AnnotationDescriptor> classAnnotations = cd.getModifier().getAnnotations();
69       for (int i = 0; i < classAnnotations.size(); i++) {
70         AnnotationDescriptor an = classAnnotations.elementAt(i);
71         String marker = an.getMarker();
72         if (marker.equals(LATTICE)) {
73           SSJavaLattice<String> locOrder =
74               new SSJavaLattice<String>(SSJavaLattice.TOP, SSJavaLattice.BOTTOM);
75           cd2lattice.put(cd, locOrder);
76           parseClassLatticeDefinition(cd, an.getValue(), locOrder);
77         } else if (marker.equals(METHODDEFAULT)) {
78           MethodLattice<String> locOrder =
79               new MethodLattice<String>(SSJavaLattice.TOP, SSJavaLattice.BOTTOM);
80           cd2methodDefault.put(cd, locOrder);
81           parseMethodLatticeDefinition(cd, an.getValue(), locOrder);
82         }
83       }
84       if (!cd2lattice.containsKey(cd)) {
85         throw new Error("Class " + cd.getSymbol()
86             + " doesn't have any location hierarchy declaration at " + cd.getSourceFileName());
87       }
88
89       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
90         MethodDescriptor md = (MethodDescriptor) method_it.next();
91         // parsing location hierarchy declaration for the method
92         Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
93         if (methodAnnotations != null) {
94           for (int i = 0; i < methodAnnotations.size(); i++) {
95             AnnotationDescriptor an = methodAnnotations.elementAt(i);
96             if (an.getMarker().equals(LATTICE)) {
97               MethodLattice<String> locOrder =
98                   new MethodLattice<String>(SSJavaLattice.TOP, SSJavaLattice.BOTTOM);
99               md2lattice.put(md, locOrder);
100               parseMethodLatticeDefinition(cd, an.getValue(), locOrder);
101             }
102           }
103         }
104
105       }
106
107     }
108   }
109
110   private void parseMethodLatticeDefinition(ClassDescriptor cd, String value,
111       MethodLattice<String> locOrder) {
112
113     value = value.replaceAll(" ", ""); // remove all blank spaces
114
115     StringTokenizer tokenizer = new StringTokenizer(value, ",");
116
117     while (tokenizer.hasMoreTokens()) {
118       String orderElement = tokenizer.nextToken();
119       int idx = orderElement.indexOf("<");
120       if (idx > 0) {// relative order element
121         String lowerLoc = orderElement.substring(0, idx);
122         String higherLoc = orderElement.substring(idx + 1);
123         locOrder.put(higherLoc, lowerLoc);
124         if (locOrder.isIntroducingCycle(higherLoc)) {
125           throw new Error("Error: the order relation " + lowerLoc + " < " + higherLoc
126               + " introduces a cycle.");
127         }
128       } else if (orderElement.startsWith(THISLOC + "=")) {
129         String thisLoc = orderElement.substring(8);
130         locOrder.setThisLoc(thisLoc);
131       } else if (orderElement.startsWith(GLOBALLOC + "=")) {
132         String globalLoc = orderElement.substring(10);
133         locOrder.setGlobalLoc(globalLoc);
134       } else if (orderElement.contains("*")) {
135         // spin loc definition
136         locOrder.addSpinLoc(orderElement.substring(0, orderElement.length() - 1));
137       } else {
138         // single element
139         locOrder.put(orderElement);
140       }
141     }
142
143     // sanity checks
144     if (locOrder.getThisLoc() != null && !locOrder.containsKey(locOrder.getThisLoc())) {
145       throw new Error("Variable 'this' location '" + locOrder.getThisLoc()
146           + "' is not defined in the default local variable lattice at " + cd.getSourceFileName());
147     }
148
149     if (locOrder.getGlobalLoc() != null && !locOrder.containsKey(locOrder.getGlobalLoc())) {
150       throw new Error("Variable global location '" + locOrder.getGlobalLoc()
151           + "' is not defined in the default local variable lattice at " + cd.getSourceFileName());
152     }
153   }
154
155   private void parseClassLatticeDefinition(ClassDescriptor cd, String value,
156       SSJavaLattice<String> locOrder) {
157
158     value = value.replaceAll(" ", ""); // remove all blank spaces
159
160     StringTokenizer tokenizer = new StringTokenizer(value, ",");
161
162     while (tokenizer.hasMoreTokens()) {
163       String orderElement = tokenizer.nextToken();
164       int idx = orderElement.indexOf("<");
165
166       if (idx > 0) {// relative order element
167         String lowerLoc = orderElement.substring(0, idx);
168         String higherLoc = orderElement.substring(idx + 1);
169         locOrder.put(higherLoc, lowerLoc);
170         if (locOrder.isIntroducingCycle(higherLoc)) {
171           throw new Error("Error: the order relation " + lowerLoc + " < " + higherLoc
172               + " introduces a cycle.");
173         }
174       } else if (orderElement.contains("*")) {
175         // spin loc definition
176         locOrder.addSpinLoc(orderElement.substring(0, orderElement.length() - 1));
177       } else {
178         // single element
179         locOrder.put(orderElement);
180       }
181     }
182
183     // sanity check
184     Set<String> spinLocSet = locOrder.getSpinLocSet();
185     for (Iterator iterator = spinLocSet.iterator(); iterator.hasNext();) {
186       String spinLoc = (String) iterator.next();
187       if (!locOrder.containsKey(spinLoc)) {
188         throw new Error("Spin location '" + spinLoc
189             + "' is not defined in the default local variable lattice at " + cd.getSourceFileName());
190       }
191     }
192   }
193
194   public Hashtable<ClassDescriptor, SSJavaLattice<String>> getCd2lattice() {
195     return cd2lattice;
196   }
197
198   public Hashtable<ClassDescriptor, MethodLattice<String>> getCd2methodDefault() {
199     return cd2methodDefault;
200   }
201
202   public Hashtable<MethodDescriptor, MethodLattice<String>> getMd2lattice() {
203     return md2lattice;
204   }
205
206   public SSJavaLattice<String> getClassLattice(ClassDescriptor cd) {
207     return cd2lattice.get(cd);
208   }
209
210   public MethodLattice<String> getMethodLattice(MethodDescriptor md) {
211     if (md2lattice.containsKey(md)) {
212       return md2lattice.get(md);
213     } else {
214       return cd2methodDefault.get(md.getClassDesc());
215     }
216   }
217
218 }