+ public Map<NTuple<Descriptor>, NTuple<Descriptor>> getMapCallerArgToCalleeParam(
+ MethodInvokeNode min) {
+
+ if (!mapMethodInvokeNodeToMapCallerArgToCalleeArg.containsKey(min)) {
+ mapMethodInvokeNodeToMapCallerArgToCalleeArg.put(min,
+ new HashMap<NTuple<Descriptor>, NTuple<Descriptor>>());
+ }
+
+ return mapMethodInvokeNodeToMapCallerArgToCalleeArg.get(min);
+ }
+
+ public void addMapCallerArgToCalleeParam(MethodInvokeNode min, NTuple<Descriptor> callerArg,
+ NTuple<Descriptor> calleeParam) {
+ getMapCallerArgToCalleeParam(min).put(callerArg, calleeParam);
+ }
+
+ private void assignCompositeLocation() {
+ calculateGlobalValueFlowCompositeLocation();
+ translateCompositeLocationAssignmentToFlowGraph();
+ _debug_printGraph();
+ }
+
+ private void translateCompositeLocationAssignmentToFlowGraph() {
+
+ MethodDescriptor methodEventLoopDesc = ssjava.getMethodContainingSSJavaLoop();
+ translateCompositeLocationAssignmentToFlowGraph(methodEventLoopDesc);
+
+ }
+
+ private void translateCompositeLocationAssignmentToFlowGraph(MethodDescriptor mdCaller) {
+
+ System.out.println("\n#translateCompositeLocationAssignmentToFlowGraph=" + mdCaller);
+
+ // First, assign a composite location to a node in the flow graph
+ GlobalFlowGraph callerGlobalFlowGraph = getSubGlobalFlowGraph(mdCaller);
+
+ FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
+ Map<Location, CompositeLocation> callerMapLocToCompLoc =
+ callerGlobalFlowGraph.getMapLocationToInferCompositeLocation();
+ Set<Location> methodLocSet = callerMapLocToCompLoc.keySet();
+ for (Iterator iterator = methodLocSet.iterator(); iterator.hasNext();) {
+ Location methodLoc = (Location) iterator.next();
+ if (methodLoc.getDescriptor().equals(mdCaller)) {
+ CompositeLocation inferCompLoc = callerMapLocToCompLoc.get(methodLoc);
+ assignCompositeLocationToFlowGraph(callerFlowGraph, methodLoc, inferCompLoc);
+ }
+ }
+
+ Set<MethodInvokeNode> minSet = mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
+
+ Set<MethodDescriptor> calleeSet = new HashSet<MethodDescriptor>();
+ for (Iterator iterator = minSet.iterator(); iterator.hasNext();) {
+ MethodInvokeNode min = (MethodInvokeNode) iterator.next();
+ // need to translate a composite location that is started with the base
+ // tuple of 'min'.
+ if (mapMethodInvokeNodeToBaseTuple.get(min) != null) {
+ // if mapMethodInvokeNodeToBaseTuple doesn't have a mapping
+ // it means that the corresponding callee method does not cause any
+ // flows
+ translateMapLocationToInferCompositeLocationToCalleeGraph(callerGlobalFlowGraph, min);
+ }
+ calleeSet.add(min.getMethod());
+ }
+
+ for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
+ MethodDescriptor callee = (MethodDescriptor) iterator.next();
+ translateCompositeLocationAssignmentToFlowGraph(callee);
+ }
+
+ }
+
+ public void assignCompositeLocationToFlowGraph(FlowGraph flowGraph, Location loc,
+ CompositeLocation inferCompLoc) {
+ Descriptor localDesc = loc.getLocDescriptor();
+
+ Set<FlowNode> nodeSet = flowGraph.getNodeSet();
+ for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ FlowNode node = (FlowNode) iterator.next();
+ if (node.getDescTuple().startsWith(localDesc)) {
+ // need to assign the inferred composite location to this node
+ CompositeLocation newCompLoc = generateCompositeLocation(node.getDescTuple(), inferCompLoc);
+ node.setCompositeLocation(newCompLoc);
+ System.out.println("SET Node=" + node + " inferCompLoc=" + newCompLoc);
+ }
+ }
+ }
+
+ private CompositeLocation generateCompositeLocation(NTuple<Descriptor> nodeDescTuple,
+ CompositeLocation inferCompLoc) {
+
+ System.out.println("generateCompositeLocation=" + nodeDescTuple + " with inferCompLoc="
+ + inferCompLoc);
+
+ CompositeLocation newCompLoc = new CompositeLocation();
+ for (int i = 0; i < inferCompLoc.getSize(); i++) {
+ newCompLoc.addLocation(inferCompLoc.get(i));
+ }
+
+ Descriptor lastDescOfPrefix = nodeDescTuple.get(0);
+ Descriptor enclosingDescriptor;
+ if (lastDescOfPrefix instanceof InterDescriptor) {
+ enclosingDescriptor = null;
+ } else {
+ enclosingDescriptor = ((VarDescriptor) lastDescOfPrefix).getType().getClassDesc();
+ }
+
+ for (int i = 1; i < nodeDescTuple.size(); i++) {
+ Descriptor desc = nodeDescTuple.get(i);
+ Location locElement = new Location(enclosingDescriptor, desc);
+ newCompLoc.addLocation(locElement);
+
+ enclosingDescriptor = ((FieldDescriptor) desc).getClassDescriptor();
+ }
+
+ return newCompLoc;
+ }
+
+ private void translateMapLocationToInferCompositeLocationToCalleeGraph(
+ GlobalFlowGraph callerGraph, MethodInvokeNode min) {
+
+ MethodDescriptor mdCallee = min.getMethod();
+ MethodDescriptor mdCaller = callerGraph.getMethodDescriptor();
+ Map<Location, CompositeLocation> callerMapLocToCompLoc =
+ callerGraph.getMapLocationToInferCompositeLocation();
+
+ FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
+ GlobalFlowGraph calleeGlobalGraph = getSubGlobalFlowGraph(mdCallee);
+
+ NTuple<Location> baseLocTuple =
+ translateToLocTuple(mdCaller, mapMethodInvokeNodeToBaseTuple.get(min));
+
+ System.out.println("-translate caller infer composite loc to callee=" + mdCallee);
+ Set<Location> keySet = callerMapLocToCompLoc.keySet();
+ for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
+ Location key = (Location) iterator.next();
+ CompositeLocation callerCompLoc = callerMapLocToCompLoc.get(key);
+
+ if (!key.getDescriptor().equals(mdCaller)
+ && callerCompLoc.getTuple().startsWith(baseLocTuple)) {
+ // need to translate to the callee side
+ // System.out.println("need to translate callerCompLoc=" + callerCompLoc +
+ // " with baseTuple="
+ // + baseLocTuple);
+ // TODO
+ CompositeLocation newCalleeCompLoc =
+ translateCompositeLocationToCallee(callerCompLoc, baseLocTuple, mdCallee);
+ calleeGlobalGraph.addMapLocationToInferCompositeLocation(key, newCalleeCompLoc);
+ System.out.println("---callee loc=" + key + " newCalleeCompLoc=" + newCalleeCompLoc);
+ }
+ }
+
+ // If the location of an argument has a composite location
+ // need to assign a proper composite location to the corresponding callee parameter
+ System.out.println("-translate arg composite location to callee param:");
+ Map<Integer, NTuple<Descriptor>> mapIdxToArgTuple = mapMethodInvokeNodeToArgIdxMap.get(min);
+ Set<Integer> idxSet = mapIdxToArgTuple.keySet();
+ for (Iterator iterator = idxSet.iterator(); iterator.hasNext();) {
+ Integer idx = (Integer) iterator.next();
+
+ if (idx == 0 && !min.getMethod().isStatic()) {
+ continue;
+ }
+
+ NTuple<Descriptor> argTuple = mapIdxToArgTuple.get(idx);
+
+ // check if an arg tuple has been already assigned to a composite location
+ NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argTuple);
+ Location argLocalLoc = argLocTuple.get(0);
+
+ // if (!isPrimitiveType(argTuple)) {
+ if (callerMapLocToCompLoc.containsKey(argLocalLoc)) {
+
+ CompositeLocation callerCompLoc = callerMapLocToCompLoc.get(argLocalLoc);
+ for (int i = 1; i < argLocTuple.size(); i++) {
+ callerCompLoc.addLocation(argLocTuple.get(i));
+ }
+
+ if (callerCompLoc.getTuple().startsWith(baseLocTuple)) {
+
+ FlowNode calleeParamFlowNode = calleeFlowGraph.getParamFlowNode(idx);
+ NTuple<Descriptor> calleeParamDescTuple = calleeParamFlowNode.getDescTuple();
+ NTuple<Location> calleeParamLocTuple =
+ translateToLocTuple(mdCallee, calleeParamDescTuple);
+
+ CompositeLocation newCalleeCompLoc =
+ translateCompositeLocationToCallee(callerCompLoc, baseLocTuple, mdCallee);
+
+ calleeGlobalGraph.addMapLocationToInferCompositeLocation(calleeParamLocTuple.get(0),
+ newCalleeCompLoc);
+
+ System.out.println("###need to assign composite location to=" + calleeParamDescTuple
+ + " with baseTuple=" + baseLocTuple);
+ System.out.println("---newCalleeCompLoc=" + newCalleeCompLoc);
+ }
+
+ }
+
+ }
+
+ }
+
+ private boolean isPrimitiveType(NTuple<Descriptor> argTuple) {
+
+ Descriptor lastDesc = argTuple.get(argTuple.size() - 1);
+
+ if (lastDesc instanceof FieldDescriptor) {
+ return ((FieldDescriptor) lastDesc).getType().isPrimitive();
+ } else if (lastDesc instanceof VarDescriptor) {
+ return ((VarDescriptor) lastDesc).getType().isPrimitive();
+ }
+
+ return true;
+ }
+
+ private CompositeLocation translateCompositeLocationToCallee(CompositeLocation callerCompLoc,
+ NTuple<Location> baseLocTuple, MethodDescriptor mdCallee) {
+
+ CompositeLocation newCalleeCompLoc = new CompositeLocation();
+
+ // replace the last element of the caller compLoc with the 'this' location of the callee
+ for (int i = 0; i < baseLocTuple.size() - 1; i++) {
+ newCalleeCompLoc.addLocation(baseLocTuple.get(i));
+ }
+
+ Location calleeThisLoc = new Location(mdCallee, mdCallee.getThis());
+ newCalleeCompLoc.addLocation(calleeThisLoc);
+
+ for (int i = baseLocTuple.size(); i < callerCompLoc.getSize(); i++) {
+ newCalleeCompLoc.addLocation(callerCompLoc.get(i));
+ }
+
+ return newCalleeCompLoc;
+
+ }
+
+ 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: write a global flow graph
+ MethodDescriptor mdContainingSSJavaLoop = ssjava.getMethodContainingSSJavaLoop();
+ // FlowGraph globalFlowGraph =
+ // getSubGlobalFlowGraph(mdContainingSSJavaLoop);
+ // System.out.println("GLOBAL NODE SET=" + globalFlowGraph.getNodeSet());
+ // assignCompositeLocation(globalFlowGraph);
+ // try {
+ // globalFlowGraph.writeGraph("_GLOBAL");
+ // } catch (IOException e) {
+ // e.printStackTrace();
+ // }
+ // _debug_printGraph();
+
+ }
+
+ private void calculateGlobalValueFlowCompositeLocation() {
+
+ System.out.println("SSJAVA: Calculate composite locations in the global value flow graph");
+ MethodDescriptor methodDescEventLoop = ssjava.getMethodContainingSSJavaLoop();
+ GlobalFlowGraph globalFlowGraph = getSubGlobalFlowGraph(methodDescEventLoop);
+
+ Set<NTuple<Location>> prefixSet = new HashSet<NTuple<Location>>();
+
+ Set<GlobalFlowNode> nodeSet = globalFlowGraph.getNodeSet();
+
+ next: for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
+ GlobalFlowNode node = (GlobalFlowNode) iterator.next();
+ Set<GlobalFlowNode> incomingNodeSet = globalFlowGraph.getIncomingNodeSet(node);
+ List<NTuple<Location>> prefixList = calculatePrefixList(globalFlowGraph, node);
+ Set<GlobalFlowNode> reachNodeSet = globalFlowGraph.getReachableNodeSetFrom(node);
+
+ // System.out.println("node=" + node + " inNodeSet=" + incomingNodeSet
+ // + " reachableNodeSet=" + reachNodeSet);
+
+ for (int i = 0; i < prefixList.size(); i++) {
+ NTuple<Location> curPrefix = prefixList.get(i);
+ Set<NTuple<Location>> reachableCommonPrefixSet = new HashSet<NTuple<Location>>();
+
+ for (Iterator iterator2 = reachNodeSet.iterator(); iterator2.hasNext();) {
+ GlobalFlowNode reachNode = (GlobalFlowNode) iterator2.next();
+ if (reachNode.getLocTuple().startsWith(curPrefix)) {
+ reachableCommonPrefixSet.add(reachNode.getLocTuple());
+ }
+ }
+
+ if (!reachableCommonPrefixSet.isEmpty()) {
+
+ // TODO
+ if (!node.getLocTuple().startsWith(curPrefix.get(0))) {
+ CompositeLocation newCompLoc = generateCompositeLocation(curPrefix);
+ System.out.println("NEED TO ASSIGN COMP LOC TO " + node + " with prefix=" + curPrefix);
+ System.out.println("- newCompLoc=" + newCompLoc);
+
+ Location targetLocalLoc = node.getLocTuple().get(0);
+ globalFlowGraph.addMapLocationToInferCompositeLocation(targetLocalLoc, newCompLoc);
+
+ continue next;
+ }
+
+ }
+
+ }
+
+ }
+ // Set<GlobalFlowNode> inNodeSet =
+ // graph.getIncomingNodeSetWithPrefix(prefix);
+ // System.out.println("inNodeSet=" + inNodeSet + " from=" + node);
+ }
+
+ private void assignCompositeLocation(CompositeLocation compLocPrefix, GlobalFlowNode node) {
+ CompositeLocation newCompLoc = compLocPrefix.clone();
+ NTuple<Location> locTuple = node.getLocTuple();
+ for (int i = 1; i < locTuple.size(); i++) {
+ newCompLoc.addLocation(locTuple.get(i));
+ }
+ node.setInferCompositeLocation(newCompLoc);
+ }
+
+ private List<NTuple<Location>> calculatePrefixList(GlobalFlowGraph graph, GlobalFlowNode node) {
+
+ System.out.println("\n##### calculatePrefixList=" + node);
+
+ Set<GlobalFlowNode> incomingNodeSet = graph.getIncomingNodeSet(node);
+
+ List<NTuple<Location>> prefixList = new ArrayList<NTuple<Location>>();
+
+ for (Iterator iterator = incomingNodeSet.iterator(); iterator.hasNext();) {
+ GlobalFlowNode inNode = (GlobalFlowNode) iterator.next();
+ NTuple<Location> inNodeTuple = inNode.getLocTuple();
+
+ for (int i = 1; i < inNodeTuple.size(); i++) {
+ NTuple<Location> prefix = inNodeTuple.subList(0, i);
+ if (!prefixList.contains(prefix)) {
+ prefixList.add(prefix);
+ }
+ }
+ }
+
+ Collections.sort(prefixList, new Comparator<NTuple<Location>>() {
+ public int compare(NTuple<Location> arg0, NTuple<Location> arg1) {
+ int s0 = arg0.size();
+ int s1 = arg1.size();
+ if (s0 > s1) {
+ return -1;
+ } else if (s0 == s1) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
+ return prefixList;
+ }
+
+ private GlobalFlowGraph constructSubGlobalFlowGraph(FlowGraph flowGraph) {
+
+ MethodDescriptor md = flowGraph.getMethodDescriptor();
+
+ GlobalFlowGraph globalGraph = new GlobalFlowGraph(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();
+
+ // 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,
+ GlobalFlowGraph 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);
+ }
+
+ }
+
+ }
+
+ private void propagateValueFlowsToCallerFromSubGlobalFlowGraph(MethodInvokeNode min,
+ MethodDescriptor mdCaller, MethodDescriptor possibleMdCallee) {
+
+ System.out.println("propagateValueFlowsToCallerFromSubGlobalFlowGraph=" + min.printNode(0)
+ + " by 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);
+ addMapCallerArgToCalleeParam(min, argDescTuple, paramDescTuple);
+ }
+
+ }
+
+ NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
+ GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(possibleMdCallee);
+ Set<GlobalFlowNode> calleeNodeSet = calleeSubGlobalGraph.getNodeSet();
+ System.out.println("#calleeNodeSet=" + calleeNodeSet);
+ for (Iterator iterator = calleeNodeSet.iterator(); iterator.hasNext();) {
+ GlobalFlowNode calleeNode = (GlobalFlowNode) iterator.next();
+ addValueFlowFromCalleeNode(min, mdCaller, possibleMdCallee, calleeNode);
+ }
+
+ // int numParam = calleeFlowGraph.getNumParameters();
+ // for (int idx = 0; idx < numParam; idx++) {
+ //
+ // FlowNode paramNode = calleeFlowGraph.getParamFlowNode(idx);
+ //
+ // NTuple<Location> paramLocTuple =
+ // translateToLocTuple(possibleMdCallee, paramNode.getCurrentDescTuple());
+ //
+ // GlobalFlowNode globalParamNode =
+ // calleeSubGlobalGraph.getFlowNode(paramLocTuple);
+ //
+ // NTuple<Descriptor> argTuple =
+ // mapMethodInvokeNodeToArgIdxMap.get(min).get(idx);
+ //
+ // NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argTuple);
+ //
+ // System.out.println("argTupleSet=" + argLocTuple + " param=" +
+ // paramLocTuple);
+ // // here, it adds all value flows reachable from the paramNode in the
+ // callee's flow graph
+ //
+ // addValueFlowsFromCalleeParam(mdCaller, argLocTuple, baseLocTuple,
+ // possibleMdCallee,
+ // globalParamNode);
+ // }
+ //
+ // // TODO
+ // // 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 addValueFlowFromCalleeNode(MethodInvokeNode min, MethodDescriptor mdCaller,
+ MethodDescriptor mdCallee, GlobalFlowNode calleeSrcNode) {
+
+ GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(mdCallee);
+ GlobalFlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
+
+ NTuple<Location> callerSrcNodeLocTuple =
+ translateToCallerLocTuple(min, mdCallee, mdCaller, calleeSrcNode.getLocTuple());
+
+
+ if (callerSrcNodeLocTuple != null) {
+ 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());
+ if (callerDstNodeLocTuple != null) {
+ callerSubGlobalGraph.addValueFlowEdge(callerSrcNodeLocTuple, callerDstNodeLocTuple);
+ }
+ }
+ }
+
+ }
+
+ private NTuple<Location> translateToCallerLocTuple(MethodInvokeNode min,
+ MethodDescriptor mdCallee, MethodDescriptor mdCaller, NTuple<Location> nodeLocTuple) {
+ // this method will return NULL if the corresponding argument is literal
+ // value.
+ // assumes that we don't need to propagate callee flows to the argument
+ // which is literal.
+
+ System.out.println("---translateToCallerLocTuple=" + min.printNode(0)
+ + " callee nodeLocTuple=" + 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);
+ // System.out.println(" mapMethodInvokeNodeToArgIdxMap.get(min)="
+ // + mapMethodInvokeNodeToArgIdxMap.get(min));
+
+ if (argDescTuple.size() == 0) {
+ // argument is literal
+ return null;
+ }
+ 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();
+ }
+
+ }
+
+ 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;
+
+ }
+
+ private void addValueFlowsFromCalleeParam(MethodDescriptor mdCaller,
+ NTuple<Location> argLocTuple, NTuple<Location> baseLocTuple, MethodDescriptor mdCallee,
+ GlobalFlowNode globalParamNode) {
+
+ Set<GlobalFlowNode> visited = new HashSet<GlobalFlowNode>();
+ visited.add(globalParamNode);
+ recurAddValueFlowsFromCalleeParam(mdCaller, argLocTuple, baseLocTuple, mdCallee,
+ globalParamNode);
+
+ }
+
+ private void recurAddValueFlowsFromCalleeParam(MethodDescriptor mdCaller,
+ NTuple<Location> argLocTuple, NTuple<Location> baseLocTuple, MethodDescriptor mdCallee,
+ GlobalFlowNode calleeCurNode) {
+
+ // FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
+ // GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(mdCallee);
+ //
+ // NTuple<Location> curNodeLocTuple = calleeCurNode.getLocTuple();
+ // NTuple<Descriptor> curNodeDescTuple = calleeCurNode.getDescTuple();
+ // if (calleeFlowGraph.isParameter(curNodeDescTuple)) {
+ // curNodeLocTuple = translateToCaller(argLocTuple, curNodeLocTuple);
+ // }
+ //
+ // Set<GlobalFlowNode> outNodeSet =
+ // calleeSubGlobalGraph.getOutNodeSet(calleeCurNode);
+ // for (Iterator iterator = outNodeSet.iterator(); iterator.hasNext();) {
+ // GlobalFlowNode outNode = (GlobalFlowNode) iterator.next();
+ //
+ // NTuple<Location> curNodeLocTuple = calleeCurNode.getLocTuple();
+ // NTuple<Descriptor> curNodeDescTuple = calleeCurNode.getDescTuple();
+ // if (calleeFlowGraph.isParameter(curNodeDescTuple)) {
+ // curNodeLocTuple = translateToCaller(argLocTuple, curNodeLocTuple);
+ // }
+ //
+ // outNode.getDescTuple();
+ //
+ // if (calleeFlowGraph.is)
+ //
+ // 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);
+ // }
+ //
+ // }
+ //
+ // 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<Location> translateToCaller(NTuple<Location> argLocTuple,
+ NTuple<Location> curNodeLocTuple) {
+
+ NTuple<Location> callerLocTuple = new NTuple<Location>();
+
+ callerLocTuple.addAll(argLocTuple);
+ for (int i = 1; i < curNodeLocTuple.size(); i++) {
+ callerLocTuple.add(curNodeLocTuple.get(i));
+ }
+
+ return callerLocTuple;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+