fix bug
[IRC.git] / Robust / src / Analysis / CallGraph / CallGraph.java
index 1c24b244d966a2d78796aa766449bb1839ef9327..3573cd5668559a3d5ffb239a9652933623e245f8 100644 (file)
@@ -13,16 +13,18 @@ import java.util.*;
 import java.io.*;
 
 public class CallGraph {
-  private State state;
+  protected State state;
 
   // MethodDescriptor maps to HashSet<MethodDescriptor>
-  private Hashtable mapVirtual2ImplementationSet;
+  protected Hashtable mapVirtual2ImplementationSet;
 
   // MethodDescriptor or TaskDescriptor maps to HashSet<MethodDescriptor>
-  private Hashtable mapCaller2CalleeSet;
+  protected Hashtable mapCaller2CalleeSet;
 
   // MethodDescriptor maps to HashSet<MethodDescriptor or TaskDescriptor>
-  private Hashtable mapCallee2CallerSet;
+  protected Hashtable mapCallee2CallerSet;
+
+  protected CallGraph() {}
 
   public CallGraph(State state) {
     this.state=state;
@@ -37,7 +39,12 @@ public class CallGraph {
   // (MethodDescriptors and/or TaskDescriptors)
   //  that call the given method
   public Set getCallerSet(MethodDescriptor md) {
-    return (Set) mapCallee2CallerSet.get(md);
+    Set s = (Set) mapCallee2CallerSet.get(md);
+    
+    if( s == null ) {
+      return new HashSet();
+    }
+    return s;
   }
 
   // this method returns the set of MethodDescriptors that
@@ -46,12 +53,17 @@ public class CallGraph {
     assert(d instanceof MethodDescriptor) ||
     (d instanceof TaskDescriptor);
 
-    return (Set) mapCaller2CalleeSet.get(d);
+    Set s = (Set) mapCaller2CalleeSet.get(d);
+
+    if( s == null ) {
+      return new HashSet();
+    }
+    return s;
   }
 
   // build a mapping of virtual methods to all
   // possible implementations of that method
-  private void buildVirtualMap() {
+  protected void buildVirtualMap() {
     //Iterator through classes
     Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
     while(it.hasNext()) {
@@ -114,15 +126,47 @@ public class CallGraph {
 
     HashSet ns=new HashSet();
     ns.add(d);
+    return getMoreMethodCalls(ns, d);
+  }
+
+  private Set getMoreMethodCalls(HashSet found, Descriptor d) {
+    HashSet ns=new HashSet();
+    ns.add(d);
+    found.add(d);
     Set s=(Set)mapCaller2CalleeSet.get(d);
     if (s!=null)
       for(Iterator it=s.iterator(); it.hasNext();) {
        MethodDescriptor md=(MethodDescriptor)it.next();
-       ns.addAll(getMethodCalls(md));
+       if( !found.contains(md) ) {
+         ns.addAll(getMoreMethodCalls(found, md));
+       }
       }
     return ns;
   }
 
+  /** Returns all methods transitively callable from d */
+
+  public Set getAllMethods(Descriptor d) {
+    HashSet tovisit=new HashSet();
+    tovisit.add(d);
+    HashSet callable=new HashSet();
+    while(!tovisit.isEmpty()) {
+      Descriptor md=(Descriptor)tovisit.iterator().next();
+      tovisit.remove(md);
+      Set s=(Set)mapCaller2CalleeSet.get(md);
+      if (s!=null) {
+       for(Iterator it=s.iterator(); it.hasNext();) {
+         MethodDescriptor md2=(MethodDescriptor)it.next();
+         if( !callable.contains(md2) ) {
+           callable.add(md2);
+           tovisit.add(md2);
+         }
+       }
+      }
+    }
+    return callable;
+  }
+
   private void buildGraph() {
     Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
     while(it.hasNext()) {
@@ -141,7 +185,7 @@ public class CallGraph {
     }
   }
 
-  private void analyzeMethod(Object caller, FlatMethod fm) {
+  protected void analyzeMethod(Object caller, FlatMethod fm) {
     HashSet toexplore=new HashSet();
     toexplore.add(fm);
     HashSet explored=new HashSet();