X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FAnalysis%2FSSJava%2FFlowGraph.java;h=2031460dd48cc983a8bd974aabfa0d93b6ce4314;hb=ddac34bb8ed87db61d32630e714e7f006a077c8e;hp=f9790963afc1fe18026f3348f23b8f7052249031;hpb=28876fc6038265b38688ea04cd0f5d8241604bd6;p=IRC.git diff --git a/Robust/src/Analysis/SSJava/FlowGraph.java b/Robust/src/Analysis/SSJava/FlowGraph.java index f9790963..2031460d 100644 --- a/Robust/src/Analysis/SSJava/FlowGraph.java +++ b/Robust/src/Analysis/SSJava/FlowGraph.java @@ -1,96 +1,937 @@ package Analysis.SSJava; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Set; +import IR.ClassDescriptor; import IR.Descriptor; +import IR.FieldDescriptor; import IR.MethodDescriptor; +import IR.NameDescriptor; +import IR.VarDescriptor; +import IR.Tree.MethodInvokeNode; public class FlowGraph { MethodDescriptor md; - Set nodeSet; + Set returnNodeSet; FlowNode thisVarNode; + Map> mapFlowNodeToInEdgeSet; + Map> mapFlowNodeToOutEdgeSet; + + Map, FlowNode> mapLocTupleToFlowNode; + Map> mapFlowNodeToLocTuple; + // maps the composite representation of field/var descriptors to infer nodes Map, FlowNode> mapDescTupleToInferNode; - // 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; + + // DS for the lattice generation + Map mapIdxToFlowNode; + + Map mapMethodInvokeNodeToFlowReturnNode; + + Map mapIntersectionDescToEnclosingDescriptor; + + public static int interseed = 0; 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.mapFlowNodeToLocTuple = new HashMap>(); + this.mapLocTupleToFlowNode = new HashMap, FlowNode>(); + this.mapDescTupleToInferNode = new HashMap, FlowNode>(); + this.mapParamDescToIdx = new HashMap(); + this.mapParamDescToIdx.putAll(mapParamDescToIdx); + this.returnNodeSet = new HashSet(); + this.mapIdxToFlowNode = new HashMap(); + this.mapFlowNodeToOutEdgeSet = new HashMap>(); + this.mapFlowNodeToInEdgeSet = new HashMap>(); + this.mapMethodInvokeNodeToFlowReturnNode = new HashMap(); + this.mapIntersectionDescToEnclosingDescriptor = new HashMap(); + + if (!md.isStatic()) { + // create a node for 'this' varialbe + // NTuple thisDescTuple = new NTuple(); + // thisDescTuple.add(md.getThis()); + + NTuple thisVarTuple = new NTuple(); + thisVarTuple.add(md.getThis()); + FlowNode thisNode = createNewFlowNode(thisVarTuple); + thisNode.setSkeleton(true); + thisVarNode = thisNode; + } + + setupMapIdxToDesc(); + + } + + public void addMapInterLocNodeToEnclosingDescriptor(Descriptor interDesc, ClassDescriptor desc) { + System.out.println("##### INTERLOC=" + interDesc + " enclosing desc=" + desc); + mapIntersectionDescToEnclosingDescriptor.put(interDesc, desc); + } + + public ClassDescriptor getEnclosingDescriptor(Descriptor interDesc) { + return mapIntersectionDescToEnclosingDescriptor.get(interDesc); + } + + public Map, FlowNode> getMapDescTupleToInferNode() { + return mapDescTupleToInferNode; + } + + public void setMapDescTupleToInferNode(Map, FlowNode> in) { + this.mapDescTupleToInferNode.putAll(in); + } + + public Map, FlowNode> getMapLocTupleToFlowNode() { + return mapLocTupleToFlowNode; + } + + public void setMapLocTupleToFlowNode(Map, FlowNode> in) { + this.mapLocTupleToFlowNode.putAll(in); + } + + public void setReturnNodeSet(Set in) { + this.returnNodeSet.addAll(in); + } + + public void setThisVarNode(FlowNode thisVarNode) { + this.thisVarNode = thisVarNode; + } + + public Map getMapParamDescToIdx() { + return mapParamDescToIdx; + } + + public FlowNode createIntermediateNode() { + NTuple tuple = new NTuple(); + Descriptor interDesc = new InterDescriptor(LocationInference.INTERLOC + interseed); + tuple.add(interDesc); + interseed++; + + FlowNode newNode = new FlowNode(tuple); + newNode.setIntermediate(true); + + mapDescTupleToInferNode.put(tuple, newNode); + // nodeSet.add(newNode); - // create a node for 'this' varialbe - FlowNode thisNode = new FlowNode(null, md.getThis()); - NTuple thisVarTuple = new NTuple(); - thisVarTuple.add(md.getThis()); - mapDescTupleToInferNode.put(thisVarTuple, thisNode); - thisVarNode = thisNode; + System.out.println("create new intermediate node= " + newNode); + return newNode; } - public void addNeighbor(FlowNode node, FlowNode neighbor) { - Set set = mapNodeToNeighborSet.get(node); - if (set == null) { - set = new HashSet(); + public FlowReturnNode getFlowReturnNode(MethodInvokeNode min) { + return mapMethodInvokeNodeToFlowReturnNode.get(min); + } + + public FlowReturnNode createReturnNode(MethodInvokeNode min) { + NTuple tuple = new NTuple(); + NameDescriptor n = new NameDescriptor("RETURNLOC" + (LocationInference.locSeed++)); + tuple.add(n); + + FlowReturnNode newNode = new FlowReturnNode(tuple, min); + mapDescTupleToInferNode.put(tuple, newNode); + mapMethodInvokeNodeToFlowReturnNode.put(min, newNode); + // nodeSet.add(newNode); + + System.out.println("create new set node= " + newNode); + + return newNode; + } + + private void setupMapIdxToDesc() { + + Set descSet = mapParamDescToIdx.keySet(); + for (Iterator iterator = descSet.iterator(); iterator.hasNext();) { + Descriptor paramDesc = (Descriptor) iterator.next(); + int idx = mapParamDescToIdx.get(paramDesc); + NTuple descTuple = new NTuple(); + descTuple.add(paramDesc); + FlowNode paramNode = getFlowNode(descTuple); + mapIdxToFlowNode.put(idx, paramNode); + paramNode.setSkeleton(true); } - set.add(neighbor); - System.out.println("add a new neighbor " + neighbor + " to " + node); } - public void addValueFlowEdge(NTuple fromDescTuple, NTuple toDescTuple) { + public int getNumParameters() { + return mapIdxToFlowNode.keySet().size(); + } + + public FlowNode getParamFlowNode(int idx) { + return mapIdxToFlowNode.get(idx); + } + + public Set getEdgeSet() { + Set edgeSet = new HashSet(); + + Set nodeSet = getNodeSet(); + for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) { + FlowNode flowNode = (FlowNode) iterator.next(); + edgeSet.addAll(getOutEdgeSet(flowNode)); + } + System.out.println("EDGESET=" + edgeSet); + return edgeSet; + } + + public Set getParamFlowNodeSet() { + Set setParamFlowNode = new HashSet(); + setParamFlowNode.addAll(mapIdxToFlowNode.values()); + return setParamFlowNode; + } + + public Set getNodeSet() { + Set set = new HashSet(); + set.addAll(mapDescTupleToInferNode.values()); + System.out.println("NODESET=" + set); + return set; + } + + public MethodDescriptor getMethodDescriptor() { + return md; + } + + public boolean isParamDesc(Descriptor desc) { + + if (mapParamDescToIdx.containsKey(desc)) { + int idx = mapParamDescToIdx.get(desc); + if (!md.isStatic() && idx == 0) { + return false; + } + return true; + } + + return false; + } + + public boolean hasEdge(NTuple fromDescTuple, NTuple toDescTuple) { FlowNode fromNode = mapDescTupleToInferNode.get(fromDescTuple); FlowNode toNode = mapDescTupleToInferNode.get(toDescTuple); - System.out.println("create an edge from " + fromNode + " to " + toNode); + Set fromNodeOutEdgeSet = getOutEdgeSet(fromNode); + for (Iterator iterator = fromNodeOutEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge flowEdge = (FlowEdge) iterator.next(); + if (flowEdge.getDst().equals(toNode)) { + return true; + } else { + if (hasEdge(flowEdge.getDst().getDescTuple(), toDescTuple)) { + return true; + } + } + } + + return false; + } + + public Set getOutEdgeSetStartingFrom(FlowNode startNode) { + + Descriptor prefixDesc = startNode.getCurrentDescTuple().get(0); + + // returns the set of edges that share the same prefix of startNode + Set edgeSet = new HashSet(); + + for (Iterator> iter = mapFlowNodeToOutEdgeSet.values().iterator(); iter.hasNext();) { + Set nodeEdgeSet = iter.next(); + for (Iterator iter2 = nodeEdgeSet.iterator(); iter2.hasNext();) { + FlowEdge edge = iter2.next(); + if (edge.getInitTuple().get(0).equals(prefixDesc)) { + edgeSet.add(edge); + } + } + } + + return edgeSet; + } + + public Set getOutEdgeSet(FlowNode node) { + if (!mapFlowNodeToOutEdgeSet.containsKey(node)) { + mapFlowNodeToOutEdgeSet.put(node, new HashSet()); + } + return mapFlowNodeToOutEdgeSet.get(node); + } + + public Set getInEdgeSet(FlowNode node) { + if (!mapFlowNodeToInEdgeSet.containsKey(node)) { + mapFlowNodeToInEdgeSet.put(node, new HashSet()); + } + return mapFlowNodeToInEdgeSet.get(node); + } + + public void addValueFlowEdge(NTuple fromDescTuple, NTuple toDescTuple) { + + FlowNode fromNode = getFlowNode(fromDescTuple); + FlowNode toNode = getFlowNode(toDescTuple); + + if (toNode.getDescTuple().get(0).equals(LocationInference.LITERALDESC)) { + return; + } + + // System.out.println("create an edge from " + fromNode + " to " + toNode); int fromTupleSize = fromDescTuple.size(); - NTuple curTuple = new NTuple(); + NTuple curFromTuple = new NTuple(); for (int i = 0; i < fromTupleSize; i++) { Descriptor desc = fromDescTuple.get(i); - curTuple.add(desc); - addNeighbor(getInferNode(curTuple), toNode); + curFromTuple.add(desc); + int toTupleSize = toDescTuple.size(); + NTuple curToTuple = new NTuple(); + for (int k = 0; k < toTupleSize; k++) { + Descriptor toDesc = toDescTuple.get(k); + curToTuple.add(toDesc); + addFlowEdge(getFlowNode(curFromTuple), getFlowNode(curToTuple), fromDescTuple, toDescTuple); + } } - int toTupleSize = toDescTuple.size(); - curTuple = new NTuple(); - for (int i = 0; i < toTupleSize; i++) { - Descriptor desc = toDescTuple.get(i); - curTuple.add(desc); - addNeighbor(fromNode, getInferNode(curTuple)); + // int fromTupleSize = fromDescTuple.size(); + // NTuple curTuple = new NTuple(); + // for (int i = 0; i < fromTupleSize; i++) { + // Descriptor desc = fromDescTuple.get(i); + // curTuple.add(desc); + // addFlowEdge(getFlowNode(curTuple), toNode, fromDescTuple, toDescTuple); + // } + // + // int toTupleSize = toDescTuple.size(); + // curTuple = new NTuple(); + // for (int i = 0; i < toTupleSize; i++) { + // Descriptor desc = toDescTuple.get(i); + // curTuple.add(desc); + // addFlowEdge(fromNode, getFlowNode(curTuple), fromDescTuple, toDescTuple); + // } + + } + + private void addFlowEdge(FlowNode fromNode, FlowNode toNode, NTuple initTuple, + NTuple endTuple) { + + FlowEdge edge = new FlowEdge(fromNode, toNode, initTuple, endTuple); + addOutEdge(fromNode, edge); + addInEdge(toNode, edge); + + // System.out.println("add a new edge=" + edge); + } + + private void addInEdge(FlowNode toNode, FlowEdge edge) { + getInEdgeSet(toNode).add(edge); + } + + private void addOutEdge(FlowNode fromNode, FlowEdge edge) { + if (!mapFlowNodeToOutEdgeSet.containsKey(fromNode)) { + mapFlowNodeToOutEdgeSet.put(fromNode, new HashSet()); } + mapFlowNodeToOutEdgeSet.get(fromNode).add(edge); + } + public boolean contains(NTuple descTuple) { + return mapDescTupleToInferNode.containsKey(descTuple); } - public FlowNode getInferNode(NTuple descTuple) { - if (mapDescTupleToInferNode.containsKey(descTuple)) { - return mapDescTupleToInferNode.get(descTuple); + public FlowNode getFlowNode(NTuple descTuple) { + if (!mapDescTupleToInferNode.containsKey(descTuple)) { + FlowNode node = createNewFlowNode(descTuple); + mapDescTupleToInferNode.put(descTuple, node); } - return null; + return mapDescTupleToInferNode.get(descTuple); } public FlowNode getThisVarNode() { return thisVarNode; } - public void createNewFlowNode(NTuple base) { + public FlowNode createNewFlowNode(NTuple tuple) { + + // System.out.println("createNewFlowNode=" + tuple); + if (!mapDescTupleToInferNode.containsKey(tuple)) { + FlowNode node = new FlowNode(tuple); + mapDescTupleToInferNode.put(tuple, node); + // nodeSet.add(node); + + mapLocTupleToFlowNode.put(getLocationTuple(node), node); - FlowNode node = new FlowNode(base); - mapDescTupleToInferNode.put(base, node); + if (tuple.size() > 1) { + NTuple baseTuple = tuple.subList(0, tuple.size() - 1); + getFlowNode(baseTuple).addFieldNode(node); + } - System.out.println("Creating new node=" + node); + // System.out.println("Creating new node=" + node); + return node; + } else { + return mapDescTupleToInferNode.get(tuple); + } } -} + public void addReturnFlowNode(NTuple tuple) { + + if (!mapDescTupleToInferNode.containsKey(tuple)) { + createNewFlowNode(tuple); + } + + FlowNode node = mapDescTupleToInferNode.get(tuple); + returnNodeSet.add(node); + } + + public Set getReturnNodeSet() { + return returnNodeSet; + } + + public Set getLocalReachFlowNodeSetFrom(FlowNode fn) { + Set set = new HashSet(); + recurLocalReachFlowNodeSet(fn, set); + return set; + } + + private void recurLocalReachFlowNodeSet(FlowNode fn, Set visited) { + + Set outEdgeSet = getOutEdgeSet(fn); + for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge edge = (FlowEdge) iterator.next(); + FlowNode originalDstNode = edge.getDst(); + + Set dstNodeSet = new HashSet(); + if (originalDstNode instanceof FlowReturnNode) { + FlowReturnNode rnode = (FlowReturnNode) originalDstNode; + Set> rtupleSetFromRNode = rnode.getReturnTupleSet(); + Set> rtupleSet = getReturnTupleSet(rtupleSetFromRNode); + for (Iterator iterator2 = rtupleSet.iterator(); iterator2.hasNext();) { + NTuple rtuple = (NTuple) iterator2.next(); + dstNodeSet.add(getFlowNode(rtuple)); + } + } else { + dstNodeSet.add(originalDstNode); + } + + for (Iterator iterator2 = dstNodeSet.iterator(); iterator2.hasNext();) { + FlowNode dstNode = (FlowNode) iterator2.next(); + if (!visited.contains(dstNode)) { + visited.add(dstNode); + recurLocalReachFlowNodeSet(dstNode, visited); + } + } + + } + + } + + private void getReachFlowNodeSetFrom(FlowNode fn, Set visited) { + + Set outEdgeSet = getOutEdgeSet(fn); + for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge edge = (FlowEdge) iterator.next(); + + if (fn.equals(getFlowNode(edge.getInitTuple()))) { + FlowNode dstNode = getFlowNode(edge.getEndTuple()); + if (!visited.contains(dstNode)) { + visited.add(dstNode); + getReachFlowNodeSetFrom(dstNode, visited); + } + } + } + + } + + public Set getReachFlowNodeSetFrom(FlowNode fn) { + Set set = new HashSet(); + getReachFlowNodeSetFrom(fn, set); + return set; + } + + public Set getReachableSetFrom(NTuple prefix) { + Set reachableSet = new HashSet(); + + Set nodeSet = getNodeSet(); + for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) { + FlowNode originalSrcNode = (FlowNode) iterator.next(); + + Set srcNodeSet = new HashSet(); + if (originalSrcNode instanceof FlowReturnNode) { + FlowReturnNode rnode = (FlowReturnNode) originalSrcNode; + Set> rtupleSetFromRNode = rnode.getReturnTupleSet(); + Set> rtupleSet = getReturnTupleSet(rtupleSetFromRNode); + // System.out.println("#rnode=" + rnode + " rtupleSet=" + rtupleSet); + for (Iterator iterator2 = rtupleSet.iterator(); iterator2.hasNext();) { + NTuple rtuple = (NTuple) iterator2.next(); + if (rtuple.startsWith(prefix)) { + // System.out.println("rtuple=" + rtuple + " give it to recur=" + originalSrcNode); + recurReachableSetFrom(originalSrcNode, reachableSet); + } + } + } else { + if (originalSrcNode.getCurrentDescTuple().startsWith(prefix)) { + recurReachableSetFrom(originalSrcNode, reachableSet); + } + } + + } + + return reachableSet; + } + + public Set> getReturnTupleSet(Set> in) { + + Set> normalTupleSet = new HashSet>(); + for (Iterator iterator2 = in.iterator(); iterator2.hasNext();) { + NTuple tuple = (NTuple) iterator2.next(); + FlowNode tupleNode = getFlowNode(tuple); + if (tupleNode instanceof FlowReturnNode) { + normalTupleSet.addAll(getReturnTupleSet(((FlowReturnNode) tupleNode).getReturnTupleSet())); + } else { + normalTupleSet.add(tuple); + } + } + return normalTupleSet; + } + + // private void getReachFlowNodeSetFrom(FlowNode fn, Set visited) { + // + // for (Iterator iterator = fn.getOutEdgeSet().iterator(); + // iterator.hasNext();) { + // FlowEdge edge = (FlowEdge) iterator.next(); + // + // if (fn.equals(getFlowNode(edge.getInitTuple()))) { + // + // FlowNode dstNode = getFlowNode(edge.getEndTuple()); + // + // if (!visited.contains(dstNode)) { + // visited.add(dstNode); + // getReachFlowNodeSetFrom(dstNode, visited); + // } + // } + // } + // + // } + + private void recurReachableSetFrom(FlowNode curNode, Set reachableSet) { + + Set edgeSet = getOutEdgeSet(curNode); + for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) { + FlowEdge edge = (FlowEdge) iterator.next(); + FlowNode dstNode = getFlowNode(edge.getEndTuple()); + if (!reachableSet.contains(dstNode)) { + reachableSet.add(dstNode); + recurReachableSetFrom(dstNode, reachableSet); + } + } + + } + + public Set> getReachableFlowTupleSet(Set> visited, FlowNode fn) { + + Set outEdgeSet = getOutEdgeSet(fn); + + for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge edge = (FlowEdge) iterator.next(); + + if (fn.getDescTuple().equals(edge.getInitTuple())) { + FlowNode dstNode = getFlowNode(edge.getEndTuple()); + NTuple dstTuple = getLocationTuple(dstNode); + + if (!visited.contains(dstTuple)) { + visited.add(dstTuple); + visited.addAll(getReachableFlowTupleSet(visited, dstNode)); + } + + } + } + return visited; + } + + public NTuple getLocationTuple(NTuple descTuple) { + return getLocationTuple(getFlowNode(descTuple)); + } + + public NTuple getLocationTuple(FlowNode fn) { + + if (!mapFlowNodeToLocTuple.containsKey(fn)) { + NTuple descTuple = fn.getDescTuple(); + NTuple locTuple = new NTuple(); + ClassDescriptor cd = null; + + Descriptor localDesc = fn.getDescTuple().get(0); + + if (fn.isIntermediate() && fn.getDescTuple().size() == 1) { + Location interLoc = new Location(md, localDesc.getSymbol()); + interLoc.setLocDescriptor(localDesc); + locTuple.add(interLoc); + } else if (localDesc.getSymbol().equals(SSJavaAnalysis.TOP)) { + Location topLoc = new Location(md, Location.TOP); + topLoc.setLocDescriptor(LocationInference.TOPDESC); + locTuple.add(topLoc); + } else if (localDesc.getSymbol().equals(LocationInference.GLOBALLOC)) { + Location globalLoc = new Location(md, LocationInference.GLOBALLOC); + globalLoc.setLocDescriptor(LocationInference.GLOBALDESC); + locTuple.add(globalLoc); + } else { + // normal case + for (int i = 0; i < descTuple.size(); i++) { + Descriptor curDesc = descTuple.get(i); + Location loc; + if (i == 0) { + loc = new Location(md, curDesc.getSymbol()); + loc.setLocDescriptor(curDesc); + if (curDesc instanceof VarDescriptor) { + cd = ((VarDescriptor) curDesc).getType().getClassDesc(); + } else if (curDesc instanceof InterDescriptor) { + cd = mapIntersectionDescToEnclosingDescriptor.get(curDesc); + } else { + // otherwise it should be the last element + cd = null; + } + } else { + loc = new Location(cd, curDesc.getSymbol()); + loc.setLocDescriptor(curDesc); + + if (curDesc instanceof FieldDescriptor) { + cd = ((FieldDescriptor) curDesc).getType().getClassDesc(); + } else if (curDesc instanceof LocationDescriptor) { + cd = ((LocationDescriptor) curDesc).getEnclosingClassDesc(); + } else { + // otherwise it should be the last element of the tuple + cd = null; + } + + } + locTuple.add(loc); + } + } + + mapFlowNodeToLocTuple.put(fn, locTuple); + } + return mapFlowNodeToLocTuple.get(fn); + } + + public Set getIncomingFlowNodeSet(FlowNode node) { + Set set = new HashSet(); + getIncomingFlowNodeSet(node, set); + return set; + } + + public void getIncomingFlowNodeSet(FlowNode node, Set visited) { + + for (Iterator iterator = getNodeSet().iterator(); iterator.hasNext();) { + FlowNode curNode = (FlowNode) iterator.next(); + Set edgeSet = getOutEdgeSet(curNode); + + for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) { + FlowEdge flowEdge = (FlowEdge) iterator2.next(); + + if (node.equals(getFlowNode(flowEdge.getEndTuple()))) { + FlowNode incomingNode = getFlowNode(flowEdge.getInitTuple()); + + if (incomingNode instanceof FlowReturnNode) { + FlowReturnNode rnode = (FlowReturnNode) incomingNode; + Set> nodeTupleSet = rnode.getReturnTupleSet(); + Set> rtupleSet = getReturnTupleSet(nodeTupleSet); + for (Iterator iterator3 = rtupleSet.iterator(); iterator3.hasNext();) { + NTuple nodeTuple = (NTuple) iterator3.next(); + FlowNode fn = getFlowNode(nodeTuple); + if (!visited.contains(fn)) { + visited.add(fn); + getIncomingFlowNodeSet(fn, visited); + } + } + } else { + if (!visited.contains(incomingNode)) { + visited.add(incomingNode); + getIncomingFlowNodeSet(incomingNode, visited); + } + } + + } + } + } + + } + + public boolean isParameter(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 firstIdxDesc = tuple.get(0); + return mapParamDescToIdx.get(firstIdxDesc); + } + + public FlowGraph clone() { + FlowGraph clone = new FlowGraph(md, mapParamDescToIdx); + + // clone.setNodeSet(getNodeSet()); + clone.setMapLocTupleToFlowNode(getMapLocTupleToFlowNode()); + clone.setMapFlowNodeToLocTuple(getMapFlowNodeToLocTuple()); + clone.setMapDescTupleToInferNode(getMapDescTupleToInferNode()); + + clone.setMapFlowNodeToOutEdgeSet(getMapFlowNodeToOutEdgeSet()); + clone.setReturnNodeSet(getReturnNodeSet()); + clone.setThisVarNode(getThisVarNode()); + + return clone; + } + + public Map> getMapFlowNodeToLocTuple() { + return mapFlowNodeToLocTuple; + } + + public void setMapFlowNodeToLocTuple(Map> in) { + this.mapFlowNodeToLocTuple.putAll(in); + } + + public Map> getMapFlowNodeToOutEdgeSet() { + return mapFlowNodeToOutEdgeSet; + } + + public Set getIncomingNodeSetByPrefix(Descriptor prefix) { + + Set incomingNodeSet = new HashSet(); + + for (Iterator iterator = getNodeSet().iterator(); iterator.hasNext();) { + FlowNode curNode = (FlowNode) iterator.next(); + Set outEdgeSet = getOutEdgeSet(curNode); + + for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) { + FlowEdge outEdge = (FlowEdge) iterator2.next(); + + if (outEdge.getEndTuple().startsWith(prefix)) { + incomingNodeSet.add(curNode); + recurIncomingNodeSetByPrefix(prefix, curNode, incomingNodeSet); + + } + + } + } + + return incomingNodeSet; + + } + + private void recurIncomingNodeSetByPrefix(Descriptor prefix, FlowNode node, Set visited) { + + Set inEdgeSet = getInEdgeSet(node); + + for (Iterator iterator = inEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge inEdge = (FlowEdge) iterator.next(); + + FlowNode inNode = getFlowNode(inEdge.getInitTuple()); + if (!inEdge.getInitTuple().startsWith(prefix) && !visited.contains(inNode)) { + visited.add(inNode); + recurIncomingNodeSetByPrefix(prefix, inNode, visited); + } + } + + } + + public void setMapFlowNodeToOutEdgeSet(Map> inMap) { + Set keySet = inMap.keySet(); + for (Iterator iterator = keySet.iterator(); iterator.hasNext();) { + FlowNode key = (FlowNode) iterator.next(); + Set newEdgeSet = new HashSet(); + newEdgeSet.addAll(inMap.get(key)); + mapFlowNodeToOutEdgeSet.put(key, newEdgeSet); + } + } + + private void drawEdges(FlowNode node, BufferedWriter bw, Set addedNodeSet, + Set addedEdgeSet) throws IOException { + + Set edgeSet = getOutEdgeSet(node); + + for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) { + FlowEdge flowEdge = iterator.next(); + + FlowNode u = flowEdge.getSrc(); + FlowNode v = flowEdge.getDst(); + + if (u.getDescTuple().equals(flowEdge.getInitTuple()) + && v.getDescTuple().equals(flowEdge.getEndTuple())) { + // only draw an edge of the actual value flow + + if (!addedEdgeSet.contains(flowEdge)) { + + if (!addedNodeSet.contains(u)) { + drawNode(u, bw); + addedNodeSet.add(u); + } + if (!addedNodeSet.contains(v)) { + drawNode(v, bw); + addedNodeSet.add(v); + } + + bw.write("" + u.getID() + " -> " + v.getID() + ";\n"); + addedEdgeSet.add(flowEdge); + } + } + + } + + } + + private void drawNode(FlowNode node, BufferedWriter bw) throws IOException { + if (node instanceof FlowReturnNode) { + FlowReturnNode rnode = (FlowReturnNode) node; + bw.write(node.getID() + " [label=\"" + node.getPrettyID() + "\"]" + ";\n"); + } else { + bw.write(node.getID() + " [label=\"" + node.getPrettyID() + "\"]" + ";\n"); + } + + } + + public void writeGraph() throws java.io.IOException { + writeGraph(""); + } + + public void writeGraph(String suffix) throws java.io.IOException { + + String graphName = "flowgraph_" + md.toString() + suffix; + graphName = graphName.replaceAll("[\\W]", ""); + + BufferedWriter bw = new BufferedWriter(new FileWriter(graphName + ".dot")); + bw.write("digraph " + graphName + " {\n"); + bw.write("compound=true;\n"); + + // then visit every flow node + + // Iterator iter = nodeSet.iterator(); + Iterator iter = getNodeSet().iterator(); + + Set addedEdgeSet = new HashSet(); + Set addedNodeSet = new HashSet(); + + while (iter.hasNext()) { + FlowNode node = iter.next(); + + if (node.getDescTuple().size() == 1) { + // here, we just care about the local variable + if (node.getFieldNodeSet().size() > 0) { + drawSubgraph(node, bw, addedEdgeSet); + } + } + drawEdges(node, bw, addedNodeSet, addedEdgeSet); + + } + + bw.write("}\n"); + bw.close(); + + } + + public boolean constainsNode(FlowNode node) { + return getNodeSet().contains(node); + } + + private void drawSubgraph(FlowNode node, BufferedWriter bw, Set addedSet) + throws IOException { + + bw.write("subgraph cluster_" + node.getID() + "{\n"); + bw.write("label=\"" + node.getPrettyID() + "\";\n"); + + Set fieldNodeSet = node.getFieldNodeSet(); + for (Iterator iterator = fieldNodeSet.iterator(); iterator.hasNext();) { + FlowNode fieldNode = (FlowNode) iterator.next(); + if (fieldNode.getFieldNodeSet().size() > 0) { + drawSubgraph(fieldNode, bw, addedSet); + } else { + Descriptor desc = fieldNode.getDescTuple().getLastElement(); + if (desc instanceof VarDescriptor) { + VarDescriptor varDesc = (VarDescriptor) desc; + if (varDesc.getType().isPrimitive()) { + bw.write(fieldNode.getID() + " [label=\"" + fieldNode.getPrettyID() + "\"];\n"); + } + } else if (desc instanceof FieldDescriptor) { + FieldDescriptor fieldDesc = (FieldDescriptor) desc; + if (fieldDesc.getType().isPrimitive()) { + bw.write(fieldNode.getID() + " [label=\"" + fieldNode.getPrettyID() + "\"];\n"); + } + } + } + } + + bw.write("}\n"); + } + + public void removeEdge(NTuple from, NTuple to) { + + Set toberemoved = new HashSet(); + Set edgeSet = getOutEdgeSet(getFlowNode(from)); + + for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) { + FlowEdge flowEdge = (FlowEdge) iterator.next(); + if (flowEdge.getInitTuple().equals(from) && flowEdge.getEndTuple().equals(to)) { + toberemoved.add(flowEdge); + } + } + + edgeSet.removeAll(toberemoved); + + } + + public void removeNode(FlowNode node) { + + NTuple tuple = node.getCurrentDescTuple(); + + Set inEdgeSet = getInEdgeSet(node); + for (Iterator iterator = inEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge flowEdge = (FlowEdge) iterator.next(); + if (flowEdge.getEndTuple().equals(tuple)) { + + Set outSet = getOutEdgeSet(getFlowNode(flowEdge.getInitTuple())); + Set toberemoved = new HashSet(); + for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) { + FlowEdge outEdge = (FlowEdge) iterator2.next(); + if (outEdge.getEndTuple().equals(tuple)) { + toberemoved.add(outEdge); + } + } + outSet.removeAll(toberemoved); + } + } + + Set outEdgeSet = getOutEdgeSet(node); + for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) { + FlowEdge flowEdge = (FlowEdge) iterator.next(); + if (flowEdge.getInitTuple().equals(tuple)) { + + Set inSet = getInEdgeSet(getFlowNode(flowEdge.getEndTuple())); + Set toberemoved = new HashSet(); + for (Iterator iterator2 = inSet.iterator(); iterator2.hasNext();) { + FlowEdge inEdge = (FlowEdge) iterator2.next(); + if (inEdge.getInitTuple().equals(tuple)) { + toberemoved.add(inEdge); + } + } + inSet.removeAll(toberemoved); + } + } + + for (Iterator iterator = getNodeSet().iterator(); iterator.hasNext();) { + FlowNode flowNode = (FlowNode) iterator.next(); + Set outSet = getOutEdgeSet(flowNode); + Set toberemoved = new HashSet(); + for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) { + FlowEdge flowEdge = (FlowEdge) iterator2.next(); + if (flowEdge.getInitTuple().equals(tuple) || flowEdge.getEndTuple().equals(tuple)) { + toberemoved.add(flowEdge); + } + } + outSet.removeAll(toberemoved); + } + + mapFlowNodeToOutEdgeSet.remove(node); + mapFlowNodeToInEdgeSet.remove(node); + System.out.println("REMOVING NODE=" + mapDescTupleToInferNode.get(tuple) + " from tuple=" + + tuple); + mapDescTupleToInferNode.remove(tuple); + System.out.println("mapDescTupleToInferNode=" + mapDescTupleToInferNode); + } +} \ No newline at end of file