From: yeom Date: Mon, 7 May 2012 00:09:43 +0000 (+0000) Subject: more implementation for the inference: propagating relations of callee parameters... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=0b423adbb0f959f90ca7845e53fe8e7e0e151b96;p=IRC.git more implementation for the inference: propagating relations of callee parameters to the caller's lattice --- diff --git a/Robust/src/Analysis/SSJava/FlowGraph.java b/Robust/src/Analysis/SSJava/FlowGraph.java index da480be4..c1181a5b 100644 --- a/Robust/src/Analysis/SSJava/FlowGraph.java +++ b/Robust/src/Analysis/SSJava/FlowGraph.java @@ -31,18 +31,22 @@ public class FlowGraph { // maps an infer node to the set of neighbors which is pointed by the node Map, Set> mapNodeToNeighborSet; + // maps a paramter descriptor to its index + Map mapParamDescToIdx; boolean debug = true; - public FlowGraph(MethodDescriptor md) { + public FlowGraph(MethodDescriptor md, Map mapParamDescToIdx) { this.md = md; nodeSet = new HashSet(); mapDescTupleToInferNode = new HashMap, FlowNode>(); mapNodeToNeighborSet = new HashMap, Set>(); + this.mapParamDescToIdx = new HashMap(); + this.mapParamDescToIdx.putAll(mapParamDescToIdx); // create a node for 'this' varialbe NTuple thisDescTuple = new NTuple(); thisDescTuple.add(md.getThis()); - FlowNode thisNode = new FlowNode(thisDescTuple); + FlowNode thisNode = new FlowNode(thisDescTuple, true); NTuple thisVarTuple = new NTuple(); thisVarTuple.add(md.getThis()); createNewFlowNode(thisVarTuple); @@ -115,7 +119,8 @@ public class FlowGraph { public FlowNode createNewFlowNode(NTuple tuple) { if (!mapDescTupleToInferNode.containsKey(tuple)) { - FlowNode node = new FlowNode(tuple); + + FlowNode node = new FlowNode(tuple, isParamter(tuple)); mapDescTupleToInferNode.put(tuple, node); nodeSet.add(node); @@ -132,6 +137,17 @@ public class FlowGraph { } + public boolean isParamter(NTuple tuple) { + // return true if a descriptor tuple is started with a parameter descriptor + Descriptor firstIdxDesc = tuple.get(0); + return mapParamDescToIdx.containsKey(firstIdxDesc); + } + + public int getParamIdx(NTuple tuple) { + Descriptor firstDesc = tuple.get(0); + return mapParamDescToIdx.get(firstDesc).intValue(); + } + private void drawEdges(FlowNode node, BufferedWriter bw, Set addedNodeSet, Set addedEdgeSet) throws IOException { diff --git a/Robust/src/Analysis/SSJava/FlowNode.java b/Robust/src/Analysis/SSJava/FlowNode.java index 86edb08d..21a2e089 100644 --- a/Robust/src/Analysis/SSJava/FlowNode.java +++ b/Robust/src/Analysis/SSJava/FlowNode.java @@ -15,13 +15,18 @@ public class FlowNode { // this set contains fields of the base type private Set fieldNodeSet; + // set true if this node is driven from a paramter + private boolean isParameter; + public Set getFieldNodeSet() { return fieldNodeSet; } private Set outEdgeSet; - public FlowNode(NTuple tuple) { + public FlowNode(NTuple tuple, boolean isParam) { + + this.isParameter = isParam; NTuple base = null; Descriptor desc = null; @@ -46,6 +51,10 @@ public class FlowNode { fieldNodeSet.add(node); } + public boolean isParameter() { + return isParameter; + } + public NTuple getDescTuple() { return descTuple; } @@ -55,7 +64,12 @@ public class FlowNode { } public String toString() { - return "[FlowNode]::" + descTuple; + String rtr = "[FlowNode]:"; + if (isParameter()) { + rtr += "param:"; + } + rtr += ":" + descTuple; + return rtr; } public Iterator iteratorOfOutEdges() { diff --git a/Robust/src/Analysis/SSJava/LocationInference.java b/Robust/src/Analysis/SSJava/LocationInference.java index 21aec9ed..66dadfa7 100644 --- a/Robust/src/Analysis/SSJava/LocationInference.java +++ b/Robust/src/Analysis/SSJava/LocationInference.java @@ -6,7 +6,6 @@ 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; @@ -58,6 +57,9 @@ public class LocationInference { List toanalyzeMethodList; Map mapMethodDescriptorToFlowGraph; + // map a method descriptor to its set of parameter descriptors + Map> mapMethodDescriptorToParamDescSet; + // keep current descriptors to visit in fixed-point interprocedural analysis, private Stack methodDescriptorsToVisitStack; @@ -73,6 +75,16 @@ public class LocationInference { // map a method descriptor to a lattice mapping private Map> cd2LatticeMapping; + // map a method descriptor to the set of hierarchy relations that are + // contributed from the callee + private Map> mapMethodDescriptorToCalleeParamRelationSet; + + // map a method descriptor to the set of method invocation nodes which are + // invoked by the method descriptor + private Map> mapMethodDescriptorToMethodInvokeNodeSet; + + private Map>> mapMethodInvokeNodeToArgIdxMap; + boolean debug = true; public LocationInference(SSJavaAnalysis ssjava, State state) { @@ -86,6 +98,13 @@ public class LocationInference { this.methodDescriptorsToVisitStack = new Stack(); this.md2LatticeMapping = new HashMap>(); this.cd2LatticeMapping = new HashMap>(); + this.mapMethodDescriptorToCalleeParamRelationSet = + new HashMap>(); + this.mapMethodDescriptorToMethodInvokeNodeSet = + new HashMap>(); + this.mapMethodInvokeNodeToArgIdxMap = + new HashMap>>(); + } public void setupToAnalyze() { @@ -198,6 +217,8 @@ public class LocationInference { SSJavaLattice methodLattice = new SSJavaLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM); + System.out.println("SSJAVA: Inferencing the lattice from " + md); + analyzeMethodLattice(md, methodLattice); SSJavaLattice prevMethodLattice = md2lattice.get(md); @@ -237,8 +258,6 @@ public class LocationInference { 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); @@ -250,31 +269,116 @@ public class LocationInference { for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) { FlowNode srcNode = (FlowNode) iterator.next(); + // first, take a look at directly connected nodes 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 + addRelationToLattice(md, methodLattice, srcNode, dstNode); + + // second, take a look at all nodes that are reachable from the source + // node + recursiveVisitNodes(md, srcNode, dstNode); + + } + + } + + } + + private void addRelationToLattice(MethodDescriptor md, SSJavaLattice methodLattice, + FlowNode srcNode, FlowNode dstNode) { + 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); + return; + } + + // add a new binary relation of dstNode < srcNode + + String srcSymbol = getSymbol(0, srcNode); + String dstSymbol = getSymbol(0, dstNode); + + methodLattice.addRelationHigherToLower(srcSymbol, dstSymbol); + + if (srcNode.isParameter() && dstNode.isParameter()) { + propagateRelationToCaller(md, srcNode, dstNode); + } + } + + private SSJavaLattice getMethodLattice(MethodDescriptor md) { + + if (!md2lattice.containsKey(md)) { + md2lattice.put(md, new SSJavaLattice(SSJavaLattice.TOP, SSJavaLattice.BOTTOM)); + } + return md2lattice.get(md); + } + + private void propagateRelationToCaller(MethodDescriptor calleeMethodDesc, FlowNode srcNode, + FlowNode newVisitNode) { + + FlowGraph calleeFlowGraph = getFlowGraph(calleeMethodDesc); + + int higherLocIdxCallee = calleeFlowGraph.getParamIdx(srcNode.getDescTuple()); + int lowerLocIdxCallee = calleeFlowGraph.getParamIdx(newVisitNode.getDescTuple()); + + System.out.println(" ssjava.getDependents(md)=" + ssjava.getDependents(calleeMethodDesc)); + Iterator depsItr = ssjava.getDependents(calleeMethodDesc).iterator(); + while (depsItr.hasNext()) { + MethodDescriptor callerMethodDesc = depsItr.next(); + + SSJavaLattice callerMethodLattice = md2lattice.get(callerMethodDesc); - VarDescriptor varDesc = (VarDescriptor) srcNode.getDescTuple().get(0); - ClassDescriptor varClassDesc = varDesc.getType().getClassDesc(); + Set minSet = mapMethodDescriptorToMethodInvokeNodeSet.get(callerMethodDesc); + for (Iterator iterator = minSet.iterator(); iterator.hasNext();) { + MethodInvokeNode methodInvokeNode = (MethodInvokeNode) iterator.next(); + if (methodInvokeNode.getMethod().equals(calleeMethodDesc)) { + // need to propagate a relation from the callee to the caller + // TODO + + System.out.println("higherLocIdxCallee=" + higherLocIdxCallee); + System.out.println("lowerLocIdxCallee=" + lowerLocIdxCallee); + + NTuple higherArg = getArgTupleByArgIdx(methodInvokeNode, higherLocIdxCallee); + NTuple lowerArg = getArgTupleByArgIdx(methodInvokeNode, lowerLocIdxCallee); + + FlowNode callerHigherFlowNode = getFlowGraph(callerMethodDesc).getFlowNode(higherArg); + FlowNode calleeHigherFlowNode = getFlowGraph(callerMethodDesc).getFlowNode(lowerArg); + + addRelationToLattice(callerMethodDesc, getMethodLattice(callerMethodDesc), + callerHigherFlowNode, calleeHigherFlowNode); - extractRelationFromFieldFlows(varClassDesc, srcNode, dstNode, 1); - continue; } + } + + } + } + + private void recursiveVisitNodes(MethodDescriptor md, FlowNode srcNode, FlowNode currentVisitNode) { + + NTuple srcTuple = srcNode.getDescTuple(); - // add a new binary relation of dstNode < srcNode + for (Iterator outEdgeIter = currentVisitNode.getOutEdgeSet().iterator(); outEdgeIter + .hasNext();) { - String srcSymbol = getSymbol(0, srcNode); - String dstSymbol = getSymbol(0, dstNode); + FlowEdge outEdge = outEdgeIter.next(); + FlowNode newVisitNode = outEdge.getDst(); - methodLattice.addRelationHigherToLower(srcSymbol, dstSymbol); + NTuple newVisitTuple = newVisitNode.getDescTuple(); + // if both the source node and the newly visit node are parameters, + // need to keep this relation, then later add a new relation between + // corresponding arguments in the caller's lattice. + if (srcNode.isParameter() && newVisitNode.isParameter()) { + System.out.println("src=" + srcNode + " newVisitNode=" + newVisitNode); + propagateRelationToCaller(md, srcNode, newVisitNode); } } @@ -325,8 +429,19 @@ public class LocationInference { if (state.SSJAVADEBUG) { System.out.println("SSJAVA: Constructing a flow graph: " + md); } - FlowGraph fg = new FlowGraph(md); + + // creates a mapping from a parameter descriptor to its index + + Map mapParamDescToIdx = new HashMap(); + int offset = md.isStatic() ? 0 : 1; + for (int i = 0; i < md.numParameters(); i++) { + Descriptor paramDesc = (Descriptor) md.getParameter(i); + mapParamDescToIdx.put(paramDesc, new Integer(i + offset)); + } + + FlowGraph fg = new FlowGraph(md, mapParamDescToIdx); mapMethodDescriptorToFlowGraph.put(md, fg); + analyzeMethodBody(cd, md); } } @@ -600,9 +715,21 @@ public class LocationInference { } + private void addMapCallerMethodDescToMethodInvokeNodeSet(MethodDescriptor caller, + MethodInvokeNode min) { + Set set = mapMethodDescriptorToMethodInvokeNodeSet.get(caller); + if (set == null) { + set = new HashSet(); + mapMethodDescriptorToMethodInvokeNodeSet.put(caller, set); + } + set.add(min); + } + private void analyzeFlowMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, NodeTupleSet implicitFlowTupleSet) { + addMapCallerMethodDescToMethodInvokeNodeSet(md, min); + MethodDescriptor calleeMD = min.getMethod(); NameDescriptor baseName = min.getBaseName(); @@ -656,6 +783,8 @@ public class LocationInference { // } // } + analyzeFlowMethodParameters(md, nametable, min); + // checkCalleeConstraints(md, nametable, min, baseLocation, constraint); // checkCallerArgumentLocationConstraints(md, nametable, min, @@ -675,6 +804,38 @@ public class LocationInference { } + private NTuple getArgTupleByArgIdx(MethodInvokeNode min, int idx) { + return mapMethodInvokeNodeToArgIdxMap.get(min).get(new Integer(idx)); + } + + private void addArgIdxMap(MethodInvokeNode min, int idx, NTuple argTuple) { + Map> mapIdxToArgTuple = mapMethodInvokeNodeToArgIdxMap.get(min); + if (mapIdxToArgTuple == null) { + mapIdxToArgTuple = new HashMap>(); + mapMethodInvokeNodeToArgIdxMap.put(min, mapIdxToArgTuple); + } + mapIdxToArgTuple.put(new Integer(idx), argTuple); + } + + private void analyzeFlowMethodParameters(MethodDescriptor callermd, SymbolTable nametable, + MethodInvokeNode min) { + + if (min.numArgs() > 0) { + + int offset = min.getMethod().isStatic() ? 0 : 1; + + for (int i = 0; i < min.numArgs(); i++) { + ExpressionNode en = min.getArg(i); + NTuple argTuple = + analyzeFlowExpressionNode(callermd, nametable, en, new NodeTupleSet(), false); + + addArgIdxMap(min, i + offset, argTuple); + } + + } + + } + private void analyzeLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode en) { // TODO Auto-generated method stub @@ -984,3 +1145,8 @@ public class LocationInference { } } + +class ParamIndexRelation { + private Integer higherIdx; + private Integer lowerIdx; +} diff --git a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java index 7f119247..344dd83b 100644 --- a/Robust/src/Analysis/SSJava/SSJavaAnalysis.java +++ b/Robust/src/Analysis/SSJava/SSJavaAnalysis.java @@ -631,6 +631,12 @@ public class SSJavaAnalysis { 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();