implemented a fixed point based interprocedural analysis that analyzes flow-graphs...
[IRC.git] / Robust / src / Analysis / SSJava / LocationInference.java
index 66dadfa782d185137835599916be82c75e7694ec..daa435f0e7f80b3df722698c69bc55d4ce44a7cb 100644 (file)
@@ -170,7 +170,7 @@ public class LocationInference {
 
       SSJavaLattice<String> classLattice = cd2lattice.get(cd);
       if (classLattice != null) {
-        ssjava.writeLatticeDotFile(cd, classLattice);
+        ssjava.writeLatticeDotFile(cd, null, classLattice);
       }
 
       while (!toAnalyzeMethodIsEmpty()) {
@@ -178,7 +178,7 @@ public class LocationInference {
         if (ssjava.needTobeAnnotated(md)) {
           SSJavaLattice<String> methodLattice = md2lattice.get(md);
           if (methodLattice != null) {
-            ssjava.writeLatticeDotFile(cd, methodLattice);
+            ssjava.writeLatticeDotFile(cd, md, methodLattice);
           }
         }
       }
@@ -212,16 +212,16 @@ public class LocationInference {
     while (!methodDescriptorsToVisitStack.isEmpty()) {
       // start to analyze leaf node
       MethodDescriptor md = methodDescriptorsToVisitStack.pop();
-      FlatMethod fm = state.getMethodFlat(md);
 
       SSJavaLattice<String> methodLattice =
           new SSJavaLattice<String>(SSJavaLattice.TOP, SSJavaLattice.BOTTOM);
 
+      System.out.println();
       System.out.println("SSJAVA: Inferencing the lattice from " + md);
 
       analyzeMethodLattice(md, methodLattice);
 
-      SSJavaLattice<String> prevMethodLattice = md2lattice.get(md);
+      SSJavaLattice<String> prevMethodLattice = getMethodLattice(md);
 
       if (!methodLattice.equals(prevMethodLattice)) {
         md2lattice.put(md, methodLattice);
@@ -248,16 +248,12 @@ public class LocationInference {
     return desc.getSymbol();
   }
 
-  private void addMappingDescriptorToLocationIdentifer(MethodDescriptor methodDesc,
-      VarDescriptor varDesc, String identifier) {
-    if (!md2LatticeMapping.containsKey(methodDesc)) {
-      md2LatticeMapping.put(methodDesc, new HashMap<VarDescriptor, String>());
-    }
-
-  }
-
   private void analyzeMethodLattice(MethodDescriptor md, SSJavaLattice<String> methodLattice) {
 
+    // first take a look at method invocation nodes to newly added relations
+    // from the callee
+    analyzeLatticeMethodInvocationNode(md);
+
     // visit each node of method flow graph
 
     FlowGraph fg = getFlowGraph(md);
@@ -265,7 +261,6 @@ public class LocationInference {
 
     // for the method lattice, we need to look at the first element of
     // NTuple<Descriptor>
-
     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
       FlowNode srcNode = (FlowNode) iterator.next();
 
@@ -277,112 +272,116 @@ public class LocationInference {
 
         addRelationToLattice(md, methodLattice, srcNode, dstNode);
 
-        // second, take a look at all nodes that are reachable from the source
-        // node
-        recursiveVisitNodes(md, srcNode, dstNode);
-
       }
 
     }
 
   }
 
-  private void addRelationToLattice(MethodDescriptor md, SSJavaLattice<String> methodLattice,
-      FlowNode srcNode, FlowNode dstNode) {
-    if ((srcNode.getDescTuple().size() > 1 && dstNode.getDescTuple().size() > 1)
-        && srcNode.getDescTuple().get(0).equals(dstNode.getDescTuple().get(0))) {
-      // value flow between fields: we don't need to add a binary relation
-      // for this case
-
-      VarDescriptor varDesc = (VarDescriptor) srcNode.getDescTuple().get(0);
-      ClassDescriptor varClassDesc = varDesc.getType().getClassDesc();
+  private void analyzeLatticeMethodInvocationNode(MethodDescriptor mdCaller) {
 
-      extractRelationFromFieldFlows(varClassDesc, srcNode, dstNode, 1);
-      return;
-    }
+    // the transformation for a call site propagates all relations between
+    // parameters from the callee
+    // if the method is virtual, it also grab all relations from any possible
+    // callees
 
-    // add a new binary relation of dstNode < srcNode
+    Set<MethodInvokeNode> setMethodInvokeNode =
+        mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
+    if (setMethodInvokeNode != null) {
 
-    String srcSymbol = getSymbol(0, srcNode);
-    String dstSymbol = getSymbol(0, dstNode);
+      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 {
+          setPossibleCallees.addAll(ssjava.getCallGraph().getMethods(mdCallee));
+        }
 
-    methodLattice.addRelationHigherToLower(srcSymbol, dstSymbol);
+        for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
+          MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
+          propagateRelationToCaller(min, mdCaller, possibleMdCallee);
+        }
 
-    if (srcNode.isParameter() && dstNode.isParameter()) {
-      propagateRelationToCaller(md, srcNode, dstNode);
+      }
     }
-  }
 
-  private SSJavaLattice<String> getMethodLattice(MethodDescriptor md) {
-
-    if (!md2lattice.containsKey(md)) {
-      md2lattice.put(md, new SSJavaLattice<String>(SSJavaLattice.TOP, SSJavaLattice.BOTTOM));
-    }
-    return md2lattice.get(md);
   }
 
-  private void propagateRelationToCaller(MethodDescriptor calleeMethodDesc, FlowNode srcNode,
-      FlowNode newVisitNode) {
+  private void propagateRelationToCaller(MethodInvokeNode min, MethodDescriptor mdCaller,
+      MethodDescriptor possibleMdCallee) {
 
-    FlowGraph calleeFlowGraph = getFlowGraph(calleeMethodDesc);
+    SSJavaLattice<String> calleeLattice = getMethodLattice(possibleMdCallee);
 
-    int higherLocIdxCallee = calleeFlowGraph.getParamIdx(srcNode.getDescTuple());
-    int lowerLocIdxCallee = calleeFlowGraph.getParamIdx(newVisitNode.getDescTuple());
+    FlowGraph calleeFlowGraph = getFlowGraph(possibleMdCallee);
 
-    System.out.println(" ssjava.getDependents(md)=" + ssjava.getDependents(calleeMethodDesc));
-    Iterator<MethodDescriptor> depsItr = ssjava.getDependents(calleeMethodDesc).iterator();
-    while (depsItr.hasNext()) {
-      MethodDescriptor callerMethodDesc = depsItr.next();
+    // find parameter node
+    Set<FlowNode> paramNodeSet = calleeFlowGraph.getParameterNodeSet();
 
-      SSJavaLattice<String> callerMethodLattice = md2lattice.get(callerMethodDesc);
+    for (Iterator iterator = paramNodeSet.iterator(); iterator.hasNext();) {
+      FlowNode paramFlowNode1 = (FlowNode) iterator.next();
 
-      Set<MethodInvokeNode> minSet = mapMethodDescriptorToMethodInvokeNodeSet.get(callerMethodDesc);
-      for (Iterator iterator = minSet.iterator(); iterator.hasNext();) {
-        MethodInvokeNode methodInvokeNode = (MethodInvokeNode) iterator.next();
-        if (methodInvokeNode.getMethod().equals(calleeMethodDesc)) {
-          // need to propagate a relation from the callee to the caller
-          // TODO
+      for (Iterator iterator2 = paramNodeSet.iterator(); iterator2.hasNext();) {
+        FlowNode paramFlowNode2 = (FlowNode) iterator2.next();
 
-          System.out.println("higherLocIdxCallee=" + higherLocIdxCallee);
-          System.out.println("lowerLocIdxCallee=" + lowerLocIdxCallee);
-
-          NTuple<Descriptor> higherArg = getArgTupleByArgIdx(methodInvokeNode, higherLocIdxCallee);
-          NTuple<Descriptor> lowerArg = getArgTupleByArgIdx(methodInvokeNode, lowerLocIdxCallee);
+        String paramSymbol1 = getSymbol(0, paramFlowNode1);
+        String paramSymbol2 = getSymbol(0, paramFlowNode2);
+        // if two parameters have relation, we need to propagate this relation
+        // to the caller
+        if (calleeLattice.isComparable(paramSymbol1, paramSymbol2)) {
+          int higherLocIdxCallee;
+          int lowerLocIdxCallee;
+          if (calleeLattice.isGreaterThan(paramSymbol1, paramSymbol2)) {
+            higherLocIdxCallee = calleeFlowGraph.getParamIdx(paramFlowNode1.getDescTuple());
+            lowerLocIdxCallee = calleeFlowGraph.getParamIdx(paramFlowNode2.getDescTuple());
+          } else {
+            higherLocIdxCallee = calleeFlowGraph.getParamIdx(paramFlowNode2.getDescTuple());
+            lowerLocIdxCallee = calleeFlowGraph.getParamIdx(paramFlowNode1.getDescTuple());
+          }
 
-          FlowNode callerHigherFlowNode = getFlowGraph(callerMethodDesc).getFlowNode(higherArg);
-          FlowNode calleeHigherFlowNode = getFlowGraph(callerMethodDesc).getFlowNode(lowerArg);
+          NTuple<Descriptor> higherArg = getArgTupleByArgIdx(min, higherLocIdxCallee);
+          NTuple<Descriptor> lowerArg = getArgTupleByArgIdx(min, lowerLocIdxCallee);
 
-          addRelationToLattice(callerMethodDesc, getMethodLattice(callerMethodDesc),
-              callerHigherFlowNode, calleeHigherFlowNode);
+          addFlowGraphEdge(mdCaller, higherArg, lowerArg);
 
         }
+
       }
 
     }
+
   }
 
-  private void recursiveVisitNodes(MethodDescriptor md, FlowNode srcNode, FlowNode currentVisitNode) {
+  private void addRelationToLattice(MethodDescriptor md, SSJavaLattice<String> methodLattice,
+      FlowNode srcNode, FlowNode dstNode) {
+    if ((srcNode.getDescTuple().size() > 1 && dstNode.getDescTuple().size() > 1)
+        && srcNode.getDescTuple().get(0).equals(dstNode.getDescTuple().get(0))) {
+      // value flow between fields: we don't need to add a binary relation
+      // for this case
+
+      VarDescriptor varDesc = (VarDescriptor) srcNode.getDescTuple().get(0);
+      ClassDescriptor varClassDesc = varDesc.getType().getClassDesc();
+
+      extractRelationFromFieldFlows(varClassDesc, srcNode, dstNode, 1);
+      return;
+    }
 
-    NTuple<Descriptor> srcTuple = srcNode.getDescTuple();
+    // add a new binary relation of dstNode < srcNode
 
-    for (Iterator<FlowEdge> outEdgeIter = currentVisitNode.getOutEdgeSet().iterator(); outEdgeIter
-        .hasNext();) {
+    String srcSymbol = getSymbol(0, srcNode);
+    String dstSymbol = getSymbol(0, dstNode);
 
-      FlowEdge outEdge = outEdgeIter.next();
-      FlowNode newVisitNode = outEdge.getDst();
+    methodLattice.addRelationHigherToLower(srcSymbol, dstSymbol);
 
-      NTuple<Descriptor> newVisitTuple = newVisitNode.getDescTuple();
+  }
 
-      // if both the source node and the newly visit node are parameters,
-      // need to keep this relation, then later add a new relation between
-      // corresponding arguments in the caller's lattice.
-      if (srcNode.isParameter() && newVisitNode.isParameter()) {
-        System.out.println("src=" + srcNode + "            newVisitNode=" + newVisitNode);
-        propagateRelationToCaller(md, srcNode, newVisitNode);
-      }
+  private SSJavaLattice<String> getMethodLattice(MethodDescriptor md) {
 
+    if (!md2lattice.containsKey(md)) {
+      md2lattice.put(md, new SSJavaLattice<String>(SSJavaLattice.TOP, SSJavaLattice.BOTTOM));
     }
-
+    return md2lattice.get(md);
   }
 
   private void extractRelationFromFieldFlows(ClassDescriptor cd, FlowNode srcNode,
@@ -509,7 +508,6 @@ public class LocationInference {
   private void analyzeSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
       SwitchStatementNode bsn) {
     // TODO Auto-generated method stub
-
   }
 
   private void analyzeFlowSubBlockNode(MethodDescriptor md, SymbolTable nametable,
@@ -1124,9 +1122,13 @@ public class LocationInference {
     return mapMethodDescriptorToFlowGraph.get(md);
   }
 
-  public void addFlowGraphEdge(MethodDescriptor md, NTuple<Descriptor> from, NTuple<Descriptor> to) {
+  public boolean addFlowGraphEdge(MethodDescriptor md, NTuple<Descriptor> from,
+      NTuple<Descriptor> to) {
+    // TODO
+    // return true if it adds a new edge
     FlowGraph graph = getFlowGraph(md);
     graph.addValueFlowEdge(from, to);
+    return true;
   }
 
   public void _debug_printGraph() {