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;
// map a method descriptor to the set of method invocation nodes which are
// invoked by the method descriptor
private Map<MethodDescriptor, Set<MethodInvokeNode>> mapMethodDescriptorToMethodInvokeNodeSet;
- private Map<MethodInvokeNode, Map<Integer, NodeTupleSet>> mapMethodInvokeNodeToArgIdxMap;
+ private Map<MethodInvokeNode, Map<Integer, NTuple<Descriptor>>> mapMethodInvokeNodeToArgIdxMap;
private Map<MethodInvokeNode, NTuple<Descriptor>> mapMethodInvokeNodeToBaseTuple;
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>>();
this.mapMethodDescriptorToMethodInvokeNodeSet =
new HashMap<MethodDescriptor, Set<MethodInvokeNode>>();
this.mapMethodInvokeNodeToArgIdxMap =
- new HashMap<MethodInvokeNode, Map<Integer, NodeTupleSet>>();
+ new HashMap<MethodInvokeNode, Map<Integer, NTuple<Descriptor>>>();
this.mapMethodDescToMethodLocationInfo = new HashMap<MethodDescriptor, MethodLocationInfo>();
this.mapMethodToCalleeSet = new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
this.mapClassToLocationInfo = new HashMap<ClassDescriptor, LocationInfo>();
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.mapDescriptorToCombineSkeletonHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
this.mapDescriptorToSimpleHierarchyGraph = 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();
+
simplifyHierarchyGraph();
+ debug_writeSimpleHierarchyDotFiles();
+
constructSkeletonHierarchyGraph();
+ debug_writeSkeletonHierarchyDotFiles();
+
insertCombinationNodes();
- debug_writeHierarchyDotFile();
+ debug_writeSkeletonCombinationHierarchyDotFiles();
+
+ buildLattice();
+
+ debug_writeLattices();
+
+ generateMethodSummary();
System.exit(0);
}
+ 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);
+ NTuple<Descriptor> argTuple = mapMethodInvokeNodeToArgIdxMap.get(min).get(idx);
+ System.out.println("argTupleSet=" + argTuple + " param=" + paramNode);
+ // here, it adds all value flows reachable from the paramNode in the callee's flow graph
+ addValueFlowsFromCalleeParam(min, calleeSubGlobalGraph, paramNode, callerSubGlobalGraph,
+ argTuple, baseTuple);
+ }
+
+ }
+
+ private void addValueFlowsFromCalleeParam(MethodInvokeNode min, FlowGraph calleeSubGlobalGraph,
+ FlowNode paramNode, FlowGraph callerSubGlobalGraph, NTuple<Descriptor> argTuple,
+ NTuple<Descriptor> baseTuple) {
+
+ Set<FlowNode> visited = new HashSet<FlowNode>();
+
+ visited.add(paramNode);
+ recurAddValueFlowsFromCalleeParam(min, calleeSubGlobalGraph, paramNode, callerSubGlobalGraph,
+ argTuple, visited, baseTuple);
+ }
+
+ private void recurAddValueFlowsFromCalleeParam(MethodInvokeNode min,
+ 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);
+ Set<FlowEdge> edgeSet = calleeSubGlobalGraph.getOutEdgeSetStartingFrom(calleeSrcNode);
+ for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
+ FlowEdge flowEdge = (FlowEdge) iterator.next();
+
+ NTuple<Descriptor> srcDescTuple = flowEdge.getInitTuple();
+ NTuple<Descriptor> dstDescTuple = flowEdge.getEndTuple();
+
+ FlowNode dstNode = calleeSubGlobalGraph.getFlowNode(dstDescTuple);
+
+ if (calleeSubGlobalGraph.isParameter(srcDescTuple)) {
+ // destination node is started with 'parameter'
+ // need to translate it in terms of the caller's a node
+ srcDescTuple =
+ translateToCaller(min, calleeSubGlobalGraph.getParamIdx(srcDescTuple), srcDescTuple);
+ }
+
+ if (calleeSubGlobalGraph.isParameter(dstDescTuple)) {
+ // destination node is started with 'parameter'
+ // need to translate it in terms of the caller's a node
+ dstDescTuple =
+ translateToCaller(min, calleeSubGlobalGraph.getParamIdx(dstDescTuple), dstDescTuple);
+ }
+
+ callerSubGlobalGraph.addValueFlowEdge(srcDescTuple, dstDescTuple);
+
+ if (!visited.contains(dstNode)) {
+ visited.add(dstNode);
+ recurAddValueFlowsFromCalleeParam(min, calleeSubGlobalGraph, dstNode, callerSubGlobalGraph,
+ dstDescTuple, visited, baseTuple);
+ }
+
+ }
+
+ }
+
+ private NTuple<Descriptor> translateToCaller(MethodInvokeNode min, int paramIdx,
+ NTuple<Descriptor> srcDescTuple) {
+
+ NTuple<Descriptor> callerTuple = new NTuple<Descriptor>();
+
+ NTuple<Descriptor> argTuple = mapMethodInvokeNodeToArgIdxMap.get(min).get(paramIdx);
+
+ for (int i = 0; i < argTuple.size(); i++) {
+ callerTuple.add(argTuple.get(i));
+ }
+
+ for (int i = 1; i < srcDescTuple.size(); i++) {
+ callerTuple.add(srcDescTuple.get(i));
+ }
+
+ return callerTuple;
+ }
+
+ private NTuple<Descriptor> traslateToCalleeParamTupleToCallerArgTuple(
+ NTuple<Descriptor> calleeInitTuple, NTuple<Descriptor> callerSrcTuple) {
+
+ NTuple<Descriptor> callerInitTuple = new NTuple<Descriptor>();
+
+ for (int i = 0; i < callerSrcTuple.size(); i++) {
+ callerInitTuple.add(callerSrcTuple.get(i));
+ }
+
+ for (int i = 1; i < calleeInitTuple.size(); i++) {
+ callerInitTuple.add(calleeInitTuple.get(i));
+ }
+
+ return callerInitTuple;
+ }
+
+ 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) {
+ writeInferredLatticeDotFile((ClassDescriptor) key, scHierarchyGraph, simpleLattice,
+ "_SIMPLE");
+ } else if (key instanceof MethodDescriptor) {
+ MethodDescriptor md = (MethodDescriptor) key;
+ 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();
+ 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();
+ writeInferredLatticeDotFile(md.getClassDesc(), md, getSkeletonCombinationHierarchyGraph(md),
+ md2lattice.get(md), "");
+ }
+
+ }
+
+ private void buildLattice() {
+
+ BuildLattice buildLattice = new BuildLattice(this);
+
+ Set<Descriptor> keySet = mapDescriptorToCombineSkeletonHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
+
+ SSJavaLattice<String> simpleLattice = buildLattice.buildLattice(desc);
+
+ addMapDescToSimpleLattice(desc, simpleLattice);
+
+ HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
+ System.out.println("## insertIntermediateNodesToStraightLine:"
+ + simpleHierarchyGraph.getName());
+ SSJavaLattice<String> lattice =
+ buildLattice.insertIntermediateNodesToStraightLine(desc, simpleLattice);
+ lattice.removeRedundantEdges();
+
+ if (desc instanceof ClassDescriptor) {
+ // field lattice
+ cd2lattice.put((ClassDescriptor) desc, lattice);
+ // ssjava.writeLatticeDotFile((ClassDescriptor) desc, null, lattice);
+ } else if (desc instanceof MethodDescriptor) {
+ // method lattice
+ md2lattice.put((MethodDescriptor) desc, lattice);
+ MethodDescriptor md = (MethodDescriptor) desc;
+ ClassDescriptor cd = md.getClassDesc();
+ // ssjava.writeLatticeDotFile(cd, md, lattice);
+ }
+
+ // System.out.println("\nSSJAVA: Insering Combination Nodes:" + desc);
+ // HierarchyGraph skeletonGraph = getSkeletonHierarchyGraph(desc);
+ // HierarchyGraph skeletonGraphWithCombinationNode = skeletonGraph.clone();
+ // skeletonGraphWithCombinationNode.setName(desc + "_SC");
+ //
+ // HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
+ // System.out.println("Identifying Combination Nodes:");
+ // skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(simpleHierarchyGraph);
+ // skeletonGraphWithCombinationNode.simplifySkeletonCombinationHierarchyGraph();
+ // mapDescriptorToCombineSkeletonHierarchyGraph.put(desc, skeletonGraphWithCombinationNode);
+ }
+
+ }
+
+ public void addMapDescToSimpleLattice(Descriptor desc, SSJavaLattice<String> lattice) {
+ mapDescriptorToSimpleLattice.put(desc, lattice);
+ }
+
+ public SSJavaLattice<String> getSimpleLattice(Descriptor desc) {
+ return mapDescriptorToSimpleLattice.get(desc);
+ }
+
private void simplifyHierarchyGraph() {
Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
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 skeletonGraphWithCombinationNode = skeletonGraph.clone();
skeletonGraphWithCombinationNode.setName(desc + "_SC");
- HierarchyGraph hierarchyGraph = getHierarchyGraph(desc);
- skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(hierarchyGraph);
+ HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
+ System.out.println("Identifying Combination Nodes:");
+ skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(simpleHierarchyGraph);
skeletonGraphWithCombinationNode.simplifySkeletonCombinationHierarchyGraph();
mapDescriptorToCombineSkeletonHierarchyGraph.put(desc, skeletonGraphWithCombinationNode);
}
HierarchyGraph skeletonGraph = simpleGraph.generateSkeletonGraph();
skeletonGraph.setMapDescToHNode(simpleGraph.getMapDescToHNode());
skeletonGraph.setMapHNodeToDescSet(simpleGraph.getMapHNodeToDescSet());
+ skeletonGraph.simplifyHierarchyGraph();
+ // skeletonGraph.combineRedundantNodes(false);
+ // skeletonGraph.removeRedundantEdges();
mapDescriptorToSkeletonHierarchyGraph.put(desc, skeletonGraph);
}
}
- private void debug_writeHierarchyDotFile() {
+ private void debug_writeHierarchyDotFiles() {
+
+ Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
+ getHierarchyGraph(desc).writeGraph();
+ }
+
+ }
+
+ private void debug_writeSimpleHierarchyDotFiles() {
Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
Descriptor desc = (Descriptor) iterator.next();
getHierarchyGraph(desc).writeGraph();
getSimpleHierarchyGraph(desc).writeGraph();
+ }
+
+ }
+
+ private void debug_writeSkeletonHierarchyDotFiles() {
+
+ Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
getSkeletonHierarchyGraph(desc).writeGraph();
+ }
+
+ }
+
+ private void debug_writeSkeletonCombinationHierarchyDotFiles() {
+
+ Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
getSkeletonCombinationHierarchyGraph(desc).writeGraph();
}
return mapDescriptorToSkeletonHierarchyGraph.get(d);
}
- private HierarchyGraph getSkeletonCombinationHierarchyGraph(Descriptor d) {
+ public HierarchyGraph getSkeletonCombinationHierarchyGraph(Descriptor d) {
if (!mapDescriptorToCombineSkeletonHierarchyGraph.containsKey(d)) {
mapDescriptorToCombineSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
}
// 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);
+
+ NTuple<Descriptor> arg1Tuple = getNodeTupleByArgIdx(min, i);
+ NTuple<Descriptor> arg2Tuple = getNodeTupleByArgIdx(min, k);
+
+ // 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);
- NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
- NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
+ System.out.println("param1=" + paramNode1 + " curDescTuple="
+ + paramNode1.getCurrentDescTuple());
+ System.out.println("param2=" + paramNode2 + " curDescTuple="
+ + paramNode2.getCurrentDescTuple());
+
+ // TODO: deprecated method
+ // NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
+ // NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
+ NodeTupleSet tupleSetArg1 = null;
+ NodeTupleSet tupleSetArg2 = null;
for (Iterator<NTuple<Descriptor>> iter1 = tupleSetArg1.iterator(); iter1.hasNext();) {
NTuple<Descriptor> arg1Tuple = iter1.next();
// 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, paramPrefix);
- CompositeLocation newCompLoc = convertToCompositeLocation(md, param1Prefix);
+ 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;
}
CompositeLocation param2 = calleeLocInfo.getParamCompositeLocation(k);
if (isGreaterThan(getLattice(possibleMdCallee), param1, param2)) {
- NodeTupleSet argDescTupleSet1 = getNodeTupleSetByArgIdx(min, i);
- NodeTupleSet argDescTupleSet2 = getNodeTupleSetByArgIdx(min, k);
+ // NodeTupleSet argDescTupleSet1 = getNodeTupleSetByArgIdx(min, i);
+ // NodeTupleSet argDescTupleSet2 = getNodeTupleSetByArgIdx(min, k);
+ NodeTupleSet argDescTupleSet1 = null;
+ NodeTupleSet argDescTupleSet2 = null;
// the callee has the relation in which param1 is higher than param2
// therefore, the caller has to have the relation in which arg1 is
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
implicitFlowTupleSet, false);
assert (baseNodeSet.size() == 1);
- mapMethodInvokeNodeToBaseTuple.put(min, baseNodeSet.iterator().next());
+ NTuple<Descriptor> baseTuple = baseNodeSet.iterator().next();
+ mapMethodInvokeNodeToBaseTuple.put(min, baseTuple);
if (!min.getMethod().isStatic()) {
- addArgIdxMap(min, 0, baseNodeSet);
+ addArgIdxMap(min, 0, baseTuple);
for (Iterator iterator = calleeReturnSet.iterator(); iterator.hasNext();) {
FlowNode returnNode = (FlowNode) iterator.next();
if (returnDescTuple.startsWith(calleeMethodDesc.getThis())) {
// the location type of the return value is started with 'this'
// reference
- for (Iterator<NTuple<Descriptor>> baseIter = baseNodeSet.iterator(); baseIter
- .hasNext();) {
- NTuple<Descriptor> baseTuple = baseIter.next();
- NTuple<Descriptor> inFlowTuple = new NTuple<Descriptor>(baseTuple.getList());
- inFlowTuple.addAll(returnDescTuple.subList(1, returnDescTuple.size()));
- nodeSet.addTuple(inFlowTuple);
- }
+ NTuple<Descriptor> inFlowTuple = new NTuple<Descriptor>(baseTuple.getList());
+ inFlowTuple.addAll(returnDescTuple.subList(1, returnDescTuple.size()));
+ nodeSet.addTuple(inFlowTuple);
} else {
+ // TODO
Set<FlowNode> inFlowSet = calleeFlowGraph.getIncomingFlowNodeSet(returnNode);
for (Iterator iterator2 = inFlowSet.iterator(); iterator2.hasNext();) {
FlowNode inFlowNode = (FlowNode) iterator2.next();
NodeTupleSet argTupleSet = new NodeTupleSet();
analyzeFlowExpressionNode(md, nametable, en, argTupleSet, false);
// if argument is liternal node, argTuple is set to NULL.
- addArgIdxMap(min, idx, argTupleSet);
+
+ NTuple<Descriptor> argTuple = new NTuple<Descriptor>();
+ if (argTupleSet.size() > 1) {
+ NTuple<Descriptor> interTuple =
+ getFlowGraph(md).createIntermediateNode().getDescTuple();
+ for (Iterator<NTuple<Descriptor>> idxIter = argTupleSet.iterator(); idxIter.hasNext();) {
+ NTuple<Descriptor> tuple = idxIter.next();
+ addFlowGraphEdge(md, tuple, interTuple);
+ }
+ argTuple = interTuple;
+ } else {
+ argTuple = argTupleSet.iterator().next();
+ }
+
+ addArgIdxMap(min, idx, argTuple);
FlowNode paramNode = calleeFlowGraph.getParamFlowNode(idx);
if (hasInFlowTo(calleeFlowGraph, paramNode, calleeReturnSet)
|| calleeMethodDesc.getModifiers().isNative()) {
return false;
}
- private NodeTupleSet getNodeTupleSetByArgIdx(MethodInvokeNode min, int idx) {
+ private NTuple<Descriptor> getNodeTupleByArgIdx(MethodInvokeNode min, int idx) {
return mapMethodInvokeNodeToArgIdxMap.get(min).get(new Integer(idx));
}
- private void addArgIdxMap(MethodInvokeNode min, int idx, NodeTupleSet tupleSet) {
- Map<Integer, NodeTupleSet> mapIdxToTupleSet = mapMethodInvokeNodeToArgIdxMap.get(min);
- if (mapIdxToTupleSet == null) {
- mapIdxToTupleSet = new HashMap<Integer, NodeTupleSet>();
- mapMethodInvokeNodeToArgIdxMap.put(min, mapIdxToTupleSet);
+ private void addArgIdxMap(MethodInvokeNode min, int idx, NTuple<Descriptor> argTuple /*
+ * NodeTupleSet
+ * tupleSet
+ */) {
+ Map<Integer, NTuple<Descriptor>> mapIdxToTuple = mapMethodInvokeNodeToArgIdxMap.get(min);
+ if (mapIdxToTuple == null) {
+ mapIdxToTuple = new HashMap<Integer, NTuple<Descriptor>>();
+ mapMethodInvokeNodeToArgIdxMap.put(min, mapIdxToTuple);
}
- mapIdxToTupleSet.put(new Integer(idx), tupleSet);
- }
-
- private void analyzeFlowMethodParameters(MethodDescriptor callermd, SymbolTable nametable,
- MethodInvokeNode min, NodeTupleSet nodeSet) {
-
- if (min.numArgs() > 0) {
-
- int offset;
- if (min.getMethod().isStatic()) {
- offset = 0;
- } else {
- offset = 1;
- // NTuple<Descriptor> thisArgTuple = new NTuple<Descriptor>();
- // thisArgTuple.add(callermd.getThis());
- // NodeTupleSet argTupleSet = new NodeTupleSet();
- // argTupleSet.addTuple(thisArgTuple);
- // addArgIdxMap(min, 0, argTupleSet);
- // nodeSet.addTuple(thisArgTuple);
- }
-
- for (int i = 0; i < min.numArgs(); i++) {
- ExpressionNode en = min.getArg(i);
- NodeTupleSet argTupleSet = new NodeTupleSet();
- analyzeFlowExpressionNode(callermd, nametable, en, argTupleSet, false);
- // if argument is liternal node, argTuple is set to NULL.
- addArgIdxMap(min, i + offset, argTupleSet);
- nodeSet.addTupleSet(argTupleSet);
- }
-
- }
-
+ mapIdxToTuple.put(new Integer(idx), argTuple);
}
private void analyzeLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode en) {
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();