successfully keep def reach info just for the store transform
[IRC.git] / Robust / src / Analysis / Disjoint / DisjointAnalysis.java
index 0617600c721f9abbfdc13c46e6cabd116ccb2bb0..4b9b4f0dc79e2e1160701da4ca25a89e69c8fda2 100644 (file)
@@ -412,6 +412,9 @@ public class DisjointAnalysis implements HeapAnalysis {
   protected EffectsAnalysis effectsAnalysis;
   protected BuildStateMachines buildStateMachines;
 
+  protected boolean doDefiniteReachAnalysis = false;
+  protected DefiniteReachAnalysis definiteReachAnalysis;
+
 
   // data structure for public interface
   private Hashtable< Descriptor, HashSet<AllocSite> >
@@ -723,8 +726,6 @@ public class DisjointAnalysis implements HeapAnalysis {
     mapDescriptorToReachGraph =
       new Hashtable<Descriptor, ReachGraph>();
 
-    pm = new PointerMethod();
-
     fc2enclosing = new Hashtable<FlatCall, Descriptor>();
   }
 
@@ -846,6 +847,12 @@ public class DisjointAnalysis implements HeapAnalysis {
     ReachGraph.debugCallSiteVisitCounter
       = 0; // count visits from 1, is incremented before first visit    
 
+    pm = new PointerMethod();
+
+    if( state.DO_DEFINITE_REACH_ANALYSIS ) {
+      doDefiniteReachAnalysis = true;
+      definiteReachAnalysis = new DefiniteReachAnalysis( pm );
+    }
 
 
     if( suppressOutput ) {
@@ -1295,12 +1302,20 @@ public class DisjointAnalysis implements HeapAnalysis {
     FlatSESEEnterNode sese;
     FlatSESEExitNode fsexn;
 
+    Set<EdgeKey> edgeKeysForLoad;
+    Set<EdgeKey> edgeKeysRemoved;
+    Set<EdgeKey> edgeKeysAdded;
+
     //Stores the flatnode's reach graph at enter
     ReachGraph rgOnEnter = new ReachGraph();
     rgOnEnter.merge(rg);
     fn2rgAtEnter.put(fn, rgOnEnter);
 
 
+    
+    boolean didDefReachTransfer = false;    
+
+
 
     // use node type to decide what transfer function
     // to apply to the reachability graph
@@ -1314,15 +1329,23 @@ public class DisjointAnalysis implements HeapAnalysis {
 
       rg.writeGraph("genReach"+fgrn.getGraphName(),
                     true,     // write labels (variables)
-                    false, //true,    // selectively hide intermediate temp vars
+                    true,    // selectively hide intermediate temp vars
                     true,     // prune unreachable heap regions
-                    true,    // hide reachability altogether
+                    false,    // hide reachability altogether
                     true,    // hide subset reachability states
                     true,     // hide predicates
                     true); //false);    // hide edge taints
     } break;
 
 
+    case FKind.FlatGenDefReachNode: {
+      FlatGenDefReachNode fgdrn = (FlatGenDefReachNode) fn;
+      if( doDefiniteReachAnalysis ) {
+        definiteReachAnalysis.writeState( fn, fgdrn.getOutputName() );
+      }
+    } break;
+
+
     case FKind.FlatMethod: {
       // construct this method's initial heap model (IHM)
       // since we're working on the FlatMethod, we know
@@ -1353,6 +1376,15 @@ public class DisjointAnalysis implements HeapAnalysis {
       rg.merge(rgPrevContext);
       mapDescriptorToInitialContext.put(d, rg);
 
+      if( doDefiniteReachAnalysis ) {
+        FlatMethod fm = (FlatMethod) fn;
+        Set<TempDescriptor> params = new HashSet<TempDescriptor>();
+        for( int i = 0; i < fm.numParameters(); ++i ) {
+          params.add( fm.getParameter( i ) );
+        }
+        definiteReachAnalysis.methodEntry( fn, params );
+        didDefReachTransfer = true;
+      }
     } break;
 
     case FKind.FlatOpNode:
@@ -1373,6 +1405,11 @@ public class DisjointAnalysis implements HeapAnalysis {
 
         // transfer func
         rg.assignTempXEqualToTempY(lhs, rhs);
+
+        if( doDefiniteReachAnalysis ) {
+          definiteReachAnalysis.copy( fn, lhs, rhs );
+          didDefReachTransfer = true;
+        }
       }
       break;
 
@@ -1396,6 +1433,11 @@ public class DisjointAnalysis implements HeapAnalysis {
 
       // transfer func
       rg.assignTempXEqualToCastedTempY(lhs, rhs, td);
+
+      if( doDefiniteReachAnalysis ) {
+        definiteReachAnalysis.copy( fn, lhs, rhs );
+        didDefReachTransfer = true;
+      }
       break;
 
     case FKind.FlatFieldNode:
@@ -1422,9 +1464,19 @@ public class DisjointAnalysis implements HeapAnalysis {
         }
       }
 
+      edgeKeysForLoad = null;
+      if( doDefiniteReachAnalysis ) {
+        edgeKeysForLoad = new HashSet<EdgeKey>();
+      }
+
       if( shouldAnalysisTrack(fld.getType() ) ) {
         // transfer func
-        rg.assignTempXEqualToTempYFieldF(lhs, rhs, fld, fn);
+        rg.assignTempXEqualToTempYFieldF( lhs, rhs, fld, fn, edgeKeysForLoad );
+
+        if( doDefiniteReachAnalysis ) {
+          definiteReachAnalysis.load( fn, lhs, rhs, fld, edgeKeysForLoad );
+          didDefReachTransfer = true;
+        }
       }
 
       // after transfer, use updated graph to
@@ -1443,6 +1495,13 @@ public class DisjointAnalysis implements HeapAnalysis {
 
       boolean strongUpdate = false;
 
+      edgeKeysRemoved = null;
+      edgeKeysAdded   = null;
+      if( doDefiniteReachAnalysis ) {
+        edgeKeysRemoved = new HashSet<EdgeKey>();
+        edgeKeysAdded   = new HashSet<EdgeKey>();
+      }
+
       // before transfer func, possibly inject
       // stall-site taints
       if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
@@ -1466,7 +1525,21 @@ public class DisjointAnalysis implements HeapAnalysis {
 
       if( shouldAnalysisTrack(fld.getType() ) ) {
         // transfer func
-        strongUpdate = rg.assignTempXFieldFEqualToTempY(lhs, fld, rhs, fn);
+        strongUpdate = rg.assignTempXFieldFEqualToTempY( lhs, 
+                                                         fld, 
+                                                         rhs, 
+                                                         fn, 
+                                                         edgeKeysRemoved,
+                                                         edgeKeysAdded );
+        if( doDefiniteReachAnalysis ) {
+          definiteReachAnalysis.store( fn, 
+                                       lhs,
+                                       fld,
+                                       rhs,
+                                       edgeKeysRemoved,
+                                       edgeKeysAdded );
+          didDefReachTransfer = true;
+        }
       }
 
       // use transformed graph to do effects analysis
@@ -1503,9 +1576,19 @@ public class DisjointAnalysis implements HeapAnalysis {
         }
       }
 
+      edgeKeysForLoad = null;
+      if( doDefiniteReachAnalysis ) {
+        edgeKeysForLoad = new HashSet<EdgeKey>();
+      }
+
       if( shouldAnalysisTrack(lhs.getType() ) ) {
         // transfer func
-        rg.assignTempXEqualToTempYFieldF(lhs, rhs, fdElement, fn);
+        rg.assignTempXEqualToTempYFieldF( lhs, rhs, fdElement, fn, edgeKeysForLoad );
+
+        if( doDefiniteReachAnalysis ) {
+          definiteReachAnalysis.load( fn, lhs, rhs, fdElement, edgeKeysForLoad );
+          didDefReachTransfer = true;
+        }
       }
 
       // use transformed graph to do effects analysis
@@ -1519,13 +1602,20 @@ public class DisjointAnalysis implements HeapAnalysis {
 
       lhs = fsen.getDst();
       rhs = fsen.getSrc();
-
+      
       assert lhs.getType() != null;
       assert lhs.getType().isArray();
 
       tdElement = lhs.getType().dereference();
       fdElement = getArrayField(tdElement);
 
+      edgeKeysRemoved = null;
+      edgeKeysAdded   = null;
+      if( doDefiniteReachAnalysis ) {
+        edgeKeysRemoved = new HashSet<EdgeKey>();
+        edgeKeysAdded   = new HashSet<EdgeKey>();
+      }
+
       // before transfer func, possibly inject
       // stall-site taints
       if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
@@ -1551,7 +1641,22 @@ public class DisjointAnalysis implements HeapAnalysis {
         // transfer func, BUT
         // skip this node if it cannot create new reachability paths
         if( !arrayReferencees.doesNotCreateNewReaching(fsen) ) {
-          rg.assignTempXFieldFEqualToTempY(lhs, fdElement, rhs, fn);
+          rg.assignTempXFieldFEqualToTempY( lhs, 
+                                            fdElement, 
+                                            rhs, 
+                                            fn, 
+                                            edgeKeysRemoved,
+                                            edgeKeysAdded );
+        }
+
+        if( doDefiniteReachAnalysis ) {
+          definiteReachAnalysis.store( fn,
+                                       lhs,
+                                       fdElement, 
+                                       rhs, 
+                                       edgeKeysRemoved,
+                                       edgeKeysAdded );
+          didDefReachTransfer = true;
         }
       }
 
@@ -1578,6 +1683,11 @@ public class DisjointAnalysis implements HeapAnalysis {
 
         // transfer func
         rg.assignTempEqualToNewAlloc(lhs, as);
+
+        if( doDefiniteReachAnalysis ) {
+          definiteReachAnalysis.newObject( fn, lhs );
+          didDefReachTransfer = true;
+        }
       }
       break;
 
@@ -1643,11 +1753,10 @@ public class DisjointAnalysis implements HeapAnalysis {
       FlatMethod fmCallee = state.getMethodFlat(mdCallee);
 
 
-
-
-
-
-
+      if( doDefiniteReachAnalysis ) {
+        definiteReachAnalysis.methodCall( fn, fc.getReturnTemp() );
+        didDefReachTransfer = true;
+      }
 
       
       // the transformation for a call site should update the
@@ -1706,6 +1815,7 @@ public class DisjointAnalysis implements HeapAnalysis {
         Set<Integer> callerNodeIDsCopiedToCallee =
           new HashSet<Integer>();
 
+
         ReachGraph heapForThisCall_cur =
           rg.makeCalleeView(fc,
                             fmPossible,
@@ -1713,6 +1823,7 @@ public class DisjointAnalysis implements HeapAnalysis {
                             dcsd.writeDebugDOTs
                             );
 
+
         // enforce that a call site contribution can only
         // monotonically increase
         heapForThisCall_cur.merge(heapForThisCall_old);
@@ -1727,7 +1838,7 @@ public class DisjointAnalysis implements HeapAnalysis {
           fc2enclosing.put(fc, mdCaller);
 
           if( state.DISJOINTDEBUGSCHEDULING ) {
-            System.out.println("  context changed, scheduling callee: "+mdPossible);
+            System.out.println("  context changed at callsite: "+fc+", scheduling callee: "+mdPossible);
           }
 
           if( state.DISJOINTDVISITSTACKEESONTOP ) {
@@ -1785,9 +1896,11 @@ public class DisjointAnalysis implements HeapAnalysis {
       }
       
 
+
       statusDebugCallSite( dcsd );
 
 
+
       // now that we've taken care of building heap models for
       // callee analysis, finish this transformation
       rg = rgMergeOfPossibleCallers;
@@ -1831,6 +1944,13 @@ public class DisjointAnalysis implements HeapAnalysis {
     } // end switch
 
 
+
+    if( doDefiniteReachAnalysis && !didDefReachTransfer ) {
+      definiteReachAnalysis.otherStatement( fn );
+    }
+
+
+
     // dead variables were removed before the above transfer function
     // was applied, so eliminate heap regions and edges that are no
     // longer part of the abstractly-live heap graph, and sweep up
@@ -1852,6 +1972,7 @@ public class DisjointAnalysis implements HeapAnalysis {
     fn2rgAtExit.put(fn, rgOnExit);
 
 
+
     // at this point rg should be the correct update
     // by an above transfer function, or untouched if
     // the flat node type doesn't affect the heap
@@ -2365,7 +2486,13 @@ public class DisjointAnalysis implements HeapAnalysis {
     Hashtable<FlatCall, ReachGraph> heapsFromCallers =
       getIHMcontributions(d);
 
-    heapsFromCallers.put(fc, rg);
+    // ensure inputs to initial contexts increase monotonically
+    ReachGraph merged = new ReachGraph();
+    merged.merge( rg );
+    merged.merge( heapsFromCallers.get( fc ) );
+
+    heapsFromCallers.put( fc, merged );
+    
   }
 
 
@@ -2916,12 +3043,25 @@ public class DisjointAnalysis implements HeapAnalysis {
         state.DISJOINTDEBUGCALLER.equals( taskOrMethodCaller.getSymbol() );
     }
 
+
     dcsd.debugCallSite = debugCalleeMatches && debugCallerMatches;
-    dcsd.writeDebugDOTs = dcsd.debugCallSite;
+
+
+    dcsd.writeDebugDOTs = 
+      
+      dcsd.debugCallSite &&
+
+      (ReachGraph.debugCallSiteVisitCounter >=
+       ReachGraph.debugCallSiteVisitStartCapture)  &&
+         
+      (ReachGraph.debugCallSiteVisitCounter <
+       ReachGraph.debugCallSiteVisitStartCapture +
+       ReachGraph.debugCallSiteNumVisitsToCapture);
+         
+
 
     if( dcsd.debugCallSite ) {
       dcsd.didOneDebug = true;
-      System.out.println( "       --> Debugging "+taskOrMethodCaller+" calling "+mdCallee );
     }
   }
 
@@ -2931,7 +3071,6 @@ public class DisjointAnalysis implements HeapAnalysis {
     dcsd.stopAfter      = false;
 
     if( dcsd.didOneDebug ) {
-      ++ReachGraph.debugCallSiteVisitCounter;
       System.out.println("    $$$ Debug call site visit "+
                          ReachGraph.debugCallSiteVisitCounter+
                          " $$$"
@@ -2954,6 +3093,8 @@ public class DisjointAnalysis implements HeapAnalysis {
           dcsd.stopAfter = true;
         }
       }
+
+      ++ReachGraph.debugCallSiteVisitCounter;
     }
 
     if( dcsd.stopAfter ) {
@@ -3008,7 +3149,7 @@ public class DisjointAnalysis implements HeapAnalysis {
                     true,    // selectively hide intermediate temp vars
                     true,    // prune unreachable heap regions
                     false,   // hide reachability
-                    false,   // hide subset reachability states
+                    true,   // hide subset reachability states
                     true,    // hide predicates
                     true);   // hide edge taints
     }