most of the missing context-rewriting code
authorjjenista <jjenista>
Mon, 15 Mar 2010 19:55:17 +0000 (19:55 +0000)
committerjjenista <jjenista>
Mon, 15 Mar 2010 19:55:17 +0000 (19:55 +0000)
Robust/src/Analysis/Disjoint/Canonical.java
Robust/src/Analysis/Disjoint/CanonicalOp.java
Robust/src/Analysis/Disjoint/ReachGraph.java
Robust/src/Tests/disjoint/predicateTest3/test.java

index 7c913fbc0dd28696d4083e8400f67138b8f9d7b1..23c39bb630f1bf8f3e7d7dacb22af131b40a4740 100644 (file)
@@ -942,6 +942,290 @@ abstract public class Canonical {
     op2result.put( op, out );
     return out;
   }
-  
+
+
+  public static ReachSet toCallerContext( ReachSet  rs,
+                                          AllocSite as ) {
+    assert rs != null;
+    assert as != null;
+    assert rs.isCanonical();
+    assert as.isCanonical();
+
+    CanonicalOp op = 
+      new CanonicalOp( CanonicalOp.REACHSET_TOCALLERCONTEXT_ALLOCSITE,
+                       rs, 
+                       as );
+    
+    Canonical result = op2result.get( op );
+    if( result != null ) {
+      return (ReachSet) result;
+    }
+
+    // otherwise, no cached result...
+    ReachSet out = ReachSet.factory();
+    Iterator<ReachState> itr = rs.iterator();
+    while( itr.hasNext() ) {
+      ReachState state = itr.next();
+      out = Canonical.union( out,
+                             Canonical.toCallerContext( state, as )
+                             );
+    }
+
+    assert out.isCanonical();
+    op2result.put( op, out );
+    return out;
+  }
+
+  public static ReachSet toCallerContext( ReachState state,
+                                          AllocSite  as ) {
+    assert state != null;
+    assert as    != null;
+    assert state.isCanonical();
+    assert as.isCanonical();
+
+    CanonicalOp op = 
+      new CanonicalOp( CanonicalOp.REACHSTATE_TOCALLERCONTEXT_ALLOCSITE,
+                       state, 
+                       as );
+    
+    Canonical result = op2result.get( op );
+    if( result != null ) {
+      return (ReachSet) result;
+    }
+
+    // otherwise, no cached result...
+    ReachSet out = ReachSet.factory();
+
+    // this method returns a ReachSet instead of a ReachState
+    // because the companion method, toCallee, translates
+    // symbols many-to-one, so state->state
+    // but this method does an ~inverse mapping, one-to-many
+    // so one state can split into a set of branched states
+
+    // 0    -> -0
+    // 1    -> -1
+    // 2S   -> -2S
+    // 2S*  -> -2S*
+    //
+    // 0?   -> 0
+    // 1?   -> 1
+    // 2S?  -> 2S
+    //      -> 0?
+    //      -> 1?
+    //      -> 2S?
+    // 2S?* -> {2S*, 2S?*}    
+
+    boolean found2Sooc = false;
+
+    ReachState baseState = ReachState.factory();
+
+    Iterator<ReachTuple> itr = state.iterator();
+    while( itr.hasNext() ) {
+      ReachTuple rt = itr.next();
+
+      int age = as.getAgeCategory( rt.getHrnID() );
+
+      if( age == AllocSite.AGE_notInThisSite ) {
+        // things not from the site just go back in
+       baseState = Canonical.union( baseState, rt );
+
+      } else if( age == AllocSite.AGE_summary ) {
+
+        if( rt.isOutOfContext() ) {
+          // if its out-of-context, we only deal here with the ZERO-OR-MORE
+          // arity, if ARITY-ONE we'll branch the base state after the loop
+          if( rt.getArity() == ReachTuple.ARITY_ZEROORMORE ) {
+            // add two overly conservative symbols to reach state (PUNTING)
+            baseState = Canonical.union( baseState,
+                                         ReachTuple.factory( as.getSummary(),
+                                                             true, // multi
+                                                             ReachTuple.ARITY_ZEROORMORE,
+                                                             false // out-of-context
+                                                             )
+                                         );            
+            baseState = Canonical.union( baseState,
+                                         ReachTuple.factory( as.getSummary(),
+                                                             true, // multi
+                                                             ReachTuple.ARITY_ZEROORMORE,
+                                                             true  // out-of-context
+                                                             )
+                                         );            
+          } else {
+            assert rt.getArity() == ReachTuple.ARITY_ONE;
+            found2Sooc = true;
+          }
+
+        } else {
+          // the in-context just becomes shadow
+          baseState = Canonical.union( baseState,
+                                       ReachTuple.factory( as.getSummaryShadow(),
+                                                           true, // multi
+                                                           rt.getArity(),
+                                                           false  // out-of-context
+                                                           )
+                                       );
+        }
+
+      } else {
+        // otherwise the ith symbol becomes shadowed
+       Integer I = as.getAge( rt.getHrnID() );
+       assert I != null;
+        
+        assert !rt.isMultiObject();
+
+        baseState = Canonical.union( baseState,
+                                     ReachTuple.factory( -rt.getHrnID(),
+                                                         false, // multi
+                                                         rt.getArity(),
+                                                         false  // out-of-context
+                                                         )
+                                     );        
+      }
+    }
+
+    // now either make branches if we have 2S?, or
+    // the current baseState is the only state we need
+    if( found2Sooc ) {
+      // make a branch with every possibility of the one-to-many
+      // mapping for 2S? appended to the baseState
+      out = Canonical.union( out,
+                             Canonical.union( baseState,
+                                              ReachTuple.factory( as.getSummary(),
+                                                                  true, // multi
+                                                                  ReachTuple.ARITY_ONE,
+                                                                  false  // out-of-context
+                                                                  )
+                                              )
+                             );
+
+      out = Canonical.union( out,
+                             Canonical.union( baseState,
+                                              ReachTuple.factory( as.getSummary(),
+                                                                  true, // multi
+                                                                  ReachTuple.ARITY_ONE,
+                                                                  true  // out-of-context
+                                                                  )
+                                              )
+                             );      
+
+      for( int i = 0; i < as.getAllocationDepth(); ++i ) {
+        out = Canonical.union( out,
+                               Canonical.union( baseState,
+                                                ReachTuple.factory( as.getIthOldest( i ),
+                                                                    false, // multi
+                                                                    ReachTuple.ARITY_ONE,
+                                                                    true  // out-of-context
+                                                                    )
+                                                )
+                               );
+      }
+
+    } else {
+      // just use current baseState      
+      out = Canonical.union( out,
+                             baseState );
+    }
+
+
+    assert out.isCanonical();
+    op2result.put( op, out );
+    return out;
+  }
+
+
+
+
+
+
+
+
+
+  public static ReachSet unshadow( ReachSet  rs,
+                                   AllocSite as ) {
+    assert rs != null;
+    assert as != null;
+    assert rs.isCanonical();
+    assert as.isCanonical();
+
+    CanonicalOp op = 
+      new CanonicalOp( CanonicalOp.REACHSET_UNSHADOW_ALLOCSITE,
+                       rs, 
+                       as );
+    
+    Canonical result = op2result.get( op );
+    if( result != null ) {
+      return (ReachSet) result;
+    }
+
+    // otherwise, no cached result...
+    ReachSet out = ReachSet.factory();
+    Iterator<ReachState> itr = rs.iterator();
+    while( itr.hasNext() ) {
+      ReachState state = itr.next();
+      out = Canonical.add( out,
+                           Canonical.unshadow( state, as )
+                           );
+    }
+
+    assert out.isCanonical();
+    op2result.put( op, out );
+    return out;
+  }
+
+  public static ReachState unshadow( ReachState state,
+                                     AllocSite  as ) {
+    assert state != null;
+    assert as    != null;
+    assert state.isCanonical();
+    assert as.isCanonical();
+
+    CanonicalOp op = 
+      new CanonicalOp( CanonicalOp.REACHSTATE_UNSHADOW_ALLOCSITE,
+                       state, 
+                       as );
+    
+    Canonical result = op2result.get( op );
+    if( result != null ) {
+      return (ReachState) result;
+    }
+
+    // this is the current mapping, where 0, 1, 2S were allocated
+    // in the current context, 0?, 1? and 2S? were allocated in a
+    // previous context, and we're translating to a future context
+    //
+    // -0   -> 0
+    // -1   -> 1
+    // -2S  -> 2S
+    
+    // otherwise, no cached result...
+    ReachState out = ReachState.factory();
+    Iterator<ReachTuple> itr = state.iterator();
+    while( itr.hasNext() ) {
+      ReachTuple rt = itr.next();
+
+      int age = as.getShadowAgeCategory( rt.getHrnID() );
+      
+      if( age == AllocSite.SHADOWAGE_notInThisSite ) {
+        // things not from the site just go back in
+       out = Canonical.union( out, rt );
+
+      } else {
+        assert !rt.isOutOfContext();
+
+        // otherwise unshadow it
+        out = Canonical.union( out,
+                               ReachTuple.factory( -rt.getHrnID(),
+                                                   rt.isMultiObject(),
+                                                   rt.getArity(),
+                                                   false
+                                                   )
+                               );
+      }
+    }
+
+    assert out.isCanonical();
+    op2result.put( op, out );
+    return out;
+  }
 
 }
index b9e8a1558f6dc3f486ba4f78c39c92b11b7b33a0..7f5dd6cf208bdb2b95da28fb3e3a6cb6dd71013b 100644 (file)
@@ -8,27 +8,31 @@ package Analysis.Disjoint;
 // first and do a result look-up
 public class CanonicalOp {
 
-  public static final int REACHTUPLE_UNIONARITY_REACHTUPLE   = 0x1a34;
-  public static final int REACHSTATE_UNION_REACHSTATE        = 0x5678;
-  public static final int REACHSTATE_UNION_REACHTUPLE        = 0x32b6;
-  public static final int REACHSTATE_UNIONUPARITY_REACHSTATE = 0x9152;
-  public static final int REACHSTATE_REMOVE_REACHTUPLE       = 0x8173;
-  public static final int REACHSTATE_AGETUPLESFROM_ALLOCSITE = 0x4f65;
-  public static final int REACHSET_UNION_REACHSET            = 0x2131;
-  public static final int REACHSET_UNION_REACHSTATE          = 0xe3c8;
-  public static final int REACHSET_INTERSECTION_REACHSET     = 0x3361;
-  public static final int REACHSET_REMOVE_REACHSTATE         = 0x9391;
-  public static final int REACHSET_APPLY_CHANGESET           = 0x1d55;
-  public static final int REACHSET_UNIONTOCHANGESET_REACHSET = 0x46a9;
-  public static final int REACHSET_AGETUPLESFROM_ALLOCSITE   = 0x22bb;
-  public static final int REACHSET_PRUNEBY_REACHSET          = 0xd774;
-  public static final int CHANGESET_UNION_CHANGESET          = 0x53b3;
-  public static final int CHANGESET_UNION_CHANGETUPLE        = 0x9ee4;
-  public static final int EXISTPREDSET_JOIN_EXISTPREDSET     = 0x8a21;
-  public static final int EXISTPREDSET_ADD_EXISTPRED         = 0xba5f;
-  public static final int PRIM_OP_UNUSED                     = 0xef01;
-  public static final int REACHSET_TOCALLEECONTEXT_ALLOCSITE = 0x56f6;
+  public static final int REACHTUPLE_UNIONARITY_REACHTUPLE     = 0x1a34;
+  public static final int REACHSTATE_UNION_REACHSTATE          = 0x5678;
+  public static final int REACHSTATE_UNION_REACHTUPLE          = 0x32b6;
+  public static final int REACHSTATE_UNIONUPARITY_REACHSTATE   = 0x9152;
+  public static final int REACHSTATE_REMOVE_REACHTUPLE         = 0x8173;
+  public static final int REACHSTATE_AGETUPLESFROM_ALLOCSITE   = 0x4f65;
+  public static final int REACHSET_UNION_REACHSET              = 0x2131;
+  public static final int REACHSET_UNION_REACHSTATE            = 0xe3c8;
+  public static final int REACHSET_INTERSECTION_REACHSET       = 0x3361;
+  public static final int REACHSET_REMOVE_REACHSTATE           = 0x9391;
+  public static final int REACHSET_APPLY_CHANGESET             = 0x1d55;
+  public static final int REACHSET_UNIONTOCHANGESET_REACHSET   = 0x46a9;
+  public static final int REACHSET_AGETUPLESFROM_ALLOCSITE     = 0x22bb;
+  public static final int REACHSET_PRUNEBY_REACHSET            = 0xd774;
+  public static final int CHANGESET_UNION_CHANGESET            = 0x53b3;
+  public static final int CHANGESET_UNION_CHANGETUPLE          = 0x9ee4;
+  public static final int EXISTPREDSET_JOIN_EXISTPREDSET       = 0x8a21;
+  public static final int EXISTPREDSET_ADD_EXISTPRED           = 0xba5f;
+  public static final int PRIM_OP_UNUSED                       = 0xef01;
+  public static final int REACHSET_TOCALLEECONTEXT_ALLOCSITE   = 0x56f6;
   public static final int REACHSTATE_TOCALLEECONTEXT_ALLOCSITE = 0x7faf;
+  public static final int REACHSET_TOCALLERCONTEXT_ALLOCSITE   = 0x2f6a;
+  public static final int REACHSTATE_TOCALLERCONTEXT_ALLOCSITE = 0xb2b1;
+  public static final int REACHSET_UNSHADOW_ALLOCSITE          = 0x1049;
+  public static final int REACHSTATE_UNSHADOW_ALLOCSITE        = 0x08ef;
 
   protected int opCode;
   protected Canonical operand1;
index ff811bc41268ea246d8d182230f690e10aa171b6..c8a63bf03994ff02662ed54c936a018b01273158 100644 (file)
@@ -1291,6 +1291,32 @@ public class ReachGraph {
     return out;
   }
 
+  // used below to convert a ReachSet to its caller-context
+  // equivalent with respect to allocation sites in this graph
+  protected ReachSet toCallerContext( ReachSet rs ) {
+    ReachSet out = rs;
+    Iterator<AllocSite> asItr = allocSites.iterator();
+    while( asItr.hasNext() ) {
+      AllocSite as = asItr.next();
+      out = Canonical.toCallerContext( out, as );
+    }
+    assert out.isCanonical();
+    return out;
+  }
+
+  // used below to convert a ReachSet to an equivalent
+  // version with shadow IDs merged into unshadowed IDs
+  protected ReachSet unshadow( ReachSet rs ) {
+    ReachSet out = rs;
+    Iterator<AllocSite> asItr = allocSites.iterator();
+    while( asItr.hasNext() ) {
+      AllocSite as = asItr.next();
+      out = Canonical.unshadow( out, as );
+    }
+    assert out.isCanonical();
+    return out;
+  }
+
 
   // use this method to make a new reach graph that is
   // what heap the FlatMethod callee from the FlatCall 
@@ -1903,7 +1929,7 @@ public class ReachGraph {
                                    false,                      // out-of-context?
                                    hrnCallee.getType(),        // type                          
                                    hrnCallee.getAllocSite(),   // allocation site                       
-                                   hrnCallee.getInherent(),    // inherent reach
+                                   toCallerContext( hrnCallee.getInherent() ),    // inherent reach
                                    null,                       // current reach                 
                                    predsEmpty,                 // predicates
                                    hrnCallee.getDescription()  // description
@@ -1913,7 +1939,7 @@ public class ReachGraph {
       }
 
       // TODO: alpha should be some rewritten version of callee in caller context
-      hrnCaller.setAlpha( hrnCallee.getAlpha() );
+      hrnCaller.setAlpha( toCallerContext( hrnCallee.getAlpha() ) );
 
       hrnCaller.setPreds( preds );
     }
@@ -1996,8 +2022,8 @@ public class ReachGraph {
                                        false,                         // out-of-context?
                                        hrnSrcCallee.getType(),        // type                           
                                        hrnSrcCallee.getAllocSite(),   // allocation site                        
-                                       hrnSrcCallee.getInherent(),    // inherent reach
-                                       hrnSrcCallee.getAlpha(),       // current reach                 
+                                       toCallerContext( hrnSrcCallee.getInherent() ),    // inherent reach
+                                       toCallerContext( hrnSrcCallee.getAlpha() ),       // current reach                 
                                        predsEmpty,                    // predicates
                                        hrnSrcCallee.getDescription()  // description
                                        );                                        
@@ -2025,7 +2051,7 @@ public class ReachGraph {
                                         hrnDstCaller,
                                         reCallee.getType(),
                                         reCallee.getField(),
-                                        reCallee.getBeta(),
+                                        toCallerContext( reCallee.getBeta() ),
                                         preds
                                         );
         
@@ -2107,8 +2133,8 @@ public class ReachGraph {
                                      false,                         // out-of-context?
                                      hrnDstCallee.getType(),        // type                             
                                      hrnDstCallee.getAllocSite(),   // allocation site                  
-                                     hrnDstCallee.getInherent(),    // inherent reach
-                                     hrnDstCallee.getAlpha(),       // current reach                 
+                                     toCallerContext( hrnDstCallee.getInherent() ),    // inherent reach
+                                     toCallerContext( hrnDstCallee.getAlpha() ),       // current reach                 
                                      predsTrue,                     // predicates
                                      hrnDstCallee.getDescription()  // description
                                      );                                        
@@ -2126,7 +2152,7 @@ public class ReachGraph {
                                         hrnDstCaller,
                                         tdNewEdge,
                                         null,
-                                        reCallee.getBeta(),
+                                        toCallerContext( reCallee.getBeta() ),
                                         predsTrue
                                         );
 
@@ -2233,6 +2259,30 @@ public class ReachGraph {
     }
 
 
+    if( writeDebugDOTs ) {
+      try {
+        writeGraph( "caller45BeforeUnshadow", 
+                    true, false, false, false, true, true );
+      } catch( IOException e ) {}
+    }
+    
+    
+    Iterator itrAllHRNodes = id2hrn.entrySet().iterator();
+    while( itrAllHRNodes.hasNext() ) {
+      Map.Entry      me  = (Map.Entry)      itrAllHRNodes.next();
+      HeapRegionNode hrn = (HeapRegionNode) me.getValue();
+      
+      hrn.setAlpha( unshadow( hrn.getAlpha() ) );
+      
+      Iterator<RefEdge> itrEdges = hrn.iteratorToReferencers();
+      while( itrEdges.hasNext() ) {
+        RefEdge re = itrEdges.next();
+        re.setBeta( unshadow( re.getBeta() ) );
+      }
+    }
+    
+
+
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller50BeforeGlobalSweep", 
index 256cbdda0251134badf3761499abf4fdc4a3fd54..f8b640b95395497aea943fdc1d27e85f440eb060 100644 (file)
@@ -1,40 +1,17 @@
 public class Foo {
   public Foo() {}
   public Foo f;
-  public Bar b;
-}
-
-public class Bar {
-  public Bar() {}
 }
 
 public class Test {
 
   static public void main( String[] args ) {
-
-    Foo f1 = disjoint high1 new Foo();
-    Foo extraVar = f1;
-    addSomething( f1 );
-    
-    Foo f2 = disjoint high2 new Foo();
-    addSomething( f2 );    
-
-
-    Foo f3 = getAFoo();
-    Foo f4 = getAFoo();
-    f3.f = f4;
+    Foo top = disjoint inMain new Foo();
+    addSomething( top );    
   }   
 
-  public static void addSomething( Foo f ) {
-    addBar( f );
-  }
-
-  public static void addBar( Foo g ) {    
-    if( true ) {
-      g.b = disjoint low1 new Bar();
-    } else {
-      g.b = disjoint low2 new Bar();
-    }    
+  public static void addSomething( Foo x ) {
+    x.f = new Foo();
   }
 
   public static Foo getAFoo() {