bug fix: when calculating methods dependent on a new result, only include methods...
authorjjenista <jjenista>
Tue, 26 Aug 2008 22:46:56 +0000 (22:46 +0000)
committerjjenista <jjenista>
Tue, 26 Aug 2008 22:46:56 +0000 (22:46 +0000)
Robust/src/Analysis/CallGraph/CallGraph.java
Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java
Robust/src/Tests/OwnershipAnalysisTest/test02/makefile
Robust/src/Tests/OwnershipAnalysisTest/test02/test02.java
Robust/src/Tests/OwnershipAnalysisTest/test03/makefile

index 3042da3ee960b561b8a241f2412861d614019110..393a86bef2fc068810d9a1f8036249bc5ee9eb73 100644 (file)
@@ -100,14 +100,25 @@ public class CallGraph {
 
   /** Given a call to MethodDescriptor, lists the methods which
       could actually be call by that method. */
+  public Set getMethodCalls(TaskDescriptor td) {
+    return getMethodCalls( (Descriptor) td );
+  }
+
   public Set getMethodCalls(MethodDescriptor md) {
+    return getMethodCalls( (Descriptor) md );
+  }
+
+  public Set getMethodCalls(Descriptor d) {
+    assert d instanceof MethodDescriptor ||
+      d instanceof TaskDescriptor;
+    
     HashSet ns=new HashSet();
-    ns.add(md);
-    Set s=(Set)mapCaller2CalleeSet.get(md);
+    ns.add(d);
+    Set s=(Set)mapCaller2CalleeSet.get(d);
     if (s!=null)
       for(Iterator it=s.iterator(); it.hasNext();) {
-       MethodDescriptor md2=(MethodDescriptor)it.next();
-       ns.addAll(getMethodCalls(md2));
+       MethodDescriptor md=(MethodDescriptor)it.next();
+       ns.addAll(getMethodCalls(md));
       }
     return ns;
   }
@@ -169,66 +180,123 @@ public class CallGraph {
     }
   }
 
-  public void writeToDot(String graphName)  throws java.io.IOException {
-    // each task or method only needs to be labeled once
-    // in a dot file
+
+  public void writeVirtual2ImplemToDot(String graphName)  throws java.io.IOException {
     HashSet labeledInDot = new HashSet();
 
-    // write out the call graph using the callees mapping
-    BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+"byCallees.dot") );
-    bw.write("digraph "+graphName+"byCallees {\n");
-    Iterator mapItr = mapCallee2CallerSet.entrySet().iterator();
+    BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+".dot") );
+    bw.write("digraph "+graphName+" {\n");
+    Iterator mapItr =  mapVirtual2ImplementationSet.entrySet().iterator();
     while( mapItr.hasNext() ) {
-      Map.Entry me        = (Map.Entry)mapItr.next();
-      MethodDescriptor callee    = (MethodDescriptor) me.getKey();
-      HashSet callerSet = (HashSet)          me.getValue();
+      Map.Entry        me        = (Map.Entry)        mapItr.next();
+      MethodDescriptor virtual   = (MethodDescriptor) me.getKey();
+      HashSet          implemSet = (HashSet)          me.getValue();
 
-      if( !labeledInDot.contains(callee) ) {
-       labeledInDot.add(callee);
-       bw.write("  " + callee.getNum() + "[label=\"" + callee + "\"];\n");
+      if( !labeledInDot.contains(virtual) ) {
+       labeledInDot.add(virtual);
+       bw.write("  "+virtual.getNum()+"[label=\""+virtual+"\"];\n");
       }
 
-      Iterator callerItr = callerSet.iterator();
-      while( callerItr.hasNext() ) {
-       Descriptor caller = (Descriptor) callerItr.next();
+      Iterator implemItr = implemSet.iterator();
+      while( implemItr.hasNext() ) {
+       Descriptor implem = (Descriptor) implemItr.next();
 
-       if( !labeledInDot.contains(caller) ) {
-         labeledInDot.add(caller);
-         bw.write("  " + caller.getNum() + "[label=\"" + caller + "\"];\n");
+       if( !labeledInDot.contains(implem) ) {
+         labeledInDot.add(implem);
+         bw.write("  "+implem.getNum()+"[label=\""+implem+"\"];\n");
        }
 
-       bw.write("  " + callee.getNum() + "->" + caller.getNum() + ";\n");
+       bw.write("  "+virtual.getNum()+"->"+implem.getNum()+";\n");
       }
     }
     bw.write("}\n");
     bw.close();
+  }
 
+
+  public void writeCaller2CalleesToDot(String graphName)  throws java.io.IOException {
     // write out the call graph (should be equivalent) by
     // using the callers mapping
-    labeledInDot = new HashSet();
-    bw = new BufferedWriter(new FileWriter(graphName+"byCallers.dot") );
+    HashSet labeledInDot = new HashSet();
+    BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+"byCallers.dot") );
     bw.write("digraph "+graphName+"byCallers {\n");
-    mapItr = mapCaller2CalleeSet.entrySet().iterator();
+    Iterator mapItr = mapCaller2CalleeSet.entrySet().iterator();
     while( mapItr.hasNext() ) {
       Map.Entry me        = (Map.Entry)mapItr.next();
       Descriptor caller    = (Descriptor) me.getKey();
       HashSet calleeSet = (HashSet)    me.getValue();
 
+      String callerString =  caller.toString().replaceAll("[\\W]", "");
+
+      /*
       if( !labeledInDot.contains(caller) ) {
        labeledInDot.add(caller);
-       bw.write("  " + caller.getNum() + "[label=\"" + caller + "\"];\n");
+       bw.write("  " + caller.getNum() + "[label=\"" + callerString + "\"];\n");
       }
+      */
 
       Iterator calleeItr = calleeSet.iterator();
       while( calleeItr.hasNext() ) {
        MethodDescriptor callee = (MethodDescriptor) calleeItr.next();
 
+       String calleeString =  callee.toString().replaceAll("[\\W]", "");
+
+       /*
        if( !labeledInDot.contains(callee) ) {
          labeledInDot.add(callee);
-         bw.write("  " + callee.getNum() + "[label=\"" + callee + "\"];\n");
+         bw.write("  " + callee.getNum() + "[label=\"" + calleeString + "\"];\n");
        }
+       */
+       bw.write("  " + caller.getNum() + "->" + callee.getNum() + ";\n");
+       
+
+       //bw.write("  " + callerString + "->" + calleeString + ";\n");
+      }
+    }
+    bw.write("}\n");
+    bw.close();
+  }
+
+
+  public void writeCallee2CallersToDot(String graphName)  throws java.io.IOException {
+    // each task or method only needs to be labeled once
+    // in a dot file
+    HashSet labeledInDot = new HashSet();
+
+    // write out the call graph using the callees mapping
+    BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+"byCallees.dot") );
+    bw.write("digraph "+graphName+"byCallees {\n");
+    Iterator mapItr = mapCallee2CallerSet.entrySet().iterator();
+    while( mapItr.hasNext() ) {
+      Map.Entry me        = (Map.Entry)mapItr.next();
+      MethodDescriptor callee    = (MethodDescriptor) me.getKey();
+      HashSet callerSet = (HashSet)          me.getValue();
+
+      String calleeString =  callee.toString().replaceAll("[\\W]", "");
+
+      /*
+      if( !labeledInDot.contains(callee) ) {
+       labeledInDot.add(callee);
+       bw.write("  " + callee.getNum() + "[label=\"" + calleeString + "\"];\n");
+      }
+      */
+
+      Iterator callerItr = callerSet.iterator();
+      while( callerItr.hasNext() ) {
+       Descriptor caller = (Descriptor) callerItr.next();
+       String callerString =  caller.toString().replaceAll("[\\W]", "");
+
+       /*
+       if( !labeledInDot.contains(caller) ) {
+         labeledInDot.add(caller);
+         bw.write("  " + caller.getNum() + "[label=\"" + callerString + "\"];\n");
+       }
+       */
+
+       bw.write("  " + caller.getNum() + "->" + callee.getNum() + ";\n");
+
 
-       bw.write("  " + callee.getNum() + "->" + caller.getNum() + ";\n");
+       //bw.write("  " + callerString + "->" + calleeString + ";\n");
       }
     }
     bw.write("}\n");
index a67ac4e3f7a7d9187d7543c8325e86391689e9ad..1c246e2a4f71d7c4fa256b690eed1ce753969cd0 100644 (file)
@@ -175,7 +175,6 @@ public class OwnershipAnalysis {
   // processing all methods in the program, and by methods
   // TaskDescriptor and MethodDescriptor are combined
   // together, with a common parent class Descriptor
-  private HashSet  <Descriptor>                           descriptorsToVisit;
   private Hashtable<Descriptor, OwnershipGraph>           mapDescriptorToCompleteOwnershipGraph;
   private Hashtable<FlatNew,    AllocationSite>           mapFlatNewToAllocationSite;
   private Hashtable<Descriptor, HashSet<AllocationSite> > mapDescriptorToAllocationSiteSet;
@@ -186,6 +185,18 @@ public class OwnershipAnalysis {
   private Hashtable<FlatNode, OwnershipGraph> mapFlatNodeToOwnershipGraph;
   private HashSet  <FlatReturnNode>           returnNodesToCombineForCompleteOwnershipGraph;
 
+  // descriptorsToAnalyze identifies the set of tasks and methods
+  // that are reachable from the program tasks, this set is initialized
+  // and then remains static
+  private HashSet<Descriptor> descriptorsToAnalyze;
+
+  // descriptorsToVisit is initialized to descriptorsToAnalyze and is
+  // reduced by visiting a descriptor during analysis.  When dependents
+  // must be scheduled, only those contained in descriptorsToAnalyze
+  // should be re-added to this set
+  private HashSet<Descriptor> descriptorsToVisit;
+
+
 
   // this analysis generates an ownership graph for every task
   // in the program
@@ -197,7 +208,7 @@ public class OwnershipAnalysis {
     this.allocationDepth = allocationDepth;
 
 
-    descriptorsToVisit = new HashSet<Descriptor>();
+    descriptorsToAnalyze = new HashSet<Descriptor>();
 
     mapDescriptorToCompleteOwnershipGraph =
       new Hashtable<Descriptor, OwnershipGraph>();
@@ -208,10 +219,6 @@ public class OwnershipAnalysis {
     mapDescriptorToAllocationSiteSet =
       new Hashtable<Descriptor, HashSet<AllocationSite> >();
 
-    // use this set to prevent infinite recursion when
-    // traversing the call graph
-    HashSet<Descriptor> calleesScheduled = new HashSet<Descriptor>();
-
 
     // initialize methods to visit as the set of all tasks in the
     // program and then any method that could be called starting
@@ -219,16 +226,13 @@ public class OwnershipAnalysis {
     Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
     while( taskItr.hasNext() ) {
       Descriptor d = (Descriptor) taskItr.next();
-      descriptorsToVisit.add(d);
-
-      // recursively find all callees from this task
-      scheduleAllCallees(calleesScheduled, d);
+      scheduleAllCallees(d);
     }
 
     // before beginning analysis, initialize every scheduled method
     // with an ownership graph that has populated parameter index tables
     // by analyzing the first node which is always a FlatMethod node
-    Iterator<Descriptor> dItr = calleesScheduled.iterator();
+    Iterator<Descriptor> dItr = descriptorsToAnalyze.iterator();
     while( dItr.hasNext() ) {
       Descriptor d  = dItr.next();
       OwnershipGraph og = new OwnershipGraph(allocationDepth);
@@ -252,25 +256,27 @@ public class OwnershipAnalysis {
 
   // called from the constructor to help initialize the set
   // of methods that needs to be analyzed by ownership analysis
-  private void scheduleAllCallees(HashSet<Descriptor> calleesScheduled,
-                                  Descriptor d) {
-    if( calleesScheduled.contains(d) ) {
+  private void scheduleAllCallees(Descriptor d) {
+    if( descriptorsToAnalyze.contains(d) ) {
       return;
     }
-    calleesScheduled.add(d);
+    descriptorsToAnalyze.add(d);
 
-    Set callees = callGraph.getCalleeSet(d);
-    if( callees == null ) {
-      return;
+    // start with all method calls to further schedule
+    Set moreMethodsToCheck = moreMethodsToCheck = callGraph.getMethodCalls( d );
+
+    if( d instanceof MethodDescriptor ) {
+      // see if this method has virtual dispatch
+      Set virtualMethods = callGraph.getMethods( (MethodDescriptor)d );
+      moreMethodsToCheck.addAll( virtualMethods );
     }
 
-    Iterator methItr = callees.iterator();
+    // keep following any further methods identified in
+    // the call chain
+    Iterator methItr = moreMethodsToCheck.iterator();
     while( methItr.hasNext() ) {
-      MethodDescriptor md = (MethodDescriptor) methItr.next();
-      descriptorsToVisit.add(md);
-
-      // recursively find all callees from this task
-      scheduleAllCallees(calleesScheduled, md);
+      Descriptor m = (Descriptor) methItr.next();
+      scheduleAllCallees(m);
     }
   }
 
@@ -279,6 +285,8 @@ public class OwnershipAnalysis {
   // and be sure to reschedule tasks/methods when the methods
   // they call are updated
   private void analyzeMethods() throws java.io.IOException {
+    
+    descriptorsToVisit = (HashSet<Descriptor>)descriptorsToAnalyze.clone();
 
     while( !descriptorsToVisit.isEmpty() ) {
       Descriptor d = (Descriptor) descriptorsToVisit.iterator().next();
@@ -313,7 +321,7 @@ public class OwnershipAnalysis {
           boolean pruneGarbage,
           boolean writeReferencers
         */
-       og.writeGraph(d, true, true, true, false);
+       og.writeGraph(d, true, true, false, false);
 
        // only methods have dependents, tasks cannot
        // be invoked by any user program calls
@@ -321,7 +329,13 @@ public class OwnershipAnalysis {
          MethodDescriptor md = (MethodDescriptor) d;
          Set dependents = callGraph.getCallerSet(md);
          if( dependents != null ) {
-           descriptorsToVisit.addAll(dependents);
+           Iterator depItr = dependents.iterator();
+           while( depItr.hasNext() ) {
+             Descriptor dependent = (Descriptor) depItr.next();
+             if( descriptorsToAnalyze.contains( dependent ) ) {
+               descriptorsToVisit.add(dependent);
+             }
+           }
          }
        }
       }
@@ -330,9 +344,6 @@ public class OwnershipAnalysis {
   }
 
 
-  int x = 0;
-
-
   // keep passing the Descriptor of the method along for debugging
   // and dot file writing
   private OwnershipGraph
@@ -386,16 +397,6 @@ public class OwnershipAnalysis {
       if( !og.equals(ogPrev) ) {
        setGraphForFlatNode(fn, og);
 
-
-
-       x++;
-       if( x > 0 ) {
-         String s = String.format("debug%04d", x);
-         //og.writeGraph( s, true, true, true, false );
-       }
-
-
-
        for( int i = 0; i < fn.numNext(); i++ ) {
          FlatNode nn = fn.getNext(i);
          flatNodesToVisit.add(nn);
@@ -483,55 +484,32 @@ public class OwnershipAnalysis {
       break;
 
     case FKind.FlatCall:
-      FlatCall fc           = (FlatCall) fn;
-      MethodDescriptor md           = fc.getMethod();
-      FlatMethod flatm        = state.getMethodFlat(md);
-      //HashSet<AllocationSite> allocSiteSet = getAllocationSiteSet( md );
-      OwnershipGraph ogAllPossibleCallees  = new OwnershipGraph(allocationDepth);
+      FlatCall fc = (FlatCall) fn;
+      MethodDescriptor md = fc.getMethod();
+      FlatMethod flatm = state.getMethodFlat(md);
+      OwnershipGraph ogAllPossibleCallees = new OwnershipGraph(allocationDepth);
 
       if( md.isStatic() ) {
        // a static method is simply always the same, makes life easy
        OwnershipGraph onlyPossibleCallee = mapDescriptorToCompleteOwnershipGraph.get(md);
        ogAllPossibleCallees.merge(onlyPossibleCallee);
 
-       /*
-          if( onlyPossibleCallee != null ) {
-           onlyPossibleCallee.writeGraph( "only", false, false );
-           System.out.println( "There was only one possible callee, "+md );
-          }
-        */
-
       } else {
        // if the method descriptor is virtual, then there could be a
        // set of possible methods that will actually be invoked, so
        // find all of them and merge all of their graphs together
-       TypeDescriptor typeDesc        = fc.getThis().getType();
+       TypeDescriptor typeDesc = fc.getThis().getType();
        Set possibleCallees = callGraph.getMethods(md, typeDesc);
 
-       //int j = 0;
-
        Iterator i = possibleCallees.iterator();
        while( i.hasNext() ) {
          MethodDescriptor possibleMd = (MethodDescriptor) i.next();
-         //allocSiteSet.addAll( getAllocationSiteSet( possibleMd ) );
          OwnershipGraph ogPotentialCallee = mapDescriptorToCompleteOwnershipGraph.get(possibleMd);
-
-         /*
-            if( ogPotentialCallee != null ) {
-             ogPotentialCallee.writeGraph( "potential"+j, false, false );
-          ++j;
-            }
-          */
-
          ogAllPossibleCallees.merge(ogPotentialCallee);
        }
-
-       //System.out.println( "There were "+j+" potential callees merged together." );
       }
-
-      //System.out.println( "AllocationSiteSet has "+allocSiteSet.size()+" items." );
-
-      // now we should have the following information to resolve this method call:
+      
+      // Now we should have the following information to resolve this method call:
       //
       // 1. A FlatCall fc to query for the caller's context (argument labels, etc)
       //
@@ -545,9 +523,6 @@ public class OwnershipAnalysis {
       // 4. The OwnershipGraph ogAllPossibleCallees is a merge of every ownership graph of all the possible
       // methods to capture any possible references made.
       //
-      // 5. The Set of AllocationSite objects, allocSiteSet that is the set of allocation sites from
-      // every possible method we might have chosen
-      //
       og.resolveMethodCall(fc, md.isStatic(), flatm, ogAllPossibleCallees);
       break;
 
index 65cc0bbd340734de374148affd8d6c680364b461..4281e17d9115e3db54b8dd07770d9e77cabe08b5 100644 (file)
@@ -1,4 +1,4 @@
-PROGRAM=test01
+PROGRAM=test02
 
 SOURCE_FILES=$(PROGRAM).java
 
index 03aedb9b8b7e8536c0f2ddf58b613a95ddbe4054..7aad47c150cf194b42de5614354f732f52b9b781 100644 (file)
@@ -18,6 +18,46 @@ public class Penguin {
     public void bar() { x = 1; }
 }
 
+public class Voo {
+    flag f; int x; Baw b; Baw bb;
+
+    public Voo() {}
+}
+
+public class Baw {
+    int y;
+    Foo f;
+
+    public Baw() {}
+
+    public void doTheBaw( Voo v ) { v = new Voo(); }
+}
+
+public class Foo {
+    flag f;
+
+    public Foo() {}
+
+    public Foo x;
+    public Foo y;
+    public Foo z;
+
+    public void ruinSomeFoos( Foo a, Foo b ) {
+       a.x = b.x;
+    }
+
+    static public void aStaticMethod( Foo p0, Foo p1 ) {
+       Foo f0 = new Foo();
+       Foo f1 = new Foo();
+       Foo f2 = new Foo();
+
+       f0.x = f1;
+       p0.x = f0;
+       p1.x = f1;
+       p1.x = f2;
+    }
+}
+
 task Startup( StartupObject s{ initialstate } ) {
 
     /*
index 65cc0bbd340734de374148affd8d6c680364b461..78e3c5bd173f63ec60f5951b40ab4e2611923d3c 100644 (file)
@@ -1,4 +1,4 @@
-PROGRAM=test01
+PROGRAM=test03
 
 SOURCE_FILES=$(PROGRAM).java