Got clarification on how to resolve method calls, introduced concept of
authorjjenista <jjenista>
Tue, 25 Mar 2008 20:36:06 +0000 (20:36 +0000)
committerjjenista <jjenista>
Tue, 25 Mar 2008 20:36:06 +0000 (20:36 +0000)
a set of possible callees on virtual dispatch, have to take the merge of
those ownership graphs and allocation sites to be correct.  Stable, but
only a draft of the OwnershipAnalysis portion.  OwnershipGraph mechanics
to determine mapping of references in callee merge-o-tron to caller graph
not added yet.

Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java
Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java

index 685ac580277b0410b22cdff1af3e65cda35b0d60..aa53286da4118ae7f16275f035acb43abfce0fa6 100644 (file)
@@ -27,10 +27,10 @@ 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 HashSet  <Descriptor>                           descriptorsToVisit;
+    private Hashtable<Descriptor, OwnershipGraph>           mapDescriptorToCompleteOwnershipGraph;
+    private Hashtable<FlatNew,    AllocationSite>           mapFlatNewToAllocationSite;
+    private Hashtable<Descriptor, HashSet<AllocationSite> > mapDescriptorToAllocationSiteSet;
 
     // Use these data structures to track progress of one pass of
     // processing the FlatNodes of a particular method
@@ -48,13 +48,16 @@ public class OwnershipAnalysis {
        this.callGraph       = callGraph;
        this.allocationDepth = allocationDepth;
 
+       descriptorsToVisit = new HashSet<Descriptor>();
+
        mapDescriptorToCompleteOwnershipGraph =
            new Hashtable<Descriptor, OwnershipGraph>();
 
        mapFlatNewToAllocationSite =
            new Hashtable<FlatNew, AllocationSite>();
 
-       descriptorsToVisit = new HashSet<Descriptor>();
+       mapDescriptorToAllocationSiteSet =
+           new Hashtable<Descriptor, HashSet<AllocationSite> >();
 
        // use this set to prevent infinite recursion when
        // traversing the call graph
@@ -287,20 +290,59 @@ public class OwnershipAnalysis {
            
        case FKind.FlatNew:
            FlatNew fnn = (FlatNew) fn;
-           dst = fnn.getDst();
+            dst = fnn.getDst();
            AllocationSite as = getAllocationSiteFromFlatNew( fnn );
+
            og.assignTempToNewAllocation( dst, as );
-           
-           // !!!!!!!!!!!!!!
-           // do this if the new object is a flagged type
-           //og.addAnalysisRegion( tdParam );      
            break;
 
        case FKind.FlatCall:
-           //FlatCall         fc = (FlatCall) fn;
-           //MethodDescriptor md = fc.getMethod();
-           //descriptorsToVisit.add( md );
-           //System.out.println( "    Descs to visit: " + descriptorsToVisit );
+           FlatCall                fc           = (FlatCall) fn;
+           MethodDescriptor        md           = fc.getMethod();
+           FlatMethod              flatm        = state.getMethodFlat( md );
+           HashSet<AllocationSite> allocSiteSet = getAllocationSiteSet( 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 );
+
+           } 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();
+               Set            possibleCallees = callGraph.getMethods( md, typeDesc );
+
+               Iterator i = possibleCallees.iterator();
+               while( i.hasNext() ) {
+                   MethodDescriptor possibleMd = (MethodDescriptor) i.next();
+                   allocSiteSet.addAll( getAllocationSiteSet( possibleMd ) );
+                   OwnershipGraph ogPotentialCallee = mapDescriptorToCompleteOwnershipGraph.get( possibleMd );
+                   ogAllPossibleCallees.merge( ogPotentialCallee );
+               }
+           }
+
+           // 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)
+           //
+           // 2. Whether the method is static; if not we need to deal with the "this" pointer
+           //
+           // *******************************************************************************************
+           // 3. The original FlatMethod flatm to query for callee's context (paramter labels)
+           //   NOTE!  I assume FlatMethod before virtual dispatch accurately describes all possible methods!
+           // *******************************************************************************************
+           //
+           // 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, allocSiteSet );
+
            //og.writeGraph( methodDesc, fn );
            break;
 
@@ -332,6 +374,7 @@ public class OwnershipAnalysis {
     }
 
 
+    // return just the allocation site associated with one FlatNew node
     private AllocationSite getAllocationSiteFromFlatNew( FlatNew fn ) {
        if( !mapFlatNewToAllocationSite.containsKey( fn ) ) {
            AllocationSite as = new AllocationSite( allocationDepth );
@@ -351,4 +394,55 @@ public class OwnershipAnalysis {
 
        return mapFlatNewToAllocationSite.get( fn );
     }
+
+
+    // return all allocation sites in the method (there is one allocation
+    // site per FlatNew node in a method)
+    private HashSet<AllocationSite> getAllocationSiteSet( Descriptor d ) {
+       if( !mapDescriptorToAllocationSiteSet.containsKey( d ) ) {
+           buildAllocationSiteSet( d );   
+       }
+
+       return mapDescriptorToAllocationSiteSet.get( d );
+
+    }
+
+    private void buildAllocationSiteSet( Descriptor d ) {
+       HashSet<AllocationSite> s = new HashSet<AllocationSite>();
+
+       FlatMethod fm;
+       if( d instanceof MethodDescriptor ) {
+           fm = state.getMethodFlat( (MethodDescriptor) d );
+       } else {
+           assert d instanceof TaskDescriptor;
+           fm = state.getMethodFlat( (TaskDescriptor) d );
+       }
+
+       // visit every node in this FlatMethod's IR graph
+       // and make a set of the allocation sites from the
+       // FlatNew node's visited
+       HashSet<FlatNode> visited = new HashSet<FlatNode>();
+       HashSet<FlatNode> toVisit = new HashSet<FlatNode>();
+       toVisit.add( fm );
+
+       while( !toVisit.isEmpty() ) {
+           FlatNode n = toVisit.iterator().next();
+
+           if( n instanceof FlatNew ) {
+               s.add( getAllocationSiteFromFlatNew( (FlatNew) n ) );
+           }
+
+           toVisit.remove( n );
+           visited.add( n );
+
+           for( int i = 0; i < n.numNext(); ++i ) {
+               FlatNode child = n.getNext( i );
+               if( !visited.contains( child ) ) {
+                   toVisit.add( child );
+               }
+           }
+       }
+
+       mapDescriptorToAllocationSiteSet.put( d, s );
+    }
 }
index ba53898e56fb7e68440328260bd2aba40f043ef6..f84c9c66a4dbd4ff645722f678bfc3a790983fc3 100644 (file)
@@ -433,6 +433,88 @@ public class OwnershipGraph {
     }
 
 
+    
+    // some notes:
+    // the heap regions that are specially allocated as multiple-object
+    // regions for method parameters need to be remembered in order to
+    // resolve a function call.  So actually, we need a mapping from
+    // caller argument descriptors to the callee parameter heap regions
+    // to apply reference edges in the callee to the caller graph.
+    // 
+    // also, Constructors and virtual dispatch methods have a "this"
+    // argument that make the mapping of arguments to parameters a little
+    // tricky.  What happens to that this region?
+
+
+    public void resolveMethodCall( FlatCall                fc,
+                                  boolean                 isStatic,
+                                  FlatMethod              fm,
+                                  OwnershipGraph          ogCallee,
+                                  HashSet<AllocationSite> allocSiteSet ) {
+       
+       // first age all of the allocation sites from
+       // the callee graph in this graph
+       Iterator i = allocSiteSet.iterator();
+       while( i.hasNext() ) {
+           this.age( (AllocationSite) i.next() );
+       }
+
+       // the heap regions represented by the arguments (caller graph)
+       // and heap regions for the parameters (callee graph)
+       // don't correspond to each other by heap region ID.  In fact,
+       // an argument label node can be referencing several heap regions
+       // so the parameter label always references a multiple-object
+       // heap region in order to handle the range of possible contexts
+       // for a method call.  This means we need to make a special mapping
+       // of argument->parameter regions in order to update the caller graph,
+       // then remember which heap regions were used so we can ignore them
+       // in the more general algorithm below that includes all heap regions
+       // of the callee graph
+       HashSet<Integer> calleeParameterIDs = new HashSet<Integer>();
+
+       if( isStatic ) {
+           assert fc.numArgs()     == fm.numParameters();
+       } else {
+           assert fc.numArgs() + 1 == fm.numParameters();
+       }
+
+       for( int a = 0; a < fc.numArgs(); ++a ) {
+           
+       }
+
+       // for every heap region->heap region edge in the
+       // callee graph, create the matching edge or edges
+       // in the caller graph
+       Set      sCallee = ogCallee.id2hrn.entrySet();
+       Iterator iCallee = sCallee.iterator();
+       while( iCallee.hasNext() ) {
+           Map.Entry      meCallee  = (Map.Entry)      iCallee.next();
+           Integer        idCallee  = (Integer)        meCallee.getKey();
+           HeapRegionNode hrnCallee = (HeapRegionNode) meCallee.getValue();
+
+           HeapRegionNode hrnChildCallee = null;
+           Iterator heapRegionsItrCallee = hrnCallee.setIteratorToReferencedRegions();     
+           while( heapRegionsItrCallee.hasNext() ) {
+               Map.Entry me                 = (Map.Entry)               heapRegionsItrCallee.next();
+               hrnChildCallee               = (HeapRegionNode)          me.getKey();
+               ReferenceEdgeProperties repC = (ReferenceEdgeProperties) me.getValue();
+
+               Integer idChildCallee = hrnChildCallee.getID();
+               
+               // now we know that in the callee method's ownership graph
+               // there is a heap region->heap region reference edge given
+               // by the ownership-graph independent ID's:
+               // idCallee->idChildCallee
+               // 
+
+
+               // at this point we know an edge in graph A exists
+               // idA -> idChildA, does this exist in B?
+           } 
+       }       
+    }
+
+
 
     ////////////////////////////////////////////////////
     // in merge() and equals() methods the suffix A