caller local variables to in-context regions are modeled as out-of-context edges...
authorjjenista <jjenista>
Thu, 11 Mar 2010 20:08:50 +0000 (20:08 +0000)
committerjjenista <jjenista>
Thu, 11 Mar 2010 20:08:50 +0000 (20:08 +0000)
Robust/src/Analysis/Disjoint/ExistPred.java
Robust/src/Analysis/Disjoint/ReachGraph.java
Robust/src/Tests/disjoint/predicateTest2/test.java

index c008a8428e8027580e46d91f73a447db23c3a172..88267e1df2abda3feaef4493f61b39a0b2d1f038 100644 (file)
@@ -56,6 +56,8 @@ public class ExistPred extends Canonical {
   // satisfied when the edge exists AND it has the state.
   // the source of an edge is *either* a variable
   // node or a heap region node
+  protected boolean        e_srcOutContext;
+
   protected TempDescriptor e_tdSrc;
   protected Integer        e_hrnSrcID;
 
@@ -85,6 +87,7 @@ public class ExistPred extends Canonical {
     e_hrnDstID = null;
     e_type     = null;
     e_field    = null;
+    e_srcOutContext = false;
   }
 
   // node predicates
@@ -108,6 +111,7 @@ public class ExistPred extends Canonical {
     e_hrnDstID = null;
     e_type     = null;
     e_field    = null;
+    e_srcOutContext = false;
   }
 
   // edge predicates
@@ -116,14 +120,16 @@ public class ExistPred extends Canonical {
                                    Integer        hrnDstID,
                                    TypeDescriptor type,    
                                    String         field,   
-                                   ReachState     state ) {
+                                   ReachState     state,
+                                   boolean        srcOutContext ) {
 
     ExistPred out = new ExistPred( tdSrc,   
                                    hrnSrcID,
                                    hrnDstID,
                                    type,    
                                    field,   
-                                   state );
+                                   state,
+                                   srcOutContext );
 
     out = (ExistPred) Canonical.makeCanonical( out );
     return out;
@@ -134,7 +140,8 @@ public class ExistPred extends Canonical {
                        Integer        hrnDstID,
                        TypeDescriptor type,
                        String         field,
-                       ReachState     state ) {
+                       ReachState     state,
+                       boolean        srcOutContext ) {
     
     assert (tdSrc == null) || (hrnSrcID == null);
     assert hrnDstID != null;
@@ -143,7 +150,8 @@ public class ExistPred extends Canonical {
     // fields can be null when the edge is from
     // a variable node to a heap region!
     // assert field    != null;
-    
+    this.e_srcOutContext = srcOutContext;
+
     this.e_tdSrc    = tdSrc;
     this.e_hrnSrcID = hrnSrcID;
     this.e_hrnDstID = hrnDstID;
@@ -215,7 +223,10 @@ public class ExistPred extends Canonical {
       if( vnSrc != null ) {
         rsn = vnSrc;
       } else {
-        if( !calleeReachableNodes.contains( e_hrnSrcID ) ) {
+        if( !calleeReachableNodes.contains( e_hrnSrcID ) && !e_srcOutContext ) {
+          return null;
+        }
+        if( calleeReachableNodes.contains( e_hrnSrcID ) && e_srcOutContext ) {
           return null;
         }
         rsn = hrnSrc;
@@ -332,6 +343,10 @@ public class ExistPred extends Canonical {
       return false;
     }
 
+    // if the identifiers match, this should
+    // always match    
+    assert e_srcOutContext == pred.e_srcOutContext;
+
     return true;
   }
 
@@ -401,6 +416,10 @@ public class ExistPred extends Canonical {
         s += e_hrnSrcID.toString();
       }
 
+      if( e_srcOutContext ) {
+        s += "(ooc)";
+      }
+
       s += "-->"+e_hrnDstID+")";
 
       if( ne_state != null ) {
index 9c838529793d1ede550eab976735b41edd2a1f4e..7f75a6bf80e9c405c27a57043bddfb9ac6b37702 100644 (file)
@@ -1419,7 +1419,8 @@ public class ReachGraph {
                                  hrnDstID,
                                  reCaller.getType(),
                                  reCaller.getField(),
-                                 null );
+                                 null,
+                                 rsnCaller instanceof VariableNode ); // out-of-context
 
             ExistPredSet preds = 
               ExistPredSet.factory( pred );
@@ -1468,10 +1469,15 @@ public class ReachGraph {
         TypeDescriptor oocNodeType;
         ReachSet       oocReach;
 
+        TempDescriptor oocPredSrcTemp = null;
+        Integer        oocPredSrcID   = null;
+
         if( rsnCallerAndOutContext instanceof VariableNode ) {
           // variables are always out-of-context
           oocNodeType = null;
           oocReach    = rsetEmpty;
+          oocPredSrcTemp = 
+            ((VariableNode)rsnCallerAndOutContext).getTempDescriptor();
 
         } else {
           
@@ -1484,10 +1490,25 @@ public class ReachGraph {
             continue;
           }
 
-          oocNodeType = hrnCallerAndOutContext.getType();
-          oocReach    = hrnCallerAndOutContext.getAlpha();          
+          oocNodeType  = hrnCallerAndOutContext.getType();
+          oocReach     = hrnCallerAndOutContext.getAlpha(); 
+          oocPredSrcID = hrnCallerAndOutContext.getID();
         }        
 
+        // if we're here we've found an out-of-context edge
+
+        ExistPred pred =
+          ExistPred.factory( oocPredSrcTemp, 
+                             oocPredSrcID, 
+                             hrnID,
+                             edgeMightCross.getType(),
+                             edgeMightCross.getField(),
+                             null,
+                             true ); // out-of-context
+
+        ExistPredSet preds = 
+          ExistPredSet.factory( pred );
+
 
         HeapRegionNode hrnCalleeAndInContext = 
           rg.id2hrn.get( hrnCallerAndInContext.getID() );
@@ -1528,7 +1549,7 @@ public class ReachGraph {
                                           null,  // alloc site, shouldn't be used
                                           /*toShadowTokens( this,*/ oocReach  /*)*/, // inherent
                                           /*toShadowTokens( this,*/ oocReach /*)*/, // alpha
-                                          predsEmpty,
+                                          preds,
                                           "out-of-context"
                                           );       
 
@@ -1545,7 +1566,7 @@ public class ReachGraph {
                                           null,  // alloc site, shouldn't be used
                                           /*toShadowTokens( this,*/ oocReach  /*)*/, // inherent
                                           /*toShadowTokens( this,*/ oocReach /*)*/, // alpha
-                                          predsEmpty,
+                                          preds,
                                           "out-of-context"
                                           );       
           }
@@ -1557,7 +1578,7 @@ public class ReachGraph {
                                       edgeMightCross.getType(),
                                       edgeMightCross.getField(),
                                       /*toShadowTokens( this,*/ edgeMightCross.getBeta() /*)*/,
-                                      predsEmpty
+                                      preds
                                       )
                          );              
 
@@ -1785,19 +1806,35 @@ public class ReachGraph {
     }
 
 
-    // 3.b) callee -> callee edges
+    // 3.b) callee -> callee edges AND out-of-context -> callee
     satisItr = calleeEdgesSatisfied.entrySet().iterator();
     while( satisItr.hasNext() ) {
       Map.Entry    me       = (Map.Entry)    satisItr.next();
       RefEdge      reCallee = (RefEdge)      me.getKey();
       ExistPredSet preds    = (ExistPredSet) me.getValue();
 
-      RefSrcNode rsnCallee = reCallee.getSrc();
-      RefSrcNode rsnCaller;
+      RefSrcNode     rsnCallee    = reCallee.getSrc();
+      HeapRegionNode hrnDstCallee = reCallee.getDst();
+
+      // even though we don't know yet what we're doing with
+      // this edge, do this translation from callee dst to
+      // caller dst a little early so we can use the result
+      // for out-of-context matching below
+      AllocSite asDst = 
+        hrnDstCallee.getAllocSite();
+      Integer hrnIDDstShadow = 
+        asDst.getShadowIDfromID( hrnDstCallee.getID() );
+      HeapRegionNode hrnDstCaller = 
+        id2hrn.get( hrnIDDstShadow );
+
+      // we'll find the set of sources in the caller that
+      // this callee source could be (out-of-context node
+      // can potentially map to multiple caller nodes)
+      Set<RefSrcNode> rsnCallers = new HashSet<RefSrcNode>();
 
       if( rsnCallee instanceof VariableNode ) {          
-        continue;
-        /*
+        // variable -> node in the callee should only
+        // come into the caller if its from a param var
         VariableNode   vnCallee = (VariableNode) rsnCallee;
         TempDescriptor tdParam  = vnCallee.getTempDescriptor();
         TempDescriptor tdArg    = fc.getArgMatchingParam( fm,
@@ -1807,75 +1844,107 @@ public class ReachGraph {
           // to the callee so we ignore it in call site transfer
           continue;
         }
-        
-        System.out.println( "going with "+tdParam+" to "+tdArg );
 
-        rsnCaller = this.getVariableNodeFromTemp( tdArg );
-        */
+        rsnCallers.add( this.getVariableNodeFromTemp( tdArg ) );
+        
       } else {
         HeapRegionNode hrnSrcCallee = (HeapRegionNode) reCallee.getSrc();
+        
+        if( !hrnSrcCallee.isOutOfContext() ) {
+          AllocSite asSrc = hrnSrcCallee.getAllocSite();
+          allocSites.add( asSrc );
+          
+          Integer hrnIDSrcShadow = asSrc.getShadowIDfromID( hrnSrcCallee.getID() );
+          rsnCallers.add( id2hrn.get( hrnIDSrcShadow ) );
 
-        AllocSite asSrc = hrnSrcCallee.getAllocSite();
-        allocSites.add( asSrc );
-
-        Integer hrnIDSrcShadow = asSrc.getShadowIDfromID( hrnSrcCallee.getID() );
-        rsnCaller = id2hrn.get( hrnIDSrcShadow );
+        } else {
+          // for out-of-context sources we have to find all
+          // caller sources that might match
+          assert hrnDstCaller != null;
+          
+          Iterator<RefEdge> reItr = hrnDstCaller.iteratorToReferencers();
+          while( reItr.hasNext() ) {
+            // the edge and field (either possibly null) must match
+            RefEdge reCaller = reItr.next();
+            if( !reCaller.typeEquals ( reCallee.getType()  ) ||
+                !reCaller.fieldEquals( reCallee.getField() ) 
+                ) {
+              continue;
+            }
+
+            RefSrcNode rsnCaller = reCaller.getSrc();
+            if( rsnCaller instanceof VariableNode ) {
+              // a variable node matches an OOC region with null type
+              if( hrnSrcCallee.getType() != null ) {
+                continue;
+              }
+
+            } else {
+              // otherwise types should match
+              HeapRegionNode hrnCallerSrc = (HeapRegionNode) rsnCaller;
+              if( !hrnSrcCallee.getType().equals( hrnCallerSrc.getType() ) ) {
+                continue;
+              }
+            }
+
+            // it matches, add to sources of edges to make
+            rsnCallers.add( rsnCaller );
+          }
+        }
       }
       
-      assert rsnCaller != null;
-      
-      HeapRegionNode hrnDstCallee = reCallee.getDst();
+      assert !rsnCallers.isEmpty();
 
-      AllocSite asDst = hrnDstCallee.getAllocSite();
       allocSites.add( asDst );
 
-      Integer hrnIDDstShadow = asDst.getShadowIDfromID( hrnDstCallee.getID() );
-
-      HeapRegionNode hrnDstCaller = id2hrn.get( hrnIDDstShadow );
       assert hrnDstCaller != null;
       
-      // TODO: beta rewrites
-      RefEdge reCaller = new RefEdge( rsnCaller,
-                                      hrnDstCaller,
-                                      reCallee.getType(),
-                                      reCallee.getField(),
-                                      rsetEmpty,
-                                      preds
-                                      );
-
-      // look to see if an edge with same field exists
-      // and merge with it, otherwise just add the edge
-      RefEdge edgeExisting = rsnCaller.getReferenceTo( hrnDstCaller, 
-                                                       reCallee.getType(),
-                                                       reCallee.getField()
-                                                       );      
-      if( edgeExisting != null ) {
-        edgeExisting.setBeta(
-                             Canonical.union( edgeExisting.getBeta(),
-                                              reCaller.getBeta()
-                                              )
-                             );
-        edgeExisting.setPreds(
-                              Canonical.join( edgeExisting.getPreds(),
-                                              reCaller.getPreds()
-                                              )
-                              );
-       
-      } else {                   
-        addRefEdge( rsnCaller, hrnDstCaller, reCaller );       
+      Iterator<RefSrcNode> rsnItr = rsnCallers.iterator();
+      while( rsnItr.hasNext() ) {
+        RefSrcNode rsnCaller = rsnItr.next();
+
+        // TODO: beta rewrites
+        RefEdge reCaller = new RefEdge( rsnCaller,
+                                        hrnDstCaller,
+                                        reCallee.getType(),
+                                        reCallee.getField(),
+                                        rsetEmpty,
+                                        preds
+                                        );
+
+        // look to see if an edge with same field exists
+        // and merge with it, otherwise just add the edge
+        RefEdge edgeExisting = rsnCaller.getReferenceTo( hrnDstCaller, 
+                                                         reCallee.getType(),
+                                                         reCallee.getField()
+                                                         );    
+        if( edgeExisting != null ) {
+          edgeExisting.setBeta(
+                               Canonical.union( edgeExisting.getBeta(),
+                                                reCaller.getBeta()
+                                                )
+                               );
+          edgeExisting.setPreds(
+                                Canonical.join( edgeExisting.getPreds(),
+                                                reCaller.getPreds()
+                                                )
+                                );
+          
+        } else {                         
+          addRefEdge( rsnCaller, hrnDstCaller, reCaller );     
+        }
       }
-      
     }
 
 
+    /*
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller33BeforeResolveOutOfContextEdges", 
                     true, false, false, false, true, true );
       } catch( IOException e ) {}
     }
-
-    // 3.c) resolve out-of-context -> callee edges
+    */
 
 
 
index da84da304be3b29417edac8bf07174d307d960fa..19e73f4ea1445707ef316de137715747d3c875ba 100644 (file)
@@ -12,6 +12,7 @@ public class Test {
   static public void main( String[] args ) {
 
     Foo f1 = new Foo();
+    Foo extraVar = f1;
     addSomething( f1 );
     
     Foo f2 = new Foo();