this.infer = infer;
}
- public SSJavaLattice<String> buildLattice(HierarchyGraph inputGraph) {
+ public SSJavaLattice<String> buildLattice(Descriptor desc) {
+
+ HierarchyGraph inputGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
+ LocationSummary locSummary = infer.getLocationSummary(desc);
BasisSet basisSet = inputGraph.computeBasisSet();
debug_print(inputGraph);
Family family = generateFamily(basisSet);
Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = coveringGraph(basisSet, family);
- SSJavaLattice<String> lattice = buildLattice(basisSet, inputGraph, mapImSucc);
+ SSJavaLattice<String> lattice = buildLattice(basisSet, inputGraph, locSummary, mapImSucc);
return lattice;
}
private SSJavaLattice<String> buildLattice(BasisSet basisSet, HierarchyGraph inputGraph,
- Map<Set<Integer>, Set<Set<Integer>>> mapImSucc) {
+ LocationSummary locSummary, Map<Set<Integer>, Set<Set<Integer>>> mapImSucc) {
SSJavaLattice<String> lattice =
new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM);
Set<Integer> higher = (Set<Integer>) iterator.next();
String higherName = generateElementName(basisSet, inputGraph, mapFToLocName, higher);
+ locSummary.addMapHNodeNameToLocationName(higherName, higherName);
+
+ HNode higherNode = inputGraph.getHNode(higherName);
+ if (higherNode != null && higherNode.isSharedNode()) {
+ lattice.addSharedLoc(higherName);
+ }
Set<Set<Integer>> lowerSet = mapImSucc.get(higher);
for (Iterator iterator2 = lowerSet.iterator(); iterator2.hasNext();) {
Set<Integer> lower = (Set<Integer>) iterator2.next();
String lowerName = generateElementName(basisSet, inputGraph, mapFToLocName, lower);
+ locSummary.addMapHNodeNameToLocationName(lowerName, lowerName);
+
+ HNode lowerNode = inputGraph.getHNode(higherName);
+ if (lowerNode != null && lowerNode.isSharedNode()) {
+ lattice.addSharedLoc(lowerName);
+ }
if (higher.size() == 0) {
// empty case
return lattice;
}
- public HNode getCombinationNodeInSCGraph(Descriptor desc, HNode simpleGraphNode) {
+ public HNode getCombinationNodeInSCGraph(Descriptor desc, HNode nodeFromSimpleGraph) {
+
+ HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
+
+ if (nodeFromSimpleGraph.isSkeleton()) {
+ return scGraph.getCurrentHNode(nodeFromSimpleGraph);
+ }
Set<HNode> combineSkeletonNodeSet =
- infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(simpleGraphNode);
+ infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(nodeFromSimpleGraph);
HNode combinationNodeInSCGraph =
- infer.getSkeletonCombinationHierarchyGraph(desc).getCombinationNode(combineSkeletonNodeSet);
+ infer.getSkeletonCombinationHierarchyGraph(desc).getMapCombineNodeSetToCombinationNode()
+ .get(combineSkeletonNodeSet);
+
+ // Set<HNode> combineSkeletonNodeSet =
+ // infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(simpleGraphNode);
+ // HNode combinationNodeInSCGraph =
+ // infer.getSkeletonCombinationHierarchyGraph(desc).getCombinationNode(combineSkeletonNodeSet);
return combinationNodeInSCGraph;
}
HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
+ LocationSummary locSummary = infer.getLocationSummary(desc);
SSJavaLattice<String> lattice = skeletonLattice.clone();
- Map<TripleItem, String> mapIntermediateLocation = new HashMap<TripleItem, String>();
-
Set<HNode> visited = new HashSet<HNode>();
Set<HNode> nodeSet = simpleGraph.getNodeSet();
- // expand a combination node
Map<TripleItem, String> mapIntermediateLoc = new HashMap<TripleItem, String>();
for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
HNode node = (HNode) iterator.next();
if (!outNode.isSkeleton()) {
if (outNode.isCombinationNode()) {
+ // expand the combination node 'outNode'
+ System.out.println("-COMBINATION NODE=" + outNode);
// here we need to expand the corresponding combination location in the lattice
HNode combinationNodeInSCGraph = getCombinationNodeInSCGraph(desc, outNode);
Set<HNode> combineSkeletonNodeSet =
simpleGraph.getCombineSetByCombinationNode(outNode);
+
+ System.out.println("combineSkeletonNodeSet=" + combineSkeletonNodeSet);
+
Set<HNode> combinationNodeSet =
simpleGraph.getCombinationNodeSetByCombineNodeSet(combineSkeletonNodeSet);
+
+ System.out.println("combinationNodeSet=" + combinationNodeSet);
+
Set<HNode> endNodeSetFromSimpleGraph =
simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(outNode,
combinationNodeSet);
+ System.out.println("-endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph);
Set<HNode> endCombNodeSet = new HashSet<HNode>();
for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
HNode endNode = (HNode) iterator3.next();
endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
}
+ System.out.println("-endCombNodeSet=" + endCombNodeSet);
visited.add(outNode);
+
// follows the straight line up to another skeleton/combination node
if (endCombNodeSet.size() > 0) {
+ endCombNodeSet =
+ removeTransitivelyReachToNode(desc, combinationNodeInSCGraph, endCombNodeSet);
recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
- mapIntermediateLoc, 1, outNode);
+ mapIntermediateLoc, 1, locSummary, outNode);
+ // recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
+ // mapIntermediateLoc, 1, locSummary, outNode);
}
} else {
// we have a node that is neither combination or skeleton node
- HNode startNode = node;
+ System.out.println("skeleton node=" + node + " outNode=" + outNode);
+ HNode startNode = scGraph.getCurrentHNode(node);
+
+ // if (node.getDescriptor() != null) {
+ // // node is a skeleton node and it might be merged into another node in the SC
+ // graph.
+ // startNode = scGraph.getHNode(node.getDescriptor());
+ // } else {
+ // // this node has already been merged before the SC graph.
+ // startNode = node;
+ // }
+
Set<HNode> endNodeSetFromSimpleGraph =
simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(outNode, null);
+ System.out.println("endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph
+ + " from=" + outNode);
Set<HNode> endCombNodeSet = new HashSet<HNode>();
for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
HNode endNode = (HNode) iterator3.next();
visited.add(outNode);
if (endCombNodeSet.size() > 0) {
// follows the straight line up to another skeleton/combination node
+ endCombNodeSet = removeTransitivelyReachToNode(desc, startNode, endCombNodeSet);
recurDFSNormalNode(desc, lattice, startNode, endCombNodeSet, visited,
- mapIntermediateLoc, 1, outNode);
-
+ mapIntermediateLoc, 1, locSummary, outNode);
}
-
}
}
}
+ } else if (!node.isSkeleton() && !node.isCombinationNode() && !node.isMergeNode()
+ && !visited.contains(node)) {
+ // an intermediate node 'node' is located between "TOP" location and a skeleton node
+
+ Set<HNode> outNodeSet = simpleGraph.getOutgoingNodeSet(node);
+ Set<String> belowSkeletonLocNameSet = new HashSet<String>();
+ for (Iterator iterator2 = outNodeSet.iterator(); iterator2.hasNext();) {
+ HNode outNode = (HNode) iterator2.next();
+ if (outNode.isSkeleton()) {
+ belowSkeletonLocNameSet.add(scGraph.getCurrentHNode(outNode).getName());
+ }
+ }
+ String newLocName = "ILOC" + (seed++);
+ lattice.insertNewLocationBetween(lattice.getTopItem(), belowSkeletonLocNameSet, newLocName);
+ locSummary.addMapHNodeNameToLocationName(node.getName(), newLocName);
}
}
}
+ private Set<HNode> removeTransitivelyReachToNode(Descriptor desc, HNode startNode,
+ Set<HNode> endNodeSet) {
+
+ // if an end node is not directly connected to the start node in the SC graph
+ // replace it with a directly connected one which transitively reaches to it.
+
+ HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
+ Set<HNode> newEndNodeSet = new HashSet<HNode>();
+
+ for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
+ HNode endNode = (HNode) iterator.next();
+ if (scGraph.isDirectlyConnectedTo(startNode, endNode)) {
+ newEndNodeSet.add(endNode);
+ } else {
+ HNode newEndNode =
+ getDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, endNode);
+ System.out.println("#### old END NODE=" + endNode + " --->" + newEndNode);
+ newEndNodeSet.add(newEndNode);
+ }
+ }
+
+ System.out.println("removeTransitivelyReachToNode=" + endNodeSet + " newSet=" + newEndNodeSet);
+
+ return newEndNodeSet;
+
+ }
+
+ private HNode getDirectlyReachableNodeFromStartNodeReachToEndNode(HierarchyGraph scGraph,
+ HNode startNode, HNode endNode) {
+ Set<HNode> connected = new HashSet<HNode>();
+ recurDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, endNode, connected);
+ return connected.iterator().next();
+ }
+
+ private void recurDirectlyReachableNodeFromStartNodeReachToEndNode(HierarchyGraph scGraph,
+ HNode startNode, HNode curNode, Set<HNode> connected) {
+
+ Set<HNode> inNodeSet = scGraph.getIncomingNodeSet(curNode);
+ for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
+ HNode inNode = (HNode) iterator.next();
+ if (inNode.equals(startNode)) {
+ connected.add(curNode);
+ } else {
+ System.out.println("inNode=" + inNode);
+ recurDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, inNode, connected);
+ }
+ }
+
+ }
+
private void recurDFSNormalNode(Descriptor desc, SSJavaLattice<String> lattice, HNode startNode,
Set<HNode> endNodeSet, Set<HNode> visited, Map<TripleItem, String> mapIntermediateLoc,
- int idx, HNode curNode) {
+ int idx, LocationSummary locSummary, HNode curNode) {
TripleItem item = new TripleItem(startNode, endNodeSet, idx);
-
+ System.out.println("item=" + item);
if (!mapIntermediateLoc.containsKey(item)) {
// need to create a new intermediate location in the lattice
String newLocName = "ILOC" + (seed++);
}
String locName = mapIntermediateLoc.get(item);
+ locSummary.addMapHNodeNameToLocationName(curNode.getName(), locName);
HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
Set<HNode> outSet = graph.getOutgoingNodeSet(curNode);
if (!outNode.isSkeleton() && !outNode.isCombinationNode() && !visited.contains(outNode)) {
visited.add(outNode);
recurDFSNormalNode(desc, lattice, startNode, endNodeSet, visited, mapIntermediateLoc,
- idx + 1, outNode);
+ idx + 1, locSummary, outNode);
}
}
private void recurDFS(Descriptor desc, SSJavaLattice<String> lattice,
HNode combinationNodeInSCGraph, Set<HNode> endNodeSet, Set<HNode> visited,
- Map<TripleItem, String> mapIntermediateLoc, int idx, HNode curNode) {
+ Map<TripleItem, String> mapIntermediateLoc, int idx, LocationSummary locSummary, HNode curNode) {
TripleItem item = new TripleItem(combinationNodeInSCGraph, endNodeSet, idx);
if (!mapIntermediateLoc.containsKey(item)) {
// need to create a new intermediate location in the lattice
- String newLocName = "ILOC" + (seed++);
String above;
if (idx == 1) {
- above = combinationNodeInSCGraph.getName();
+ String newLocName = combinationNodeInSCGraph.getName();
+ mapIntermediateLoc.put(item, newLocName);
} else {
+ String newLocName = "ILOC" + (seed++);
int prevIdx = idx - 1;
TripleItem prevItem = new TripleItem(combinationNodeInSCGraph, endNodeSet, prevIdx);
above = mapIntermediateLoc.get(prevItem);
- }
- Set<String> belowSet = new HashSet<String>();
- for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
- HNode endNode = (HNode) iterator.next();
- belowSet.add(endNode.getName());
+ Set<String> belowSet = new HashSet<String>();
+ for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
+ HNode endNode = (HNode) iterator.next();
+ belowSet.add(endNode.getName());
+ }
+ lattice.insertNewLocationBetween(above, belowSet, newLocName);
+ mapIntermediateLoc.put(item, newLocName);
+
}
- lattice.insertNewLocationBetween(above, belowSet, newLocName);
- mapIntermediateLoc.put(item, newLocName);
+ }
- String locName = mapIntermediateLoc.get(item);
+ String locName = mapIntermediateLoc.get(item);
+ locSummary.addMapHNodeNameToLocationName(curNode.getName(), locName);
- }
+ System.out.println("-TripleItem=" + item);
+ System.out.println("-curNode=" + curNode.getName() + " locName=" + locName);
HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
Set<HNode> outSet = graph.getOutgoingNodeSet(curNode);
if (combinationNodeInSCGraph.equals(getCombinationNodeInSCGraph(desc, outNode))) {
visited.add(outNode);
recurDFS(desc, lattice, combinationNodeInSCGraph, endNodeSet, visited,
- mapIntermediateLoc, idx + 1, outNode);
+ mapIntermediateLoc, idx + 1, locSummary, outNode);
}
}
}
MethodDescriptor md;
Set<FlowNode> nodeSet;
+
Set<FlowNode> returnNodeSet;
FlowNode thisVarNode;
+ Map<FlowNode, Set<FlowEdge>> mapFlowNodeToOutEdgeSet;
+
Map<NTuple<Location>, FlowNode> mapLocTupleToFlowNode;
Map<FlowNode, NTuple<Location>> mapFlowNodeToLocTuple;
// maps the composite representation of field/var descriptors to infer nodes
Map<NTuple<Descriptor>, FlowNode> mapDescTupleToInferNode;
- // maps an infer node to the set of neighbors which is pointed by the node
- Map<NTuple<Descriptor>, Set<FlowNode>> mapNodeToNeighborSet;
-
// maps a paramter descriptor to its index
Map<Descriptor, Integer> mapParamDescToIdx;
+ // DS for the lattice generation
Map<Integer, FlowNode> mapIdxToFlowNode;
public static int interseed = 0;
this.mapLocTupleToFlowNode = new HashMap<NTuple<Location>, FlowNode>();
this.nodeSet = new HashSet<FlowNode>();
this.mapDescTupleToInferNode = new HashMap<NTuple<Descriptor>, FlowNode>();
- this.mapNodeToNeighborSet = new HashMap<NTuple<Descriptor>, Set<FlowNode>>();
this.mapParamDescToIdx = new HashMap<Descriptor, Integer>();
this.mapParamDescToIdx.putAll(mapParamDescToIdx);
this.returnNodeSet = new HashSet<FlowNode>();
this.mapIdxToFlowNode = new HashMap<Integer, FlowNode>();
+ this.mapFlowNodeToOutEdgeSet = new HashMap<FlowNode, Set<FlowEdge>>();
if (!md.isStatic()) {
// create a node for 'this' varialbe
}
+ public Map<NTuple<Descriptor>, FlowNode> getMapDescTupleToInferNode() {
+ return mapDescTupleToInferNode;
+ }
+
+ public void setMapDescTupleToInferNode(Map<NTuple<Descriptor>, FlowNode> in) {
+ this.mapDescTupleToInferNode.putAll(in);
+ }
+
+ public Map<NTuple<Location>, FlowNode> getMapLocTupleToFlowNode() {
+ return mapLocTupleToFlowNode;
+ }
+
+ public void setMapLocTupleToFlowNode(Map<NTuple<Location>, FlowNode> in) {
+ this.mapLocTupleToFlowNode.putAll(in);
+ }
+
+ public void setNodeSet(Set<FlowNode> in) {
+ this.nodeSet.addAll(in);
+ }
+
+ public void setReturnNodeSet(Set<FlowNode> in) {
+ this.returnNodeSet.addAll(in);
+ }
+
+ public void setThisVarNode(FlowNode thisVarNode) {
+ this.thisVarNode = thisVarNode;
+ }
+
public Map<Descriptor, Integer> getMapParamDescToIdx() {
return mapParamDescToIdx;
}
return md;
}
- public void addNeighbor(FlowNode node, FlowNode neighbor) {
- Set<FlowNode> set = mapNodeToNeighborSet.get(node);
- if (set == null) {
- set = new HashSet<FlowNode>();
- }
- set.add(neighbor);
-
- // System.out.println("add a new neighbor " + neighbor + " to " + node);
- }
-
public boolean isParamDesc(Descriptor desc) {
if (mapParamDescToIdx.containsKey(desc)) {
FlowNode fromNode = mapDescTupleToInferNode.get(fromDescTuple);
FlowNode toNode = mapDescTupleToInferNode.get(toDescTuple);
- Set<FlowEdge> fromNodeOutEdgeSet = fromNode.getOutEdgeSet();
+ Set<FlowEdge> fromNodeOutEdgeSet = getOutEdgeSet(fromNode);
for (Iterator iterator = fromNodeOutEdgeSet.iterator(); iterator.hasNext();) {
FlowEdge flowEdge = (FlowEdge) iterator.next();
if (flowEdge.getDst().equals(toNode)) {
return false;
}
+ public Set<FlowEdge> getOutEdgeSet(FlowNode node) {
+ if (!mapFlowNodeToOutEdgeSet.containsKey(node)) {
+ mapFlowNodeToOutEdgeSet.put(node, new HashSet<FlowEdge>());
+ }
+ return mapFlowNodeToOutEdgeSet.get(node);
+ }
+
public void addValueFlowEdge(NTuple<Descriptor> fromDescTuple, NTuple<Descriptor> toDescTuple) {
FlowNode fromNode = getFlowNode(fromDescTuple);
NTuple<Descriptor> endTuple) {
FlowEdge edge = new FlowEdge(fromNode, toNode, initTuple, endTuple);
- fromNode.addOutEdge(edge);
+ addOutEdge(fromNode, edge);
+
+ // System.out.println("add a new edge=" + edge);
+ }
- System.out.println("add a new edge=" + edge);
+ private void addOutEdge(FlowNode fromNode, FlowEdge edge) {
+ if (!mapFlowNodeToOutEdgeSet.containsKey(fromNode)) {
+ mapFlowNodeToOutEdgeSet.put(fromNode, new HashSet<FlowEdge>());
+ }
+ mapFlowNodeToOutEdgeSet.get(fromNode).add(edge);
}
public FlowNode getFlowNode(NTuple<Descriptor> descTuple) {
private void recurLocalReachFlowNodeSet(FlowNode fn, Set<FlowNode> visited) {
- for (Iterator iterator = fn.getOutEdgeSet().iterator(); iterator.hasNext();) {
+ Set<FlowEdge> outEdgeSet = getOutEdgeSet(fn);
+ for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) {
FlowEdge edge = (FlowEdge) iterator.next();
FlowNode dstNode = edge.getDst();
private void getReachFlowNodeSetFrom(FlowNode fn, Set<FlowNode> visited) {
- for (Iterator iterator = fn.getOutEdgeSet().iterator(); iterator.hasNext();) {
+ Set<FlowEdge> outEdgeSet = getOutEdgeSet(fn);
+ for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) {
FlowEdge edge = (FlowEdge) iterator.next();
if (fn.equals(getFlowNode(edge.getInitTuple()))) {
// }
public Set<NTuple<Location>> getReachableFlowTupleSet(Set<NTuple<Location>> visited, FlowNode fn) {
- for (Iterator iterator = fn.getOutEdgeSet().iterator(); iterator.hasNext();) {
+
+ Set<FlowEdge> outEdgeSet = getOutEdgeSet(fn);
+
+ for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) {
FlowEdge edge = (FlowEdge) iterator.next();
if (fn.getDescTuple().equals(edge.getInitTuple())) {
} else {
loc = new Location(cd, curDesc.getSymbol());
loc.setLocDescriptor(curDesc);
- cd = ((FieldDescriptor) curDesc).getType().getClassDesc();
+
+ if (curDesc instanceof FieldDescriptor) {
+ cd = ((FieldDescriptor) curDesc).getType().getClassDesc();
+ } else {
+ cd = ((LocationDescriptor) curDesc).getEnclosingClassDesc();
+ }
+
}
locTuple.add(loc);
}
for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
FlowNode curNode = (FlowNode) iterator.next();
- Set<FlowEdge> edgeSet = curNode.getOutEdgeSet();
+ Set<FlowEdge> edgeSet = getOutEdgeSet(curNode);
for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
FlowEdge flowEdge = (FlowEdge) iterator2.next();
for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
FlowNode node = (FlowNode) iterator.next();
- Set<FlowEdge> edgeSet = node.getOutEdgeSet();
+
+ Set<FlowEdge> edgeSet = getOutEdgeSet(node);
for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
FlowEdge flowEdge = (FlowEdge) iterator2.next();
if (dstTuple.equals(flowEdge.getEndTuple())) {
return mapParamDescToIdx.containsKey(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<FlowNode, NTuple<Location>> getMapFlowNodeToLocTuple() {
+ return mapFlowNodeToLocTuple;
+ }
+
+ public void setMapFlowNodeToLocTuple(Map<FlowNode, NTuple<Location>> in) {
+ this.mapFlowNodeToLocTuple.putAll(in);
+ }
+
+ public Map<FlowNode, Set<FlowEdge>> getMapFlowNodeToOutEdgeSet() {
+ return mapFlowNodeToOutEdgeSet;
+ }
+
+ public void setMapFlowNodeToOutEdgeSet(Map<FlowNode, Set<FlowEdge>> inMap) {
+ Set<FlowNode> keySet = inMap.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ FlowNode key = (FlowNode) iterator.next();
+ Set<FlowEdge> newEdgeSet = new HashSet<FlowEdge>();
+ newEdgeSet.addAll(inMap.get(key));
+ mapFlowNodeToOutEdgeSet.put(key, newEdgeSet);
+ }
+ }
+
private void drawEdges(FlowNode node, BufferedWriter bw, Set<FlowNode> addedNodeSet,
Set<FlowEdge> addedEdgeSet) throws IOException {
- Set<FlowEdge> edgeSet = node.getOutEdgeSet();
+ Set<FlowEdge> edgeSet = getOutEdgeSet(node);
for (Iterator<FlowEdge> iterator = edgeSet.iterator(); iterator.hasNext();) {
FlowEdge flowEdge = iterator.next();
}
public void writeGraph() throws java.io.IOException {
+ writeGraph("");
+ }
+
+ public void writeGraph(String suffix) throws java.io.IOException {
- String graphName = "flowgraph_" + md.toString();
+ String graphName = "flowgraph_" + md.toString() + suffix;
graphName = graphName.replaceAll("[\\W]", "");
BufferedWriter bw = new BufferedWriter(new FileWriter(graphName + ".dot"));
Descriptor desc;
String name;
- Map<Descriptor, HNode> mapDescToHNode;
- Map<HNode, Set<Descriptor>> mapHNodeToDescSet;
+
+ // graph structure
Map<HNode, Set<HNode>> mapHNodeToIncomingSet;
Map<HNode, Set<HNode>> mapHNodeToOutgoingSet;
+
+ Map<Descriptor, HNode> mapDescToHNode;
+ Map<HNode, Set<Descriptor>> mapHNodeToDescSet;
+ Map<HNode, HNode> mapHNodeToCurrentHNode; // tracking which node corresponds to the initial node
+ Map<HNode, Set<HNode>> mapMergeNodetoMergingSet;
+
+ // data structures for a combination node
Map<Set<HNode>, HNode> mapSkeletonNodeSetToCombinationNode;
Map<HNode, Set<HNode>> mapCombinationNodeToCombineNodeSet;
Map<Set<HNode>, HNode> mapCombineNodeSetToCombinationNode;
Map<Set<HNode>, Set<HNode>> mapCombineNodeSetToOutgoingNodeSet;
+
Map<HNode, String> mapHNodeToLocationName;
Set<HNode> nodeSet;
mapHNodeToBasis = new HashMap<HNode, Set<Integer>>();
mapHNodeToLocationName = new HashMap<HNode, String>();
+ mapMergeNodetoMergingSet = new HashMap<HNode, Set<HNode>>();
+
+ mapHNodeToCurrentHNode = new HashMap<HNode, HNode>();
}
mapHNodeToDescSet.putAll(map);
}
+ public Map<HNode, HNode> getMapHNodeToCurrentHNode() {
+ return mapHNodeToCurrentHNode;
+ }
+
+ public void setMapHNodeToCurrentHNode(Map<HNode, HNode> mapHNodeToCurrentHNode) {
+ this.mapHNodeToCurrentHNode = mapHNodeToCurrentHNode;
+ }
+
public Map<Descriptor, HNode> getMapDescToHNode() {
return mapDescToHNode;
}
if (possibleCycleSet.size() == 1) {
if (dstHNode.isSharedNode()) {
// it has already been assigned shared node.
- return;
+ } else {
+ dstHNode.setSharedNode(true);
}
+ return;
}
HNode newMergeNode = mergeNodes(possibleCycleSet, false);
return mapDescToHNode.get(d);
}
+ public HNode getHNode(String name) {
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ HNode node = (HNode) iterator.next();
+ if (node.getName().equals(name)) {
+ return node;
+ }
+ }
+ return null;
+ }
+
private void mappingDescriptorToHNode(Descriptor desc, HNode node) {
mapDescToHNode.put(desc, node);
if (!mapHNodeToDescSet.containsKey(node)) {
skeletonGraph.setMapDescToHNode(getMapDescToHNode());
skeletonGraph.setMapHNodeToDescSet(getMapHNodeToDescSet());
+ skeletonGraph.setMapHNodetoMergeSet(getMapHNodetoMergeSet());
+ skeletonGraph.setMapHNodeToCurrentHNode(getMapHNodeToCurrentHNode());
return skeletonGraph;
} while (isUpdated);
}
- private Set<HNode> getIncomingNodeSet(HNode node) {
+ public Set<HNode> getIncomingNodeSet(HNode node) {
if (!mapHNodeToIncomingSet.containsKey(node)) {
mapHNodeToIncomingSet.put(node, new HashSet<HNode>());
}
}
String nodeName;
+ boolean isMergeNode = false;
if (onlyCombinationNodes) {
nodeName = "Comb" + (seed++);
} else {
nodeName = "Node" + (seed++);
+ isMergeNode = true;
}
HNode newMergeNode = new HNode(nodeName);
+ newMergeNode.setMergeNode(isMergeNode);
nodeSet.add(newMergeNode);
nodeSet.removeAll(set);
}
}
+ Set<HNode> mergedSkeletonNode = new HashSet<HNode>();
+ for (Iterator<HNode> iter = set.iterator(); iter.hasNext();) {
+ HNode merged = iter.next();
+ if (merged.isSkeleton()) {
+ mergedSkeletonNode.add(merged);
+ }
+ }
+ mapMergeNodetoMergingSet.put(newMergeNode, mergedSkeletonNode);
+ for (Iterator iterator = mergedSkeletonNode.iterator(); iterator.hasNext();) {
+ HNode mergedNode = (HNode) iterator.next();
+ addMapHNodeToCurrentHNode(mergedNode, newMergeNode);
+ }
+
System.out.println("###MERGING NODE=" + set + " new node=" + newMergeNode);
return newMergeNode;
}
+ private void addMapHNodeToCurrentHNode(HNode curNode, HNode newNode) {
+ if (curNode.isMergeNode()) {
+ Set<HNode> mergingSet = getMergingSet(curNode);
+ for (Iterator iterator = mergingSet.iterator(); iterator.hasNext();) {
+ HNode mergingNode = (HNode) iterator.next();
+ mapHNodeToCurrentHNode.put(mergingNode, newNode);
+ }
+ } else {
+ mapHNodeToCurrentHNode.put(curNode, newNode);
+ }
+ }
+
+ public HNode getCurrentHNode(HNode node) {
+ if (!mapHNodeToCurrentHNode.containsKey(node)) {
+ mapHNodeToCurrentHNode.put(node, node);
+ }
+ return mapHNodeToCurrentHNode.get(node);
+ }
+
+ private Set<HNode> getMergingSet(HNode mergeNode) {
+ Set<HNode> mergingSet = new HashSet<HNode>();
+ Set<HNode> mergedNode = mapMergeNodetoMergingSet.get(mergeNode);
+ for (Iterator iterator = mergedNode.iterator(); iterator.hasNext();) {
+ HNode node = (HNode) iterator.next();
+ if (node.isMergeNode()) {
+ mergingSet.addAll(getMergingSet(node));
+ } else {
+ mergingSet.add(node);
+ }
+ }
+ return mergingSet;
+ }
+
private Set<Descriptor> getDescSetOfNode(HNode node) {
if (!mapHNodeToDescSet.containsKey(node)) {
mapHNodeToDescSet.put(node, new HashSet<Descriptor>());
return mapCombineNodeSetToCombinationNode.get(combineSet);
}
+ public Map<Set<HNode>, HNode> getMapCombineNodeSetToCombinationNode() {
+ return mapCombineNodeSetToCombinationNode;
+ }
+
public Set<Set<HNode>> getCombineNodeSet() {
return mapCombineNodeSetToOutgoingNodeSet.keySet();
}
- public void insertCombinationNodesToGraph(HierarchyGraph hierarchyGraph) {
+ public void insertCombinationNodesToGraph(HierarchyGraph simpleHierarchyGraph) {
// add a new combination node where parameter/field flows are actually combined.
- hierarchyGraph.identifyCombinationNodes();
+ simpleHierarchyGraph.identifyCombinationNodes();
- Set<Set<HNode>> keySet = hierarchyGraph.getCombineNodeSet();
+ Set<Set<HNode>> keySet = simpleHierarchyGraph.getCombineNodeSet();
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
Set<HNode> combineSet = (Set<HNode>) iterator.next();
System.out.println("--combineSet=" + combineSet);
}
// add an edge from the combination node to outgoing nodes
- Set<HNode> outSet = hierarchyGraph.getOutgoingNodeSetByCombineSet(combineSet);
+ Set<HNode> outSet = simpleHierarchyGraph.getOutgoingNodeSetByCombineSet(combineSet);
for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
HNode curNode = (HNode) iterator2.next();
if (curNode.isCombinationNode()) {
- Set<HNode> combineNode = hierarchyGraph.getCombineSetByCombinationNode(curNode);
+ Set<HNode> combineNode = simpleHierarchyGraph.getCombineSetByCombinationNode(curNode);
HNode outNode = getCombinationNode(combineNode);
addEdgeWithNoCycleCheck(combinationNode, outNode);
} else if (curNode.isSkeleton()) {
- addEdgeWithNoCycleCheck(combinationNode, curNode);
+ // HNode dstNode = getHNode(curNode.getDescriptor());
+ HNode dstNode = getCurrentHNode(curNode);
+ addEdgeWithNoCycleCheck(combinationNode, dstNode);
}
}
clone.setMapHNodeToOutgoingSet(getMapHNodeToOutgoingSet());
clone.setMapDescToHNode(getMapDescToHNode());
clone.setMapHNodeToDescSet(getMapHNodeToDescSet());
-
+ clone.setMapHNodetoMergeSet(getMapHNodetoMergeSet());
+ clone.setMapHNodeToCurrentHNode(getMapHNodeToCurrentHNode());
return clone;
}
+ public Map<HNode, Set<HNode>> getMapHNodetoMergeSet() {
+ return mapMergeNodetoMergingSet;
+ }
+
+ public void setMapHNodetoMergeSet(Map<HNode, Set<HNode>> mapHNodetoMergeSet) {
+ this.mapMergeNodetoMergingSet = mapHNodetoMergeSet;
+ }
+
public Set<HNode> getOutgoingNodeSetByCombineSet(Set<HNode> combineSet) {
if (!mapCombineNodeSetToOutgoingNodeSet.containsKey(combineSet)) {
HNode node = (HNode) iterator.next();
if (!node.isSkeleton()) {
Set<HNode> reachToSet = getSkeleteNodeSetReachTo(node);
- // if (reachToSet.size() > 1) {
- if (countSkeletonNodes(reachToSet) > 1) {
+ if (reachToSet.size() > 1) {
+ // if (countSkeletonNodes(reachToSet) > 1) {
System.out.println("-node=" + node + " reachToSet=" + reachToSet);
System.out.println("-set combinationnode=" + node);
node.setCombinationNode(true);
basis.remove(getHNodeIndex(node));
for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
HNode reachableNode = (HNode) iterator2.next();
+ System.out.println("reachableNode=" + reachableNode);
int idx = getHNodeIndex(reachableNode);
basis.remove(idx);
}
}
}
+ public boolean contains(HNode node) {
+ return nodeSet.contains(node);
+ }
+
+ public boolean isDirectlyConnectedTo(HNode src, HNode dst) {
+ return getOutgoingNodeSet(src).contains(dst);
+ }
+
+ private String convertMergeSetToString(Set<HNode> mergeSet) {
+ String str = "";
+ for (Iterator iterator = mergeSet.iterator(); iterator.hasNext();) {
+ HNode merged = (HNode) iterator.next();
+ if (merged.isMergeNode()) {
+ str += " " + convertMergeSetToString(mapMergeNodetoMergingSet.get(merged));
+ } else {
+ str += " " + merged.getName();
+ }
+ }
+ return str;
+ }
+
private void drawNode(BufferedWriter bw, HNode node) throws IOException {
- String nodeName = node.toString();
- nodeName = nodeName.substring(1, nodeName.length() - 1);
+ String nodeName;
+ if (node.isMergeNode()) {
+ nodeName = node.getNamePropertyString();
+ Set<HNode> mergeSet = mapMergeNodetoMergingSet.get(node);
+ nodeName += ":" + convertMergeSetToString(mergeSet);
+ } else {
+ nodeName = node.getNamePropertyString();
+ }
bw.write(node.getName() + " [label=\"" + nodeName + "\"]" + ";\n");
}
-
}
State state;
SSJavaAnalysis ssjava;
- List<ClassDescriptor> toanalyzeList;
- List<MethodDescriptor> toanalyzeMethodList;
+ List<ClassDescriptor> temp_toanalyzeList;
+ List<MethodDescriptor> temp_toanalyzeMethodList;
Map<MethodDescriptor, FlowGraph> mapMethodDescriptorToFlowGraph;
+ LinkedList<MethodDescriptor> toanalyze_methodDescList;
+
// map a method descriptor to its set of parameter descriptors
Map<MethodDescriptor, Set<Descriptor>> mapMethodDescriptorToParamDescSet;
// map a method/class descriptor to a skeleton hierarchy graph with combination nodes
private Map<Descriptor, HierarchyGraph> mapDescriptorToCombineSkeletonHierarchyGraph;
- // map a method descriptor to a method summary
- private Map<MethodDescriptor, MethodSummary> mapMethodDescToMethodSummary;
-
// map a descriptor to a simple lattice
private Map<Descriptor, SSJavaLattice<String>> mapDescriptorToSimpleLattice;
private Map<Descriptor, Integer> mapDescToDefinitionLine;
+ private Map<Descriptor, LocationSummary> mapDescToLocationSummary;
+
+ // maps a method descriptor to a sub global flow graph that captures all value flows caused by the
+ // set of callees reachable from the method
+ private Map<MethodDescriptor, FlowGraph> mapMethodDescriptorToSubGlobalFlowGraph;
+
public static final String GLOBALLOC = "GLOBALLOC";
public static final String TOPLOC = "TOPLOC";
public LocationInference(SSJavaAnalysis ssjava, State state) {
this.ssjava = ssjava;
this.state = state;
- this.toanalyzeList = new ArrayList<ClassDescriptor>();
- this.toanalyzeMethodList = new ArrayList<MethodDescriptor>();
+ this.temp_toanalyzeList = new ArrayList<ClassDescriptor>();
+ this.temp_toanalyzeMethodList = new ArrayList<MethodDescriptor>();
this.mapMethodDescriptorToFlowGraph = new HashMap<MethodDescriptor, FlowGraph>();
this.cd2lattice = new HashMap<ClassDescriptor, SSJavaLattice<String>>();
this.md2lattice = new HashMap<MethodDescriptor, SSJavaLattice<String>>();
new HashMap<MethodDescriptor, Set<FlowNode>>();
this.mapDescriptorToHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
- this.mapMethodDescToMethodSummary = new HashMap<MethodDescriptor, MethodSummary>();
this.mapMethodInvokeNodeToBaseTuple = new HashMap<MethodInvokeNode, NTuple<Descriptor>>();
this.mapDescriptorToSkeletonHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
this.mapDescriptorToSimpleLattice = new HashMap<Descriptor, SSJavaLattice<String>>();
+ this.mapDescToLocationSummary = new HashMap<Descriptor, LocationSummary>();
+
+ mapMethodDescriptorToSubGlobalFlowGraph = new HashMap<MethodDescriptor, FlowGraph>();
+
}
public void setupToAnalyze() {
SymbolTable classtable = state.getClassSymbolTable();
- toanalyzeList.clear();
- toanalyzeList.addAll(classtable.getValueSet());
+ temp_toanalyzeList.clear();
+ temp_toanalyzeList.addAll(classtable.getValueSet());
// Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
// public int compare(ClassDescriptor o1, ClassDescriptor o2) {
// return o1.getClassName().compareToIgnoreCase(o2.getClassName());
public void setupToAnalazeMethod(ClassDescriptor cd) {
SymbolTable methodtable = cd.getMethodTable();
- toanalyzeMethodList.clear();
- toanalyzeMethodList.addAll(methodtable.getValueSet());
- Collections.sort(toanalyzeMethodList, new Comparator<MethodDescriptor>() {
+ temp_toanalyzeMethodList.clear();
+ temp_toanalyzeMethodList.addAll(methodtable.getValueSet());
+ Collections.sort(temp_toanalyzeMethodList, new Comparator<MethodDescriptor>() {
public int compare(MethodDescriptor o1, MethodDescriptor o2) {
return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
}
}
public boolean toAnalyzeMethodIsEmpty() {
- return toanalyzeMethodList.isEmpty();
+ return temp_toanalyzeMethodList.isEmpty();
}
public boolean toAnalyzeIsEmpty() {
- return toanalyzeList.isEmpty();
+ return temp_toanalyzeList.isEmpty();
}
public ClassDescriptor toAnalyzeNext() {
- return toanalyzeList.remove(0);
+ return temp_toanalyzeList.remove(0);
}
public MethodDescriptor toAnalyzeMethodNext() {
- return toanalyzeMethodList.remove(0);
+ return temp_toanalyzeMethodList.remove(0);
}
public void inference() {
// 1) construct value flow graph
constructFlowGraph();
+ constructGlobalFlowGraph();
+
+ System.exit(0);
+
constructHierarchyGraph();
debug_writeHierarchyDotFiles();
debug_writeLattices();
+ generateMethodSummary();
+
System.exit(0);
// 2) construct lattices
}
+ private void constructGlobalFlowGraph() {
+
+ System.out.println("");
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
+
+ System.out.println("@@@methodDescList=" + methodDescList);
+ // System.exit(0);
+
+ while (!methodDescList.isEmpty()) {
+ MethodDescriptor md = methodDescList.removeLast();
+ if (state.SSJAVADEBUG) {
+ System.out.println();
+ System.out.println("SSJAVA: Constructing a global flow graph: " + md);
+
+ FlowGraph flowGraph = getFlowGraph(md);
+ FlowGraph subGlobalFlowGraph = flowGraph.clone();
+ mapMethodDescriptorToSubGlobalFlowGraph.put(md, subGlobalFlowGraph);
+
+ addValueFlowsFromCalleeSubGlobalFlowGraph(md, subGlobalFlowGraph);
+
+ try {
+ subGlobalFlowGraph.writeGraph("_SUBGLOBAL");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // FlowGraph fg = new FlowGraph(md, mapParamDescToIdx);
+ // mapMethodDescriptorToFlowGraph.put(md, fg);
+ // analyzeMethodBody(md.getClassDesc(), md);
+
+ }
+ }
+ // _debug_printGraph();
+
+ }
+
+ private void addValueFlowsFromCalleeSubGlobalFlowGraph(MethodDescriptor mdCaller,
+ FlowGraph subGlobalFlowGraph) {
+
+ // the transformation for a call site propagates flows through parameters
+ // if the method is virtual, it also grab all relations from any possible
+ // callees
+
+ Set<MethodInvokeNode> setMethodInvokeNode = getMethodInvokeNodeSet(mdCaller);
+
+ for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
+ MethodInvokeNode min = (MethodInvokeNode) iterator.next();
+ MethodDescriptor mdCallee = min.getMethod();
+ Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
+ if (mdCallee.isStatic()) {
+ setPossibleCallees.add(mdCallee);
+ } else {
+ Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
+ // removes method descriptors that are not invoked by the caller
+ calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
+ setPossibleCallees.addAll(calleeSet);
+ }
+
+ for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
+ MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
+ propagateValueFlowsToCallerFromSubGlobalFlowGraph(min, mdCaller, possibleMdCallee);
+ // propagateFlowsToCallerWithNoCompositeLocation(min, mdCaller, possibleMdCallee);
+ }
+
+ }
+
+ }
+
+ private void propagateValueFlowsToCallerFromSubGlobalFlowGraph(MethodInvokeNode min,
+ MethodDescriptor mdCaller, MethodDescriptor possibleMdCallee) {
+
+ NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
+
+ FlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
+ FlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(possibleMdCallee);
+
+ int numParam = calleeSubGlobalGraph.getNumParameters();
+ for (int idx = 0; idx < numParam; idx++) {
+ FlowNode paramNode = calleeSubGlobalGraph.getParamFlowNode(idx);
+ NodeTupleSet argTupleSet = mapMethodInvokeNodeToArgIdxMap.get(min).get(idx);
+ System.out.println("argTupleSet=" + argTupleSet + " param=" + paramNode);
+ for (Iterator<NTuple<Descriptor>> iter = argTupleSet.iterator(); iter.hasNext();) {
+ NTuple<Descriptor> argTuple = iter.next();
+ addValueFlowsFromCalleeParam(calleeSubGlobalGraph, paramNode, callerSubGlobalGraph,
+ argTuple, baseTuple);
+ }
+ }
+
+ }
+
+ private void addValueFlowsFromCalleeParam(FlowGraph calleeSubGlobalGraph, FlowNode paramNode,
+ FlowGraph callerSubGlobalGraph, NTuple<Descriptor> argTuple, NTuple<Descriptor> baseTuple) {
+
+ Set<FlowNode> visited = new HashSet<FlowNode>();
+
+ visited.add(paramNode);
+ recurAddValueFlowsFromCalleeParam(calleeSubGlobalGraph, paramNode, callerSubGlobalGraph,
+ argTuple, visited, baseTuple);
+ }
+
+ private void recurAddValueFlowsFromCalleeParam(FlowGraph calleeSubGlobalGraph,
+ FlowNode calleeSrcNode, FlowGraph callerSubGlobalGraph, NTuple<Descriptor> callerSrcTuple,
+ Set<FlowNode> visited, NTuple<Descriptor> baseTuple) {
+
+ MethodDescriptor mdCallee = calleeSubGlobalGraph.getMethodDescriptor();
+
+ Set<FlowEdge> edgeSet = calleeSubGlobalGraph.getOutEdgeSet(calleeSrcNode);
+ for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
+ FlowEdge flowEdge = (FlowEdge) iterator.next();
+ FlowNode dstNode = flowEdge.getDst();
+
+ NTuple<Descriptor> dstDescTuple = dstNode.getCurrentDescTuple();
+ if (dstDescTuple.get(0).equals(mdCallee.getThis())) {
+ // destination node is started with 'this' variable
+ // need to translate it in terms of the caller's base node
+ dstDescTuple = translateToCaller(dstDescTuple, baseTuple);
+ }
+
+ callerSubGlobalGraph.addValueFlowEdge(callerSrcTuple, dstDescTuple);
+
+ if (!visited.contains(dstNode)) {
+ visited.add(dstNode);
+ recurAddValueFlowsFromCalleeParam(calleeSubGlobalGraph, dstNode, callerSubGlobalGraph,
+ dstDescTuple, visited, baseTuple);
+ }
+
+ }
+
+ }
+
+ private NTuple<Descriptor> translateToCaller(NTuple<Descriptor> dstDescTuple,
+ NTuple<Descriptor> baseTuple) {
+ NTuple<Descriptor> callerDescTuple = new NTuple<Descriptor>();
+
+ callerDescTuple.addAll(baseTuple);
+ for (int i = 1; i < dstDescTuple.size(); i++) {
+ callerDescTuple.add(dstDescTuple.get(i));
+ }
+
+ return callerDescTuple;
+ }
+
+ public LocationSummary getLocationSummary(Descriptor d) {
+ if (!mapDescToLocationSummary.containsKey(d)) {
+ if (d instanceof MethodDescriptor) {
+ mapDescToLocationSummary.put(d, new MethodSummary((MethodDescriptor) d));
+ } else if (d instanceof ClassDescriptor) {
+ mapDescToLocationSummary.put(d, new FieldSummary());
+ }
+ }
+ return mapDescToLocationSummary.get(d);
+ }
+
+ private void generateMethodSummary() {
+
+ Set<MethodDescriptor> keySet = md2lattice.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+
+ System.out.println("\nSSJAVA: generate method summary: " + md);
+
+ FlowGraph flowGraph = getFlowGraph(md);
+ MethodSummary methodSummary = getMethodSummary(md);
+
+ // construct a parameter mapping that maps a parameter descriptor to an inferred composite
+ // location
+
+ for (int paramIdx = 0; paramIdx < flowGraph.getNumParameters(); paramIdx++) {
+ FlowNode flowNode = flowGraph.getParamFlowNode(paramIdx);
+ NTuple<Descriptor> descTuple = flowNode.getDescTuple();
+
+ CompositeLocation assignedCompLoc = flowNode.getCompositeLocation();
+ CompositeLocation inferredCompLoc;
+ if (assignedCompLoc != null) {
+ inferredCompLoc = translateCompositeLocation(assignedCompLoc);
+ } else {
+ Descriptor locDesc = descTuple.get(0);
+ Location loc = new Location(md, locDesc.getSymbol());
+ loc.setLocDescriptor(locDesc);
+ inferredCompLoc = new CompositeLocation(loc);
+ }
+ System.out.println("-paramIdx=" + paramIdx + " infer=" + inferredCompLoc);
+ methodSummary.addMapParamIdxToInferLoc(paramIdx, inferredCompLoc);
+ }
+
+ }
+
+ }
+
+ private CompositeLocation translateCompositeLocation(CompositeLocation compLoc) {
+ CompositeLocation newCompLoc = new CompositeLocation();
+
+ // System.out.println("compLoc=" + compLoc);
+ for (int i = 0; i < compLoc.getSize(); i++) {
+ Location loc = compLoc.get(i);
+ Descriptor enclosingDescriptor = loc.getDescriptor();
+ Descriptor locDescriptor = loc.getLocDescriptor();
+
+ HNode hnode = getHierarchyGraph(enclosingDescriptor).getHNode(locDescriptor);
+ // System.out.println("-hnode=" + hnode + " from=" + locDescriptor +
+ // " enclosingDescriptor="
+ // + enclosingDescriptor);
+ // System.out.println("-getLocationSummary(enclosingDescriptor)="
+ // + getLocationSummary(enclosingDescriptor));
+ String locName = getLocationSummary(enclosingDescriptor).getLocationName(hnode.getName());
+ // System.out.println("-locName=" + locName);
+ Location newLoc = new Location(enclosingDescriptor, locName);
+ newLoc.setLocDescriptor(locDescriptor);
+ newCompLoc.addLocation(newLoc);
+ }
+
+ return newCompLoc;
+ }
+
private void debug_writeLattices() {
Set<Descriptor> keySet = mapDescriptorToSimpleLattice.keySet();
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
Descriptor key = (Descriptor) iterator.next();
SSJavaLattice<String> simpleLattice = mapDescriptorToSimpleLattice.get(key);
+ // HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(key);
+ HierarchyGraph scHierarchyGraph = getSkeletonCombinationHierarchyGraph(key);
if (key instanceof ClassDescriptor) {
- ssjava.writeLatticeDotFile((ClassDescriptor) key, null, simpleLattice, "_SIMPLE");
+ writeInferredLatticeDotFile((ClassDescriptor) key, scHierarchyGraph, simpleLattice,
+ "_SIMPLE");
} else if (key instanceof MethodDescriptor) {
MethodDescriptor md = (MethodDescriptor) key;
- ssjava.writeLatticeDotFile(md.getClassDesc(), md, simpleLattice, "_SIMPLE");
+ writeInferredLatticeDotFile(md.getClassDesc(), md, scHierarchyGraph, simpleLattice,
+ "_SIMPLE");
}
+
+ LocationSummary ls = getLocationSummary(key);
+ System.out.println("####LOC SUMMARY=" + key + "\n" + ls.getMapHNodeNameToLocationName());
}
Set<ClassDescriptor> cdKeySet = cd2lattice.keySet();
for (Iterator iterator = cdKeySet.iterator(); iterator.hasNext();) {
ClassDescriptor cd = (ClassDescriptor) iterator.next();
- ssjava.writeLatticeDotFile(cd, null, cd2lattice.get(cd));
+ writeInferredLatticeDotFile((ClassDescriptor) cd, getSkeletonCombinationHierarchyGraph(cd),
+ cd2lattice.get(cd), "");
}
Set<MethodDescriptor> mdKeySet = md2lattice.keySet();
for (Iterator iterator = mdKeySet.iterator(); iterator.hasNext();) {
MethodDescriptor md = (MethodDescriptor) iterator.next();
- ssjava.writeLatticeDotFile(md.getClassDesc(), md, md2lattice.get(md));
+ writeInferredLatticeDotFile(md.getClassDesc(), md, getSkeletonCombinationHierarchyGraph(md),
+ md2lattice.get(md), "");
}
}
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
Descriptor desc = (Descriptor) iterator.next();
- HierarchyGraph graph = getSkeletonCombinationHierarchyGraph(desc);
- SSJavaLattice<String> simpleLattice = buildLattice.buildLattice(graph);
+ SSJavaLattice<String> simpleLattice = buildLattice.buildLattice(desc);
addMapDescToSimpleLattice(desc, simpleLattice);
Descriptor desc = (Descriptor) iterator.next();
HierarchyGraph simpleHierarchyGraph = getHierarchyGraph(desc).clone();
simpleHierarchyGraph.setName(desc + "_SIMPLE");
- simpleHierarchyGraph.simplifyHierarchyGraph();
+ simpleHierarchyGraph.removeRedundantEdges();
+ // simpleHierarchyGraph.simplifyHierarchyGraph();
mapDescriptorToSimpleHierarchyGraph.put(desc, simpleHierarchyGraph);
}
}
HierarchyGraph skeletonGraph = simpleGraph.generateSkeletonGraph();
skeletonGraph.setMapDescToHNode(simpleGraph.getMapDescToHNode());
skeletonGraph.setMapHNodeToDescSet(simpleGraph.getMapHNodeToDescSet());
- skeletonGraph.removeRedundantEdges();
+ skeletonGraph.simplifyHierarchyGraph();
+ // skeletonGraph.combineRedundantNodes(false);
+ // skeletonGraph.removeRedundantEdges();
mapDescriptorToSkeletonHierarchyGraph.put(desc, skeletonGraph);
}
}
// start to analyze leaf node
MethodDescriptor md = methodDescriptorsToVisitStack.pop();
- HierarchyGraph methodGraph = new HierarchyGraph(md);
- MethodSummary methodSummary = new MethodSummary();
+ HierarchyGraph hierarchyGraph = new HierarchyGraph(md);
+ // MethodSummary methodSummary = new MethodSummary(md);
- MethodLocationInfo methodInfo = new MethodLocationInfo(md);
- curMethodInfo = methodInfo;
+ // MethodLocationInfo methodInfo = new MethodLocationInfo(md);
+ // curMethodInfo = methodInfo;
System.out.println();
System.out.println("SSJAVA: Construcing the hierarchy graph from " + md);
- constructHierarchyGraph(md, methodGraph, methodSummary);
+ constructHierarchyGraph(md, hierarchyGraph);
- HierarchyGraph prevMethodGraph = getHierarchyGraph(md);
- MethodSummary prevMethodSummary = getMethodSummary(md);
+ HierarchyGraph prevHierarchyGraph = getHierarchyGraph(md);
+ // MethodSummary prevMethodSummary = getMethodSummary(md);
- if ((!methodGraph.equals(prevMethodGraph)) || (!methodSummary.equals(prevMethodSummary))) {
+ if (!hierarchyGraph.equals(prevHierarchyGraph)) {
- mapDescriptorToHierarchyGraph.put(md, methodGraph);
- mapMethodDescToMethodSummary.put(md, methodSummary);
+ mapDescriptorToHierarchyGraph.put(md, hierarchyGraph);
+ // mapDescToLocationSummary.put(md, methodSummary);
// results for callee changed, so enqueue dependents caller for
// further analysis
return mapDescriptorToHierarchyGraph.get(d);
}
- private void constructHierarchyGraph(MethodDescriptor md, HierarchyGraph methodGraph,
- MethodSummary methodSummary) {
+ private void constructHierarchyGraph(MethodDescriptor md, HierarchyGraph methodGraph) {
// visit each node of method flow graph
FlowGraph fg = getFlowGraph(md);
for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
FlowNode srcNode = (FlowNode) iterator.next();
- Set<FlowEdge> outEdgeSet = srcNode.getOutEdgeSet();
+ Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(srcNode);
for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
FlowEdge outEdge = (FlowEdge) iterator2.next();
FlowNode dstNode = outEdge.getDst();
}
private MethodSummary getMethodSummary(MethodDescriptor md) {
- if (!mapMethodDescToMethodSummary.containsKey(md)) {
- mapMethodDescToMethodSummary.put(md, new MethodSummary());
+ if (!mapDescToLocationSummary.containsKey(md)) {
+ mapDescToLocationSummary.put(md, new MethodSummary(md));
}
- return mapMethodDescToMethodSummary.get(md);
+ return (MethodSummary) mapDescToLocationSummary.get(md);
}
private void addMapClassDefinitionToLineNum(ClassDescriptor cd, String strLine, int lineNum) {
for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
FlowNode srcNode = (FlowNode) iterator.next();
- Set<FlowEdge> outEdgeSet = srcNode.getOutEdgeSet();
+ Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(srcNode);
for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
FlowEdge outEdge = (FlowEdge) iterator2.next();
FlowNode dstNode = outEdge.getDst();
}
- private void propagateFlowsFromCallee(MethodInvokeNode min, MethodDescriptor mdCaller,
+ // private void propagateFlowsFromCallee(MethodInvokeNode min, MethodDescriptor mdCaller,
+ // MethodDescriptor mdCallee) {
+ //
+ // // the transformation for a call site propagates all relations between
+ // // parameters from the callee
+ // // if the method is virtual, it also grab all relations from any possible
+ // // callees
+ //
+ // Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
+ // if (mdCallee.isStatic()) {
+ // setPossibleCallees.add(mdCallee);
+ // } else {
+ // Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
+ // // removes method descriptors that are not invoked by the caller
+ // calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
+ // setPossibleCallees.addAll(calleeSet);
+ // }
+ //
+ // for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
+ // MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
+ // propagateFlowsToCaller(min, mdCaller, possibleMdCallee);
+ // }
+ //
+ // }
+
+ private void contributeCalleeFlows(MethodInvokeNode min, MethodDescriptor mdCaller,
MethodDescriptor mdCallee) {
- // the transformation for a call site propagates all relations between
- // parameters from the callee
- // if the method is virtual, it also grab all relations from any possible
- // callees
+ System.out.println("\n##contributeCalleeFlows callee=" + mdCallee + "TO caller=" + mdCaller);
- Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
- if (mdCallee.isStatic()) {
- setPossibleCallees.add(mdCallee);
- } else {
- Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
- // removes method descriptors that are not invoked by the caller
- calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
- setPossibleCallees.addAll(calleeSet);
- }
+ getSubGlobalFlowGraph(mdCallee);
- for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
- MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
- propagateFlowsToCaller(min, mdCaller, possibleMdCallee);
+ }
+
+ private FlowGraph getSubGlobalFlowGraph(MethodDescriptor md) {
+ return mapMethodDescriptorToSubGlobalFlowGraph.get(md);
+ }
+
+ private void propagateFlowsToCallerWithNoCompositeLocation(MethodInvokeNode min,
+ MethodDescriptor mdCaller, MethodDescriptor mdCallee) {
+
+ System.out.println("\n##PROPAGATE callee=" + mdCallee + "TO caller=" + mdCaller);
+
+ // if the parameter A reaches to the parameter B
+ // then, add an edge the argument A -> the argument B to the caller's flow
+ // graph
+
+ FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
+ FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
+ int numParam = calleeFlowGraph.getNumParameters();
+
+ for (int i = 0; i < numParam; i++) {
+ for (int k = 0; k < numParam; k++) {
+
+ if (i != k) {
+
+ FlowNode paramNode1 = calleeFlowGraph.getParamFlowNode(i);
+ FlowNode paramNode2 = calleeFlowGraph.getParamFlowNode(k);
+
+ NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
+ NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
+
+ for (Iterator<NTuple<Descriptor>> iter1 = tupleSetArg1.iterator(); iter1.hasNext();) {
+ NTuple<Descriptor> arg1Tuple = iter1.next();
+
+ for (Iterator<NTuple<Descriptor>> iter2 = tupleSetArg2.iterator(); iter2.hasNext();) {
+ NTuple<Descriptor> arg2Tuple = iter2.next();
+
+ // check if the callee propagates an ordering constraints through
+ // parameters
+
+ Set<FlowNode> localReachSet =
+ calleeFlowGraph.getLocalReachFlowNodeSetFrom(paramNode1);
+
+ if (localReachSet.contains(paramNode2)) {
+ // need to propagate an ordering relation s.t. arg1 is higher
+ // than arg2
+
+ System.out
+ .println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
+ System.out.println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple="
+ + arg2Tuple);
+
+ // otherwise, flows between method/field locations...
+ callerFlowGraph.addValueFlowEdge(arg1Tuple, arg2Tuple);
+ System.out.println("arg1=" + arg1Tuple + " arg2=" + arg2Tuple);
+
+ }
+
+ }
+
+ }
+ System.out.println();
+ }
+ }
}
+ System.out.println("##\n");
}
private void propagateFlowsToCaller(MethodInvokeNode min, MethodDescriptor mdCaller,
MethodDescriptor mdCallee) {
+ System.out.println("\n##PROPAGATE callee=" + mdCallee + "TO caller=" + mdCaller);
+
// if the parameter A reaches to the parameter B
// then, add an edge the argument A -> the argument B to the caller's flow
// graph
+ // TODO
+ // also if a parameter is a composite location and is started with "this" reference,
+ // need to make sure that the corresponding argument is higher than the translated location of
+ // the parameter.
+
FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
int numParam = calleeFlowGraph.getNumParameters();
FlowNode paramNode1 = calleeFlowGraph.getParamFlowNode(i);
FlowNode paramNode2 = calleeFlowGraph.getParamFlowNode(k);
+ System.out.println("param1=" + paramNode1 + " curDescTuple="
+ + paramNode1.getCurrentDescTuple());
+ System.out.println("param2=" + paramNode2 + " curDescTuple="
+ + paramNode2.getCurrentDescTuple());
+
NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
// need to propagate an ordering relation s.t. arg1 is higher
// than arg2
+ System.out
+ .println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
+ System.out.println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple="
+ + arg2Tuple);
+
if (!min.getMethod().isStatic()) {
// check if this is the case that values flow to/from the
// current object reference 'this'
NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
Descriptor baseRef = baseTuple.get(baseTuple.size() - 1);
+ System.out.println("paramNode1.getCurrentDescTuple()="
+ + paramNode1.getCurrentDescTuple());
// calculate the prefix of the argument
+
if (arg2Tuple.size() == 1 && arg2Tuple.get(0).equals(baseRef)) {
+ // in this case, the callee flow causes a caller flow to the object whose method
+ // is invoked.
if (!paramNode1.getCurrentDescTuple().startsWith(mdCallee.getThis())) {
+ // check whether ???
NTuple<Descriptor> param1Prefix =
calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg1Tuple,
paramNode1);
if (param1Prefix != null && param1Prefix.startsWith(mdCallee.getThis())) {
- // in this case, we need to create a new edge
- // 'this.FIELD'->'this'
- // but we couldn't... instead we assign the
- // corresponding
- // parameter a new composite location started with
- // 'this'
- // reference
+ // in this case, we need to create a new edge 'this.FIELD'->'this'
+ // but we couldn't... instead we assign a new composite location started
+ // with 'this' reference to the corresponding parameter
CompositeLocation compLocForParam1 =
generateCompositeLocation(mdCallee, param1Prefix);
- // System.out.println("set comp loc=" + compLocForParam1
- // +
- // " to " + paramNode1);
+ System.out
+ .println("set comp loc=" + compLocForParam1 + " to " + paramNode1);
paramNode1.setCompositeLocation(compLocForParam1);
+
+ // then, we need to make sure that the corresponding argument in the caller
+ // is required to be higher than or equal to the translated parameter
+ // location
+
+ NTuple<Descriptor> translatedParamTuple =
+ translateCompositeLocationToCaller(min, compLocForParam1);
+
+ // TODO : check if the arg >= the tranlated parameter
+
+ System.out.println("add a flow edge= " + arg1Tuple + "->"
+ + translatedParamTuple);
+ callerFlowGraph.addValueFlowEdge(arg1Tuple, translatedParamTuple);
+
continue;
+
}
+
+ } else {
+ // param1 has already been assigned a composite location
+
+ System.out.println("--param1 has already been assigned a composite location");
+ CompositeLocation compLocForParam1 = paramNode1.getCompositeLocation();
+ NTuple<Descriptor> translatedParamTuple =
+ translateCompositeLocationToCaller(min, compLocForParam1);
+
+ // TODO : check if the arg >= the tranlated parameter
+
+ System.out.println("add a flow edge= " + arg1Tuple + "->"
+ + translatedParamTuple);
+ callerFlowGraph.addValueFlowEdge(arg1Tuple, translatedParamTuple);
+
+ continue;
+
}
} else if (arg1Tuple.size() == 1 && arg1Tuple.get(0).equals(baseRef)) {
+ // in this case, the callee flow causes a caller flow originated from the object
+ // whose
+ // method is invoked.
+
+ System.out.println("###FROM CASE");
if (!paramNode2.getCurrentDescTuple().startsWith(mdCallee.getThis())) {
NTuple<Descriptor> param2Prefix =
- calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg1Tuple,
- paramNode1);
+ calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg2Tuple,
+ paramNode2);
if (param2Prefix != null && param2Prefix.startsWith(mdCallee.getThis())) {
// in this case, we need to create a new edge 'this' ->
- // 'this.FIELD'
- // but we couldn't... instead we assign the
- // corresponding
- // parameter a new composite location started with
- // 'this'
- // reference
+ // 'this.FIELD' but we couldn't... instead we assign the corresponding
+ // parameter a new composite location started with 'this' reference
CompositeLocation compLocForParam2 =
generateCompositeLocation(mdCallee, param2Prefix);
// otherwise, flows between method/field locations...
callerFlowGraph.addValueFlowEdge(arg1Tuple, arg2Tuple);
- // System.out.println("arg1=" + arg1Tuple + " arg2=" +
- // arg2Tuple);
+ System.out.println("arg1=" + arg1Tuple + " arg2=" + arg2Tuple);
}
}
}
+ System.out.println();
}
}
}
+ System.out.println("##\n");
+ }
+
+ private NTuple<Descriptor> translateCompositeLocationToCaller(MethodInvokeNode min,
+ CompositeLocation compLocForParam1) {
+ NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
+
+ NTuple<Descriptor> tuple = new NTuple<Descriptor>();
+ for (int i = 0; i < baseTuple.size(); i++) {
+ tuple.add(baseTuple.get(i));
+ }
+
+ for (int i = 1; i < compLocForParam1.getSize(); i++) {
+ Location loc = compLocForParam1.get(i);
+ tuple.add(loc.getLocDescriptor());
+ }
+
+ return tuple;
}
private CompositeLocation generateCompositeLocation(MethodDescriptor md,
- NTuple<Descriptor> param1Prefix) {
+ NTuple<Descriptor> paramPrefix) {
+
+ System.out.println("generateCompositeLocation=" + paramPrefix);
- CompositeLocation newCompLoc = convertToCompositeLocation(md, param1Prefix);
+ CompositeLocation newCompLoc = convertToCompositeLocation(md, paramPrefix);
+
+ Descriptor lastDescOfPrefix = paramPrefix.get(paramPrefix.size() - 1);
+ // System.out.println("lastDescOfPrefix=" + lastDescOfPrefix + " kind="
+ // + lastDescOfPrefix.getClass());
+ ClassDescriptor enclosingDescriptor;
+ if (lastDescOfPrefix instanceof FieldDescriptor) {
+ enclosingDescriptor = ((FieldDescriptor) lastDescOfPrefix).getType().getClassDesc();
+ // System.out.println("enclosingDescriptor0=" + enclosingDescriptor);
+ } else {
+ // var descriptor case
+ enclosingDescriptor = ((VarDescriptor) lastDescOfPrefix).getType().getClassDesc();
+ }
+ // System.out.println("enclosingDescriptor=" + enclosingDescriptor);
LocationDescriptor newLocDescriptor = generateNewLocationDescriptor();
+ newLocDescriptor.setEnclosingClassDesc(enclosingDescriptor);
- Descriptor enclosingDescriptor = param1Prefix.get(param1Prefix.size() - 1);
Location newLoc = new Location(enclosingDescriptor, newLocDescriptor.getSymbol());
newLoc.setLocDescriptor(newLocDescriptor);
newCompLoc.addLocation(newLoc);
- System.out.println("newCompLoc=" + newCompLoc);
+ // System.out.println("--newCompLoc=" + newCompLoc);
return newCompLoc;
}
List<NTuple<Descriptor>> callerPrefixList = calculatePrefixList(callerFlowGraph, flowNodeArg1);
System.out.println("callerPrefixList=" + callerPrefixList);
+ List<NTuple<Descriptor>> prefixList = calculatePrefixList(calleeFlowGraph, paramNode1);
+ System.out.println("###prefixList from node=" + paramNode1 + " =" + prefixList);
+
List<NTuple<Descriptor>> calleePrefixList =
translatePrefixListToCallee(baseRef, min.getMethod(), callerPrefixList);
private List<NTuple<Descriptor>> calculatePrefixList(FlowGraph flowGraph, FlowNode flowNode) {
+ System.out.println("\n##### calculatePrefixList=" + flowNode);
+
Set<FlowNode> inNodeSet = flowGraph.getIncomingFlowNodeSet(flowNode);
inNodeSet.add(flowNode);
+ System.out.println("inNodeSet=" + inNodeSet);
+
List<NTuple<Descriptor>> prefixList = new ArrayList<NTuple<Descriptor>>();
for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
}
- System.out.println("convertToCompositeLocation from=" + tuple + " to " + compLoc);
+ System.out.println("-convertToCompositeLocation from=" + tuple + " to " + compLoc);
return compLoc;
}
ClassDescriptor cd = toAnalyzeNext();
setupToAnalazeMethod(cd);
- toanalyzeMethodList.removeAll(visited);
+ temp_toanalyzeMethodList.removeAll(visited);
while (!toAnalyzeMethodIsEmpty()) {
MethodDescriptor md = toAnalyzeMethodNext();
if ((!ssjava.isTrustMethod(calleemd))
&& (!ssjava.isSSJavaUtil(calleemd.getClassDesc()))) {
if (!visited.contains(calleemd)) {
- toanalyzeMethodList.add(calleemd);
+ temp_toanalyzeMethodList.add(calleemd);
}
reachableCallee.add(calleemd);
needToAnalyzeCalleeSet.add(calleemd);
public void constructFlowGraph() {
System.out.println("");
- LinkedList<MethodDescriptor> methodDescList = computeMethodList();
+ toanalyze_methodDescList = computeMethodList();
+
+ LinkedList<MethodDescriptor> methodDescList =
+ (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
System.out.println("@@@methodDescList=" + methodDescList);
// System.exit(0);
mapMethodDescriptorToFlowGraph.put(md, fg);
analyzeMethodBody(md.getClassDesc(), md);
- propagateFlowsFromCallees(md);
- assignCompositeLocation(md);
+ propagateFlowsFromCalleesWithNoCompositeLocation(md);
+ // assignCompositeLocation(md);
}
}
}
+ private Set<MethodInvokeNode> getMethodInvokeNodeSet(MethodDescriptor md) {
+ if (!mapMethodDescriptorToMethodInvokeNodeSet.containsKey(md)) {
+ mapMethodDescriptorToMethodInvokeNodeSet.put(md, new HashSet<MethodInvokeNode>());
+ }
+ return mapMethodDescriptorToMethodInvokeNodeSet.get(md);
+ }
+
+ private void constructSubGlobalFlowGraph(MethodDescriptor md) {
+
+ FlowGraph flowGraph = getFlowGraph(md);
+
+ Set<MethodInvokeNode> setMethodInvokeNode = getMethodInvokeNodeSet(md);
+
+ for (Iterator<MethodInvokeNode> iter = setMethodInvokeNode.iterator(); iter.hasNext();) {
+ MethodInvokeNode min = iter.next();
+ propagateFlowsFromMethodInvokeNode(md, min);
+ }
+
+ }
+
+ private void propagateFlowsFromMethodInvokeNode(MethodDescriptor mdCaller, MethodInvokeNode min) {
+ // the transformation for a call site propagates flows through parameters
+ // if the method is virtual, it also grab all relations from any possible
+ // callees
+
+ MethodDescriptor mdCallee = min.getMethod();
+ Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
+ if (mdCallee.isStatic()) {
+ setPossibleCallees.add(mdCallee);
+ } else {
+ Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
+ // removes method descriptors that are not invoked by the caller
+ calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
+ setPossibleCallees.addAll(calleeSet);
+ }
+
+ for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
+ MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
+ contributeCalleeFlows(min, mdCaller, possibleMdCallee);
+ }
+
+ }
+
private void assignCompositeLocation(MethodDescriptor md) {
FlowGraph flowGraph = getFlowGraph(md);
}
+ private void propagateFlowsFromCalleesWithNoCompositeLocation(MethodDescriptor mdCaller) {
+
+ // the transformation for a call site propagates flows through parameters
+ // if the method is virtual, it also grab all relations from any possible
+ // callees
+
+ Set<MethodInvokeNode> setMethodInvokeNode =
+ mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
+
+ if (setMethodInvokeNode != null) {
+
+ for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
+ MethodInvokeNode min = (MethodInvokeNode) iterator.next();
+ MethodDescriptor mdCallee = min.getMethod();
+ Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
+ if (mdCallee.isStatic()) {
+ setPossibleCallees.add(mdCallee);
+ } else {
+ Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
+ // removes method descriptors that are not invoked by the caller
+ calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
+ setPossibleCallees.addAll(calleeSet);
+ }
+
+ for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
+ MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
+ propagateFlowsToCallerWithNoCompositeLocation(min, mdCaller, possibleMdCallee);
+ }
+
+ }
+ }
+
+ }
+
private void propagateFlowsFromCallees(MethodDescriptor mdCaller) {
// the transformation for a call site propagates flows through parameters
analyzeFlowExpressionNode(md, nametable, an.getSrc(), nodeSetRHS, null, implicitFlowTupleSet,
false);
- System.out.println("-analyzeFlowAssignmentNode=" + an.printNode(0));
- System.out.println("-nodeSetLHS=" + nodeSetLHS);
- System.out.println("-nodeSetRHS=" + nodeSetRHS);
- System.out.println("-implicitFlowTupleSet=" + implicitFlowTupleSet);
- System.out.println("-");
+ // System.out.println("-analyzeFlowAssignmentNode=" + an.printNode(0));
+ // System.out.println("-nodeSetLHS=" + nodeSetLHS);
+ // System.out.println("-nodeSetRHS=" + nodeSetRHS);
+ // System.out.println("-implicitFlowTupleSet=" + implicitFlowTupleSet);
+ // System.out.println("-");
if (an.getOperation().getOp() >= 2 && an.getOperation().getOp() <= 12) {
// if assignment contains OP+EQ operator, creates edges from LHS to LHS
}
+ public void writeInferredLatticeDotFile(ClassDescriptor cd, HierarchyGraph simpleHierarchyGraph,
+ SSJavaLattice<String> locOrder, String nameSuffix) {
+ writeInferredLatticeDotFile(cd, null, simpleHierarchyGraph, locOrder, nameSuffix);
+ }
+
+ public void writeInferredLatticeDotFile(ClassDescriptor cd, MethodDescriptor md,
+ HierarchyGraph simpleHierarchyGraph, SSJavaLattice<String> locOrder, String nameSuffix) {
+
+ String fileName = "lattice_";
+ if (md != null) {
+ fileName +=
+ cd.getSymbol().replaceAll("[\\W_]", "") + "_" + md.toString().replaceAll("[\\W_]", "");
+ } else {
+ fileName += cd.getSymbol().replaceAll("[\\W_]", "");
+ }
+
+ fileName += nameSuffix;
+
+ Set<Pair<String, String>> pairSet = locOrder.getOrderingPairSet();
+
+ Set<String> addedLocSet = new HashSet<String>();
+
+ 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 <higher, lower>
+ Pair<String, String> pair = (Pair<String, String>) iterator.next();
+
+ String highLocId = pair.getFirst();
+ String lowLocId = pair.getSecond();
+
+ if (!addedLocSet.contains(highLocId)) {
+ addedLocSet.add(highLocId);
+ drawNode(bw, locOrder, simpleHierarchyGraph, highLocId);
+ }
+
+ if (!addedLocSet.contains(lowLocId)) {
+ addedLocSet.add(lowLocId);
+ drawNode(bw, locOrder, simpleHierarchyGraph, lowLocId);
+ }
+
+ bw.write(highLocId + " -> " + lowLocId + ";\n");
+ }
+ bw.write("}\n");
+ bw.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ }
+
+ private String convertMergeSetToString(HierarchyGraph graph, Set<HNode> mergeSet) {
+ String str = "";
+ for (Iterator iterator = mergeSet.iterator(); iterator.hasNext();) {
+ HNode merged = (HNode) iterator.next();
+ if (merged.isMergeNode()) {
+ str += convertMergeSetToString(graph, graph.getMapHNodetoMergeSet().get(merged));
+ } else {
+ str += " " + merged.getName();
+ }
+ }
+ return str;
+ }
+
+ private void drawNode(BufferedWriter bw, SSJavaLattice<String> lattice, HierarchyGraph graph,
+ String locName) throws IOException {
+
+ HNode node = graph.getHNode(locName);
+
+ if (node == null) {
+ return;
+ }
+
+ String prettyStr;
+ if (lattice.isSharedLoc(locName)) {
+ prettyStr = locName + "*";
+ } else {
+ prettyStr = locName;
+ }
+
+ if (node.isMergeNode()) {
+ Set<HNode> mergeSet = graph.getMapHNodetoMergeSet().get(node);
+ prettyStr += ":" + convertMergeSetToString(graph, mergeSet);
+ }
+ bw.write(locName + " [label=\"" + prettyStr + "\"]" + ";\n");
+ }
+
public void _debug_printGraph() {
Set<MethodDescriptor> keySet = mapMethodDescriptorToFlowGraph.keySet();