bug fixes, make stack/Q method-visiting a cmd line arg, some code for debugging monot...
authorjjenista <jjenista>
Tue, 30 Mar 2010 21:31:09 +0000 (21:31 +0000)
committerjjenista <jjenista>
Tue, 30 Mar 2010 21:31:09 +0000 (21:31 +0000)
Robust/src/Analysis/Disjoint/DisjointAnalysis.java
Robust/src/Analysis/Disjoint/PointerMethod.java
Robust/src/Analysis/Disjoint/ReachGraph.java
Robust/src/Analysis/Disjoint/ReachSet.java
Robust/src/Benchmarks/disjoint/makefile
Robust/src/IR/State.java
Robust/src/Main/Main.java

index 8ecc2dfaf462ee5f48e4028379b5dcdde4fcd079..81eeb49602710240b3a7f4cbd3e96f159865b90c 100644 (file)
@@ -360,8 +360,9 @@ public class DisjointAnalysis {
   // current descriptors to visit in fixed-point
   // interprocedural analysis, prioritized by
   // dependency in the call graph
-  protected Stack<DescriptorQWrapper> 
-  //protected PriorityQueue<DescriptorQWrapper> 
+  protected Stack<DescriptorQWrapper>
+    descriptorsToVisitStack;
+  protected PriorityQueue<DescriptorQWrapper> 
     descriptorsToVisitQ;
   
   // a duplication of the above structure, but
@@ -409,7 +410,6 @@ public class DisjointAnalysis {
   protected Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >
     mapDescriptorToIHMcontributions;
 
-  // TODO -- CHANGE EDGE/TYPE/FIELD storage!
   public static final String arrayElementFieldName = "___element_";
   static protected Hashtable<TypeDescriptor, FieldDescriptor>
     mapTypeToArrayField;
@@ -426,11 +426,12 @@ public class DisjointAnalysis {
   
   //map task descriptor to initial task parameter 
   protected Hashtable<Descriptor, ReachGraph>
-  mapDescriptorToReachGraph;
+    mapDescriptorToReachGraph;
 
   protected PointerMethod pm;
 
-  protected Hashtable<FlatMethod, ReachGraph> hackmap;
+  static protected Hashtable<FlatNode, ReachGraph> fn2rg =
+    new Hashtable<FlatNode, ReachGraph>();
 
 
   // allocate various structures that are not local
@@ -459,9 +460,15 @@ public class DisjointAnalysis {
     mapTypeToArrayField = 
       new Hashtable <TypeDescriptor, FieldDescriptor>();
 
-    descriptorsToVisitQ =
-      new Stack<DescriptorQWrapper>();
-    //new PriorityQueue<DescriptorQWrapper>();
+    if( state.DISJOINTDVISITSTACK ) {
+      descriptorsToVisitStack =
+        new Stack<DescriptorQWrapper>();
+    }
+
+    if( state.DISJOINTDVISITPQUE ) {
+      descriptorsToVisitQ =
+        new PriorityQueue<DescriptorQWrapper>();
+    }
 
     descriptorsToVisitSet =
       new HashSet<Descriptor>();
@@ -474,8 +481,6 @@ public class DisjointAnalysis {
     
     mapDescriptorToReachGraph = 
        new Hashtable<Descriptor, ReachGraph>();
-
-    hackmap = new Hashtable<FlatMethod, ReachGraph>();
   }
 
 
@@ -520,6 +525,8 @@ public class DisjointAnalysis {
     this.snapNodeCounter         = 0; // count nodes from 0
     this.pm=new PointerMethod();
 
+    assert state.DISJOINTDVISITSTACK || state.DISJOINTDVISITPQUE;
+    assert !(state.DISJOINTDVISITSTACK && state.DISJOINTDVISITPQUE);
            
     // set some static configuration for ReachGraphs
     ReachGraph.allocationDepth = allocationDepth;
@@ -564,6 +571,18 @@ public class DisjointAnalysis {
   }
 
 
+  protected boolean moreDescriptorsToVisit() {
+    if( state.DISJOINTDVISITSTACK ) {
+      return !descriptorsToVisitStack.isEmpty();
+
+    } else if( state.DISJOINTDVISITPQUE ) {
+      return !descriptorsToVisitQ.isEmpty();
+    }
+
+    throw new Error( "Neither descriptor visiting mode set" );
+  }
+
+
   // fixed-point computation over the call graph--when a
   // method's callees are updated, it must be reanalyzed
   protected void analyzeMethods() throws java.io.IOException {  
@@ -614,16 +633,30 @@ public class DisjointAnalysis {
     Iterator<Descriptor> dItr = sortedDescriptors.iterator();
     while( dItr.hasNext() ) {
       Descriptor d = dItr.next();
+
       mapDescriptorToPriority.put( d, new Integer( p ) );
-      descriptorsToVisitQ.add( new DescriptorQWrapper( p, d ) );
+
+      if( state.DISJOINTDVISITSTACK ) {
+        descriptorsToVisitStack.add( new DescriptorQWrapper( p, d ) );
+
+      } else if( state.DISJOINTDVISITPQUE ) {
+        descriptorsToVisitQ.add( new DescriptorQWrapper( p, d ) );
+      }
+
       descriptorsToVisitSet.add( d );
       ++p;
     }
 
     // analyze methods from the priority queue until it is empty
-    while( !descriptorsToVisitQ.isEmpty() ) {
-      Descriptor d = descriptorsToVisitQ.pop().getDescriptor();
-      //Descriptor d = descriptorsToVisitQ.poll().getDescriptor();
+    while( moreDescriptorsToVisit() ) {
+      Descriptor d = null;
+
+      if( state.DISJOINTDVISITSTACK ) {
+        d = descriptorsToVisitStack.pop().getDescriptor();
+
+      } else if( state.DISJOINTDVISITPQUE ) {
+        d = descriptorsToVisitQ.poll().getDescriptor();
+      }
 
       assert descriptorsToVisitSet.contains( d );
       descriptorsToVisitSet.remove( d );
@@ -665,10 +698,13 @@ public class DisjointAnalysis {
     } else {
       fm = state.getMethodFlat( d );
     }
-    pm.analyzeMethod(fm);
+    pm.analyzeMethod( fm );
+
     // intraprocedural work set
     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
     flatNodesToVisit.add( fm );
+
+    Set<FlatNode> debugVisited = new HashSet<FlatNode>();
     
     // mapping of current partial results
     Hashtable<FlatNode, ReachGraph> mapFlatNodeToReachGraph =
@@ -682,6 +718,8 @@ public class DisjointAnalysis {
       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
       flatNodesToVisit.remove( fn );
 
+      debugVisited.add( fn );
+
       // effect transfer function defined by this node,
       // then compare it to the old graph at this node
       // to see if anything was updated.
@@ -743,8 +781,37 @@ public class DisjointAnalysis {
       }
     }
 
+
+    // assert that the fixed-point results for each
+    // node in the method is no smaller than the last
+    // time this method was analyzed (monotonicity)
+    /*
+    Iterator<FlatNode> nItr = fm.getNodeSet().iterator();
+    while( nItr.hasNext() ) {
+      FlatNode   fn     = nItr.next();      
+      ReachGraph last   = fn2rg.get( fn );
+      ReachGraph newest = mapFlatNodeToReachGraph.get( fn );
+
+      if( newest == null ) {
+        System.out.println( "**********\nfn null result: "+fn+
+                            "\nnum visited="+debugVisited.size()+", num in set="+fm.getNodeSet().size()+
+                            "\nvisited:"+debugVisited );
+      }
+
+      assert newest != null;
+      if( last != null ) {
+        if( !ReachGraph.isNoSmallerThan( last, newest ) ) {
+          last.writeGraph( "last", true, false, false, true, true );
+          newest.writeGraph( "newest", true, false, false, true, true );
+          throw new Error( "transfer func for "+fn+" was not monotic" );
+        }
+      }
+      fn2rg.put( fn, newest );
+    }
+    */
+
     // end by merging all return nodes into a complete
-    // ownership graph that represents all possible heap
+    // reach graph that represents all possible heap
     // states after the flat method returns
     ReachGraph completeGraph = new ReachGraph();
 
@@ -829,11 +896,6 @@ public class DisjointAnalysis {
 
         rg.merge_diffMethodContext( rgContrib );
       }
-      FlatMethod hackfm=(FlatMethod)fn;
-      if (hackmap.containsKey(hackfm)) {
-       rg.merge(hackmap.get(hackfm));
-      }
-      hackmap.put(hackfm, rg);
     } break;
       
     case FKind.FlatOpNode:
@@ -1054,6 +1116,7 @@ public class DisjointAnalysis {
     return rg;
   }
 
+
   
   // this method should generate integers strictly greater than zero!
   // special "shadow" regions are made from a heap region by negating
@@ -1330,9 +1393,18 @@ public class DisjointAnalysis {
   protected void enqueue( Descriptor d ) {
     if( !descriptorsToVisitSet.contains( d ) ) {
       Integer priority = mapDescriptorToPriority.get( d );
-      descriptorsToVisitQ.add( new DescriptorQWrapper( priority, 
-                                                       d ) 
-                               );
+
+      if( state.DISJOINTDVISITSTACK ) {
+        descriptorsToVisitStack.add( new DescriptorQWrapper( priority, 
+                                                             d ) 
+                                     );
+
+      } else if( state.DISJOINTDVISITPQUE ) {
+        descriptorsToVisitQ.add( new DescriptorQWrapper( priority, 
+                                                         d ) 
+                                 );
+      }
+
       descriptorsToVisitSet.add( d );
     }
   }
index c7b1d91916065ccad1f18af1b35068c7152f87b2..1062c1635698285f41c62f4a5396cc6226f4b387 100644 (file)
@@ -44,7 +44,8 @@ public class PointerMethod {
       if (analysisCares(fn)) {
        HashSet<FlatNode> myset=new HashSet<FlatNode>();
        for(int i=0;i<fn.numPrev();i++) {
-         myset.addAll(map.get(fn.getPrev(i)));
+          if (map.containsKey(fn.getPrev(i)))
+            myset.addAll(map.get(fn.getPrev(i)));
        }
        if (!prevmap.containsKey(fn))
          prevmap.put(fn, new Vector());
index 6f2c42bcd4a3ca298495f644031ef15fba4932d1..7dba300b39467deecdc26e7016e82874e08d9c1b 100644 (file)
@@ -9,7 +9,7 @@ import java.io.*;
 public class ReachGraph {
 
   // use to disable improvements for comparison
-  protected static final boolean DISABLE_STRONG_UPDATES = false;
+  protected static final boolean DISABLE_STRONG_UPDATES = true;
   protected static final boolean DISABLE_GLOBAL_SWEEP   = false;
                   
   // a special out-of-scope temp
@@ -1937,7 +1937,12 @@ public class ReachGraph {
                        ) {
 
     if( writeDebugDOTs ) {
-      debugGraphPrefix = String.format( "call%02d", debugCallSiteVisits );
+      System.out.println( "  Writing out visit "+
+                          debugCallSiteVisits+
+                          " to debug call site" );
+
+      debugGraphPrefix = String.format( "call%02d", 
+                                        debugCallSiteVisits );
       
       rgCallee.writeGraph( debugGraphPrefix+"callee", 
                            resolveMethodDebugDOTwriteLabels,    
@@ -3713,6 +3718,8 @@ public class ReachGraph {
       return false;
     }
 
+    
+
     return true;
   }
 
@@ -3826,6 +3833,94 @@ public class ReachGraph {
   }
 
 
+  // can be used to assert monotonicity
+  static public boolean isNoSmallerThan( ReachGraph rgA, 
+                                         ReachGraph rgB ) {
+
+    //System.out.println( "*** Asking if A is no smaller than B ***" );
+
+
+    Iterator iA = rgA.id2hrn.entrySet().iterator();
+    while( iA.hasNext() ) {
+      Map.Entry      meA  = (Map.Entry)      iA.next();
+      Integer        idA  = (Integer)        meA.getKey();
+      HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
+
+      if( !rgB.id2hrn.containsKey( idA ) ) {
+        System.out.println( "  regions smaller" );
+       return false;
+      }
+
+      //HeapRegionNode hrnB = rgB.id2hrn.get( idA );
+      /* NOT EQUALS, NO SMALLER THAN!
+      if( !hrnA.equalsIncludingAlphaAndPreds( hrnB ) ) {
+        System.out.println( "  regions smaller" );
+       return false;
+      }
+      */
+    }
+    
+    // this works just fine, no smaller than
+    if( !areallVNinAalsoinBandequal( rgA, rgB ) ) {
+      System.out.println( "  vars smaller:" );
+      System.out.println( "    A:"+rgA.td2vn.keySet() );
+      System.out.println( "    B:"+rgB.td2vn.keySet() );
+      return false;
+    }
+
+
+    iA = rgA.id2hrn.entrySet().iterator();
+    while( iA.hasNext() ) {
+      Map.Entry      meA  = (Map.Entry)      iA.next();
+      Integer        idA  = (Integer)        meA.getKey();
+      HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
+
+      Iterator<RefEdge> reItr = hrnA.iteratorToReferencers();
+      while( reItr.hasNext() ) {
+        RefEdge    edgeA = reItr.next();
+        RefSrcNode rsnA  = edgeA.getSrc();
+
+        // we already checked that nodes were present
+        HeapRegionNode hrnB = rgB.id2hrn.get( hrnA.getID() );
+        assert hrnB != null;
+
+        RefSrcNode rsnB;
+        if( rsnA instanceof VariableNode ) {
+          VariableNode vnA = (VariableNode) rsnA;
+          rsnB = rgB.td2vn.get( vnA.getTempDescriptor() );
+
+        } else {
+          HeapRegionNode hrnSrcA = (HeapRegionNode) rsnA;
+          rsnB = rgB.id2hrn.get( hrnSrcA.getID() );
+        }
+        assert rsnB != null;
+
+        RefEdge edgeB = rsnB.getReferenceTo( hrnB,
+                                             edgeA.getType(),
+                                             edgeA.getField()
+                                             );
+        if( edgeB == null ) {
+          System.out.println( "  edges smaller:" );          
+          return false;
+        }        
+
+        // REMEMBER, IS NO SMALLER THAN
+        /*
+          System.out.println( "  edges smaller" );
+          return false;
+          }
+        */
+
+      }
+    }
+
+    
+    return true;
+  }
+
+
+
+
 
   // this analysis no longer has the "match anything"
   // type which was represented by null
index 01882156adc38f8a8743a06661058534fc605652..e299f71a9fcf2e09901cec8f0edd228bee360a13 100644 (file)
@@ -77,26 +77,6 @@ public class ReachSet extends Canonical {
     return null;
   }
 
-  /*
-  public boolean containsWithZeroes( ReachState state ) {
-    assert state != null;
-
-    if( reachStates.contains( state ) ) {
-      return true;
-    }
-
-    Iterator<ReachState> itr = iterator();
-    while( itr.hasNext() ) {
-      ReachState stateThis = itr.next();
-      if( stateThis.containsWithZeroes( state ) ) {
-       return true;
-      }
-    }
-    
-    return false;    
-  }
-  */
-
   public boolean containsSuperSet( ReachState state ) {
     return containsSuperSet( state, false );
   }
index 1b7e685cccf2982f18708bcfaddd0295bb50aa34..39ec62e50edf03f98eecd011132d3140c0e2b886 100644 (file)
@@ -1,19 +1,30 @@
 BUILDSCRIPT=~/research/Robust/src/buildscript
 
-#DEBUGFLAGS= -disjoint-debug-callsite MDRunner t3 100
-#DEBUGFLAGS= -disjoint-debug-callsite calcGoodFeature calcGoodFeatureTask 100
-#DEBUGFLAGS= -disjoint-debug-callsite getRows calcGoodFeature 4
-#DEBUGFLAGS= -disjoint-debug-callsite setKMeans t3 500
-#DEBUGFLAGS= -disjoint-debug-callsite innerKMeansSetting t6 20
+#################################################
+##
+##  To debug a call site, supply the symbols for
+##  the callee, then caller, then max number of
+##  analysis visits to the call site to write out
+##
+#################################################
 #DEBUGFLAGS= -disjoint-debug-callsite setClusters innerKMeansSetting 20
-
+DEBUGFLAGS= -disjoint-debug-callsite ensureCapacity addElement 100
+
+
+#################################################
+##
+##  To get snapshots (graphs) for the exit of every
+##  node in a method, supply method symbol then the
+##  number of analysis visits to the method to skip
+##  (early visits usually uninteresting), then the
+##  number of visits to take snapshots for, finally
+##  a boolean value indicating if the analysis should
+##  immediately terminate after the last snapshot visit
+##
+#################################################
 #SNAPFLAGS= -disjoint-debug-snap-method calcGoodFeatureTask 5 10 true
 #SNAPFLAGS= -disjoint-debug-snap-method calcGoodFeature 5 1 true
-
 #SNAPFLAGS= -disjoint-debug-snap-method t3 1 1 true
-#SNAPFLAGS= -disjoint-debug-snap-method t6 5 20 true
-
-#SNAPFLAGS= -disjoint-debug-snap-method innerKMeansSetting 1 20 true
 
 
 
@@ -21,25 +32,28 @@ BUILDSCRIPT=~/research/Robust/src/buildscript
 BAMBOOFLAGS= -recover
 JAVAFLAGS= -mainclass test
 
+VISITMODE= -disjoint-dvisit-stack
+#VISITMODE= -disjoint-dvisit-pqueue
+
 DEBUGMODE= -enable-assertions -disjoint-write-dots final -disjoint-alias-file aliases.txt normal
 RELEASEMODE= -disjoint-release-mode -disjoint-alias-file aliases.txt tabbed
 
-BSFLAGS= -justanalyze -disjoint -disjoint-k 1 
+BSFLAGS= -justanalyze -disjoint -disjoint-k 1 -flatirusermethods
 
 all:
        echo 'pass another arg: <bamboo/bamboo-release/java/java-release>'
 
 bamboo:
-       $(BUILDSCRIPT) $(BAMBOOFLAGS) $(DEBUGMODE)   $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
+       $(BUILDSCRIPT) $(BAMBOOFLAGS) $(DEBUGMODE)   $(VISITMODE) $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
 
 bamboo-release:
-       $(BUILDSCRIPT) $(BAMBOOFLAGS) $(RELEASEMODE) $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
+       $(BUILDSCRIPT) $(BAMBOOFLAGS) $(RELEASEMODE) $(VISITMODE) $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
 
 java:
-       $(BUILDSCRIPT) $(JAVAFLAGS)   $(DEBUGMODE)   $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
+       $(BUILDSCRIPT) $(JAVAFLAGS)   $(DEBUGMODE)   $(VISITMODE) $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
 
 java-release:
-       $(BUILDSCRIPT) $(JAVAFLAGS)   $(RELEASEMODE) $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
+       $(BUILDSCRIPT) $(JAVAFLAGS)   $(RELEASEMODE) $(VISITMODE) $(BSFLAGS) $(DEBUGFLAGS) $(SNAPFLAGS) *.java
 
 clean:
        rm -f  *.bin
index 88ddfca88ea7f3f0dec8d616ad43d2b37a9fb3e7..065c72c7f9695c6755e4b281741899d2b01daee7 100644 (file)
@@ -83,6 +83,8 @@ public class State {
   public int DISJOINTSNAPVISITTOSTART=0;
   public int DISJOINTSNAPNUMVISITS=0;
   public boolean DISJOINTSNAPSTOPAFTER=false;
+  public boolean DISJOINTDVISITSTACK=true;
+  public boolean DISJOINTDVISITPQUE=false;
 
   public boolean OPTIONAL=false;
   public boolean ARRAYPAD=false;
index 7471b41530aea60c64d632f8d1c1bfc9ba3544e3..d7f6175c4939792e70b604ec5f7b8f040afd9c1f 100644 (file)
@@ -218,7 +218,13 @@ public class Main {
         }
 
       } else if( option.equals( "-disjoint-release-mode" ) ) {
-        state.DISJOINTRELEASEMODE = true;
+        state.DISJOINTRELEASEMODE = true;        
+
+      } else if( option.equals( "-disjoint-dvisit-stack" ) ) {
+        state.DISJOINTDVISITSTACK = true;      
+
+      } else if( option.equals( "-disjoint-dvisit-pqueue" ) ) {
+        state.DISJOINTDVISITPQUE = true;
       }