Added generation of method dependency map
authorjjenista <jjenista>
Mon, 11 Feb 2008 21:51:21 +0000 (21:51 +0000)
committerjjenista <jjenista>
Mon, 11 Feb 2008 21:51:21 +0000 (21:51 +0000)
Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java

index 314b9d0c014390b1a4dca46bcf690b656923c583..511c48ea396462a4b9593dddd901bf622ef432ad 100644 (file)
@@ -8,28 +8,133 @@ import java.io.*;
 
 public class OwnershipAnalysis {
 
-    
+    // from the compiler
     private State state;
-    private HashSet<FlatNode> visited;
-    private HashSet<FlatNode> toVisit;
-
-    private int labelindex;
-    private Hashtable<FlatNode, Integer> flatnodetolabel;
-
-    private Hashtable<FlatNode, OwnershipGraph> flatNodeToOwnershipGraph;
+    private int   allocationDepthK;
+
+    // Use these data structures to track progress of 
+    // processing all methods in the program
+    private HashSet  <FlatMethod>                       flatMethodsToVisit;
+    private Hashtable<FlatMethod, OwnershipGraph>       mapFlatMethodToCompleteOwnershipGraph;
+    private Hashtable<Descriptor, HashSet<Descriptor> > mapMethodToDependentMethods;
+
+    // Use these data structures to track progress of one pass of
+    // processing the FlatNodes in a FlatMethod
+    private HashSet  <FlatNode>                 flatNodesToVisit;
+    private Hashtable<FlatNode, OwnershipGraph> mapFlatNodeToOwnershipGraph;    
+    private HashSet  <FlatReturnNode>           returnNodesToCombineForComplete;
+
+    // for generating unique ownership node ID's throughout the
+    // ownership analysis
+    static private int uniqueIDcount = 0;
+
+    static public Integer generateUniqueID() {
+       ++uniqueIDcount;
+       return new Integer( uniqueIDcount );
+    }
 
-    private int newDepthK;
 
     // this analysis generates an ownership graph for every task
     // in the program
     public OwnershipAnalysis( State state ) throws java.io.IOException {
-       this.state=state;      
-       this.newDepthK = 3;
-       analyzeTasks();
+       this.state            = state;      
+       this.allocationDepthK = 3;
+
+       // the analyzeMethods() function will keep analyzing the contents
+       // of flatMethodsToVisit until it is empty.  The following function
+       // will generate the method dependencies and put every task (subclass
+       // of method) in flatMethodsToVisit so the ownership analysis will
+       // cover at least every task, but might not analyze every method of
+       // the program if there is no dependency chain back to a task
+       prepareForAndEnqueueTasks();
+
+       // as mentioned above, analyze methods one-by-one, possibly revisiting
+       // a method if the methods that it calls are updated
+       analyzeMethods();
+    }
+
+    // run once per program analysis
+    private void prepareForAndEnqueueTasks() {
+       flatMethodsToVisit = new HashSet<FlatMethod>();
+
+       mapFlatMethodToCompleteOwnershipGraph =
+           new Hashtable<FlatMethod, OwnershipGraph>();
+
+       mapMethodToDependentMethods =
+           new Hashtable<Descriptor, HashSet<Descriptor> >();
+
+       // once the dependency map is generated here it
+       // doesn't need to be modified anymore.  It is
+       // used when a method is updated to enqueue the
+       // methods that are dependent on the result.  They
+       // may or may not have a different analysis outcome
+
+       // first put all the tasks into the dependency map
+       Iterator itrTasks = state.getTaskSymbolTable().getDescriptorsIterator();
+       while( itrTasks.hasNext() ) {
+           TaskDescriptor td = itrTasks.next();
+           FlatMethod     fm = state.getMethodFlat( td );
+           
+           searchFlatMethodForCallNodes( td, fm );
+       }
+
+       // then put all the methods of classes into the map
+    }
+
+    // called on each task and class method before ownership
+    // analysis is started so the method dependency map can
+    // be generated
+    private void searchFlatMethodForCallNodes( Descriptor caller, FlatMethod fm ) {
+       // borrow this data structure before the ownership
+       // analysis proper begins in order to search the IR
+       flatNodesToVisit = new HashSet<FlatNode>();
+
+       flatNodesToVisit.add( fm );
+
+       while( !flatNodesToVisit.isEmpty() ) {
+           FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+           flatNodesToVisit.remove( fn );
+           
+           if( fn.kind() == FKind.FlatClass ) {
+               FlatCall fc = (FlatCall) fn;
+               addMethodDependency( caller, fc.getMethod() );
+           }
+       }
+    }
+
+    // supports creation of the method dependency map
+    private void addMethodDependency( Descriptor caller, Descriptor callee ) {
+
+       // the caller is calling the callee so the caller's
+       // analysis depends on the callee's analysis,
+       // therefore build a map that looks like this:
+       //   callee: <caller1, caller2, ...>
+       //
+       // and only add the dependency if it doesn't already exist
+
+       if( !mapMethodToDependentMethods.containsKey( callee ) ) {
+           // there is no map entry for this callee, so add it with
+           // just the caller as the only dependent method and return
+           mapMethodToDependentMethods.put( callee, caller );
+           return;
+       }
+
+       // if there is already an entry for the callee, check to see
+       // if the caller is already in the value for that map entry
+       HashSet dependentMethods = (HashSet) mapMethodToDependentMethods.get( callee );
+       
+       if( !dependentMethods.contains( caller ) ) {
+           // the caller is not in the set of dependent methods for
+           // this callee, so add it and return
+           dependentMethods.add( caller );
+           return;
+       }
+
+       // the dependency was already there, do nothing
     }
 
 
-    public void analyzeTasks() throws java.io.IOException {
+    private void analyzeMethods() throws java.io.IOException {
        for( Iterator it_tasks=state.getTaskSymbolTable().getDescriptorsIterator();
             it_tasks.hasNext();
             ) {
@@ -49,23 +154,12 @@ public class OwnershipAnalysis {
            labelindex      = 0;
            labelFlatNodes( fm );
 
-           String taskname = td.getSymbol();
-           analyzeFlatIRGraph( fm, taskname );
+           String methodname = td.getSymbol();
+           analyzeFlatIRGraph( fm, methodname );
        }       
     }
 
-    private void labelFlatNodes( FlatNode fn ) {
-       visited.add( fn );
-       flatnodetolabel.put( fn, new Integer( labelindex++ ) );
-       for( int i = 0; i < fn.numNext(); i++ ) {
-           FlatNode nn = fn.getNext( i );
-           if( !visited.contains( nn ) ) {
-               labelFlatNodes( nn );
-           }
-       }
-    }
-
-    private OwnershipGraph getGraphFromFlat( FlatNode fn ) {
+    private OwnershipGraph getGraphFromFlatNode( FlatNode fn ) {
        if( !flatNodeToOwnershipGraph.containsKey( fn ) ) {
            flatNodeToOwnershipGraph.put( fn, new OwnershipGraph( newDepthK ) );
        }
@@ -73,32 +167,52 @@ public class OwnershipAnalysis {
        return flatNodeToOwnershipGraph.get( fn );
     }
 
-    private void setGraphForFlat( FlatNode fn, OwnershipGraph og ) {
+    private void setGraphForFlatNode( FlatNode fn, OwnershipGraph og ) {
        flatNodeToOwnershipGraph.put( fn, og );
     }
 
-    private void analyzeFlatIRGraph( FlatMethod flatm, String taskname ) throws java.io.IOException {
-       visited=new HashSet<FlatNode>();
+    private void analyzeFlatMethod( FlatMethod flatm, String methodname ) throws java.io.IOException {
        toVisit=new HashSet<FlatNode>();
        toVisit.add( flatm );
 
        while( !toVisit.isEmpty() ) {
-           FlatNode fn = (FlatNode)toVisit.iterator().next();
+           FlatNode fn = (FlatNode) toVisit.iterator().next();
            toVisit.remove( fn );
-           visited.add( fn );
 
            // perform this node's contributions to the ownership
            // graph on a new copy, then compare it to the old graph
            // at this node to see if anything was updated.
            OwnershipGraph og = new OwnershipGraph( newDepthK );
 
-           // start by merging all incoming node's graphs
+           // start by merging all node's parents' graphs
            for( int i = 0; i < fn.numPrev(); ++i ) {
                FlatNode       pn       = fn.getPrev( i );
-               OwnershipGraph ogParent = getGraphFromFlat( pn );
+               OwnershipGraph ogParent = getGraphFromFlatNode( pn );
                og.merge( ogParent );
            }
            
+           analyzeFlatNode( fn );
+           
+           // if the results of the new graph are different from
+           // the current graph at this node, replace the graph
+           // with the update and enqueue the children for
+           // processing
+           OwnershipGraph ogOld = getGraphFromFlatNode( fn );
+
+           if( !og.equals( ogOld ) ) {
+               setGraphForFlatNode( fn, og );
+
+               for( int i = 0; i < fn.numNext(); i++ ) {
+                   FlatNode nn = fn.getNext( i );
+                   visited.remove( nn );
+                   toVisit.add( nn );
+               }
+           }
+       }
+    }
+
+
+    private void analyzeFlatNode( FlatNode fn, String methodname ) {
            TempDescriptor  src;
            TempDescriptor  dst;
            FieldDescriptor fld;
@@ -173,40 +287,24 @@ public class OwnershipAnalysis {
            case FKind.FlatReturnNode:
                nodeDescription = "Return";
                writeGraph = true;
-               og.writeCondensedAnalysis( makeCondensedAnalysisName( taskname, flatnodetolabel.get(fn) ) );
+               og.writeCondensedAnalysis( makeCondensedAnalysisName( methodname, flatnodetolabel.get(fn) ) );
                break;
            }
 
            if( writeGraph ) {
-               og.writeGraph( makeNodeName( taskname, 
+               og.writeGraph( makeNodeName( methodname, 
                                             flatnodetolabel.get( fn ), 
                                             nodeDescription ) );
            }
-           
-           // if the results of the new graph are different from
-           // the current graph at this node, replace the graph
-           // with the update and enqueue the children for
-           // processing
-           OwnershipGraph ogOld = getGraphFromFlat( fn );
-
-           if( !og.equals( ogOld ) ) {
-               setGraphForFlat( fn, og );
-
-               for( int i = 0; i < fn.numNext(); i++ ) {
-                   FlatNode nn = fn.getNext( i );
-                   visited.remove( nn );
-                   toVisit.add( nn );
-               }
-           }
-       }
     }
 
-    private String makeNodeName( String taskname, Integer id, String type ) {
+
+    private String makeNodeName( String methodname, Integer id, String type ) {
        String s = String.format( "%05d", id );
-       return "task"+taskname+"_FN"+s+"_"+type;
+       return "method_"+methodname+"_FN"+s+"_"+type;
     }
 
-    private String makeCondensedAnalysisName( String taskname, Integer id ) {
-       return "task"+taskname+"_Ownership_from"+id;
+    private String makeCondensedAnalysisName( String methodname, Integer id ) {
+       return "method_"+methodname+"_Ownership_from"+id;
     }
 }