X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FAnalysis%2FSSJava%2FSSJavaAnalysis.java;h=2d1f8ffc800af698eea65210c47079e7926dadc2;hb=15e12c52c54314d14b860b578c46251adb3e8625;hp=31075ece9d5fbde878f7fd9d855a95b08fcc2cf3;hpb=7bc8bfe860ceea4a366d0e35998ce5386b8226c3;p=IRC.git diff --git a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java index 31075ece..2d1f8ffc 100644 --- a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java +++ b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java @@ -6,10 +6,13 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.Vector; @@ -23,6 +26,7 @@ import IR.ClassDescriptor; import IR.Descriptor; import IR.FieldDescriptor; import IR.MethodDescriptor; +import IR.NameDescriptor; import IR.State; import IR.SymbolTable; import IR.TypeUtil; @@ -39,6 +43,7 @@ public class SSJavaAnalysis { public static final String THISLOC = "THISLOC"; public static final String GLOBALLOC = "GLOBALLOC"; public static final String RETURNLOC = "RETURNLOC"; + public static final String PCLOC = "PCLOC"; public static final String LOC = "LOC"; public static final String DELTA = "DELTA"; public static final String TERMINATE = "TERMINATE"; @@ -46,6 +51,9 @@ public class SSJavaAnalysis { public static final String DELEGATETHIS = "DELEGATETHIS"; public static final String TRUST = "TRUST"; + public static final String TOP = "_top_"; + public static final String BOTTOM = "_bottom_"; + State state; TypeUtil tu; FlowDownCheck flowDownChecker; @@ -79,6 +87,9 @@ public class SSJavaAnalysis { // the set of method descriptors annotated as "TRUST" Set trustWorthyMDSet; + // method -> the initial program counter location + Map md2pcLoc; + // points to method containing SSJAVA Loop private MethodDescriptor methodContainingSSJavaLoop; @@ -93,6 +104,19 @@ public class SSJavaAnalysis { LinearTypeCheck checker; + // maps a descriptor to its known dependents: namely + // methods or tasks that call the descriptor's method + // AND are part of this analysis (reachable from main) + private Hashtable> mapDescriptorToSetDependents; + + private LinkedList sortedDescriptors; + + private Map> mapSharedLocToDescSet; + + private Map> mapDescToCompleteLattice; + public Map mapNumLocsMapManual; + public Map mapNumPathsMapManual; + public SSJavaAnalysis(State state, TypeUtil tu, BuildFlat bf, CallGraph callgraph) { this.state = state; this.tu = tu; @@ -109,27 +133,177 @@ public class SSJavaAnalysis { this.trustWorthyMDSet = new HashSet(); this.mapMethodToOwnedFieldSet = new Hashtable>(); this.sameHeightWriteFlatNodeSet = new HashSet(); + this.mapDescriptorToSetDependents = new Hashtable>(); + this.sortedDescriptors = new LinkedList(); + this.md2pcLoc = new HashMap(); + this.mapSharedLocToDescSet = new HashMap>(); + this.mapDescToCompleteLattice = new HashMap>(); + this.mapNumLocsMapManual = new HashMap(); + this.mapNumPathsMapManual = new HashMap(); } public void doCheck() { doMethodAnnotationCheck(); - computeLinearTypeCheckMethodSet(); - doLinearTypeCheck(); + + if (state.SSJAVA && !state.SSJAVAINFER) { + init(); + computeLinearTypeCheckMethodSet(); + doLinearTypeCheck(); + } + if (state.SSJAVADEBUG) { - // debugPrint(); + // debug_printAnnotationRequiredSet(); } if (state.SSJAVAINFER) { - inference(); + inference(); + System.exit(0); } else { parseLocationAnnotation(); + debug_countNumLocations(); + // System.exit(0); doFlowDownCheck(); doDefinitelyWrittenCheck(); doLoopCheck(); } + + for (Iterator iterator = annotationRequireSet.iterator(); iterator.hasNext();) { + MethodDescriptor md = (MethodDescriptor) iterator.next(); + MethodLattice locOrder = getMethodLattice(md); + writeLatticeDotFile(md.getClassDesc(), md, getMethodLattice(md)); + System.out.println("~~~\t" + md.getClassDesc() + "_" + md + "\t" + + locOrder.getKeySet().size()); + } + + } + + private void debug_countNumLocations() { + + BuildLattice buildLattice = new BuildLattice(); + + for (Iterator iterator = cd2lattice.keySet().iterator(); iterator.hasNext();) { + ClassDescriptor cd = (ClassDescriptor) iterator.next(); + SSJavaLattice lattice = cd2lattice.get(cd).clone(); + SSJavaLattice completeLattice = debug_buildCompleteLattice(buildLattice, cd, lattice); + mapDescToCompleteLattice.put(cd, completeLattice); + writeLatticeDotFile(cd, null, completeLattice); + } + + for (Iterator iterator = md2lattice.keySet().iterator(); iterator.hasNext();) { + MethodDescriptor md = (MethodDescriptor) iterator.next(); + SSJavaLattice lattice = md2lattice.get(md).clone(); + SSJavaLattice completeLattice = debug_buildCompleteLattice(buildLattice, md, lattice); + mapDescToCompleteLattice.put(md, completeLattice); + writeLatticeDotFile(md.getClassDesc(), md, completeLattice); + } + + for (Iterator iterator = annotationRequireSet.iterator(); iterator.hasNext();) { + MethodDescriptor md = (MethodDescriptor) iterator.next(); + SSJavaLattice lattice = getMethodLattice(md).clone(); + if (!mapDescToCompleteLattice.containsKey(md)) { + System.out.println("@NOT FOUND!"); + SSJavaLattice completeLattice = + debug_buildCompleteLattice(buildLattice, md, lattice); + mapDescToCompleteLattice.put(md, completeLattice); + writeLatticeDotFile(md.getClassDesc(), md, completeLattice); + } + } + + writeNumLocsPathsCSVFile(); + + } + + public SSJavaLattice debug_buildCompleteLattice(BuildLattice buildLattice, + Descriptor desc, SSJavaLattice lattice) { + + // First, create a hierarchy graph + HierarchyGraph hierarchyGraph = new HierarchyGraph(); + Set keySet = lattice.getKeySet(); + + Map mapLocNameToDesc = new HashMap(); + + for (Iterator iterator2 = keySet.iterator(); iterator2.hasNext();) { + String higher = (String) iterator2.next(); + Set lowerSet = lattice.get(higher); + if (!mapLocNameToDesc.containsKey(higher)) { + mapLocNameToDesc.put(higher, new NameDescriptor(higher)); + } + + Descriptor higherDesc = mapLocNameToDesc.get(higher); + + for (Iterator iterator3 = lowerSet.iterator(); iterator3.hasNext();) { + String lower = (String) iterator3.next(); + if (!mapLocNameToDesc.containsKey(lower)) { + mapLocNameToDesc.put(lower, new NameDescriptor(lower)); + } + Descriptor lowerDesc = mapLocNameToDesc.get(lower); + hierarchyGraph.addEdge(higherDesc, lowerDesc); + } + } + + BasisSet basisSet = hierarchyGraph.computeBasisSet(new HashSet()); + + SSJavaLattice completeLattice = buildLattice.buildLattice(hierarchyGraph); + + int numLocs = completeLattice.getKeySet().size(); + LocationInference.numLocationsSInfer += numLocs; + mapNumLocsMapManual.put(desc, new Integer(numLocs)); + + System.out.println(desc + "::" + "lattice=" + lattice.getKeySet().size() + " complete=" + + numLocs); + + int numPaths = completeLattice.countPaths(); + LocationInference.numLocationsSInfer += numPaths; + mapNumPathsMapManual.put(desc, new Integer(numPaths)); + + return completeLattice; + } + + public void writeNumLocsPathsCSVFile() { + + try { + BufferedWriter bw = new BufferedWriter(new FileWriter("manualnumbers.csv")); + + Set keySet = mapNumLocsMapManual.keySet(); + for (Iterator iterator = keySet.iterator(); iterator.hasNext();) { + Descriptor desc = (Descriptor) iterator.next(); + int numLocs = mapNumLocsMapManual.get(desc); + int numPaths = mapNumPathsMapManual.get(desc); + bw.write(desc.getSymbol().replaceAll("[,]", "") + "," + numLocs + "," + numPaths + "\n"); + } + bw.close(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public void init() { + // perform topological sort over the set of methods accessed by the main + // event loop + Set methodDescriptorsToAnalyze = new HashSet(); + methodDescriptorsToAnalyze.addAll(getAnnotationRequireSet()); + sortedDescriptors = topologicalSort(methodDescriptorsToAnalyze); + } + + public LinkedList getSortedDescriptors() { + return (LinkedList) sortedDescriptors.clone(); + } + + public void addSharedDesc(Location loc, Descriptor fd) { + if (!mapSharedLocToDescSet.containsKey(loc)) { + mapSharedLocToDescSet.put(loc, new HashSet()); + } + mapSharedLocToDescSet.get(loc).add(fd); + } + + public Set getSharedDescSet(Location loc) { + return mapSharedLocToDescSet.get(loc); } private void inference() { - LocationInference inferEngine = new LocationInference(this, state); + LocationInference inferEngine = new LocationInference(this, state, tu); inferEngine.inference(); } @@ -207,6 +381,8 @@ public class SSJavaAnalysis { } } + linearTypeCheckMethodSet.addAll(sortedDescriptors); + } private void doLinearTypeCheck() { @@ -214,11 +390,11 @@ public class SSJavaAnalysis { checker.linearTypeCheck(); } - public void debugPrint() { + public void debug_printAnnotationRequiredSet() { System.out.println("SSJAVA: SSJava is checking the following methods:"); for (Iterator iterator = annotationRequireSet.iterator(); iterator.hasNext();) { MethodDescriptor md = iterator.next(); - System.out.print(" " + md); + System.out.println(md); } System.out.println(); } @@ -227,6 +403,10 @@ public class SSJavaAnalysis { methodAnnotationChecker = new MethodAnnotationCheck(this, state, tu); methodAnnotationChecker.methodAnnoatationCheck(); methodAnnotationChecker.methodAnnoataionInheritanceCheck(); + if (state.SSJAVAINFER) { + annotationRequireClassSet.add(methodContainingSSJavaLoop.getClassDesc()); + annotationRequireSet.add(methodContainingSSJavaLoop); + } state.setAnnotationRequireSet(annotationRequireSet); } @@ -251,20 +431,22 @@ public class SSJavaAnalysis { String marker = an.getMarker(); if (marker.equals(LATTICE)) { SSJavaLattice locOrder = - new SSJavaLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM); + new SSJavaLattice(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM); cd2lattice.put(cd, locOrder); parseClassLatticeDefinition(cd, an.getValue(), locOrder); if (state.SSJAVADEBUG) { // generate lattice dot file - writeLatticeDotFile(cd, locOrder); + writeLatticeDotFile(cd, null, locOrder); + System.out.println("~~~\t" + cd + "\t" + locOrder.getKeySet().size()); } } else if (marker.equals(METHODDEFAULT)) { MethodLattice locOrder = - new MethodLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM); + new MethodLattice(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM); cd2methodDefault.put(cd, locOrder); parseMethodDefaultLatticeDefinition(cd, an.getValue(), locOrder); + // writeLatticeDotFile(cd, null, locOrder, "METHOD_DEFAULT"); } } @@ -280,9 +462,11 @@ public class SSJavaAnalysis { if (an.getMarker().equals(LATTICE)) { // developer explicitly defines method lattice MethodLattice locOrder = - new MethodLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM); + new MethodLattice(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM); md2lattice.put(md, locOrder); + System.out.println("parsing method lattice=" + md); parseMethodDefaultLatticeDefinition(cd, an.getValue(), locOrder); + writeLatticeDotFile(cd, md, locOrder, ""); } else if (an.getMarker().equals(TERMINATE)) { // developer explicitly wants to skip loop termination analysis String value = an.getValue(); @@ -301,36 +485,59 @@ public class SSJavaAnalysis { } } - private void writeLatticeDotFile(ClassDescriptor cd, SSJavaLattice locOrder) { + public void writeLatticeDotFile(ClassDescriptor cd, MethodDescriptor md, + SSJavaLattice locOrder) { + writeLatticeDotFile(cd, md, locOrder, ""); - String className = cd.getSymbol().replaceAll("[\\W_]", ""); + } - Set> pairSet = locOrder.getOrderingPairSet(); + public void writeLatticeDotFile(ClassDescriptor cd, MethodDescriptor md, + SSJavaLattice locOrder, String nameSuffix) { - try { - BufferedWriter bw = new BufferedWriter(new FileWriter(className + ".dot")); + String fileName = "lattice_"; + if (md != null) { + fileName += + cd.getSymbol().replaceAll("[\\W_]", "") + "_" + md.toString().replaceAll("[\\W_]", ""); + } else { + fileName += cd.getSymbol().replaceAll("[\\W_]", ""); + } - bw.write("digraph " + className + " {\n"); + fileName += nameSuffix; - for (Iterator iterator = pairSet.iterator(); iterator.hasNext();) { - // pair is in the form of - Pair pair = (Pair) iterator.next(); + Set> pairSet = locOrder.getOrderingPairSet(); - String highLocId = pair.getFirst(); - if (locOrder.isSharedLoc(highLocId)) { - highLocId = "\"" + highLocId + "*\""; - } - String lowLocId = pair.getSecond(); - if (locOrder.isSharedLoc(lowLocId)) { - lowLocId = "\"" + lowLocId + "*\""; + if (pairSet.size() > 0) { + try { + BufferedWriter bw = new BufferedWriter(new FileWriter(fileName + ".dot")); + + bw.write("digraph " + fileName + " {\n"); + + for (Iterator iterator = pairSet.iterator(); iterator.hasNext();) { + // pair is in the form of + Pair pair = (Pair) iterator.next(); + + T highLocId = pair.getFirst(); + String highLocStr, lowLocStr; + if (locOrder.isSharedLoc(highLocId)) { + highLocStr = "\"" + highLocId + "*\""; + } else { + highLocStr = highLocId.toString(); + } + T lowLocId = pair.getSecond(); + if (locOrder.isSharedLoc(lowLocId)) { + lowLocStr = "\"" + lowLocId + "*\""; + } else { + lowLocStr = lowLocId.toString(); + } + bw.write(highLocStr + " -> " + lowLocStr + ";\n"); } - bw.write(highLocId + " -> " + lowLocId + ";\n"); + bw.write("}\n"); + bw.close(); + + } catch (IOException e) { + e.printStackTrace(); } - bw.write("}\n"); - bw.close(); - } catch (IOException e) { - e.printStackTrace(); } } @@ -400,7 +607,7 @@ public class SSJavaAnalysis { locOrder.put(higherLoc, lowerLoc); if (locOrder.isIntroducingCycle(higherLoc)) { throw new Error("Error: the order relation " + lowerLoc + " < " + higherLoc - + " introduces a cycle."); + + " introduces a cycle in the class lattice " + cd); } } else if (orderElement.contains("*")) { // spin loc definition @@ -456,6 +663,19 @@ public class SSJavaAnalysis { } } + public CompositeLocation getPCLocation(MethodDescriptor md) { + if (!md2pcLoc.containsKey(md)) { + // by default, the initial pc location is TOP + CompositeLocation pcLoc = new CompositeLocation(new Location(md, Location.TOP)); + md2pcLoc.put(md, pcLoc); + } + return md2pcLoc.get(md); + } + + public void setPCLocation(MethodDescriptor md, CompositeLocation pcLoc) { + md2pcLoc.put(md, pcLoc); + } + public boolean needToCheckLinearType(MethodDescriptor md) { return linearTypeCheckMethodSet.contains(md); } @@ -575,4 +795,78 @@ public class SSJavaAnalysis { return this.sameHeightWriteFlatNodeSet.contains(fn); } + public LinkedList topologicalSort(Set toSort) { + + Set discovered = new HashSet(); + + LinkedList sorted = new LinkedList(); + + Iterator itr = toSort.iterator(); + while (itr.hasNext()) { + MethodDescriptor d = itr.next(); + + if (!discovered.contains(d)) { + dfsVisit(d, toSort, sorted, discovered); + } + } + + return sorted; + } + + // While we're doing DFS on call graph, remember + // dependencies for efficient queuing of methods + // during interprocedural analysis: + // + // a dependent of a method decriptor d for this analysis is: + // 1) a method or task that invokes d + // 2) in the descriptorsToAnalyze set + private void dfsVisit(MethodDescriptor md, Set toSort, + LinkedList sorted, Set discovered) { + + discovered.add(md); + + Iterator itr2 = callgraph.getCalleeSet(md).iterator(); + while (itr2.hasNext()) { + MethodDescriptor dCallee = (MethodDescriptor) itr2.next(); + addDependent(dCallee, md); + } + + Iterator itr = callgraph.getCallerSet(md).iterator(); + while (itr.hasNext()) { + MethodDescriptor dCaller = (MethodDescriptor) itr.next(); + // only consider callers in the original set to analyze + if (!toSort.contains(dCaller)) { + continue; + } + if (!discovered.contains(dCaller)) { + addDependent(md, // callee + dCaller // caller + ); + + dfsVisit(dCaller, toSort, sorted, discovered); + } + } + + // for leaf-nodes last now! + sorted.addLast(md); + } + + public void addDependent(MethodDescriptor callee, MethodDescriptor caller) { + Set deps = mapDescriptorToSetDependents.get(callee); + if (deps == null) { + deps = new HashSet(); + } + deps.add(caller); + mapDescriptorToSetDependents.put(callee, deps); + } + + public Set getDependents(MethodDescriptor callee) { + Set deps = mapDescriptorToSetDependents.get(callee); + if (deps == null) { + deps = new HashSet(); + mapDescriptorToSetDependents.put(callee, deps); + } + return deps; + } + }