From: yeom Date: Mon, 30 Apr 2012 17:16:35 +0000 (+0000) Subject: changes on the SJava inference X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e94f955167b58e9356e2258eac3e66564084129b;p=IRC.git changes on the SJava inference --- diff --git a/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java b/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java index f187a38d..052ec485 100644 --- a/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java +++ b/Robust/src/Analysis/SSJava/DefinitelyWrittenCheck.java @@ -42,11 +42,6 @@ public class DefinitelyWrittenCheck { int debugcount = 0; - // 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; - // maps a flat node to its WrittenSet: this keeps all heap path overwritten // previously. private Hashtable>> mapFlatNodeToMustWriteSet; @@ -119,8 +114,6 @@ public class DefinitelyWrittenCheck { private Hashtable mapFlatNodeToSharedLocMapping; private Hashtable mapFlatNodeToDeleteSet; - private LinkedList sortedDescriptors; - private LoopFinder ssjavaLoop; private Set loopIncElements; @@ -143,7 +136,6 @@ public class DefinitelyWrittenCheck { this.ssjava = ssjava; this.callGraph = ssjava.getCallGraph(); this.mapFlatNodeToMustWriteSet = new Hashtable>>(); - this.mapDescriptorToSetDependents = new Hashtable>(); this.mapHeapPath = new Hashtable>(); this.mapDescriptorToLocationPath = new Hashtable>(); this.mapFlatMethodToReadSet = new Hashtable>>(); @@ -194,8 +186,7 @@ public class DefinitelyWrittenCheck { private void sharedLocAnalysis() { // perform method READ/OVERWRITE analysis - LinkedList descriptorListToAnalyze = - (LinkedList) sortedDescriptors.clone(); + LinkedList descriptorListToAnalyze = ssjava.getSortedDescriptors(); // current descriptors to visit in fixed-point interprocedural analysis, // prioritized by @@ -232,7 +223,7 @@ public class DefinitelyWrittenCheck { // results for callee changed, so enqueue dependents caller for // further // analysis - Iterator depsItr = getDependents(md).iterator(); + Iterator depsItr = ssjava.getDependents(md).iterator(); while (depsItr.hasNext()) { MethodDescriptor methodNext = depsItr.next(); if (!methodDescriptorsToVisitStack.contains(methodNext) @@ -579,8 +570,7 @@ public class DefinitelyWrittenCheck { } private void computeSharedCoverSet() { - LinkedList descriptorListToAnalyze = - (LinkedList) sortedDescriptors.clone(); + LinkedList descriptorListToAnalyze = ssjava.getSortedDescriptors(); // current descriptors to visit in fixed-point interprocedural analysis, // prioritized by @@ -2045,9 +2035,10 @@ public class DefinitelyWrittenCheck { // perform topological sort over the set of methods accessed by the main // event loop - Set methodDescriptorsToAnalyze = new HashSet(); - methodDescriptorsToAnalyze.addAll(ssjava.getAnnotationRequireSet()); - sortedDescriptors = topologicalSort(methodDescriptorsToAnalyze); + // Set methodDescriptorsToAnalyze = new + // HashSet(); + // methodDescriptorsToAnalyze.addAll(ssjava.getAnnotationRequireSet()); + // sortedDescriptors = topologicalSort(methodDescriptorsToAnalyze); liveInTempSetToEventLoop = liveness.getLiveInTemps(state.getMethodFlat(methodContainingSSJavaLoop), @@ -2056,8 +2047,7 @@ public class DefinitelyWrittenCheck { private void methodReadWriteSetAnalysis() { // perform method READ/OVERWRITE analysis - LinkedList descriptorListToAnalyze = - (LinkedList) sortedDescriptors.clone(); + LinkedList descriptorListToAnalyze = ssjava.getSortedDescriptors(); // current descriptors to visit in fixed-point interprocedural analysis, // prioritized by @@ -2099,7 +2089,7 @@ public class DefinitelyWrittenCheck { // results for callee changed, so enqueue dependents caller for // further // analysis - Iterator depsItr = getDependents(md).iterator(); + Iterator depsItr = ssjava.getDependents(md).iterator(); while (depsItr.hasNext()) { MethodDescriptor methodNext = depsItr.next(); if (!methodDescriptorsToVisitStack.contains(methodNext) @@ -2498,78 +2488,6 @@ public class DefinitelyWrittenCheck { } - // Borrowed it from disjoint analysis - private 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 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); - } - - // 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 addDependent(MethodDescriptor callee, MethodDescriptor caller) { - Set deps = mapDescriptorToSetDependents.get(callee); - if (deps == null) { - deps = new HashSet(); - } - deps.add(caller); - mapDescriptorToSetDependents.put(callee, deps); - } - - private Set getDependents(MethodDescriptor callee) { - Set deps = mapDescriptorToSetDependents.get(callee); - if (deps == null) { - deps = new HashSet(); - mapDescriptorToSetDependents.put(callee, deps); - } - return deps; - } - private NTuple computePath(Descriptor td) { // generate proper path fot input td // if td is local variable, it just generate one element tuple path diff --git a/Robust/src/Analysis/SSJava/FlowDownCheck.java b/Robust/src/Analysis/SSJava/FlowDownCheck.java index 45ceee75..a78bf475 100644 --- a/Robust/src/Analysis/SSJava/FlowDownCheck.java +++ b/Robust/src/Analysis/SSJava/FlowDownCheck.java @@ -6,6 +6,7 @@ import java.util.Comparator; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.StringTokenizer; @@ -607,7 +608,7 @@ public class FlowDownCheck { // check 'for loop' case BlockNode bn = ln.getInitializer(); // need to check initialization node - checkLocationFromBlockNode(md, nametable, bn, constraint); + checkLocationFromBlockNode(md, bn.getVarTable(), bn, constraint); bn.getVarTable().setParent(nametable); // calculate glb location of condition and update statements diff --git a/Robust/src/Analysis/SSJava/FlowGraph.java b/Robust/src/Analysis/SSJava/FlowGraph.java index 049317d8..da480be4 100644 --- a/Robust/src/Analysis/SSJava/FlowGraph.java +++ b/Robust/src/Analysis/SSJava/FlowGraph.java @@ -45,11 +45,15 @@ public class FlowGraph { FlowNode thisNode = new FlowNode(thisDescTuple); NTuple thisVarTuple = new NTuple(); thisVarTuple.add(md.getThis()); - mapDescTupleToInferNode.put(thisVarTuple, thisNode); + createNewFlowNode(thisVarTuple); thisVarNode = thisNode; } + public Set getNodeSet() { + return nodeSet; + } + public void addNeighbor(FlowNode node, FlowNode neighbor) { Set set = mapNodeToNeighborSet.get(node); if (set == null) { diff --git a/Robust/src/Analysis/SSJava/LocationInference.java b/Robust/src/Analysis/SSJava/LocationInference.java index cb2bb28b..21aec9ed 100644 --- a/Robust/src/Analysis/SSJava/LocationInference.java +++ b/Robust/src/Analysis/SSJava/LocationInference.java @@ -6,11 +6,16 @@ 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.Stack; +import Analysis.SSJava.FlowDownCheck.ComparisonResult; +import Analysis.SSJava.FlowDownCheck.CompositeLattice; import IR.ClassDescriptor; import IR.Descriptor; import IR.FieldDescriptor; @@ -21,6 +26,7 @@ import IR.State; import IR.SymbolTable; import IR.TypeDescriptor; import IR.VarDescriptor; +import IR.Flat.FlatMethod; import IR.Tree.ArrayAccessNode; import IR.Tree.AssignmentNode; import IR.Tree.BlockExpressionNode; @@ -52,6 +58,21 @@ public class LocationInference { List toanalyzeMethodList; Map mapMethodDescriptorToFlowGraph; + // keep current descriptors to visit in fixed-point interprocedural analysis, + private Stack methodDescriptorsToVisitStack; + + // map a class descriptor to a field lattice + private Map> cd2lattice; + + // map a method descriptor to a method lattice + private Map> md2lattice; + + // map a method descriptor to a lattice mapping + private Map> md2LatticeMapping; + + // map a method descriptor to a lattice mapping + private Map> cd2LatticeMapping; + boolean debug = true; public LocationInference(SSJavaAnalysis ssjava, State state) { @@ -60,6 +81,11 @@ public class LocationInference { this.toanalyzeList = new ArrayList(); this.toanalyzeMethodList = new ArrayList(); this.mapMethodDescriptorToFlowGraph = new HashMap(); + this.cd2lattice = new HashMap>(); + this.md2lattice = new HashMap>(); + this.methodDescriptorsToVisitStack = new Stack(); + this.md2LatticeMapping = new HashMap>(); + this.cd2LatticeMapping = new HashMap>(); } public void setupToAnalyze() { @@ -103,7 +129,189 @@ public class LocationInference { public void inference() { - // 2) construct value flow graph + // 1) construct value flow graph + constructFlowGraph(); + + // 2) construct lattices + inferLattices(); + + debug_writeLatticeDotFile(); + + } + + private void debug_writeLatticeDotFile() { + // generate lattice dot file + + setupToAnalyze(); + + while (!toAnalyzeIsEmpty()) { + ClassDescriptor cd = toAnalyzeNext(); + + setupToAnalazeMethod(cd); + + SSJavaLattice classLattice = cd2lattice.get(cd); + if (classLattice != null) { + ssjava.writeLatticeDotFile(cd, classLattice); + } + + while (!toAnalyzeMethodIsEmpty()) { + MethodDescriptor md = toAnalyzeMethodNext(); + if (ssjava.needTobeAnnotated(md)) { + SSJavaLattice methodLattice = md2lattice.get(md); + if (methodLattice != null) { + ssjava.writeLatticeDotFile(cd, methodLattice); + } + } + } + } + + } + + private void inferLattices() { + + // do fixed-point analysis + + // perform method READ/OVERWRITE analysis + LinkedList descriptorListToAnalyze = ssjava.getSortedDescriptors(); + + // current descriptors to visit in fixed-point interprocedural analysis, + // prioritized by + // dependency in the call graph + methodDescriptorsToVisitStack.clear(); + + descriptorListToAnalyze.removeFirst(); + + Set methodDescriptorToVistSet = new HashSet(); + methodDescriptorToVistSet.addAll(descriptorListToAnalyze); + + while (!descriptorListToAnalyze.isEmpty()) { + MethodDescriptor md = descriptorListToAnalyze.removeFirst(); + methodDescriptorsToVisitStack.add(md); + } + + // analyze scheduled methods until there are no more to visit + while (!methodDescriptorsToVisitStack.isEmpty()) { + // start to analyze leaf node + MethodDescriptor md = methodDescriptorsToVisitStack.pop(); + FlatMethod fm = state.getMethodFlat(md); + + SSJavaLattice methodLattice = + new SSJavaLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM); + + analyzeMethodLattice(md, methodLattice); + + SSJavaLattice prevMethodLattice = md2lattice.get(md); + + if (!methodLattice.equals(prevMethodLattice)) { + md2lattice.put(md, methodLattice); + + // results for callee changed, so enqueue dependents caller for + // further analysis + Iterator depsItr = ssjava.getDependents(md).iterator(); + while (depsItr.hasNext()) { + MethodDescriptor methodNext = depsItr.next(); + if (!methodDescriptorsToVisitStack.contains(methodNext) + && methodDescriptorToVistSet.contains(methodNext)) { + methodDescriptorsToVisitStack.add(methodNext); + } + } + + } + + } + + } + + private String getSymbol(int idx, FlowNode node) { + Descriptor desc = node.getDescTuple().get(idx); + return desc.getSymbol(); + } + + private void addMappingDescriptorToLocationIdentifer(MethodDescriptor methodDesc, + VarDescriptor varDesc, String identifier) { + if (!md2LatticeMapping.containsKey(methodDesc)) { + md2LatticeMapping.put(methodDesc, new HashMap()); + } + + } + + private void analyzeMethodLattice(MethodDescriptor md, SSJavaLattice methodLattice) { + + System.out.println("# Create the method lattice for " + md); + + // visit each node of method flow graph + + FlowGraph fg = getFlowGraph(md); + Set nodeSet = fg.getNodeSet(); + + // for the method lattice, we need to look at the first element of + // NTuple + + for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) { + FlowNode srcNode = (FlowNode) iterator.next(); + + Set outEdgeSet = srcNode.getOutEdgeSet(); + for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) { + FlowEdge outEdge = (FlowEdge) iterator2.next(); + + FlowNode dstNode = outEdge.getDst(); + + if ((srcNode.getDescTuple().size() > 1 && dstNode.getDescTuple().size() > 1) + && srcNode.getDescTuple().get(0).equals(dstNode.getDescTuple().get(0))) { + // value flow between fields: we don't need to add a binary relation + // for this case + + VarDescriptor varDesc = (VarDescriptor) srcNode.getDescTuple().get(0); + ClassDescriptor varClassDesc = varDesc.getType().getClassDesc(); + + extractRelationFromFieldFlows(varClassDesc, srcNode, dstNode, 1); + continue; + } + + // add a new binary relation of dstNode < srcNode + + String srcSymbol = getSymbol(0, srcNode); + String dstSymbol = getSymbol(0, dstNode); + + methodLattice.addRelationHigherToLower(srcSymbol, dstSymbol); + + } + + } + + } + + private void extractRelationFromFieldFlows(ClassDescriptor cd, FlowNode srcNode, + FlowNode dstNode, int idx) { + + if (srcNode.getDescTuple().get(idx).equals(dstNode.getDescTuple().get(idx))) { + // value flow between fields: we don't need to add a binary relation + // for this case + VarDescriptor varDesc = (VarDescriptor) srcNode.getDescTuple().get(idx); + ClassDescriptor varClassDesc = varDesc.getType().getClassDesc(); + extractRelationFromFieldFlows(varClassDesc, srcNode, dstNode, idx + 1); + } else { + + Descriptor srcFieldDesc = srcNode.getDescTuple().get(idx); + Descriptor dstFieldDesc = dstNode.getDescTuple().get(idx); + + // add a new binary relation of dstNode < srcNode + + SSJavaLattice fieldLattice = getFieldLattice(cd); + fieldLattice.addRelationHigherToLower(srcFieldDesc.getSymbol(), dstFieldDesc.getSymbol()); + + } + + } + + public SSJavaLattice getFieldLattice(ClassDescriptor cd) { + if (!cd2lattice.containsKey(cd)) { + cd2lattice.put(cd, new SSJavaLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM)); + } + return cd2lattice.get(cd); + } + + public void constructFlowGraph() { setupToAnalyze(); @@ -125,12 +333,12 @@ public class LocationInference { } _debug_printGraph(); - } private void analyzeMethodBody(ClassDescriptor cd, MethodDescriptor md) { BlockNode bn = state.getMethodBody(md); - analyzeFlowBlockNode(md, md.getParameterTable(), bn, null); + NodeTupleSet implicitFlowTupleSet = new NodeTupleSet(); + analyzeFlowBlockNode(md, md.getParameterTable(), bn, implicitFlowTupleSet); } private void analyzeFlowBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, @@ -206,9 +414,8 @@ public class LocationInference { NodeTupleSet condTupleNode = new NodeTupleSet(); analyzeFlowExpressionNode(md, nametable, ln.getCondition(), condTupleNode, null, - implicitFlowTupleSet); + implicitFlowTupleSet, false); condTupleNode.addTupleSet(implicitFlowTupleSet); - System.out.println("condTupleNode=" + condTupleNode); // add edges from condNodeTupleSet to all nodes of conditional nodes analyzeFlowBlockNode(md, nametable, ln.getBody(), condTupleNode); @@ -216,14 +423,13 @@ public class LocationInference { } else { // check 'for loop' case BlockNode bn = ln.getInitializer(); - analyzeFlowBlockNode(md, nametable, bn, implicitFlowTupleSet); + analyzeFlowBlockNode(md, bn.getVarTable(), bn, implicitFlowTupleSet); bn.getVarTable().setParent(nametable); NodeTupleSet condTupleNode = new NodeTupleSet(); - analyzeFlowExpressionNode(md, nametable, ln.getCondition(), condTupleNode, null, - implicitFlowTupleSet); + analyzeFlowExpressionNode(md, bn.getVarTable(), ln.getCondition(), condTupleNode, null, + implicitFlowTupleSet, false); condTupleNode.addTupleSet(implicitFlowTupleSet); - System.out.println("condTupleNode=" + condTupleNode); analyzeFlowBlockNode(md, bn.getVarTable(), ln.getUpdate(), condTupleNode); analyzeFlowBlockNode(md, bn.getVarTable(), ln.getBody(), condTupleNode); @@ -237,7 +443,7 @@ public class LocationInference { NodeTupleSet condTupleNode = new NodeTupleSet(); analyzeFlowExpressionNode(md, nametable, isn.getCondition(), condTupleNode, null, - implicitFlowTupleSet); + implicitFlowTupleSet, false); // add edges from condNodeTupleSet to all nodes of conditional nodes condTupleNode.addTupleSet(implicitFlowTupleSet); @@ -261,7 +467,7 @@ public class LocationInference { NodeTupleSet tupleSetRHS = new NodeTupleSet(); analyzeFlowExpressionNode(md, nametable, dn.getExpression(), tupleSetRHS, null, - implicitFlowTupleSet); + implicitFlowTupleSet, false); // add a new flow edge from rhs to lhs for (Iterator> iter = tupleSetRHS.iterator(); iter.hasNext();) { @@ -275,12 +481,18 @@ public class LocationInference { private void analyzeBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben, NodeTupleSet implicitFlowTupleSet) { - analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null, null, implicitFlowTupleSet); + analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null, null, implicitFlowTupleSet, + false); + } + + private NTuple analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable, + ExpressionNode en, NodeTupleSet nodeSet, boolean isLHS) { + return analyzeFlowExpressionNode(md, nametable, en, nodeSet, null, new NodeTupleSet(), isLHS); } private NTuple analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en, NodeTupleSet nodeSet, NTuple base, - NodeTupleSet implicitFlowTupleSet) { + NodeTupleSet implicitFlowTupleSet, boolean isLHS) { // note that expression node can create more than one flow node // nodeSet contains of flow nodes @@ -317,7 +529,7 @@ public class LocationInference { break; case Kind.ArrayAccessNode: - analyzeArrayAccessNode(md, nametable, (ArrayAccessNode) en); + analyzeFlowArrayAccessNode(md, nametable, (ArrayAccessNode) en, nodeSet, isLHS); break; case Kind.LiteralNode: @@ -325,15 +537,15 @@ public class LocationInference { break; case Kind.MethodInvokeNode: - analyzeMethodInvokeNode(md, nametable, (MethodInvokeNode) en); + analyzeFlowMethodInvokeNode(md, nametable, (MethodInvokeNode) en, implicitFlowTupleSet); break; case Kind.TertiaryNode: - analyzeTertiaryNode(md, nametable, (TertiaryNode) en); + analyzeFlowTertiaryNode(md, nametable, (TertiaryNode) en, nodeSet, implicitFlowTupleSet); break; case Kind.CastNode: - analyzeCastNode(md, nametable, (CastNode) en); + analyzeFlowCastNode(md, nametable, (CastNode) en, implicitFlowTupleSet); break; // case Kind.InstanceOfNode: @@ -358,19 +570,108 @@ public class LocationInference { } - private void analyzeCastNode(MethodDescriptor md, SymbolTable nametable, CastNode en) { - // TODO Auto-generated method stub + private void analyzeFlowCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, + NodeTupleSet implicitFlowTupleSet) { + + NodeTupleSet nodeTupleSet = new NodeTupleSet(); + analyzeFlowExpressionNode(md, nametable, cn.getExpression(), nodeTupleSet, false); } - private void analyzeTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) { - // TODO Auto-generated method stub + private void analyzeFlowTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn, + NodeTupleSet nodeSet, NodeTupleSet implicitFlowTupleSet) { + + System.out.println("### analyzeFlowTertiaryNode=" + tn.printNode(0)); + + NodeTupleSet tertiaryTupleNode = new NodeTupleSet(); + analyzeFlowExpressionNode(md, nametable, tn.getCond(), tertiaryTupleNode, null, + implicitFlowTupleSet, false); + + // add edges from tertiaryTupleNode to all nodes of conditional nodes + tertiaryTupleNode.addTupleSet(implicitFlowTupleSet); + System.out.println("### TertiarayNode's condition=" + tertiaryTupleNode); + analyzeFlowExpressionNode(md, nametable, tn.getTrueExpr(), tertiaryTupleNode, null, + implicitFlowTupleSet, false); + + analyzeFlowExpressionNode(md, nametable, tn.getFalseExpr(), tertiaryTupleNode, null, + implicitFlowTupleSet, false); + + nodeSet.addTupleSet(tertiaryTupleNode); } - private void analyzeMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, - MethodInvokeNode en) { - // TODO Auto-generated method stub + private void analyzeFlowMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, + MethodInvokeNode min, NodeTupleSet implicitFlowTupleSet) { + + MethodDescriptor calleeMD = min.getMethod(); + + NameDescriptor baseName = min.getBaseName(); + boolean isSystemout = false; + if (baseName != null) { + isSystemout = baseName.getSymbol().equals("System.out"); + } + + if (!ssjava.isSSJavaUtil(calleeMD.getClassDesc()) && !ssjava.isTrustMethod(calleeMD) + && !calleeMD.getModifiers().isNative() && !isSystemout) { + + // CompositeLocation baseLocation = null; + if (min.getExpression() != null) { + + NodeTupleSet baseNodeSet = new NodeTupleSet(); + System.out.println("Analyzing base of method=" + min.getExpression()); + analyzeFlowExpressionNode(calleeMD, nametable, min.getExpression(), baseNodeSet, null, + implicitFlowTupleSet, false); + + } else { + if (min.getMethod().isStatic()) { + // String globalLocId = ssjava.getMethodLattice(md).getGlobalLoc(); + // if (globalLocId == null) { + // throw new + // Error("Method lattice does not define global variable location at " + // + generateErrorMessage(md.getClassDesc(), min)); + // } + // baseLocation = new CompositeLocation(new Location(md, + // globalLocId)); + } else { + // 'this' var case + // String thisLocId = ssjava.getMethodLattice(md).getThisLoc(); + // baseLocation = new CompositeLocation(new Location(md, thisLocId)); + } + } + + // constraint case: + // if (constraint != null) { + // int compareResult = + // CompositeLattice.compare(constraint, baseLocation, true, + // generateErrorMessage(cd, min)); + // if (compareResult != ComparisonResult.GREATER) { + // // if the current constraint is higher than method's THIS location + // // no need to check constraints! + // CompositeLocation calleeConstraint = + // translateCallerLocToCalleeLoc(calleeMD, baseLocation, constraint); + // // System.out.println("check method body for constraint:" + calleeMD + + // // " calleeConstraint=" + // // + calleeConstraint); + // checkMethodBody(calleeMD.getClassDesc(), calleeMD, calleeConstraint); + // } + // } + + // checkCalleeConstraints(md, nametable, min, baseLocation, constraint); + + // checkCallerArgumentLocationConstraints(md, nametable, min, + // baseLocation, constraint); + + if (!min.getMethod().getReturnType().isVoid()) { + // If method has a return value, compute the highest possible return + // location in the caller's perspective + // CompositeLocation ceilingLoc = + // computeCeilingLocationForCaller(md, nametable, min, baseLocation, + // constraint); + // return ceilingLoc; + } + } + + // return new CompositeLocation(Location.createTopLocation(md)); } @@ -379,8 +680,31 @@ public class LocationInference { } - private void analyzeArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode en) { - // TODO Auto-generated method stub + private void analyzeFlowArrayAccessNode(MethodDescriptor md, SymbolTable nametable, + ArrayAccessNode aan, NodeTupleSet nodeSet, boolean isLHS) { + + NodeTupleSet expNodeTupleSet = new NodeTupleSet(); + analyzeFlowExpressionNode(md, nametable, aan.getExpression(), expNodeTupleSet, isLHS); + + NodeTupleSet idxNodeTupleSet = new NodeTupleSet(); + analyzeFlowExpressionNode(md, nametable, aan.getIndex(), idxNodeTupleSet, isLHS); + + if (isLHS) { + // need to create an edge from idx to array + + for (Iterator> idxIter = idxNodeTupleSet.iterator(); idxIter.hasNext();) { + NTuple idxTuple = idxIter.next(); + for (Iterator> arrIter = expNodeTupleSet.iterator(); arrIter.hasNext();) { + NTuple arrTuple = arrIter.next(); + getFlowGraph(md).addValueFlowEdge(idxTuple, arrTuple); + } + } + + nodeSet.addTupleSet(expNodeTupleSet); + } else { + nodeSet.addTupleSet(expNodeTupleSet); + nodeSet.addTupleSet(idxNodeTupleSet); + } } @@ -397,13 +721,16 @@ public class LocationInference { NodeTupleSet rightOpSet = new NodeTupleSet(); // left operand - analyzeFlowExpressionNode(md, nametable, on.getLeft(), leftOpSet, null, implicitFlowTupleSet); + System.out.println("Analyzing left op=" + on.getLeft().printNode(0) + "::" + + on.getLeft().getClass()); + analyzeFlowExpressionNode(md, nametable, on.getLeft(), leftOpSet, null, implicitFlowTupleSet, + false); System.out.println("leftOpSet=" + leftOpSet); if (on.getRight() != null) { // right operand analyzeFlowExpressionNode(md, nametable, on.getRight(), rightOpSet, null, - implicitFlowTupleSet); + implicitFlowTupleSet, false); System.out.println("rightOpSet=" + rightOpSet); } @@ -458,9 +785,10 @@ public class LocationInference { } NameDescriptor nd = nn.getName(); + if (nd.getBase() != null) { analyzeFlowExpressionNode(md, nametable, nn.getExpression(), nodeSet, base, - implicitFlowTupleSet); + implicitFlowTupleSet, false); } else { String varname = nd.toString(); if (varname.equals("this")) { @@ -471,13 +799,8 @@ public class LocationInference { Descriptor d = (Descriptor) nametable.get(varname); - // CompositeLocation localLoc = null; if (d instanceof VarDescriptor) { VarDescriptor vd = (VarDescriptor) d; - // localLoc = d2loc.get(vd); - // the type of var descriptor has a composite location! - // loc = ((SSJavaType) - // vd.getType().getExtension()).getCompLoc().clone(); base.add(vd); } else if (d instanceof FieldDescriptor) { // the type of field descriptor has a location! @@ -562,7 +885,8 @@ public class LocationInference { // left = aan.getExpression(); // } // fanNodeSet - base = analyzeFlowExpressionNode(md, nametable, left, nodeSet, base, implicitFlowTupleSet); + base = + analyzeFlowExpressionNode(md, nametable, left, nodeSet, base, implicitFlowTupleSet, false); if (!left.getType().isPrimitive()) { @@ -596,14 +920,14 @@ public class LocationInference { // if LHS is array access node, need to capture value flows between an array // and its index value - analyzeFlowExpressionNode(md, nametable, an.getDest(), nodeSetLHS, null, implicitFlowTupleSet); + analyzeFlowExpressionNode(md, nametable, an.getDest(), nodeSetLHS, null, implicitFlowTupleSet, + true); System.out.println("ASSIGNMENT NODE nodeSetLHS=" + nodeSetLHS); - // NTuple lhsDescTuple = analyzeFlowExpressionNode(md, - // nametable, an.getDest(), base); if (!postinc) { // analyze value flows of rhs expression - analyzeFlowExpressionNode(md, nametable, an.getSrc(), nodeSetRHS, null, implicitFlowTupleSet); + analyzeFlowExpressionNode(md, nametable, an.getSrc(), nodeSetRHS, null, implicitFlowTupleSet, + false); System.out.println("ASSIGNMENT NODE nodeSetRHS=" + nodeSetRHS); // creates edges from RHS to LHS diff --git a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java index 31075ece..7f119247 100644 --- a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java +++ b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java @@ -9,6 +9,7 @@ import java.util.Comparator; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.StringTokenizer; @@ -16,6 +17,7 @@ import java.util.Vector; import Analysis.CallGraph.CallGraph; import Analysis.Loops.GlobalFieldType; +import Analysis.Loops.LoopFinder; import Analysis.Loops.LoopOptimize; import Analysis.Loops.LoopTerminate; import IR.AnnotationDescriptor; @@ -93,6 +95,13 @@ 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; + public SSJavaAnalysis(State state, TypeUtil tu, BuildFlat bf, CallGraph callgraph) { this.state = state; this.tu = tu; @@ -109,17 +118,22 @@ public class SSJavaAnalysis { this.trustWorthyMDSet = new HashSet(); this.mapMethodToOwnedFieldSet = new Hashtable>(); this.sameHeightWriteFlatNodeSet = new HashSet(); + this.mapDescriptorToSetDependents = new Hashtable>(); + this.sortedDescriptors = new LinkedList(); } public void doCheck() { doMethodAnnotationCheck(); computeLinearTypeCheckMethodSet(); doLinearTypeCheck(); + + init(); + if (state.SSJAVADEBUG) { // debugPrint(); } if (state.SSJAVAINFER) { - inference(); + inference(); } else { parseLocationAnnotation(); doFlowDownCheck(); @@ -128,6 +142,18 @@ public class SSJavaAnalysis { } } + private 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(); + } + private void inference() { LocationInference inferEngine = new LocationInference(this, state); inferEngine.inference(); @@ -301,7 +327,7 @@ public class SSJavaAnalysis { } } - private void writeLatticeDotFile(ClassDescriptor cd, SSJavaLattice locOrder) { + public void writeLatticeDotFile(ClassDescriptor cd, SSJavaLattice locOrder) { String className = cd.getSymbol().replaceAll("[\\W_]", ""); @@ -575,4 +601,72 @@ 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 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; + } + } diff --git a/Robust/src/Analysis/SSJava/SSJavaLattice.java b/Robust/src/Analysis/SSJava/SSJavaLattice.java index e0dec6cb..cbbae46c 100644 --- a/Robust/src/Analysis/SSJava/SSJavaLattice.java +++ b/Robust/src/Analysis/SSJava/SSJavaLattice.java @@ -29,4 +29,11 @@ public class SSJavaLattice extends Lattice { return sharedLocSet.contains(loc); } + public boolean addRelationHigherToLower(T higher, T lower) { + + System.out.println("add a relation: " + lower + "<" + higher); + + return put(higher, lower); + } + }