+ });
+
+ // remove a prefix which is not suitable for generating composite location
+ Location localVarLoc = node.getLocTuple().get(0);
+ MethodDescriptor md = (MethodDescriptor) localVarLoc.getDescriptor();
+ ClassDescriptor cd = md.getClassDesc();
+
+ int idx = 0;
+ Set<NTuple<Location>> toberemoved = new HashSet<NTuple<Location>>();
+ // for (int i = 0; i < prefixList.size(); i++) {
+ // NTuple<Location> prefixLocTuple = prefixList.get(i);
+ // if (!containsClassDesc(cd, prefixLocTuple)) {
+ // toberemoved.add(prefixLocTuple);
+ // }
+ // }
+
+ // System.out.println("method class=" + cd + " toberemoved=" + toberemoved);
+
+ prefixList.removeAll(toberemoved);
+
+ return prefixList;
+
+ }
+
+ private boolean containsClassDesc(ClassDescriptor cd, NTuple<Location> prefixLocTuple) {
+ for (int i = 0; i < prefixLocTuple.size(); i++) {
+ Location loc = prefixLocTuple.get(i);
+ Descriptor locDesc = loc.getLocDescriptor();
+ if (locDesc != null) {
+ ClassDescriptor type = getClassTypeDescriptor(locDesc);
+ if (type != null && type.equals(cd)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private GlobalFlowGraph constructSubGlobalFlowGraph(FlowGraph flowGraph) {
+
+ MethodDescriptor md = flowGraph.getMethodDescriptor();
+
+ GlobalFlowGraph globalGraph = getSubGlobalFlowGraph(md);
+
+ // Set<FlowNode> nodeSet = flowGraph.getNodeSet();
+ Set<FlowEdge> edgeSet = flowGraph.getEdgeSet();
+
+ for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
+
+ FlowEdge edge = (FlowEdge) iterator.next();
+ NTuple<Descriptor> srcDescTuple = edge.getInitTuple();
+ NTuple<Descriptor> dstDescTuple = edge.getEndTuple();
+
+ if (flowGraph.getFlowNode(srcDescTuple) instanceof FlowReturnNode
+ || flowGraph.getFlowNode(dstDescTuple) instanceof FlowReturnNode) {
+ continue;
+ }
+
+ // here only keep the first element(method location) of the descriptor
+ // tuple
+ NTuple<Location> srcLocTuple = translateToLocTuple(md, srcDescTuple);
+ // Location srcMethodLoc = srcLocTuple.get(0);
+ // Descriptor srcVarDesc = srcMethodLoc.getLocDescriptor();
+ // // if (flowGraph.isParamDesc(srcVarDesc) &&
+ // (!srcVarDesc.equals(md.getThis()))) {
+ // if (!srcVarDesc.equals(md.getThis())) {
+ // srcLocTuple = new NTuple<Location>();
+ // Location loc = new Location(md, srcVarDesc);
+ // srcLocTuple.add(loc);
+ // }
+ //
+ NTuple<Location> dstLocTuple = translateToLocTuple(md, dstDescTuple);
+ // Location dstMethodLoc = dstLocTuple.get(0);
+ // Descriptor dstVarDesc = dstMethodLoc.getLocDescriptor();
+ // if (!dstVarDesc.equals(md.getThis())) {
+ // dstLocTuple = new NTuple<Location>();
+ // Location loc = new Location(md, dstVarDesc);
+ // dstLocTuple.add(loc);
+ // }
+
+ globalGraph.addValueFlowEdge(srcLocTuple, dstLocTuple);
+
+ }
+
+ return globalGraph;
+ }
+
+ private NTuple<Location> translateToLocTuple(MethodDescriptor md, NTuple<Descriptor> descTuple) {
+
+ NTuple<Location> locTuple = new NTuple<Location>();
+
+ Descriptor enclosingDesc = md;
+ System.out.println("md=" + md + " descTuple=" + descTuple);
+ for (int i = 0; i < descTuple.size(); i++) {
+ Descriptor desc = descTuple.get(i);
+
+ Location loc = new Location(enclosingDesc, desc);
+ locTuple.add(loc);
+
+ if (desc instanceof VarDescriptor) {
+ enclosingDesc = ((VarDescriptor) desc).getType().getClassDesc();
+ } else if (desc instanceof FieldDescriptor) {
+ enclosingDesc = ((FieldDescriptor) desc).getType().getClassDesc();
+ } else {
+ // TODO: inter descriptor case
+ enclosingDesc = desc;
+ }
+
+ }
+
+ return locTuple;
+
+ }
+
+ private void addValueFlowsFromCalleeSubGlobalFlowGraph(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 = 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);
+ }
+
+ }
+
+ }
+
+ private void propagateValueFlowsToCallerFromSubGlobalFlowGraph(MethodInvokeNode min,
+ MethodDescriptor mdCaller, MethodDescriptor possibleMdCallee) {
+
+ System.out.println("---propagate from " + min.printNode(0) + " to caller=" + mdCaller);
+ FlowGraph calleeFlowGraph = getFlowGraph(possibleMdCallee);
+ Map<Integer, NTuple<Descriptor>> mapIdxToArg = mapMethodInvokeNodeToArgIdxMap.get(min);
+
+ System.out.println("-----mapMethodInvokeNodeToArgIdxMap.get(min)="
+ + mapMethodInvokeNodeToArgIdxMap.get(min));
+
+ Set<Integer> keySet = mapIdxToArg.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Integer idx = (Integer) iterator.next();
+ NTuple<Descriptor> argDescTuple = mapIdxToArg.get(idx);
+ if (argDescTuple.size() > 0) {
+ NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argDescTuple);
+ NTuple<Descriptor> paramDescTuple = calleeFlowGraph.getParamFlowNode(idx).getDescTuple();
+ NTuple<Location> paramLocTuple = translateToLocTuple(possibleMdCallee, paramDescTuple);
+ System.out.println("-------paramDescTuple=" + paramDescTuple + "->argDescTuple="
+ + argDescTuple);
+ addMapCallerArgToCalleeParam(min, argDescTuple, paramDescTuple);
+ }
+ }
+
+ // addValueFlowBetweenParametersToCaller(min, mdCaller, possibleMdCallee);
+
+ NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
+ GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(possibleMdCallee);
+ Set<GlobalFlowNode> calleeNodeSet = calleeSubGlobalGraph.getNodeSet();
+ for (Iterator iterator = calleeNodeSet.iterator(); iterator.hasNext();) {
+ GlobalFlowNode calleeNode = (GlobalFlowNode) iterator.next();
+ addValueFlowFromCalleeNode(min, mdCaller, possibleMdCallee, calleeNode);
+ }
+
+ System.out.println("$$$GLOBAL PC LOC ADD=" + mdCaller);
+ Set<NTuple<Location>> pcLocTupleSet = mapMethodInvokeNodeToPCLocTupleSet.get(min);
+ System.out.println("---pcLocTupleSet=" + pcLocTupleSet);
+ GlobalFlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
+ for (Iterator iterator = calleeNodeSet.iterator(); iterator.hasNext();) {
+ GlobalFlowNode calleeNode = (GlobalFlowNode) iterator.next();
+ if (calleeNode.isParamNodeWithIncomingFlows()) {
+ System.out.println("calleeNode.getLocTuple()" + calleeNode.getLocTuple());
+ NTuple<Location> callerSrcNodeLocTuple =
+ translateToCallerLocTuple(min, possibleMdCallee, mdCaller, calleeNode.getLocTuple());
+ System.out.println("---callerSrcNodeLocTuple=" + callerSrcNodeLocTuple);
+ if (callerSrcNodeLocTuple != null && callerSrcNodeLocTuple.size() > 0) {
+ for (Iterator iterator2 = pcLocTupleSet.iterator(); iterator2.hasNext();) {
+ NTuple<Location> pcLocTuple = (NTuple<Location>) iterator2.next();
+ callerSubGlobalGraph.addValueFlowEdge(pcLocTuple, callerSrcNodeLocTuple);
+ }
+ }
+ }
+
+ }
+
+ }
+
+ private void addValueFlowFromCalleeNode(MethodInvokeNode min, MethodDescriptor mdCaller,
+ MethodDescriptor mdCallee, GlobalFlowNode calleeSrcNode) {
+
+ GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(mdCallee);
+ GlobalFlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
+
+ // System.out.println("$addValueFlowFromCalleeNode calleeSrcNode=" + calleeSrcNode);
+
+ NTuple<Location> callerSrcNodeLocTuple =
+ translateToCallerLocTuple(min, mdCallee, mdCaller, calleeSrcNode.getLocTuple());
+ // System.out.println("---callerSrcNodeLocTuple=" + callerSrcNodeLocTuple);
+
+ if (callerSrcNodeLocTuple != null && callerSrcNodeLocTuple.size() > 0) {
+
+ Set<GlobalFlowNode> outNodeSet = calleeSubGlobalGraph.getOutNodeSet(calleeSrcNode);
+
+ for (Iterator iterator = outNodeSet.iterator(); iterator.hasNext();) {
+ GlobalFlowNode outNode = (GlobalFlowNode) iterator.next();
+ NTuple<Location> callerDstNodeLocTuple =
+ translateToCallerLocTuple(min, mdCallee, mdCaller, outNode.getLocTuple());
+ // System.out.println("outNode=" + outNode + " callerDstNodeLocTuple="
+ // + callerDstNodeLocTuple);
+ if (callerDstNodeLocTuple != null) {
+ callerSubGlobalGraph.addValueFlowEdge(callerSrcNodeLocTuple, callerDstNodeLocTuple);
+ }
+ }
+ }
+
+ }
+
+ private NTuple<Location> translateToCallerLocTuple(MethodInvokeNode min,
+ MethodDescriptor mdCallee, MethodDescriptor mdCaller, NTuple<Location> nodeLocTuple) {
+ // this method will return the same nodeLocTuple if the corresponding argument is literal
+ // value.
+
+ // System.out.println("translateToCallerLocTuple=" + nodeLocTuple);
+
+ FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
+ NTuple<Descriptor> nodeDescTuple = translateToDescTuple(nodeLocTuple);
+ if (calleeFlowGraph.isParameter(nodeDescTuple)) {
+ int paramIdx = calleeFlowGraph.getParamIdx(nodeDescTuple);
+ NTuple<Descriptor> argDescTuple = mapMethodInvokeNodeToArgIdxMap.get(min).get(paramIdx);
+
+ // if (isPrimitive(nodeLocTuple.get(0).getLocDescriptor())) {
+ // // the type of argument is primitive.
+ // return nodeLocTuple.clone();
+ // }
+ // System.out.println("paramIdx=" + paramIdx + " argDescTuple=" + argDescTuple + " from min="
+ // + min.printNode(0));
+ NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argDescTuple);
+
+ NTuple<Location> callerLocTuple = new NTuple<Location>();
+
+ callerLocTuple.addAll(argLocTuple);
+ for (int i = 1; i < nodeLocTuple.size(); i++) {
+ callerLocTuple.add(nodeLocTuple.get(i));
+ }
+ return callerLocTuple;
+ } else {
+ return nodeLocTuple.clone();
+ }
+
+ }
+
+ public static boolean isPrimitive(Descriptor desc) {
+
+ if (desc instanceof FieldDescriptor) {
+ return ((FieldDescriptor) desc).getType().isPrimitive();
+ } else if (desc instanceof VarDescriptor) {
+ return ((VarDescriptor) desc).getType().isPrimitive();
+ } else if (desc instanceof InterDescriptor) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static boolean isReference(Descriptor desc) {
+
+ if (desc instanceof FieldDescriptor) {
+
+ TypeDescriptor type = ((FieldDescriptor) desc).getType();
+ if (type.isArray()) {
+ return false;
+ } else {
+ return type.isPtr();
+ }
+
+ } else if (desc instanceof VarDescriptor) {
+ TypeDescriptor type = ((VarDescriptor) desc).getType();
+ if (type.isArray()) {
+ return false;
+ } else {
+ return type.isPtr();
+ }
+ }
+
+ return false;
+ }
+
+ private NTuple<Descriptor> translateToDescTuple(NTuple<Location> locTuple) {
+
+ NTuple<Descriptor> descTuple = new NTuple<Descriptor>();
+ for (int i = 0; i < locTuple.size(); i++) {
+ descTuple.add(locTuple.get(i).getLocDescriptor());
+ }
+ return descTuple;
+
+ }
+
+ 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);
+
+ HierarchyGraph scGraph = getSkeletonCombinationHierarchyGraph(md);
+
+ // set the 'this' reference location
+ if (!md.isStatic()) {
+ System.out.println("setThisLocName=" + scGraph.getHNode(md.getThis()).getName());
+ methodSummary.setThisLocName(scGraph.getHNode(md.getThis()).getName());
+ }
+
+ // set the 'global' reference location if needed
+ if (methodSummary.hasGlobalAccess()) {
+ methodSummary.setGlobalLocName(scGraph.getHNode(GLOBALDESC).getName());
+ }
+
+ // 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);
+ CompositeLocation inferredCompLoc =
+ updateCompositeLocation(flowNode.getCompositeLocation());
+ // 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 + " original="
+ + flowNode.getCompositeLocation());
+
+ Descriptor localVarDesc = flowNode.getDescTuple().get(0);
+ methodSummary.addMapVarNameToInferCompLoc(localVarDesc, inferredCompLoc);
+ methodSummary.addMapParamIdxToInferLoc(paramIdx, inferredCompLoc);
+ }
+
+ }
+
+ }
+
+ private boolean hasOrderingRelation(NTuple<Location> locTuple1, NTuple<Location> locTuple2) {
+
+ int size = locTuple1.size() >= locTuple2.size() ? locTuple2.size() : locTuple1.size();
+
+ for (int idx = 0; idx < size; idx++) {
+ Location loc1 = locTuple1.get(idx);
+ Location loc2 = locTuple2.get(idx);
+
+ Descriptor desc1 = loc1.getDescriptor();
+ Descriptor desc2 = loc2.getDescriptor();
+
+ if (!desc1.equals(desc2)) {
+ throw new Error("Fail to compare " + locTuple1 + " and " + locTuple2);
+ }
+
+ Descriptor locDesc1 = loc1.getLocDescriptor();
+ Descriptor locDesc2 = loc2.getLocDescriptor();
+
+ HierarchyGraph hierarchyGraph = getHierarchyGraph(desc1);
+
+ HNode node1 = hierarchyGraph.getHNode(locDesc1);
+ HNode node2 = hierarchyGraph.getHNode(locDesc2);
+
+ System.out.println("---node1=" + node1 + " node2=" + node2);
+ System.out.println("---hierarchyGraph.getIncomingNodeSet(node2)="
+ + hierarchyGraph.getIncomingNodeSet(node2));
+
+ if (locDesc1.equals(locDesc2)) {
+ continue;
+ } else if (!hierarchyGraph.getIncomingNodeSet(node2).contains(node1)
+ && !hierarchyGraph.getIncomingNodeSet(node1).contains(node2)) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ return false;
+
+ }
+
+ private boolean isHigherThan(NTuple<Location> locTuple1, NTuple<Location> locTuple2) {
+
+ int size = locTuple1.size() >= locTuple2.size() ? locTuple2.size() : locTuple1.size();
+
+ for (int idx = 0; idx < size; idx++) {
+ Location loc1 = locTuple1.get(idx);
+ Location loc2 = locTuple2.get(idx);
+
+ Descriptor desc1 = loc1.getDescriptor();
+ Descriptor desc2 = loc2.getDescriptor();
+
+ if (!desc1.equals(desc2)) {
+ throw new Error("Fail to compare " + locTuple1 + " and " + locTuple2);
+ }
+
+ Descriptor locDesc1 = loc1.getLocDescriptor();
+ Descriptor locDesc2 = loc2.getLocDescriptor();
+
+ HierarchyGraph hierarchyGraph = getHierarchyGraph(desc1);
+
+ HNode node1 = hierarchyGraph.getHNode(locDesc1);
+ HNode node2 = hierarchyGraph.getHNode(locDesc2);
+
+ System.out.println("---node1=" + node1 + " node2=" + node2);
+ System.out.println("---hierarchyGraph.getIncomingNodeSet(node2)="
+ + hierarchyGraph.getIncomingNodeSet(node2));
+
+ if (locDesc1.equals(locDesc2)) {
+ continue;
+ } else if (hierarchyGraph.getIncomingNodeSet(node2).contains(node1)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ return false;
+ }
+
+ 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("\n## 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();
+ // System.out.println("SSJAVA: remove redundant edges: " + desc);
+ HierarchyGraph simpleHierarchyGraph = getHierarchyGraph(desc).clone();
+ simpleHierarchyGraph.setName(desc + "_SIMPLE");
+ simpleHierarchyGraph.removeRedundantEdges();
+ mapDescriptorToSimpleHierarchyGraph.put(desc, simpleHierarchyGraph);
+ }
+ }
+
+ private void insertCombinationNodes() {
+ Set<Descriptor> keySet = mapDescriptorToSkeletonHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
+ 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);
+ }
+ }
+
+ private void constructSkeletonHierarchyGraph() {
+ Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
+ System.out.println("SSJAVA: Constructing Skeleton Hierarchy Graph: " + desc);
+ HierarchyGraph simpleGraph = getSimpleHierarchyGraph(desc);
+ 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_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();
+ }
+
+ }
+
+ public HierarchyGraph getSimpleHierarchyGraph(Descriptor d) {
+ return mapDescriptorToSimpleHierarchyGraph.get(d);
+ }
+
+ private HierarchyGraph getSkeletonHierarchyGraph(Descriptor d) {
+ if (!mapDescriptorToSkeletonHierarchyGraph.containsKey(d)) {
+ mapDescriptorToSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
+ }
+ return mapDescriptorToSkeletonHierarchyGraph.get(d);
+ }
+
+ public HierarchyGraph getSkeletonCombinationHierarchyGraph(Descriptor d) {
+ if (!mapDescriptorToCombineSkeletonHierarchyGraph.containsKey(d)) {
+ mapDescriptorToCombineSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
+ }
+ return mapDescriptorToCombineSkeletonHierarchyGraph.get(d);
+ }
+
+ private void constructHierarchyGraph() {
+
+ // do fixed-point analysis
+
+ LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
+
+ // Collections.sort(descriptorListToAnalyze, new
+ // Comparator<MethodDescriptor>() {
+ // public int compare(MethodDescriptor o1, MethodDescriptor o2) {
+ // return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
+ // }
+ // });
+
+ // current descriptors to visit in fixed-point interprocedural analysis,
+ // prioritized by dependency in the call graph
+ methodDescriptorsToVisitStack.clear();
+
+ Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
+ methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
+
+ while (!descriptorListToAnalyze.isEmpty()) {
+ MethodDescriptor md = descriptorListToAnalyze.removeFirst();
+ methodDescriptorsToVisitStack.add(md);
+ }
+
+ // analyze scheduled methods until there are no more to visit
+ while (!methodDescriptorsToVisitStack.isEmpty()) {
+ // start to analyze leaf node
+ MethodDescriptor md = methodDescriptorsToVisitStack.pop();
+
+ HierarchyGraph hierarchyGraph = new HierarchyGraph(md);
+ // MethodSummary methodSummary = new MethodSummary(md);
+
+ // MethodLocationInfo methodInfo = new MethodLocationInfo(md);
+ // curMethodInfo = methodInfo;
+
+ System.out.println();
+ System.out.println("SSJAVA: Construcing the hierarchy graph from " + md);
+
+ constructHierarchyGraph(md, hierarchyGraph);
+
+ HierarchyGraph prevHierarchyGraph = getHierarchyGraph(md);
+ // MethodSummary prevMethodSummary = getMethodSummary(md);
+
+ if (!hierarchyGraph.equals(prevHierarchyGraph)) {
+
+ mapDescriptorToHierarchyGraph.put(md, hierarchyGraph);
+ // mapDescToLocationSummary.put(md, methodSummary);
+
+ // results for callee changed, so enqueue dependents caller for
+ // further analysis
+ Iterator<MethodDescriptor> depsItr = ssjava.getDependents(md).iterator();
+ while (depsItr.hasNext()) {
+ MethodDescriptor methodNext = depsItr.next();
+ if (!methodDescriptorsToVisitStack.contains(methodNext)
+ && methodDescriptorToVistSet.contains(methodNext)) {
+ methodDescriptorsToVisitStack.add(methodNext);
+ }
+ }
+
+ }
+
+ }
+
+ setupToAnalyze();
+ while (!toAnalyzeIsEmpty()) {
+ ClassDescriptor cd = toAnalyzeNext();
+ HierarchyGraph graph = getHierarchyGraph(cd);
+ for (Iterator iter = cd.getFields(); iter.hasNext();) {
+ FieldDescriptor fieldDesc = (FieldDescriptor) iter.next();
+ if (!(fieldDesc.isStatic() && fieldDesc.isFinal())) {
+ graph.getHNode(fieldDesc);
+ }
+ }
+ }
+
+ Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Descriptor key = (Descriptor) iterator.next();
+ HierarchyGraph graph = getHierarchyGraph(key);
+
+ Set<HNode> nodeToBeConnected = new HashSet<HNode>();
+ for (Iterator iterator2 = graph.getNodeSet().iterator(); iterator2.hasNext();) {
+ HNode node = (HNode) iterator2.next();
+ if (!node.isSkeleton() && !node.isCombinationNode()) {
+ if (graph.getIncomingNodeSet(node).size() == 0) {
+ nodeToBeConnected.add(node);
+ }
+ }
+ }
+
+ for (Iterator iterator2 = nodeToBeConnected.iterator(); iterator2.hasNext();) {
+ HNode node = (HNode) iterator2.next();
+ System.out.println("NEED TO BE CONNECTED TO TOP=" + node);
+ graph.addEdge(graph.getHNode(TOPDESC), node);
+ }
+
+ }
+
+ }
+
+ private HierarchyGraph getHierarchyGraph(Descriptor d) {
+ if (!mapDescriptorToHierarchyGraph.containsKey(d)) {
+ mapDescriptorToHierarchyGraph.put(d, new HierarchyGraph(d));
+ }
+ return mapDescriptorToHierarchyGraph.get(d);
+ }
+
+ private void constructHierarchyGraph(MethodDescriptor md, HierarchyGraph methodGraph) {
+
+ // visit each node of method flow graph
+ FlowGraph fg = getFlowGraph(md);
+ // Set<FlowNode> nodeSet = fg.getNodeSet();
+
+ Set<FlowEdge> edgeSet = fg.getEdgeSet();
+
+ Set<Descriptor> paramDescSet = fg.getMapParamDescToIdx().keySet();
+ for (Iterator iterator = paramDescSet.iterator(); iterator.hasNext();) {
+ Descriptor desc = (Descriptor) iterator.next();
+ methodGraph.getHNode(desc).setSkeleton(true);
+ }
+
+ // for the method lattice, we need to look at the first element of
+ // NTuple<Descriptor>
+ boolean hasGlobalAccess = false;
+ // for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ // FlowNode originalSrcNode = (FlowNode) iterator.next();
+ for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
+ FlowEdge edge = (FlowEdge) iterator.next();
+
+ FlowNode originalSrcNode = fg.getFlowNode(edge.getInitTuple());
+ Set<FlowNode> sourceNodeSet = new HashSet<FlowNode>();
+ if (originalSrcNode instanceof FlowReturnNode) {
+ FlowReturnNode rnode = (FlowReturnNode) originalSrcNode;
+ System.out.println("rnode=" + rnode);
+ Set<NTuple<Descriptor>> tupleSet = rnode.getReturnTupleSet();
+ for (Iterator iterator2 = tupleSet.iterator(); iterator2.hasNext();) {
+ NTuple<Descriptor> nTuple = (NTuple<Descriptor>) iterator2.next();
+ sourceNodeSet.add(fg.getFlowNode(nTuple));
+ System.out.println("&&&SOURCE fg.getFlowNode(nTuple)=" + fg.getFlowNode(nTuple));
+ }
+ } else {
+ sourceNodeSet.add(originalSrcNode);
+ }
+
+ // System.out.println("---sourceNodeSet=" + sourceNodeSet + " from originalSrcNode="
+ // + originalSrcNode);
+
+ for (Iterator iterator3 = sourceNodeSet.iterator(); iterator3.hasNext();) {
+ FlowNode srcNode = (FlowNode) iterator3.next();
+
+ NTuple<Descriptor> srcNodeTuple = srcNode.getDescTuple();
+ Descriptor srcLocalDesc = srcNodeTuple.get(0);
+
+ if (srcLocalDesc instanceof InterDescriptor
+ && ((InterDescriptor) srcLocalDesc).getMethodArgIdxPair() != null) {
+
+ if (srcNode.getCompositeLocation() == null) {
+ continue;
+ }
+ }
+
+ // if the srcNode is started with the global descriptor
+ // need to set as a skeleton node
+ if (!hasGlobalAccess && srcNode.getDescTuple().startsWith(GLOBALDESC)) {
+ hasGlobalAccess = true;
+ }
+
+ // Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(originalSrcNode);
+ // for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
+ // FlowEdge outEdge = (FlowEdge) iterator2.next();
+ // FlowNode originalDstNode = outEdge.getDst();
+ FlowNode originalDstNode = fg.getFlowNode(edge.getEndTuple());
+
+ Set<FlowNode> dstNodeSet = new HashSet<FlowNode>();
+ if (originalDstNode instanceof FlowReturnNode) {
+ FlowReturnNode rnode = (FlowReturnNode) originalDstNode;
+ // System.out.println("\n-returnNode=" + rnode);
+ Set<NTuple<Descriptor>> tupleSet = rnode.getReturnTupleSet();
+ for (Iterator iterator4 = tupleSet.iterator(); iterator4.hasNext();) {
+ NTuple<Descriptor> nTuple = (NTuple<Descriptor>) iterator4.next();
+ dstNodeSet.add(fg.getFlowNode(nTuple));
+ System.out.println("&&&DST fg.getFlowNode(nTuple)=" + fg.getFlowNode(nTuple));
+ }
+ } else {
+ dstNodeSet.add(originalDstNode);
+ }
+ // System.out.println("---dstNodeSet=" + dstNodeSet);
+ for (Iterator iterator4 = dstNodeSet.iterator(); iterator4.hasNext();) {
+ FlowNode dstNode = (FlowNode) iterator4.next();
+
+ NTuple<Descriptor> dstNodeTuple = dstNode.getDescTuple();
+ Descriptor dstLocalDesc = dstNodeTuple.get(0);
+
+ if (dstLocalDesc instanceof InterDescriptor
+ && ((InterDescriptor) dstLocalDesc).getMethodArgIdxPair() != null) {
+ if (dstNode.getCompositeLocation() == null) {
+ System.out.println("%%%%%%%%%%%%%SKIP=" + dstNode);
+ continue;
+ }
+ }
+
+ // if (outEdge.getInitTuple().equals(srcNodeTuple)
+ // && outEdge.getEndTuple().equals(dstNodeTuple)) {
+
+ NTuple<Descriptor> srcCurTuple = srcNode.getCurrentDescTuple();
+ NTuple<Descriptor> dstCurTuple = dstNode.getCurrentDescTuple();
+
+ System.out.println("-srcCurTuple=" + srcCurTuple + " dstCurTuple=" + dstCurTuple
+ + " srcNode=" + srcNode + " dstNode=" + dstNode);
+
+ if ((srcCurTuple.size() > 1 && dstCurTuple.size() > 1)
+ && srcCurTuple.get(0).equals(dstCurTuple.get(0))) {
+
+ // value flows between fields
+ Descriptor desc = srcCurTuple.get(0);
+ ClassDescriptor classDesc;
+
+ if (desc.equals(GLOBALDESC)) {
+ classDesc = md.getClassDesc();
+ } else {
+ VarDescriptor varDesc = (VarDescriptor) srcCurTuple.get(0);
+ classDesc = varDesc.getType().getClassDesc();
+ }
+ extractFlowsBetweenFields(classDesc, srcNode, dstNode, 1);
+
+ } else if ((srcCurTuple.size() == 1 && dstCurTuple.size() == 1)
+ || ((srcCurTuple.size() > 1 || dstCurTuple.size() > 1) && !srcCurTuple.get(0).equals(
+ dstCurTuple.get(0)))) {
+
+ // value flow between a primitive local var - a primitive local var or local var -
+ // field
+
+ Descriptor srcDesc = srcCurTuple.get(0);
+ Descriptor dstDesc = dstCurTuple.get(0);
+
+ methodGraph.addEdge(srcDesc, dstDesc);
+
+ if (fg.isParamDesc(srcDesc)) {
+ methodGraph.setParamHNode(srcDesc);
+ }
+ if (fg.isParamDesc(dstDesc)) {
+ methodGraph.setParamHNode(dstDesc);
+ }
+
+ }
+
+ // }
+ // }
+
+ }
+
+ }
+
+ }
+
+ // If the method accesses static fields
+ // set hasGloabalAccess true in the method summary.
+ if (hasGlobalAccess) {
+ getMethodSummary(md).setHasGlobalAccess();
+ }
+ methodGraph.getHNode(GLOBALDESC).setSkeleton(true);
+
+ if (ssjava.getMethodContainingSSJavaLoop().equals(md)) {
+ // if the current method contains the event loop
+ // we need to set all nodes of the hierarchy graph as a skeleton node
+ Set<HNode> hnodeSet = methodGraph.getNodeSet();
+ for (Iterator iterator = hnodeSet.iterator(); iterator.hasNext();) {
+ HNode hnode = (HNode) iterator.next();
+ hnode.setSkeleton(true);
+ }
+ }
+
+ }
+
+ private MethodSummary getMethodSummary(MethodDescriptor md) {
+ if (!mapDescToLocationSummary.containsKey(md)) {
+ mapDescToLocationSummary.put(md, new MethodSummary(md));
+ }
+ return (MethodSummary) mapDescToLocationSummary.get(md);
+ }
+
+ private void addMapClassDefinitionToLineNum(ClassDescriptor cd, String strLine, int lineNum) {
+
+ String classSymbol = cd.getSymbol();
+ int idx = classSymbol.lastIndexOf("$");
+ if (idx != -1) {
+ classSymbol = classSymbol.substring(idx + 1);
+ }
+
+ String pattern = "class " + classSymbol + " ";
+ if (strLine.indexOf(pattern) != -1) {
+ mapDescToDefinitionLine.put(cd, lineNum);
+ }
+ }
+
+ private void addMapMethodDefinitionToLineNum(Set<MethodDescriptor> methodSet, String strLine,
+ int lineNum) {
+ for (Iterator iterator = methodSet.iterator(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+ String pattern = md.getMethodDeclaration();
+ if (strLine.indexOf(pattern) != -1) {
+ mapDescToDefinitionLine.put(md, lineNum);
+ methodSet.remove(md);
+ return;
+ }
+ }
+
+ }
+
+ private void readOriginalSourceFiles() {
+
+ SymbolTable classtable = state.getClassSymbolTable();
+
+ Set<ClassDescriptor> classDescSet = new HashSet<ClassDescriptor>();
+ classDescSet.addAll(classtable.getValueSet());
+
+ try {
+ // inefficient implement. it may re-visit the same file if the file
+ // contains more than one class definitions.
+ for (Iterator iterator = classDescSet.iterator(); iterator.hasNext();) {
+ ClassDescriptor cd = (ClassDescriptor) iterator.next();
+
+ Set<MethodDescriptor> methodSet = new HashSet<MethodDescriptor>();
+ methodSet.addAll(cd.getMethodTable().getValueSet());
+
+ String sourceFileName = cd.getSourceFileName();
+ Vector<String> lineVec = new Vector<String>();
+
+ mapFileNameToLineVector.put(sourceFileName, lineVec);
+
+ BufferedReader in = new BufferedReader(new FileReader(sourceFileName));
+ String strLine;
+ int lineNum = 1;
+ lineVec.add(""); // the index is started from 1.
+ while ((strLine = in.readLine()) != null) {
+ lineVec.add(lineNum, strLine);
+ addMapClassDefinitionToLineNum(cd, strLine, lineNum);
+ addMapMethodDefinitionToLineNum(methodSet, strLine, lineNum);
+ lineNum++;
+ }
+
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ private String generateLatticeDefinition(Descriptor desc) {
+
+ Set<String> sharedLocSet = new HashSet<String>();
+
+ SSJavaLattice<String> lattice = getLattice(desc);
+ String rtr = "@LATTICE(\"";
+
+ Map<String, Set<String>> map = lattice.getTable();
+ Set<String> keySet = map.keySet();
+ boolean first = true;
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ String key = (String) iterator.next();
+ if (!key.equals(lattice.getTopItem())) {
+ Set<String> connectedSet = map.get(key);
+
+ if (connectedSet.size() == 1) {
+ if (connectedSet.iterator().next().equals(lattice.getBottomItem())) {
+ if (!first) {
+ rtr += ",";
+ } else {
+ rtr += "LOC,";
+ first = false;
+ }
+ rtr += key;
+ if (lattice.isSharedLoc(key)) {
+ rtr += "," + key + "*";
+ }
+ }
+ }
+
+ for (Iterator iterator2 = connectedSet.iterator(); iterator2.hasNext();) {
+ String loc = (String) iterator2.next();
+ if (!loc.equals(lattice.getBottomItem())) {
+ if (!first) {
+ rtr += ",";
+ } else {
+ rtr += "LOC,";
+ first = false;
+ }
+ rtr += loc + "<" + key;
+ if (lattice.isSharedLoc(key) && (!sharedLocSet.contains(key))) {
+ rtr += "," + key + "*";
+ sharedLocSet.add(key);
+ }
+ if (lattice.isSharedLoc(loc) && (!sharedLocSet.contains(loc))) {
+ rtr += "," + loc + "*";
+ sharedLocSet.add(loc);
+ }
+
+ }
+ }
+ }
+ }
+
+ if (desc instanceof MethodDescriptor) {
+ System.out.println("#EXTRA LOC DECLARATION GEN=" + desc);
+
+ MethodDescriptor md = (MethodDescriptor) desc;
+ MethodSummary methodSummary = getMethodSummary(md);
+
+ TypeDescriptor returnType = ((MethodDescriptor) desc).getReturnType();
+ if (!ssjava.getMethodContainingSSJavaLoop().equals(desc) && returnType != null
+ && (!returnType.isVoid())) {
+ CompositeLocation returnLoc = methodSummary.getRETURNLoc();
+ if (returnLoc.getSize() == 1) {
+ String returnLocStr = generateLocationAnnoatation(methodSummary.getRETURNLoc());
+ if (rtr.indexOf(returnLocStr) == -1) {
+ rtr += "," + returnLocStr;
+ }
+ }
+ }
+ rtr += "\")";
+
+ if (!ssjava.getMethodContainingSSJavaLoop().equals(desc)) {
+ if (returnType != null && (!returnType.isVoid())) {
+ rtr +=
+ "\n@RETURNLOC(\"" + generateLocationAnnoatation(methodSummary.getRETURNLoc()) + "\")";
+ }
+
+ CompositeLocation pcLoc = methodSummary.getPCLoc();
+ if ((pcLoc != null) && (!pcLoc.get(0).isTop())) {
+ rtr += "\n@PCLOC(\"" + generateLocationAnnoatation(pcLoc) + "\")";
+ }
+ }
+
+ if (!md.isStatic()) {
+ rtr += "\n@THISLOC(\"" + methodSummary.getThisLocName() + "\")";
+ }
+ rtr += "\n@GLOBALLOC(\"" + methodSummary.getGlobalLocName() + "\")";
+
+ } else {
+ rtr += "\")";
+ }
+
+ return rtr;
+ }
+
+ private void generateAnnoatedCode() {
+
+ readOriginalSourceFiles();
+
+ setupToAnalyze();
+ while (!toAnalyzeIsEmpty()) {
+ ClassDescriptor cd = toAnalyzeNext();
+
+ setupToAnalazeMethod(cd);
+
+ String sourceFileName = cd.getSourceFileName();
+
+ if (cd.isInterface()) {
+ continue;
+ }
+
+ int classDefLine = mapDescToDefinitionLine.get(cd);
+ Vector<String> sourceVec = mapFileNameToLineVector.get(sourceFileName);
+
+ LocationSummary fieldLocSummary = getLocationSummary(cd);
+
+ String fieldLatticeDefStr = generateLatticeDefinition(cd);
+ String annoatedSrc = fieldLatticeDefStr + newline + sourceVec.get(classDefLine);
+ sourceVec.set(classDefLine, annoatedSrc);
+
+ // generate annotations for field declarations
+ // Map<Descriptor, CompositeLocation> inferLocMap = fieldLocInfo.getMapDescToInferLocation();
+ Map<String, String> mapFieldNameToLocName = fieldLocSummary.getMapHNodeNameToLocationName();
+
+ for (Iterator iter = cd.getFields(); iter.hasNext();) {
+ FieldDescriptor fd = (FieldDescriptor) iter.next();
+
+ String locAnnotationStr;
+ // CompositeLocation inferLoc = inferLocMap.get(fd);
+ String locName = mapFieldNameToLocName.get(fd.getSymbol());
+
+ if (locName != null) {
+ // infer loc is null if the corresponding field is static and final
+ // locAnnotationStr = "@LOC(\"" + generateLocationAnnoatation(inferLoc) + "\")";
+ locAnnotationStr = "@LOC(\"" + locName + "\")";
+ int fdLineNum = fd.getLineNum();
+ String orgFieldDeclarationStr = sourceVec.get(fdLineNum);
+ String fieldDeclaration = fd.toString();
+ fieldDeclaration = fieldDeclaration.substring(0, fieldDeclaration.length() - 1);
+ String annoatedStr = locAnnotationStr + " " + orgFieldDeclarationStr;
+ sourceVec.set(fdLineNum, annoatedStr);
+ }
+
+ }
+
+ while (!toAnalyzeMethodIsEmpty()) {
+ MethodDescriptor md = toAnalyzeMethodNext();
+
+ if (!ssjava.needTobeAnnotated(md)) {
+ continue;
+ }
+
+ SSJavaLattice<String> methodLattice = md2lattice.get(md);
+ if (methodLattice != null) {
+
+ int methodDefLine = md.getLineNum();
+
+ // MethodLocationInfo methodLocInfo = getMethodLocationInfo(md);
+ // Map<Descriptor, CompositeLocation> methodInferLocMap =
+ // methodLocInfo.getMapDescToInferLocation();
+
+ MethodSummary methodSummary = getMethodSummary(md);
+
+ Map<Descriptor, CompositeLocation> mapVarDescToInferLoc =
+ methodSummary.getMapVarDescToInferCompositeLocation();
+ System.out.println("-----md=" + md);
+ System.out.println("-----mapVarDescToInferLoc=" + mapVarDescToInferLoc);
+
+ Set<Descriptor> localVarDescSet = mapVarDescToInferLoc.keySet();
+
+ Set<String> localLocElementSet = methodLattice.getElementSet();
+
+ for (Iterator iterator = localVarDescSet.iterator(); iterator.hasNext();) {
+ Descriptor localVarDesc = (Descriptor) iterator.next();
+ System.out.println("-------localVarDesc=" + localVarDesc);
+ CompositeLocation inferLoc = mapVarDescToInferLoc.get(localVarDesc);
+
+ String localLocIdentifier = inferLoc.get(0).getLocIdentifier();
+ if (!localLocElementSet.contains(localLocIdentifier)) {
+ methodLattice.put(localLocIdentifier);
+ }
+
+ String locAnnotationStr = "@LOC(\"" + generateLocationAnnoatation(inferLoc) + "\")";
+
+ if (!isParameter(md, localVarDesc)) {
+ if (mapDescToDefinitionLine.containsKey(localVarDesc)) {
+ int varLineNum = mapDescToDefinitionLine.get(localVarDesc);
+ String orgSourceLine = sourceVec.get(varLineNum);
+ System.out.println("varLineNum=" + varLineNum + " org src=" + orgSourceLine);
+ int idx =
+ orgSourceLine.indexOf(generateVarDeclaration((VarDescriptor) localVarDesc));
+ System.out.println("idx=" + idx
+ + " generateVarDeclaration((VarDescriptor) localVarDesc)="
+ + generateVarDeclaration((VarDescriptor) localVarDesc));
+ assert (idx != -1);
+ String annoatedStr =
+ orgSourceLine.substring(0, idx) + locAnnotationStr + " "
+ + orgSourceLine.substring(idx);
+ sourceVec.set(varLineNum, annoatedStr);
+ }
+ } else {
+ String methodDefStr = sourceVec.get(methodDefLine);
+
+ int idx =
+ getParamLocation(methodDefStr,
+ generateVarDeclaration((VarDescriptor) localVarDesc));
+ System.out.println("methodDefStr=" + methodDefStr + " localVarDesc=" + localVarDesc
+ + " idx=" + idx);
+ assert (idx != -1);
+
+ String annoatedStr =
+ methodDefStr.substring(0, idx) + locAnnotationStr + " "
+ + methodDefStr.substring(idx);
+ sourceVec.set(methodDefLine, annoatedStr);
+ }
+
+ }
+
+ // check if the lattice has to have the location type for the this
+ // reference...
+
+ // boolean needToAddthisRef = hasThisReference(md);
+ // if (localLocElementSet.contains("this")) {
+ // methodLattice.put("this");
+ // }
+
+ String methodLatticeDefStr = generateLatticeDefinition(md);
+ String annoatedStr = methodLatticeDefStr + newline + sourceVec.get(methodDefLine);
+ sourceVec.set(methodDefLine, annoatedStr);
+
+ }
+ }
+
+ }
+
+ codeGen();
+ }
+
+ private boolean hasThisReference(MethodDescriptor md) {
+
+ FlowGraph fg = getFlowGraph(md);
+ Set<FlowNode> nodeSet = fg.getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode flowNode = (FlowNode) iterator.next();
+ if (flowNode.getDescTuple().get(0).equals(md.getThis())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private int getParamLocation(String methodStr, String paramStr) {
+
+ String pattern = paramStr + ",";
+
+ int idx = methodStr.indexOf(pattern);
+ if (idx != -1) {
+ return idx;
+ } else {
+ pattern = paramStr + ")";
+ return methodStr.indexOf(pattern);
+ }
+
+ }
+
+ private String generateVarDeclaration(VarDescriptor varDesc) {
+
+ TypeDescriptor td = varDesc.getType();
+ String rtr = td.toString();
+ if (td.isArray()) {
+ for (int i = 0; i < td.getArrayCount(); i++) {
+ rtr += "[]";
+ }
+ }
+ rtr += " " + varDesc.getName();
+ return rtr;
+
+ }
+
+ private String generateLocationAnnoatation(CompositeLocation loc) {
+ String rtr = "";
+ // method location
+ Location methodLoc = loc.get(0);
+ rtr += methodLoc.getLocIdentifier();
+
+ for (int i = 1; i < loc.getSize(); i++) {
+ Location element = loc.get(i);
+ rtr += "," + element.getDescriptor().getSymbol() + "." + element.getLocIdentifier();
+ }
+
+ return rtr;
+ }
+
+ private boolean isParameter(MethodDescriptor md, Descriptor localVarDesc) {
+ return getFlowGraph(md).isParamDesc(localVarDesc);
+ }
+
+ private String extractFileName(String fileName) {
+ int idx = fileName.lastIndexOf("/");
+ if (idx == -1) {
+ return fileName;
+ } else {
+ return fileName.substring(idx + 1);
+ }
+
+ }
+
+ private void codeGen() {
+
+ Set<String> originalFileNameSet = mapFileNameToLineVector.keySet();
+ for (Iterator iterator = originalFileNameSet.iterator(); iterator.hasNext();) {
+ String orgFileName = (String) iterator.next();
+ String outputFileName = extractFileName(orgFileName);
+
+ Vector<String> sourceVec = mapFileNameToLineVector.get(orgFileName);
+
+ try {
+
+ FileWriter fileWriter = new FileWriter("./infer/" + outputFileName);
+ BufferedWriter out = new BufferedWriter(fileWriter);
+
+ for (int i = 0; i < sourceVec.size(); i++) {
+ out.write(sourceVec.get(i));
+ out.newLine();
+ }
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ }
+
+ private void checkLattices() {
+
+ LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
+
+ // current descriptors to visit in fixed-point interprocedural analysis,
+ // prioritized by
+ // dependency in the call graph
+ methodDescriptorsToVisitStack.clear();
+
+ // descriptorListToAnalyze.removeFirst();
+
+ Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
+ methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
+
+ while (!descriptorListToAnalyze.isEmpty()) {
+ MethodDescriptor md = descriptorListToAnalyze.removeFirst();
+ checkLatticesOfVirtualMethods(md);
+ }
+
+ }
+
+ private void debug_writeLatticeDotFile() {
+ // generate lattice dot file
+
+ setupToAnalyze();
+
+ while (!toAnalyzeIsEmpty()) {
+ ClassDescriptor cd = toAnalyzeNext();
+
+ setupToAnalazeMethod(cd);
+
+ SSJavaLattice<String> classLattice = cd2lattice.get(cd);
+ if (classLattice != null) {
+ ssjava.writeLatticeDotFile(cd, null, classLattice);
+ debug_printDescriptorToLocNameMapping(cd);
+ }
+
+ while (!toAnalyzeMethodIsEmpty()) {
+ MethodDescriptor md = toAnalyzeMethodNext();
+ SSJavaLattice<String> methodLattice = md2lattice.get(md);
+ if (methodLattice != null) {
+ ssjava.writeLatticeDotFile(cd, md, methodLattice);
+ debug_printDescriptorToLocNameMapping(md);
+ }
+ }
+ }
+
+ }
+
+ private void debug_printDescriptorToLocNameMapping(Descriptor desc) {
+
+ LocationInfo info = getLocationInfo(desc);
+ System.out.println("## " + desc + " ##");
+ System.out.println(info.getMapDescToInferLocation());
+ LocationInfo locInfo = getLocationInfo(desc);
+ System.out.println("mapping=" + locInfo.getMapLocSymbolToDescSet());
+ System.out.println("###################");
+
+ }
+
+ private void calculateExtraLocations() {
+
+ LinkedList<MethodDescriptor> methodDescList = ssjava.getSortedDescriptors();
+ for (Iterator iterator = methodDescList.iterator(); iterator.hasNext();) {
+ MethodDescriptor md = (MethodDescriptor) iterator.next();
+ if (!ssjava.getMethodContainingSSJavaLoop().equals(md)) {
+ calculateExtraLocations(md);
+ }
+ }
+
+ }
+
+ private void checkLatticesOfVirtualMethods(MethodDescriptor md) {
+
+ if (!md.isStatic()) {
+ Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
+ setPossibleCallees.addAll(ssjava.getCallGraph().getMethods(md));
+
+ for (Iterator iterator = setPossibleCallees.iterator(); iterator.hasNext();) {
+ MethodDescriptor mdCallee = (MethodDescriptor) iterator.next();
+ if (!md.equals(mdCallee)) {
+ checkConsistency(md, mdCallee);
+ }
+ }
+
+ }
+
+ }
+
+ private void checkConsistency(MethodDescriptor md1, MethodDescriptor md2) {
+
+ // check that two lattice have the same relations between parameters(+PC
+ // LOC, GLOBAL_LOC RETURN LOC)
+
+ List<CompositeLocation> list1 = new ArrayList<CompositeLocation>();
+ List<CompositeLocation> list2 = new ArrayList<CompositeLocation>();
+
+ MethodLocationInfo locInfo1 = getMethodLocationInfo(md1);
+ MethodLocationInfo locInfo2 = getMethodLocationInfo(md2);
+
+ Map<Integer, CompositeLocation> paramMap1 = locInfo1.getMapParamIdxToInferLoc();
+ Map<Integer, CompositeLocation> paramMap2 = locInfo2.getMapParamIdxToInferLoc();
+
+ int numParam = locInfo1.getMapParamIdxToInferLoc().keySet().size();
+
+ // add location types of paramters
+ for (int idx = 0; idx < numParam; idx++) {
+ list1.add(paramMap1.get(Integer.valueOf(idx)));
+ list2.add(paramMap2.get(Integer.valueOf(idx)));
+ }
+
+ // add program counter location
+ list1.add(locInfo1.getPCLoc());
+ list2.add(locInfo2.getPCLoc());
+
+ if (!md1.getReturnType().isVoid()) {
+ // add return value location
+ CompositeLocation rtrLoc1 = getMethodLocationInfo(md1).getReturnLoc();
+ CompositeLocation rtrLoc2 = getMethodLocationInfo(md2).getReturnLoc();
+ list1.add(rtrLoc1);
+ list2.add(rtrLoc2);
+ }
+
+ // add global location type
+ if (md1.isStatic()) {
+ CompositeLocation globalLoc1 =
+ new CompositeLocation(new Location(md1, locInfo1.getGlobalLocName()));
+ CompositeLocation globalLoc2 =
+ new CompositeLocation(new Location(md2, locInfo2.getGlobalLocName()));
+ list1.add(globalLoc1);
+ list2.add(globalLoc2);
+ }
+
+ for (int i = 0; i < list1.size(); i++) {
+ CompositeLocation locA1 = list1.get(i);
+ CompositeLocation locA2 = list2.get(i);
+ for (int k = 0; k < list1.size(); k++) {
+ if (i != k) {
+ CompositeLocation locB1 = list1.get(k);
+ CompositeLocation locB2 = list2.get(k);
+ boolean r1 = isGreaterThan(getLattice(md1), locA1, locB1);
+
+ boolean r2 = isGreaterThan(getLattice(md1), locA2, locB2);
+
+ if (r1 != r2) {
+ throw new Error("The method " + md1 + " is not consistent with the method " + md2
+ + ".:: They have a different ordering relation between locations (" + locA1 + ","
+ + locB1 + ") and (" + locA2 + "," + locB2 + ").");
+ }
+ }
+ }
+ }
+
+ }
+
+ private String getSymbol(int idx, FlowNode node) {
+ Descriptor desc = node.getDescTuple().get(idx);
+ return desc.getSymbol();
+ }
+
+ private Descriptor getDescriptor(int idx, FlowNode node) {
+ Descriptor desc = node.getDescTuple().get(idx);
+ return desc;
+ }
+
+ private void calculatePCLOC(MethodDescriptor md) {
+
+ System.out.println("#CalculatePCLOC");
+ MethodSummary methodSummary = getMethodSummary(md);
+ FlowGraph fg = getFlowGraph(md);
+ Map<Integer, CompositeLocation> mapParamToLoc = methodSummary.getMapParamIdxToInferLoc();
+
+ // calculate the initial program counter location
+ // PC location is higher than location types of parameters which has incoming flows.
+
+ Set<NTuple<Location>> paramLocTupleHavingInFlowSet = new HashSet<NTuple<Location>>();
+ Set<Descriptor> paramDescNOTHavingInFlowSet = new HashSet<Descriptor>();
+ // Set<FlowNode> paramNodeNOThavingInFlowSet = new HashSet<FlowNode>();
+
+ int numParams = fg.getNumParameters();
+ for (int i = 0; i < numParams; i++) {
+ FlowNode paramFlowNode = fg.getParamFlowNode(i);
+ Descriptor prefix = paramFlowNode.getDescTuple().get(0);
+ NTuple<Descriptor> paramDescTuple = paramFlowNode.getCurrentDescTuple();
+ NTuple<Location> paramLocTuple = translateToLocTuple(md, paramDescTuple);
+
+ Set<FlowNode> inNodeToParamSet = fg.getIncomingNodeSetByPrefix(prefix);
+ if (inNodeToParamSet.size() > 0) {
+ // parameter has in-value flows
+
+ for (Iterator iterator = inNodeToParamSet.iterator(); iterator.hasNext();) {
+ FlowNode inNode = (FlowNode) iterator.next();
+ Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(inNode);
+ for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
+ FlowEdge flowEdge = (FlowEdge) iterator2.next();
+ if (flowEdge.getEndTuple().startsWith(prefix)) {
+ NTuple<Location> paramLocTupleWithIncomingFlow =
+ translateToLocTuple(md, flowEdge.getEndTuple());
+ paramLocTupleHavingInFlowSet.add(paramLocTupleWithIncomingFlow);
+ }
+ }
+ }
+
+ // paramLocTupleHavingInFlowSet.add(paramLocTuple);
+ } else {
+ // paramNodeNOThavingInFlowSet.add(fg.getFlowNode(paramDescTuple));
+ paramDescNOTHavingInFlowSet.add(prefix);
+ }
+ }
+
+ System.out.println("paramLocTupleHavingInFlowSet=" + paramLocTupleHavingInFlowSet);
+
+ if (paramLocTupleHavingInFlowSet.size() > 0
+ && !coversAllParamters(md, fg, paramLocTupleHavingInFlowSet)) {
+
+ // Here, generates a location in the method lattice that is higher than the
+ // paramLocTupleHavingInFlowSet
+ NTuple<Location> pcLocTuple =
+ generateLocTupleRelativeTo(md, paramLocTupleHavingInFlowSet, PCLOC);
+
+ NTuple<Descriptor> pcDescTuple = translateToDescTuple(pcLocTuple);
+
+ // System.out.println("pcLoc=" + pcLocTuple);
+
+ CompositeLocation curPCLoc = methodSummary.getPCLoc();
+ if (curPCLoc.get(0).isTop() || pcLocTuple.size() > curPCLoc.getSize()) {
+ methodSummary.setPCLoc(new CompositeLocation(pcLocTuple));
+
+ Set<FlowNode> flowNodeLowerthanPCLocSet = new HashSet<FlowNode>();
+ GlobalFlowGraph subGlobalFlowGraph = getSubGlobalFlowGraph(md);
+ // add ordering relations s.t. PCLOC is higher than all flow nodes except the set of
+ // parameters that do not have incoming flows
+ for (Iterator iterator = fg.getNodeSet().iterator(); iterator.hasNext();) {
+ FlowNode node = (FlowNode) iterator.next();
+
+ if (!(node instanceof FlowReturnNode)) {
+ if (!paramDescNOTHavingInFlowSet.contains(node.getCurrentDescTuple().get(0))) {
+ flowNodeLowerthanPCLocSet.add(node);
+ fg.addValueFlowEdge(pcDescTuple, node.getDescTuple());
+ subGlobalFlowGraph.addValueFlowEdge(pcLocTuple,
+ translateToLocTuple(md, node.getDescTuple()));
+ }
+ } else {
+ System.out.println("***SKIP PCLOC -> RETURNLOC=" + node);
+ }
+
+ }
+ fg.getFlowNode(translateToDescTuple(pcLocTuple)).setSkeleton(true);
+
+ if (pcLocTuple.get(0).getLocDescriptor().equals(md.getThis())) {
+ System.out.println("#########################################");
+ for (Iterator iterator = flowNodeLowerthanPCLocSet.iterator(); iterator.hasNext();) {
+ FlowNode lowerNode = (FlowNode) iterator.next();
+ if (lowerNode.getCompositeLocation() == null) {
+ NTuple<Location> lowerLocTuple = translateToLocTuple(md, lowerNode.getDescTuple());
+ CompositeLocation newComp =
+ calculateCompositeLocationFromSubGlobalGraph(md, lowerNode);
+ if (newComp != null) {
+ subGlobalFlowGraph.addMapLocationToInferCompositeLocation(lowerLocTuple.get(0),
+ newComp);
+ lowerNode.setCompositeLocation(newComp);
+ System.out.println("NEW COMP LOC=" + newComp + " to lowerNode=" + lowerNode);
+ }
+
+ }
+
+ }
+ }
+
+ }
+
+ }
+ }
+
+ private boolean coversAllParamters(MethodDescriptor md, FlowGraph fg,
+ Set<NTuple<Location>> paramLocTupleHavingInFlowSet) {
+
+ int numParam = fg.getNumParameters();
+ int size = paramLocTupleHavingInFlowSet.size();
+
+ if (!md.isStatic()) {
+
+ // if the method is not static && there is a parameter composite location &&
+ // it is started with 'this',
+ // paramLocTupleHavingInFlowSet need to have 'this' parameter.
+
+ FlowNode thisParamNode = fg.getParamFlowNode(0);
+ NTuple<Location> thisParamLocTuple =
+ translateToLocTuple(md, thisParamNode.getCurrentDescTuple());
+
+ if (!paramLocTupleHavingInFlowSet.contains(thisParamLocTuple)) {
+
+ for (Iterator iterator = paramLocTupleHavingInFlowSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> paramTuple = (NTuple<Location>) iterator.next();
+ if (paramTuple.size() > 1 && paramTuple.get(0).getLocDescriptor().equals(md.getThis())) {
+ // paramLocTupleHavingInFlowSet.add(thisParamLocTuple);
+ // break;
+ size++;
+ }
+ }
+
+ }
+ }
+
+ if (size == numParam) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ private void calculateRETURNLOC(MethodDescriptor md) {
+
+ System.out.println("#calculateRETURNLOC= " + md);
+
+ // calculate a return location:
+ // the return location type is lower than all parameters and the location of return values
+ MethodSummary methodSummary = getMethodSummary(md);
+ // if (methodSummary.getRETURNLoc() != null) {
+ // System.out.println("$HERE?");
+ // return;
+ // }
+
+ FlowGraph fg = getFlowGraph(md);
+ Map<Integer, CompositeLocation> mapParamToLoc = methodSummary.getMapParamIdxToInferLoc();
+ Set<Integer> paramIdxSet = mapParamToLoc.keySet();
+
+ if (md.getReturnType() != null && !md.getReturnType().isVoid()) {
+ // first, generate the set of return value location types that starts
+ // with 'this' reference
+
+ Set<FlowNode> paramFlowNodeFlowingToReturnValueSet = getParamNodeFlowingToReturnValue(md);
+ // System.out.println("paramFlowNodeFlowingToReturnValueSet="
+ // + paramFlowNodeFlowingToReturnValueSet);
+
+ Set<NTuple<Location>> tupleToBeHigherThanReturnLocSet = new HashSet<NTuple<Location>>();
+ for (Iterator iterator = paramFlowNodeFlowingToReturnValueSet.iterator(); iterator.hasNext();) {
+ FlowNode fn = (FlowNode) iterator.next();
+ NTuple<Descriptor> paramDescTuple = fn.getCurrentDescTuple();
+ tupleToBeHigherThanReturnLocSet.add(translateToLocTuple(md, paramDescTuple));
+ }
+
+ Set<FlowNode> returnNodeSet = fg.getReturnNodeSet();
+ for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
+ FlowNode returnNode = (FlowNode) iterator.next();
+ NTuple<Descriptor> returnDescTuple = returnNode.getCurrentDescTuple();
+ tupleToBeHigherThanReturnLocSet.add(translateToLocTuple(md, returnDescTuple));
+ }
+ System.out.println("-flow graph's returnNodeSet=" + returnNodeSet);
+ System.out.println("tupleSetToBeHigherThanReturnLoc=" + tupleToBeHigherThanReturnLocSet);
+
+ // Here, generates a return location in the method lattice that is lower than the
+ // locFlowingToReturnValueSet
+ NTuple<Location> returnLocTuple =
+ generateLocTupleRelativeTo(md, tupleToBeHigherThanReturnLocSet, RLOC);
+
+ // System.out.println("returnLocTuple=" + returnLocTuple);
+ NTuple<Descriptor> returnDescTuple = translateToDescTuple(returnLocTuple);
+ CompositeLocation curReturnLoc = methodSummary.getRETURNLoc();
+ if (curReturnLoc == null || returnDescTuple.size() > curReturnLoc.getSize()) {
+ methodSummary.setRETURNLoc(new CompositeLocation(returnLocTuple));
+
+ for (Iterator iterator = tupleToBeHigherThanReturnLocSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> higherTuple = (NTuple<Location>) iterator.next();
+ fg.addValueFlowEdge(translateToDescTuple(higherTuple), returnDescTuple);
+ }
+ fg.getFlowNode(returnDescTuple).setSkeleton(true);
+
+ }
+
+ // makes sure that PCLOC is higher than RETURNLOC
+ CompositeLocation pcLoc = methodSummary.getPCLoc();
+ if (!pcLoc.get(0).isTop()) {
+ NTuple<Descriptor> pcLocDescTuple = translateToDescTuple(pcLoc.getTuple());
+ fg.addValueFlowEdge(pcLocDescTuple, returnDescTuple);
+ }
+
+ }
+
+ }
+
+ private void calculateExtraLocations(MethodDescriptor md) {
+ // calcualte pcloc, returnloc,...
+
+ System.out.println("\nSSJAVA:Calculate PCLOC/RETURNLOC locations: " + md);
+
+ calculatePCLOC(md);
+ calculateRETURNLOC(md);
+
+ }
+
+ private NTuple<Location> generateLocTupleRelativeTo(MethodDescriptor md,
+ Set<NTuple<Location>> paramLocTupleHavingInFlowSet, String locNamePrefix) {
+
+ // System.out.println("-generateLocTupleRelativeTo=" + paramLocTupleHavingInFlowSet);
+
+ NTuple<Location> higherLocTuple = new NTuple<Location>();
+
+ VarDescriptor thisVarDesc = md.getThis();
+ // check if all paramter loc tuple is started with 'this' reference
+ boolean hasParamNotStartedWithThisRef = false;
+
+ int minSize = 0;
+
+ Set<NTuple<Location>> paramLocTupleStartedWithThis = new HashSet<NTuple<Location>>();
+
+ next: for (Iterator iterator = paramLocTupleHavingInFlowSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> paramLocTuple = (NTuple<Location>) iterator.next();
+ Descriptor paramLocalDesc = paramLocTuple.get(0).getLocDescriptor();
+ if (!paramLocalDesc.equals(thisVarDesc)) {
+
+ Set<FlowNode> inNodeSet = getFlowGraph(md).getIncomingNodeSetByPrefix(paramLocalDesc);
+ for (Iterator iterator2 = inNodeSet.iterator(); iterator2.hasNext();) {
+ FlowNode flowNode = (FlowNode) iterator2.next();
+ if (flowNode.getDescTuple().startsWith(thisVarDesc)) {
+ // System.out.println("paramLocTuple=" + paramLocTuple + " is lower than THIS");
+ continue next;
+ }
+ }
+ hasParamNotStartedWithThisRef = true;
+
+ } else if (paramLocTuple.size() > 1) {
+ paramLocTupleStartedWithThis.add(paramLocTuple);
+ if (minSize == 0 || minSize > paramLocTuple.size()) {
+ minSize = paramLocTuple.size();
+ }
+ }
+ }
+
+ // System.out.println("---paramLocTupleStartedWithThis=" + paramLocTupleStartedWithThis);
+ Descriptor enclosingDesc = md;
+ if (hasParamNotStartedWithThisRef) {
+ // in this case, PCLOC will be the local location
+ } else {
+ // all parameter is started with 'this', so PCLOC will be set relative to the composite
+ // location started with 'this'.
+ // for (int idx = 0; idx < minSize - 1; idx++) {
+ for (int idx = 0; idx < 1; idx++) {
+ Set<Descriptor> locDescSet = new HashSet<Descriptor>();
+ Location curLoc = null;
+ NTuple<Location> paramLocTuple = null;
+ for (Iterator iterator = paramLocTupleStartedWithThis.iterator(); iterator.hasNext();) {
+ paramLocTuple = (NTuple<Location>) iterator.next();
+ // System.out.println("-----paramLocTuple=" + paramLocTuple + " idx=" + idx);
+ curLoc = paramLocTuple.get(idx);
+ Descriptor locDesc = curLoc.getLocDescriptor();
+ locDescSet.add(locDesc);
+ }
+ // System.out.println("-----locDescSet=" + locDescSet + " idx=" + idx);
+ if (locDescSet.size() != 1) {
+ break;
+ }
+ Location newLocElement = new Location(curLoc.getDescriptor(), curLoc.getLocDescriptor());
+ System.out.println("newLocElement" + newLocElement);
+ higherLocTuple.add(newLocElement);
+ enclosingDesc = getClassTypeDescriptor(curLoc.getLocDescriptor());
+ }
+
+ }
+
+ String locIdentifier = locNamePrefix + (locSeed++);
+ NameDescriptor locDesc = new NameDescriptor(locIdentifier);
+ Location newLoc = new Location(enclosingDesc, locDesc);
+ higherLocTuple.add(newLoc);
+ System.out.println("---new loc tuple=" + higherLocTuple);
+
+ return higherLocTuple;
+
+ }
+
+ public ClassDescriptor getClassTypeDescriptor(Descriptor in) {
+
+ if (in instanceof VarDescriptor) {
+ return ((VarDescriptor) in).getType().getClassDesc();
+ } else if (in instanceof FieldDescriptor) {
+ return ((FieldDescriptor) in).getType().getClassDesc();
+ }
+ // else if (in instanceof LocationDescriptor) {
+ // // here is the case that the descriptor 'in' is the last element of the assigned composite
+ // // location
+ // return ((VarDescriptor) locTuple.get(0).getLocDescriptor()).getType().getClassDesc();
+ // }
+ else {
+ return null;
+ }
+
+ }
+
+ private Set<NTuple<Location>> calculateHighestLocTupleSet(
+ Set<NTuple<Location>> paramLocTupleHavingInFlowSet) {
+
+ Set<NTuple<Location>> highestSet = new HashSet<NTuple<Location>>();
+
+ Iterator<NTuple<Location>> iterator = paramLocTupleHavingInFlowSet.iterator();
+ NTuple<Location> highest = iterator.next();
+
+ for (; iterator.hasNext();) {
+ NTuple<Location> curLocTuple = (NTuple<Location>) iterator.next();
+ if (isHigherThan(curLocTuple, highest)) {
+ // System.out.println(curLocTuple + " is greater than " + highest);
+ highest = curLocTuple;
+ }
+ }
+
+ highestSet.add(highest);
+
+ MethodDescriptor md = (MethodDescriptor) highest.get(0).getDescriptor();
+ VarDescriptor thisVarDesc = md.getThis();
+
+ // System.out.println("highest=" + highest);
+
+ for (Iterator<NTuple<Location>> iter = paramLocTupleHavingInFlowSet.iterator(); iter.hasNext();) {
+ NTuple<Location> curLocTuple = iter.next();
+
+ if (!curLocTuple.equals(highest) && !hasOrderingRelation(highest, curLocTuple)) {
+
+ // System.out.println("add it to the highest set=" + curLocTuple);
+ highestSet.add(curLocTuple);
+
+ }
+ }
+
+ return highestSet;
+
+ }
+
+ private Set<String> getHigherLocSymbolThan(SSJavaLattice<String> lattice, String loc) {
+ Set<String> higherLocSet = new HashSet<String>();
+
+ Set<String> locSet = lattice.getTable().keySet();
+ for (Iterator iterator = locSet.iterator(); iterator.hasNext();) {
+ String element = (String) iterator.next();
+ if (lattice.isGreaterThan(element, loc) && (!element.equals(lattice.getTopItem()))) {
+ higherLocSet.add(element);
+ }
+ }
+ return higherLocSet;
+ }
+
+ private CompositeLocation getLowest(SSJavaLattice<String> methodLattice,
+ Set<CompositeLocation> set) {
+
+ CompositeLocation lowest = set.iterator().next();
+
+ if (set.size() == 1) {
+ return lowest;
+ }
+
+ for (Iterator iterator = set.iterator(); iterator.hasNext();) {
+ CompositeLocation loc = (CompositeLocation) iterator.next();
+
+ if ((!loc.equals(lowest)) && (!isComparable(methodLattice, lowest, loc))) {
+ // if there is a case where composite locations are incomparable, just
+ // return null
+ return null;
+ }
+
+ if ((!loc.equals(lowest)) && isGreaterThan(methodLattice, lowest, loc)) {
+ lowest = loc;
+ }
+ }
+ return lowest;
+ }
+
+ private boolean isComparable(SSJavaLattice<String> methodLattice, CompositeLocation comp1,
+ CompositeLocation comp2) {
+
+ int size = comp1.getSize() >= comp2.getSize() ? comp2.getSize() : comp1.getSize();
+
+ for (int idx = 0; idx < size; idx++) {
+ Location loc1 = comp1.get(idx);
+ Location loc2 = comp2.get(idx);
+
+ Descriptor desc1 = loc1.getDescriptor();
+ Descriptor desc2 = loc2.getDescriptor();
+
+ if (!desc1.equals(desc2)) {
+ throw new Error("Fail to compare " + comp1 + " and " + comp2);
+ }
+
+ String symbol1 = loc1.getLocIdentifier();
+ String symbol2 = loc2.getLocIdentifier();
+
+ SSJavaLattice<String> lattice;
+ if (idx == 0) {
+ lattice = methodLattice;
+ } else {
+ lattice = getLattice(desc1);
+ }
+
+ if (symbol1.equals(symbol2)) {
+ continue;
+ } else if (!lattice.isComparable(symbol1, symbol2)) {
+ return false;
+ }
+
+ }
+
+ return true;
+ }
+
+ private boolean isGreaterThan(SSJavaLattice<String> methodLattice, CompositeLocation comp1,
+ CompositeLocation comp2) {
+
+ int size = comp1.getSize() >= comp2.getSize() ? comp2.getSize() : comp1.getSize();
+
+ for (int idx = 0; idx < size; idx++) {
+ Location loc1 = comp1.get(idx);
+ Location loc2 = comp2.get(idx);
+
+ Descriptor desc1 = loc1.getDescriptor();
+ Descriptor desc2 = loc2.getDescriptor();
+
+ if (!desc1.equals(desc2)) {
+ throw new Error("Fail to compare " + comp1 + " and " + comp2);
+ }
+
+ String symbol1 = loc1.getLocIdentifier();
+ String symbol2 = loc2.getLocIdentifier();
+
+ SSJavaLattice<String> lattice;
+ if (idx == 0) {
+ lattice = methodLattice;
+ } else {
+ lattice = getLattice(desc1);
+ }
+
+ if (symbol1.equals(symbol2)) {
+ continue;
+ } else if (lattice.isGreaterThan(symbol1, symbol2)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ return false;
+ }
+
+ private GlobalFlowGraph getSubGlobalFlowGraph(MethodDescriptor md) {
+
+ if (!mapMethodDescriptorToSubGlobalFlowGraph.containsKey(md)) {
+ mapMethodDescriptorToSubGlobalFlowGraph.put(md, new GlobalFlowGraph(md));
+ }
+ return mapMethodDescriptorToSubGlobalFlowGraph.get(md);
+ }
+
+ private void propagateFlowsToCallerWithNoCompositeLocation(MethodInvokeNode min,
+ MethodDescriptor mdCaller, MethodDescriptor mdCallee) {
+
+ System.out.println("-propagateFlowsToCallerWithNoCompositeLocation=" + min.printNode(0));
+ // 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);
+ Set<FlowNode> localReachSet =
+ calleeFlowGraph.getReachableSetFrom(paramNode1.getDescTuple());
+
+ NTuple<Descriptor> paramDescTuple1 = paramNode1.getCurrentDescTuple();
+ NTuple<Descriptor> paramDescTuple2 = paramNode2.getCurrentDescTuple();
+
+ // System.out.println("-param1CurTuple=" + paramDescTuple1 + " param2CurTuple="
+ // + paramDescTuple2);
+ // System.out.println("-- localReachSet from param1=" + localReachSet);
+
+ if (paramDescTuple1.get(0).equals(paramDescTuple2.get(0))) {
+ // if two parameters share the same prefix
+ // it already has been assigned to a composite location
+ // so we don't need to add an additional ordering relation caused by these two
+ // paramters.
+ continue;
+ }
+
+ if (arg1Tuple.size() > 0 && arg2Tuple.size() > 0
+ && containsPrefix(paramNode2.getDescTuple().get(0), localReachSet)) {
+ // need to propagate an ordering relation s.t. arg1 is higher
+ // than arg2
+ // System.out.println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
+
+ // add a new flow between the corresponding arguments.
+ callerFlowGraph.addValueFlowEdge(arg1Tuple, arg2Tuple);
+ // System.out.println("arg1=" + arg1Tuple + " arg2=" + arg2Tuple);
+
+ // System.out
+ // .println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple=" + arg2Tuple);
+
+ }
+
+ // System.out.println();
+ }
+ }
+ }
+
+ // if a parameter has a composite location and the first element of the parameter location
+ // matches the callee's 'this'
+ // we have a more specific constraint: the caller's corresponding argument is higher than the
+ // parameter location which is translated into the caller
+
+ for (int idx = 0; idx < numParam; idx++) {
+ FlowNode paramNode = calleeFlowGraph.getParamFlowNode(idx);
+ CompositeLocation compLoc = paramNode.getCompositeLocation();
+ System.out.println("paramNode=" + paramNode + " compLoc=" + compLoc);
+ if (compLoc != null && compLoc.get(0).getLocDescriptor().equals(min.getMethod().getThis())) {
+ System.out.println("$$$COMPLOC CASE=" + compLoc + " idx=" + idx);
+
+ NTuple<Descriptor> argTuple = getNodeTupleByArgIdx(min, idx);
+ System.out.println("--- argTuple=" + argTuple + " current compLoc="
+ + callerFlowGraph.getFlowNode(argTuple).getCompositeLocation());
+
+ NTuple<Descriptor> translatedParamTuple =
+ translateCompositeLocationToCaller(idx, min, compLoc);
+ System.out.println("add a flow edge= " + argTuple + "->" + translatedParamTuple);
+ callerFlowGraph.addValueFlowEdge(argTuple, translatedParamTuple);
+
+ Set<NTuple<Location>> pcLocTupleSet = getPCLocTupleSet(min);
+ for (Iterator iterator = pcLocTupleSet.iterator(); iterator.hasNext();) {
+ NTuple<Location> pcLocTuple = (NTuple<Location>) iterator.next();
+ callerFlowGraph.addValueFlowEdge(translateToDescTuple(pcLocTuple), translatedParamTuple);
+ }
+
+ }
+ }
+
+ }
+
+ private boolean containsPrefix(Descriptor prefixDesc, Set<FlowNode> set) {
+
+ for (Iterator iterator = set.iterator(); iterator.hasNext();) {
+ FlowNode flowNode = (FlowNode) iterator.next();
+ if (flowNode.getDescTuple().startsWith(prefixDesc)) {
+ System.out.println("FOUND=" + flowNode);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private NTuple<Descriptor> translateCompositeLocationToCaller(int idx, 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(NTuple<Location> prefixLocTuple) {
+
+ System.out.println("generateCompositeLocation=" + prefixLocTuple);
+
+ CompositeLocation newCompLoc = new CompositeLocation();
+ for (int i = 0; i < prefixLocTuple.size(); i++) {
+ newCompLoc.addLocation(prefixLocTuple.get(i));
+ }
+
+ Descriptor lastDescOfPrefix = prefixLocTuple.get(prefixLocTuple.size() - 1).getLocDescriptor();
+
+ ClassDescriptor enclosingDescriptor;
+ if (lastDescOfPrefix instanceof FieldDescriptor) {
+ enclosingDescriptor = ((FieldDescriptor) lastDescOfPrefix).getType().getClassDesc();
+ // System.out.println("enclosingDescriptor0=" + enclosingDescriptor);
+ } else if (lastDescOfPrefix.equals(GLOBALDESC)) {
+ MethodDescriptor currentMethodDesc = (MethodDescriptor) prefixLocTuple.get(0).getDescriptor();
+ enclosingDescriptor = currentMethodDesc.getClassDesc();
+ } else {
+ // var descriptor case
+ enclosingDescriptor = ((VarDescriptor) lastDescOfPrefix).getType().getClassDesc();
+ }
+ // System.out.println("enclosingDescriptor=" + enclosingDescriptor);
+
+ LocationDescriptor newLocDescriptor = generateNewLocationDescriptor();
+ newLocDescriptor.setEnclosingClassDesc(enclosingDescriptor);
+
+ Location newLoc = new Location(enclosingDescriptor, newLocDescriptor.getSymbol());
+ newLoc.setLocDescriptor(newLocDescriptor);
+ newCompLoc.addLocation(newLoc);
+
+ // System.out.println("--newCompLoc=" + newCompLoc);
+ return newCompLoc;
+ }
+
+ private CompositeLocation generateCompositeLocation(MethodDescriptor md,
+ NTuple<Descriptor> paramPrefix) {
+
+ System.out.println("generateCompositeLocation=" + paramPrefix);
+
+ 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);
+
+ Location newLoc = new Location(enclosingDescriptor, newLocDescriptor.getSymbol());
+ newLoc.setLocDescriptor(newLocDescriptor);
+ newCompLoc.addLocation(newLoc);
+
+ // System.out.println("--newCompLoc=" + newCompLoc);
+ return newCompLoc;
+ }
+
+ private List<NTuple<Descriptor>> translatePrefixListToCallee(Descriptor baseRef,
+ MethodDescriptor mdCallee, List<NTuple<Descriptor>> callerPrefixList) {
+
+ List<NTuple<Descriptor>> calleePrefixList = new ArrayList<NTuple<Descriptor>>();
+
+ for (int i = 0; i < callerPrefixList.size(); i++) {
+ NTuple<Descriptor> prefix = callerPrefixList.get(i);
+ if (prefix.startsWith(baseRef)) {
+ NTuple<Descriptor> calleePrefix = new NTuple<Descriptor>();
+ calleePrefix.add(mdCallee.getThis());
+ for (int k = 1; k < prefix.size(); k++) {
+ calleePrefix.add(prefix.get(k));
+ }
+ calleePrefixList.add(calleePrefix);
+ }
+ }
+
+ return calleePrefixList;
+
+ }
+
+ public CompositeLocation convertToCompositeLocation(MethodDescriptor md, NTuple<Descriptor> tuple) {
+
+ CompositeLocation compLoc = new CompositeLocation();
+
+ Descriptor enclosingDescriptor = md;
+
+ for (int i = 0; i < tuple.size(); i++) {
+ Descriptor curDescriptor = tuple.get(i);
+ Location locElement = new Location(enclosingDescriptor, curDescriptor.getSymbol());
+ locElement.setLocDescriptor(curDescriptor);
+ compLoc.addLocation(locElement);
+
+ if (curDescriptor instanceof VarDescriptor) {
+ enclosingDescriptor = md.getClassDesc();
+ } else if (curDescriptor instanceof FieldDescriptor) {
+ enclosingDescriptor = ((FieldDescriptor) curDescriptor).getClassDescriptor();
+ } else if (curDescriptor instanceof NameDescriptor) {
+ // it is "GLOBAL LOC" case!
+ enclosingDescriptor = GLOBALDESC;
+ } else if (curDescriptor instanceof InterDescriptor) {
+ enclosingDescriptor = getFlowGraph(md).getEnclosingDescriptor(curDescriptor);
+ } else {
+ enclosingDescriptor = null;
+ }
+
+ }
+
+ return compLoc;
+ }
+
+ private LocationDescriptor generateNewLocationDescriptor() {
+ return new LocationDescriptor("Loc" + (locSeed++));
+ }
+
+ private int getPrefixIndex(NTuple<Descriptor> tuple1, NTuple<Descriptor> tuple2) {
+
+ // return the index where the prefix shared by tuple1 and tuple2 is ended
+ // if there is no prefix shared by both of them, return -1
+
+ int minSize = tuple1.size();
+ if (minSize > tuple2.size()) {
+ minSize = tuple2.size();
+ }
+
+ int idx = -1;
+ for (int i = 0; i < minSize; i++) {
+ if (!tuple1.get(i).equals(tuple2.get(i))) {
+ break;
+ } else {
+ idx++;
+ }
+ }