X-Git-Url: http://plrg.eecs.uci.edu/git/?p=IRC.git;a=blobdiff_plain;f=Robust%2Fsrc%2FAnalysis%2FSSJava%2FSSJavaAnalysis.java;h=da84de637057414a997d1f109248415384feb6e9;hp=67b50e543aaac82b114999f7b360cb75cbc6af46;hb=9d767c1f5cef3242ff67473368e5ad327c340bfa;hpb=d4d475b9430d56a8ae3fb5e8956bd0efec423020 diff --git a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java index 67b50e54..da84de63 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; @@ -28,6 +31,7 @@ import IR.SymbolTable; import IR.TypeUtil; import IR.Flat.BuildFlat; import IR.Flat.FlatMethod; +import IR.Flat.FlatNode; import Util.Pair; public class SSJavaAnalysis { @@ -38,6 +42,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"; @@ -45,6 +50,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; @@ -78,16 +86,32 @@ 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; + private FlatNode ssjavaLoopEntrance; + // keep the field ownership from the linear type checking Hashtable> mapMethodToOwnedFieldSet; + Set sameHeightWriteFlatNodeSet; + CallGraph callgraph; 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; + public SSJavaAnalysis(State state, TypeUtil tu, BuildFlat bf, CallGraph callgraph) { this.state = state; this.tu = tu; @@ -103,22 +127,65 @@ public class SSJavaAnalysis { this.bf = bf; 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>(); } public void doCheck() { doMethodAnnotationCheck(); - computeLinearTypeCheckMethodSet(); - doLinearTypeCheck(); - // if (state.SSJAVADEBUG) { - // debugPrint(); - // } - parseLocationAnnotation(); - doFlowDownCheck(); - doDefinitelyWrittenCheck(); - debugDoLoopCheck(); - } - - private void debugDoLoopCheck() { + + if (state.SSJAVA && !state.SSJAVAINFER) { + computeLinearTypeCheckMethodSet(); + doLinearTypeCheck(); + init(); + } + + if (state.SSJAVADEBUG) { + // debug_printAnnotationRequiredSet(); + } + if (state.SSJAVAINFER) { + inference(); + System.exit(0); + } else { + parseLocationAnnotation(); + doFlowDownCheck(); + doDefinitelyWrittenCheck(); + doLoopCheck(); + } + } + + 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); + inferEngine.inference(); + } + + private void doLoopCheck() { GlobalFieldType gft = new GlobalFieldType(callgraph, state, tu.getMain()); LoopOptimize lo = new LoopOptimize(gft, tu); @@ -199,11 +266,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(); } @@ -212,6 +279,11 @@ 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); } public void doFlowDownCheck() { @@ -235,18 +307,18 @@ 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); } } 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); } @@ -264,7 +336,7 @@ 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); parseMethodDefaultLatticeDefinition(cd, an.getValue(), locOrder); } else if (an.getMarker().equals(TERMINATE)) { @@ -285,36 +357,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(); } } @@ -358,12 +453,12 @@ public class SSJavaAnalysis { // sanity checks if (locOrder.getThisLoc() != null && !locOrder.containsKey(locOrder.getThisLoc())) { throw new Error("Variable 'this' location '" + locOrder.getThisLoc() - + "' is not defined in the default local variable lattice at " + cd.getSourceFileName()); + + "' is not defined in the local variable lattice at " + cd.getSourceFileName()); } if (locOrder.getGlobalLoc() != null && !locOrder.containsKey(locOrder.getGlobalLoc())) { throw new Error("Variable global location '" + locOrder.getGlobalLoc() - + "' is not defined in the default local variable lattice at " + cd.getSourceFileName()); + + "' is not defined in the local variable lattice at " + cd.getSourceFileName()); } } @@ -384,7 +479,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 @@ -430,10 +525,29 @@ public class SSJavaAnalysis { if (md2lattice.containsKey(md)) { return md2lattice.get(md); } else { - return cd2methodDefault.get(md.getClassDesc()); + + if (cd2methodDefault.containsKey(md.getClassDesc())) { + return cd2methodDefault.get(md.getClassDesc()); + } else { + throw new Error("Method Lattice of " + md + " is not defined."); + } + } } + 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); } @@ -537,4 +651,94 @@ public class SSJavaAnalysis { return false; } + public FlatNode getSSJavaLoopEntrance() { + return ssjavaLoopEntrance; + } + + public void setSSJavaLoopEntrance(FlatNode ssjavaLoopEntrance) { + this.ssjavaLoopEntrance = ssjavaLoopEntrance; + } + + public void addSameHeightWriteFlatNode(FlatNode fn) { + this.sameHeightWriteFlatNodeSet.add(fn); + } + + public boolean isSameHeightWrite(FlatNode fn) { + 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; + } + }