added concept of method context
authorjjenista <jjenista>
Tue, 11 Nov 2008 04:44:34 +0000 (04:44 +0000)
committerjjenista <jjenista>
Tue, 11 Nov 2008 04:44:34 +0000 (04:44 +0000)
Robust/src/Analysis/OwnershipAnalysis/OwnershipAnalysis.java
Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java
Robust/src/Makefile
Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/makefile [new file with mode: 0644]
Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/testMethodContexts.java [new file with mode: 0644]

index 7de280a5ec802552762063e77ba69e846ddbd2ef..2b9606421f7f83ef599e3568b49abd9bcd658f75 100644 (file)
@@ -27,11 +27,12 @@ public class OwnershipAnalysis {
     return getAllocationSiteFromFlatNewPRIVATE(fn);
   }
 
+
   public boolean createsPotentialAliases(Descriptor taskOrMethod,
                                          int paramIndex1,
                                          int paramIndex2) {
 
-    OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+    OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
     assert(og != null);
     return og.hasPotentialAlias(paramIndex1, paramIndex2);
   }
@@ -40,7 +41,7 @@ public class OwnershipAnalysis {
                                          int paramIndex,
                                          AllocationSite alloc) {
 
-    OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+    OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
     assert(og != null);
     return og.hasPotentialAlias(paramIndex, alloc);
   }
@@ -49,7 +50,7 @@ public class OwnershipAnalysis {
                                          AllocationSite alloc,
                                          int paramIndex) {
 
-    OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+    OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
     assert(og != null);
     return og.hasPotentialAlias(paramIndex, alloc);
   }
@@ -58,11 +59,33 @@ public class OwnershipAnalysis {
                                          AllocationSite alloc1,
                                          AllocationSite alloc2) {
 
-    OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+    OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
     assert(og != null);
     return og.hasPotentialAlias(alloc1, alloc2);
   }
 
+
+  protected OwnershipGraph getGraphOfAllContextsFromDescriptor(Descriptor d) {
+    assert d != null;
+
+    OwnershipGraph og = new OwnershipGraph( allocationDepth, typeUtil );
+
+    assert mapDescriptorToAllMethodContexts.containsKey( d );
+    HashSet<MethodContext> contexts = mapDescriptorToAllMethodContexts.get( d );
+    Iterator<MethodContext> mcItr = contexts.iterator();
+    while( mcItr.hasNext() ) {
+      MethodContext mc = mcItr.next();
+
+      OwnershipGraph ogContext = mapMethodContextToCompleteOwnershipGraph.get(mc);
+      assert ogContext != null;
+
+      og.merge( ogContext );
+    }
+
+    return og;
+  }
+
+
   // use the methods given above to check every possible alias
   // between task parameters and flagged allocation sites reachable
   // from the task
@@ -174,11 +197,12 @@ 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 Hashtable<FlatMethod, OwnershipGraph>           mapFlatMethodToInitialParamAllocGraph;
-  private Hashtable<Descriptor, OwnershipGraph>           mapDescriptorToCompleteOwnershipGraph;
-  private Hashtable<FlatNew,    AllocationSite>           mapFlatNewToAllocationSite;
-  private Hashtable<Descriptor, HashSet<AllocationSite> > mapDescriptorToAllocationSiteSet;
-  private Hashtable<Descriptor, Integer>                  mapDescriptorToNumUpdates;
+  private Hashtable<MethodContext, OwnershipGraph>           mapMethodContextToInitialParamAllocGraph;
+  private Hashtable<MethodContext, OwnershipGraph>           mapMethodContextToCompleteOwnershipGraph;
+  private Hashtable<FlatNew,       AllocationSite>           mapFlatNewToAllocationSite;
+  private Hashtable<Descriptor,    HashSet<AllocationSite> > mapDescriptorToAllocationSiteSet;
+  private Hashtable<MethodContext, Integer>                  mapMethodContextToNumUpdates;
+  private Hashtable<Descriptor,    HashSet<MethodContext> >  mapDescriptorToAllMethodContexts;
 
   // Use these data structures to track progress of one pass of
   // processing the FlatNodes of a particular method
@@ -195,7 +219,7 @@ public class OwnershipAnalysis {
   // 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;
+  private HashSet<MethodContext> methodContextsToVisit;
 
   // a special field descriptor for all array elements
   private static FieldDescriptor fdElement = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC),
@@ -203,6 +227,12 @@ public class OwnershipAnalysis {
                                                                  "elements",
                                                                  null,
                                                                  false);
+
+  // a special temp descriptor for setting more than one parameter label
+  // to the all-aliased-parameters heap region node
+  protected static TempDescriptor tdAliasedParams = new TempDescriptor("_AllAliasedParams___");
+
+
   // for controlling DOT file output
   private boolean writeDOTs;
   private boolean writeAllDOTs;
@@ -228,11 +258,11 @@ public class OwnershipAnalysis {
 
     descriptorsToAnalyze = new HashSet<Descriptor>();
 
-    mapFlatMethodToInitialParamAllocGraph =
-      new Hashtable<FlatMethod, OwnershipGraph>();
+    mapMethodContextToInitialParamAllocGraph =
+      new Hashtable<MethodContext, OwnershipGraph>();
 
-    mapDescriptorToCompleteOwnershipGraph =
-      new Hashtable<Descriptor, OwnershipGraph>();
+    mapMethodContextToCompleteOwnershipGraph =
+      new Hashtable<MethodContext, OwnershipGraph>();
 
     mapFlatNewToAllocationSite =
       new Hashtable<FlatNew, AllocationSite>();
@@ -240,8 +270,12 @@ public class OwnershipAnalysis {
     mapDescriptorToAllocationSiteSet =
       new Hashtable<Descriptor, HashSet<AllocationSite> >();
 
+    mapDescriptorToAllMethodContexts = 
+      new Hashtable<Descriptor, HashSet<MethodContext> >();
+
+
     if( writeAllDOTs ) {
-      mapDescriptorToNumUpdates = new Hashtable<Descriptor, Integer>();
+      mapMethodContextToNumUpdates = new Hashtable<MethodContext, Integer>();
     }
 
     // initialize methods to visit as the set of all tasks in the
@@ -269,10 +303,16 @@ public class OwnershipAnalysis {
        fm = state.getMethodFlat( (TaskDescriptor) d);
       }
 
-      System.out.println("Previsiting " + d);
+      MethodContext mc = new MethodContext( d );
+      assert !mapDescriptorToAllMethodContexts.containsKey( d );
+      HashSet<MethodContext> s = new HashSet<MethodContext>();
+      s.add( mc );
+      mapDescriptorToAllMethodContexts.put( d, s );
+
+      System.out.println("Previsiting " + mc);
 
-      og = analyzeFlatNode(d, fm, null, og);
-      setGraphForDescriptor(d, og);
+      og = analyzeFlatNode(mc, fm, null, og);
+      setGraphForMethodContext(mc, og);
     }
 
     System.out.println("");
@@ -320,11 +360,22 @@ public class OwnershipAnalysis {
   // they call are updated
   private void analyzeMethods() throws java.io.IOException {
 
-    descriptorsToVisit = (HashSet<Descriptor>)descriptorsToAnalyze.clone();
+    methodContextsToVisit = new HashSet<MethodContext>();    
+    Iterator<Descriptor> itrd2a = descriptorsToAnalyze.iterator();
+    while( itrd2a.hasNext() ) {
+      HashSet<MethodContext> mcs = mapDescriptorToAllMethodContexts.get( itrd2a.next() );
+      assert mcs != null;
+
+      Iterator<MethodContext> itrmc = mcs.iterator();
+      while( itrmc.hasNext() ) {
+       methodContextsToVisit.add( itrmc.next() );
+      }
+    }
+
+    while( !methodContextsToVisit.isEmpty() ) {
+      MethodContext mc = methodContextsToVisit.iterator().next();
+      methodContextsToVisit.remove(mc);
 
-    while( !descriptorsToVisit.isEmpty() ) {
-      Descriptor d = (Descriptor) descriptorsToVisit.iterator().next();
-      descriptorsToVisit.remove(d);
 
       // because the task or method descriptor just extracted
       // was in the "to visit" set it either hasn't been analyzed
@@ -334,8 +385,9 @@ public class OwnershipAnalysis {
       // If there is a change detected, add any methods/tasks
       // that depend on this one to the "to visit" set.
 
-      System.out.println("Analyzing " + d);
+      System.out.println("Analyzing " + mc);
 
+      Descriptor d = mc.getDescriptor();
       FlatMethod fm;
       if( d instanceof MethodDescriptor ) {
        fm = state.getMethodFlat( (MethodDescriptor) d);
@@ -344,10 +396,10 @@ public class OwnershipAnalysis {
        fm = state.getMethodFlat( (TaskDescriptor) d);
       }
 
-      OwnershipGraph og = analyzeFlatMethod(d, fm);
-      OwnershipGraph ogPrev = mapDescriptorToCompleteOwnershipGraph.get(d);
+      OwnershipGraph og = analyzeFlatMethod(mc, fm);
+      OwnershipGraph ogPrev = mapMethodContextToCompleteOwnershipGraph.get(mc);
       if( !og.equals(ogPrev) ) {
-       setGraphForDescriptor(d, og);
+       setGraphForMethodContext(mc, og);
 
        // only methods have dependents, tasks cannot
        // be invoked by any user program calls
@@ -359,7 +411,14 @@ public class OwnershipAnalysis {
            while( depItr.hasNext() ) {
              Descriptor dependent = (Descriptor) depItr.next();
              if( descriptorsToAnalyze.contains(dependent) ) {
-               descriptorsToVisit.add(dependent);
+               
+               HashSet<MethodContext> mcs = mapDescriptorToAllMethodContexts.get( dependent );
+               assert mcs != null;
+               
+               Iterator<MethodContext> itrmc = mcs.iterator();
+               while( itrmc.hasNext() ) {
+                 methodContextsToVisit.add( itrmc.next() );
+               }
              }
            }
          }
@@ -373,12 +432,11 @@ public class OwnershipAnalysis {
   // keep passing the Descriptor of the method along for debugging
   // and dot file writing
   private OwnershipGraph
-  analyzeFlatMethod(Descriptor mDesc,
+  analyzeFlatMethod(MethodContext mc,
                     FlatMethod flatm) throws java.io.IOException {
 
     // initialize flat nodes to visit as the flat method
-    // because all other nodes in this flat method are
-    // decendents of the flat method itself
+    // because it is the entry point
 
     flatNodesToVisit = new HashSet<FlatNode>();
     flatNodesToVisit.add(flatm);
@@ -415,7 +473,7 @@ public class OwnershipAnalysis {
       // apply the analysis of the flat node to the
       // ownership graph made from the merge of the
       // parent graphs
-      og = analyzeFlatNode(mDesc,
+      og = analyzeFlatNode(mc,
                            fn,
                            returnNodesToCombineForCompleteOwnershipGraph,
                            og);
@@ -457,7 +515,7 @@ public class OwnershipAnalysis {
 
 
   private OwnershipGraph
-  analyzeFlatNode(Descriptor methodDesc,
+  analyzeFlatNode(MethodContext mc,
                   FlatNode fn,
                   HashSet<FlatReturnNode> setRetNodes,
                   OwnershipGraph og) throws java.io.IOException {
@@ -481,21 +539,41 @@ public class OwnershipAnalysis {
       // parameter IDs are consistent between analysis
       // iterations, so if this step has been done already
       // just merge in the cached version
-      OwnershipGraph ogInitParamAlloc = mapFlatMethodToInitialParamAllocGraph.get(fm);
+      OwnershipGraph ogInitParamAlloc = mapMethodContextToInitialParamAllocGraph.get(mc);
       if( ogInitParamAlloc == null ) {
 
-       // analyze this node one time globally
-       for( int i = 0; i < fm.numParameters(); ++i ) {
-         TempDescriptor tdParam = fm.getParameter(i);
-         og.assignTempEqualToParamAlloc(tdParam,
-                                        methodDesc instanceof TaskDescriptor,
-                                        new Integer(i) );
+       // if the method context has aliased parameters, make sure
+       // there is a blob region for all those param labels to
+       // reference
+       Set<Integer> aliasedParamIndices = mc.getAliasedParamIndices();
+       if( !aliasedParamIndices.isEmpty() ) {
+         og.makeAliasedParamHeapRegionNode( tdAliasedParams );
        }
 
-       // then remember it
+       // set up each parameter
+       for( int i = 0; i < fm.numParameters(); ++i ) {
+         TempDescriptor tdParam = fm.getParameter( i );
+         Integer        paramIndex = new Integer( i );
+
+         if( aliasedParamIndices.contains( paramIndex ) ) {
+           // just point this one to the alias blob
+           og.assignTempEqualToAliasedParam( tdParam,
+                                             tdAliasedParams,
+                                             paramIndex );         
+         } else {
+           // this parameter is not aliased to others, give it
+           // a fresh parameter heap region
+           
+           og.assignTempEqualToParamAlloc(tdParam,
+                                          mc.getDescriptor() instanceof TaskDescriptor,
+                                          paramIndex );
+         }
+       }
+       
+       // cache the graph
        OwnershipGraph ogResult = new OwnershipGraph(allocationDepth, typeUtil);
        ogResult.merge(og);
-       mapFlatMethodToInitialParamAllocGraph.put(fm, ogResult);
+       mapMethodContextToInitialParamAllocGraph.put(mc, ogResult);
 
       } else {
        // or just leverage the cached copy
@@ -567,9 +645,22 @@ public class OwnershipAnalysis {
 
       if( md.isStatic() ) {
        // a static method is simply always the same, makes life easy
-       OwnershipGraph onlyPossibleCallee = mapDescriptorToCompleteOwnershipGraph.get(md);
        ogMergeOfAllPossibleCalleeResults = og;
-       ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee);
+
+       Set<Integer> aliasedParamIndices = 
+         ogMergeOfAllPossibleCalleeResults.calculateAliasedParamSet(fc, md.isStatic(), flatm);
+       MethodContext mcNew = new MethodContext( md, aliasedParamIndices );      
+       OwnershipGraph onlyPossibleCallee = mapMethodContextToCompleteOwnershipGraph.get( mcNew );
+
+       if( onlyPossibleCallee == null ) {
+         // if this method context has never been analyzed just schedule it for analysis
+         // and skip over this call site for now
+         methodContextsToVisit.add( mcNew );
+         
+       } else {
+         ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee);
+       }
+
       } else {
        // if the method descriptor is virtual, then there could be a
        // set of possible methods that will actually be invoked, so
@@ -580,14 +671,27 @@ public class OwnershipAnalysis {
        Iterator i = possibleCallees.iterator();
        while( i.hasNext() ) {
          MethodDescriptor possibleMd = (MethodDescriptor) i.next();
+         FlatMethod pflatm = state.getMethodFlat(possibleMd);
 
          // don't alter the working graph (og) until we compute a result for every
          // possible callee, merge them all together, then set og to that
          OwnershipGraph ogCopy = new OwnershipGraph(allocationDepth, typeUtil);
          ogCopy.merge(og);
 
-         OwnershipGraph ogPotentialCallee = mapDescriptorToCompleteOwnershipGraph.get(possibleMd);
-         ogCopy.resolveMethodCall(fc, md.isStatic(), flatm, ogPotentialCallee);
+         Set<Integer> aliasedParamIndices = 
+           ogCopy.calculateAliasedParamSet(fc, possibleMd.isStatic(), pflatm);
+         MethodContext mcNew = new MethodContext( possibleMd, aliasedParamIndices );
+         OwnershipGraph ogPotentialCallee = mapMethodContextToCompleteOwnershipGraph.get( mcNew );
+
+         if( ogPotentialCallee == null ) {
+           // if this method context has never been analyzed just schedule it for analysis
+           // and skip over this call site for now
+           methodContextsToVisit.add( mcNew );
+           
+         } else {
+           ogCopy.resolveMethodCall(fc, possibleMd.isStatic(), pflatm, ogPotentialCallee);
+         }
+
          ogMergeOfAllPossibleCalleeResults.merge(ogCopy);
        }
       }
@@ -652,10 +756,10 @@ public class OwnershipAnalysis {
   }
 
 
-  private void setGraphForDescriptor(Descriptor d, OwnershipGraph og)
+  private void setGraphForMethodContext(MethodContext mc, OwnershipGraph og)
   throws IOException {
 
-    mapDescriptorToCompleteOwnershipGraph.put(d, og);
+    mapMethodContextToCompleteOwnershipGraph.put(mc, og);
 
     // arguments to writeGraph are:
     // boolean writeLabels,
@@ -667,15 +771,15 @@ public class OwnershipAnalysis {
     if( writeDOTs ) {
 
       if( !writeAllDOTs ) {
-       og.writeGraph(d, true, true, true, false, false);
+       og.writeGraph(mc, true, true, true, false, false);
 
       } else {
-       if( !mapDescriptorToNumUpdates.containsKey(d) ) {
-         mapDescriptorToNumUpdates.put(d, new Integer(0) );
+       if( !mapMethodContextToNumUpdates.containsKey(mc) ) {
+         mapMethodContextToNumUpdates.put(mc, new Integer(0) );
        }
-       Integer n = mapDescriptorToNumUpdates.get(d);
-       og.writeGraph(d, n, true, true, true, false, false);
-       mapDescriptorToNumUpdates.put(d, n + 1);
+       Integer n = mapMethodContextToNumUpdates.get(mc);
+       og.writeGraph(mc, n, true, true, true, false, false);
+       mapMethodContextToNumUpdates.put(mc, n + 1);
       }
     }
   }
index fa51004eeee8c9fdc850ec5332921487fa4cd7c4..851b3e708ce1d159cd1554c16cd7edc4a3dcbf06 100644 (file)
@@ -19,10 +19,12 @@ public class OwnershipGraph {
 
   protected static TempDescriptor tdReturn = new TempDescriptor("_Return___");
 
+  protected static final int bogusParamIndexInt = -2;
+
 
   public Hashtable<Integer,        HeapRegionNode> id2hrn;
   public Hashtable<TempDescriptor, LabelNode     > td2ln;
-  public Hashtable<Integer,        Integer       > id2paramIndex;
+  public Hashtable<Integer,        Set<Integer>  > id2paramIndexSet;
   public Hashtable<Integer,        Integer       > paramIndex2id;
   public Hashtable<Integer,        TempDescriptor> paramIndex2tdQ;
 
@@ -35,11 +37,11 @@ public class OwnershipGraph {
     this.allocationDepth = allocationDepth;
     this.typeUtil        = typeUtil;
 
-    id2hrn         = new Hashtable<Integer,        HeapRegionNode>();
-    td2ln          = new Hashtable<TempDescriptor, LabelNode     >();
-    id2paramIndex  = new Hashtable<Integer,        Integer       >();
-    paramIndex2id  = new Hashtable<Integer,        Integer       >();
-    paramIndex2tdQ = new Hashtable<Integer,        TempDescriptor>();
+    id2hrn           = new Hashtable<Integer,        HeapRegionNode>();
+    td2ln            = new Hashtable<TempDescriptor, LabelNode     >();
+    id2paramIndexSet = new Hashtable<Integer,        Set<Integer>  >();
+    paramIndex2id    = new Hashtable<Integer,        Integer       >();
+    paramIndex2tdQ   = new Hashtable<Integer,        TempDescriptor>();
 
     allocationSites = new HashSet <AllocationSite>();
   }
@@ -567,9 +569,10 @@ public class OwnershipGraph {
     // parameter labels, the index of the parameter they
     // are for is important when resolving method calls
     Integer newID = hrn.getID();
-    assert !id2paramIndex.containsKey(newID);
-    assert !id2paramIndex.containsValue(paramIndex);
-    id2paramIndex.put(newID, paramIndex);
+    assert !id2paramIndexSet.containsKey(newID);
+    Set s = new HashSet<Integer>();
+    s.add( paramIndex );
+    id2paramIndexSet.put(newID, s);
     paramIndex2id.put(paramIndex, newID);
     paramIndex2tdQ.put(paramIndex, tdParamQ);
 
@@ -597,6 +600,94 @@ public class OwnershipGraph {
     addReferenceEdge(hrn,      hrn, edgeReflexive);
   }
 
+  public void makeAliasedParamHeapRegionNode(TempDescriptor td) {
+    assert td != null;
+
+    LabelNode lnParam = getLabelNodeFromTemp(td);
+    HeapRegionNode hrn = createNewHeapRegionNode(null,
+                                                 false,
+                                                 false,
+                                                 false,
+                                                 true,
+                                                 null,
+                                                 null,
+                                                 "aliasedParams");
+
+
+    ReachabilitySet beta = new ReachabilitySet(new TokenTuple(hrn.getID(),
+                                                              true,
+                                                              TokenTuple.ARITY_ONE).makeCanonical()
+                                               ).makeCanonical();
+
+    // heap regions for parameters are always multiple object (see above)
+    // and have a reference to themselves, because we can't know the
+    // structure of memory that is passed into the method.  We're assuming
+    // the worst here.
+
+    ReferenceEdge edgeFromLabel =
+      new ReferenceEdge(lnParam, hrn, null, false, beta);
+
+    ReferenceEdge edgeReflexive =
+      new ReferenceEdge(hrn,     hrn, null, true,  beta);
+
+    addReferenceEdge(lnParam, hrn, edgeFromLabel);
+    addReferenceEdge(hrn,     hrn, edgeReflexive);
+  }
+
+  public void assignTempEqualToAliasedParam(TempDescriptor tdParam,
+                                           TempDescriptor tdAliased,
+                                           Integer paramIndex ) {
+
+    assert tdParam   != null;
+    assert tdAliased != null;
+
+    LabelNode lnParam   = getLabelNodeFromTemp(tdParam);
+    LabelNode lnAliased = getLabelNodeFromTemp(tdAliased);
+
+    // this is a non-program-accessible label that picks up beta
+    // info to be used for fixing a caller of this method
+    TempDescriptor tdParamQ = new TempDescriptor(tdParam+"specialQ");
+    LabelNode lnParamQ = getLabelNodeFromTemp(tdParamQ);
+
+    // the lnAliased should always only reference one node, and that
+    // heap region node is the aliased param blob
+    assert lnAliased.getNumReferencees() == 1;
+    HeapRegionNode hrnAliasBlob = lnAliased.iteratorToReferencees().next().getDst();
+
+    // keep track of heap regions that were created for
+    // parameter labels, the index of the parameter they
+    // are for is important when resolving method calls
+    Integer idAliased = hrnAliasBlob.getID();
+    Set s = id2paramIndexSet.get( idAliased );
+    if( s == null ) {
+      s = new HashSet<Integer>();
+    }
+    s.add( paramIndex );
+    id2paramIndexSet.put(idAliased, s);
+    paramIndex2id.put(paramIndex, idAliased);
+    paramIndex2tdQ.put(paramIndex, tdParamQ);
+
+    ReachabilitySet beta = new ReachabilitySet(new TokenTuple(idAliased,
+                                                              true,
+                                                              TokenTuple.ARITY_ONE).makeCanonical()
+                                               ).makeCanonical();
+
+    // heap regions for parameters are always multiple object (see above)
+    // and have a reference to themselves, because we can't know the
+    // structure of memory that is passed into the method.  We're assuming
+    // the worst here.
+
+    ReferenceEdge edgeFromLabel =
+      new ReferenceEdge(lnParam, hrnAliasBlob, null, false, beta);
+
+    ReferenceEdge edgeFromLabelQ =
+      new ReferenceEdge(lnParamQ, hrnAliasBlob, null, false, beta);
+
+    addReferenceEdge(lnParam,  hrnAliasBlob, edgeFromLabel);
+    addReferenceEdge(lnParamQ, hrnAliasBlob, edgeFromLabelQ);
+  }
+
+
 
   public void assignReturnEqualToTemp(TempDescriptor x) {
 
@@ -921,6 +1012,104 @@ public class OwnershipGraph {
   }
 
 
+  public Set<Integer> calculateAliasedParamSet(FlatCall fc,
+                                              boolean isStatic,
+                                              FlatMethod fm) {
+
+    Hashtable<Integer, LabelNode> paramIndex2ln =
+      new Hashtable<Integer, LabelNode>();
+
+    Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes =
+      new Hashtable<Integer, HashSet<HeapRegionNode> >();
+
+    for( int i = 0; i < fm.numParameters(); ++i ) {
+      Integer paramIndex = new Integer(i);
+
+      // now depending on whether the callee is static or not
+      // we need to account for a "this" argument in order to
+      // find the matching argument in the caller context
+      TempDescriptor argTemp_i;
+      if( isStatic ) {
+       argTemp_i = fc.getArg(paramIndex);
+      } else {
+       if( paramIndex.equals(0) ) {
+         argTemp_i = fc.getThis();
+       } else {
+         argTemp_i = fc.getArg(paramIndex - 1);
+       }
+      }
+
+      // in non-static methods there is a "this" pointer
+      // that should be taken into account
+      if( isStatic ) {
+       assert fc.numArgs()     == fm.numParameters();
+      } else {
+       assert fc.numArgs() + 1 == fm.numParameters();
+      }
+
+      LabelNode argLabel_i = getLabelNodeFromTemp(argTemp_i);
+      paramIndex2ln.put(paramIndex, argLabel_i);
+    }
+
+    Iterator lnArgItr = paramIndex2ln.entrySet().iterator();
+    while( lnArgItr.hasNext() ) {
+      Map.Entry me      = (Map.Entry)lnArgItr.next();
+      Integer index   = (Integer)   me.getKey();
+      LabelNode lnArg_i = (LabelNode) me.getValue();
+
+      // rewrite alpha for the nodes reachable from argument label i
+      HashSet<HeapRegionNode> reachableNodes = new HashSet<HeapRegionNode>();
+      HashSet<HeapRegionNode> todoNodes = new HashSet<HeapRegionNode>();
+
+      // to find all reachable nodes, start with label referencees
+      Iterator<ReferenceEdge> edgeArgItr = lnArg_i.iteratorToReferencees();
+      while( edgeArgItr.hasNext() ) {
+       ReferenceEdge edge = edgeArgItr.next();
+       todoNodes.add(edge.getDst() );
+      }
+
+      // then follow links until all reachable nodes have been found
+      while( !todoNodes.isEmpty() ) {
+       HeapRegionNode hrn = todoNodes.iterator().next();
+       todoNodes.remove(hrn);
+       reachableNodes.add(hrn);
+
+       Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencees();
+       while( edgeItr.hasNext() ) {
+         ReferenceEdge edge = edgeItr.next();
+
+         if( !reachableNodes.contains(edge.getDst() ) ) {
+           todoNodes.add(edge.getDst() );
+         }
+       }
+      }
+
+      // save for later
+      paramIndex2reachableCallerNodes.put(index, reachableNodes);
+    }
+
+    Set<Integer> aliasedIndices = new HashSet<Integer>();
+
+    // check for arguments that are aliased
+    for( int i = 0; i < fm.numParameters(); ++i ) {
+      for( int j = 0; j < i; ++j ) {   
+       HashSet<HeapRegionNode> s1 = paramIndex2reachableCallerNodes.get( i );
+       HashSet<HeapRegionNode> s2 = paramIndex2reachableCallerNodes.get( j );
+
+       Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(s1);
+       intersection.retainAll(s2);
+
+       if( !intersection.isEmpty() ) {
+         aliasedIndices.add( new Integer( i ) );
+         aliasedIndices.add( new Integer( j ) );
+       }
+      }
+    }
+
+    return aliasedIndices;
+  }
+
+
   public void resolveMethodCall(FlatCall fc,
                                 boolean isStatic,
                                 FlatMethod fm,
@@ -965,8 +1154,8 @@ public class OwnershipGraph {
 
     // add a bogus entry with the identity rule for easy rewrite
     // of new callee nodes and edges, doesn't belong to any parameter
-    Integer bogusID = new Integer(-1);
-    Integer bogusIndex = new Integer(-1);
+    Integer bogusID = new Integer(bogusParamIndexInt);
+    Integer bogusIndex = new Integer(bogusParamIndexInt);
     TokenTuple bogusToken = new TokenTuple(bogusID, true, TokenTuple.ARITY_ONE).makeCanonical();
     TokenTuple bogusTokenPlus = new TokenTuple(bogusID, true, TokenTuple.ARITY_ONEORMORE).makeCanonical();
     ReachabilitySet rsIdentity =
@@ -1215,31 +1404,6 @@ public class OwnershipGraph {
     }
 
 
-
-
-    // check for parameters that are aliased prior to this call site
-    // if so, come to a grinding halt.  Later, we should move this
-    // up before doing any alpha/beta updates
-    for( int i = 0; i < fm.numParameters(); ++i ) {
-      for( int j = 0; j < i; ++j ) {   
-       HashSet<HeapRegionNode> s1 = paramIndex2reachableCallerNodes.get( i );
-       HashSet<HeapRegionNode> s2 = paramIndex2reachableCallerNodes.get( j );
-
-       Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(s1);
-       intersection.retainAll(s2);
-
-       if( !intersection.isEmpty() ) {
-         // uh oh
-         System.out.println( "  Arguments "+j+" and "+i+" are aliased just before" );
-         System.out.println( "  "+fc+" calls "+fm+"\n" );
-         //System.exit( -1 );
-       }
-      }
-    }
-
-
-
-
     // verify the existence of allocation sites and their
     // shadows from the callee in the context of this caller graph
     // then map allocated nodes of callee onto the caller shadows
@@ -1810,9 +1974,9 @@ public class OwnershipGraph {
 
     HashSet<HeapRegionNode> possibleCallerHRNs = new HashSet<HeapRegionNode>();
 
-    Integer paramIndexCallee = ogCallee.id2paramIndex.get(hrnCallee.getID() );
+    Set<Integer> paramIndicesCallee = ogCallee.id2paramIndexSet.get( hrnCallee.getID() );
 
-    if( paramIndexCallee == null ) {
+    if( paramIndicesCallee == null ) {
       // this is a node allocated in the callee then and it has
       // exactly one shadow node in the caller to map to
       AllocationSite as = hrnCallee.getAllocationSite();
@@ -1842,8 +2006,12 @@ public class OwnershipGraph {
     } else {
       // this is a node that was created to represent a parameter
       // so it maps to a whole mess of heap regions
-      assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee);
-      possibleCallerHRNs = paramIndex2reachableCallerNodes.get(paramIndexCallee);
+      Iterator<Integer> itrIndex = paramIndicesCallee.iterator();
+      while( itrIndex.hasNext() ) {
+       Integer paramIndexCallee = itrIndex.next();
+       assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee);
+       possibleCallerHRNs.addAll( paramIndex2reachableCallerNodes.get(paramIndexCallee) );
+      }
     }
 
     return possibleCallerHRNs;
@@ -2244,18 +2412,18 @@ public class OwnershipGraph {
   // same number of parameters, or if one or both parameter
   // index tables are empty
   protected void mergeId2paramIndex(OwnershipGraph og) {
-    if( id2paramIndex.size() == 0 ) {
-      id2paramIndex  = og.id2paramIndex;
-      paramIndex2id  = og.paramIndex2id;
-      paramIndex2tdQ = og.paramIndex2tdQ;
+    if( id2paramIndexSet.size() == 0 ) {
+      id2paramIndexSet = og.id2paramIndexSet;
+      paramIndex2id    = og.paramIndex2id;
+      paramIndex2tdQ   = og.paramIndex2tdQ;
       return;
     }
 
-    if( og.id2paramIndex.size() == 0 ) {
+    if( og.id2paramIndexSet.size() == 0 ) {
       return;
     }
 
-    assert id2paramIndex.size() == og.id2paramIndex.size();
+    assert id2paramIndexSet.size() == og.id2paramIndexSet.size();
   }
 
   protected void mergeAllocationSites(OwnershipGraph og) {
@@ -2490,7 +2658,7 @@ public class OwnershipGraph {
 
 
   protected boolean areId2paramIndexEqual(OwnershipGraph og) {
-    return id2paramIndex.size() == og.id2paramIndex.size();
+    return id2paramIndexSet.size() == og.id2paramIndexSet.size();
   }
 
   public boolean hasPotentialAlias(Integer paramIndex1, Integer paramIndex2) {
@@ -2879,7 +3047,7 @@ public class OwnershipGraph {
 
 
   // for writing ownership graphs to dot files
-  public void writeGraph(Descriptor methodDesc,
+  public void writeGraph(MethodContext mc,
                          FlatNode fn,
                          boolean writeLabels,
                          boolean labelSelect,
@@ -2888,8 +3056,7 @@ public class OwnershipGraph {
                          boolean writeParamMappings
                          ) throws java.io.IOException {
     writeGraph(
-      methodDesc.getSymbol() +
-      methodDesc.getNum() +
+      mc.toString() +
       fn.toString(),
       writeLabels,
       labelSelect,
@@ -2899,7 +3066,7 @@ public class OwnershipGraph {
       );
   }
 
-  public void writeGraph(Descriptor methodDesc,
+  public void writeGraph(MethodContext mc,
                          boolean writeLabels,
                          boolean labelSelect,
                          boolean pruneGarbage,
@@ -2907,7 +3074,7 @@ public class OwnershipGraph {
                          boolean writeParamMappings
                          ) throws java.io.IOException {
 
-    writeGraph(methodDesc+"COMPLETE",
+    writeGraph(mc+"COMPLETE",
                writeLabels,
                labelSelect,
                pruneGarbage,
@@ -2916,7 +3083,7 @@ public class OwnershipGraph {
                );
   }
 
-  public void writeGraph(Descriptor methodDesc,
+  public void writeGraph(MethodContext mc,
                          Integer numUpdate,
                          boolean writeLabels,
                          boolean labelSelect,
@@ -2925,7 +3092,7 @@ public class OwnershipGraph {
                          boolean writeParamMappings
                          ) throws java.io.IOException {
 
-    writeGraph(methodDesc+"COMPLETE"+String.format("%05d", numUpdate),
+    writeGraph(mc+"COMPLETE"+String.format("%05d", numUpdate),
                writeLabels,
                labelSelect,
                pruneGarbage,
index 91de7309f3ac3ecb0954ecde4859ce8f04ad6f2a..5f81b007eff3bf62cf631276ec1924290a955325 100644 (file)
@@ -86,6 +86,7 @@ Analysis/OwnershipAnalysis/ReachabilitySet.class                        \
 Analysis/OwnershipAnalysis/ChangeTuple.class                            \
 Analysis/OwnershipAnalysis/ChangeTupleSet.class                         \
 Analysis/OwnershipAnalysis/Canonical.class                              \
+Analysis/OwnershipAnalysis/MethodContext.class                          \
 Util/GraphNode.class Util/Namer.class Util/Relation.class              \
 Interface/HTTPHeader.class Interface/HTTPResponse.class                        \
 Interface/HTTPServices.class Interface/HashStrings.class               \
diff --git a/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/makefile b/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/makefile
new file mode 100644 (file)
index 0000000..0d63066
--- /dev/null
@@ -0,0 +1,30 @@
+PROGRAM=testMethodContexts
+
+SOURCE_FILES=$(PROGRAM).java
+
+BUILDSCRIPT=~/research/Robust/src/buildscript
+BSFLAGS= -recover -ownership -ownaliasfile aliases.txt -enable-assertions -ownwritedots final -ownallocdepth 1 #-flatirtasks
+
+
+all: $(PROGRAM).bin
+
+view: PNGs
+       eog *.png &
+
+PNGs: DOTs
+       d2p *COMPLETE*.dot
+
+DOTs: $(PROGRAM).bin
+
+$(PROGRAM).bin: $(SOURCE_FILES)
+       $(BUILDSCRIPT) $(BSFLAGS) -o $(PROGRAM) $(SOURCE_FILES)
+
+clean:
+       rm -f  $(PROGRAM).bin
+       rm -fr tmpbuilddirectory
+       rm -f  *~
+       rm -f  *.dot
+       rm -f  *.png
+       rm -f  *.ps
+       rm -f  *.eps
+       rm -f  aliases.txt
diff --git a/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/testMethodContexts.java b/Robust/src/Tests/OwnershipAnalysisTest/testMethodContexts/testMethodContexts.java
new file mode 100644 (file)
index 0000000..3305312
--- /dev/null
@@ -0,0 +1,81 @@
+public class Foo { flag f; Foo x; public Foo(){} }
+
+public class Plane {
+  public Plane(){}
+
+  public void fly( Foo p0, Foo p1 ) {
+    p0.x = new Foo(){f};
+  }
+}
+
+public class SpitFire extends Plane {
+  public SpitFire(){}
+
+  public void fly( Foo p0, Foo p1 ) {
+    p1.x = new Foo(){f};
+  }
+}
+
+public class Jet extends Plane {
+  public Jet(){}
+
+  public void fly( Foo p0, Foo p1 ) {
+    Foo jet = new Foo(){f};
+    jet.x = p0;
+  }
+}
+
+public class F14 extends Jet {
+  public F14(){}
+
+  public void fly( Foo p0, Foo p1 ) {
+    Foo f14 = new Foo(){f};
+    f14.x = p1;
+  }
+}
+
+task Startup( StartupObject s{ initialstate } ) {
+
+  Foo a0 = new Foo(){f};
+  Foo a1 = new Foo(){f};
+  
+  Plane p;
+  
+  if( false ) {
+    p = new Plane();
+  } else if( false ) {
+    p = new SpitFire();
+  } else if( false ) {
+    p = new Jet();
+  } else {
+    p = new F14();
+  }
+
+  p.fly( a0, a1 );
+  
+  taskexit( s{ !initialstate } );
+}
+
+
+task SomeOtherTask( Foo foo{f} ) {
+
+  Foo a0 = new Foo(){f};
+  Foo a1 = new Foo(){f};
+  
+  Plane p;
+  
+  if( false ) {
+    p = new Plane();
+  } else if( false ) {
+    p = new SpitFire();
+  } else if( false ) {
+    p = new Jet();
+  } else {
+    p = new F14();
+  }
+
+  a0.x = a1;
+  p.fly( a0, a1 );
+
+  taskexit( foo{!f} );
+}