check points-to module improvements along with a bug fix for disjoint call transfer...
[IRC.git] / Robust / src / Analysis / Disjoint / ReachGraph.java
index f43df03a3125b2e11d299900266d094b19dfe0cf..86550e67b7c553ec6606bb03f8f3a84affe56b4a 100644 (file)
@@ -12,8 +12,18 @@ public class ReachGraph {
   protected static final boolean DISABLE_STRONG_UPDATES = false;
   protected static final boolean DISABLE_GLOBAL_SWEEP   = false;
 
-  // a special out-of-scope temp
-  protected static final TempDescriptor tdReturn = new TempDescriptor("_Return___");
+  // a special out-of-scope temps
+  protected static TempDescriptor tdReturn;
+  protected static TempDescriptor tdStrLiteralBytes;
+  
+  public static void initOutOfScopeTemps() {
+    tdReturn = new TempDescriptor("_Return___");
+
+    tdStrLiteralBytes = 
+      new TempDescriptor("_strLiteralBytes___",
+                         new TypeDescriptor(TypeDescriptor.CHAR).makeArray( state )
+                         );
+  }
 
   // predicate constants
   public static final ExistPred predTrue   = ExistPred.factory();    // if no args, true
@@ -380,6 +390,26 @@ public class ReachGraph {
   //
   ////////////////////////////////////////////////////
 
+  public void assignTempEqualToStringLiteral(TempDescriptor  x,
+                                             AllocSite       asStringLiteral,
+                                             AllocSite       asStringLiteralBytes,
+                                             FieldDescriptor fdStringBytesField) {
+    // model this to get points-to information right for
+    // pointers to string literals, even though it doesn't affect
+    // reachability paths in the heap
+    assignTempEqualToNewAlloc( x, 
+                               asStringLiteral );
+
+    assignTempEqualToNewAlloc( tdStrLiteralBytes, 
+                               asStringLiteralBytes );
+
+    assignTempXFieldFEqualToTempY( x,
+                                   fdStringBytesField,
+                                   tdStrLiteralBytes,
+                                   null );
+  }
+
+
   public void assignTempXEqualToTempY(TempDescriptor x,
                                       TempDescriptor y) {
     assignTempXEqualToCastedTempY(x, y, null);
@@ -2217,8 +2247,8 @@ public class ReachGraph {
   private static boolean resolveMethodDebugDOTpruneGarbage    = true;
   private static boolean resolveMethodDebugDOThideReach       = true;
   private static boolean resolveMethodDebugDOThideSubsetReach = true;
-  private static boolean resolveMethodDebugDOThidePreds       = true;
-  private static boolean resolveMethodDebugDOThideEdgeTaints  = false;
+  private static boolean resolveMethodDebugDOThidePreds       = false;
+  private static boolean resolveMethodDebugDOThideEdgeTaints  = true;
 
   static String debugGraphPrefix;
   static int debugCallSiteVisitCounter;
@@ -2302,6 +2332,7 @@ public class ReachGraph {
       new Hashtable< RefEdge, Set<RefSrcNode> >();
 
 
+
     Iterator meItr = rgCallee.id2hrn.entrySet().iterator();
     while( meItr.hasNext() ) {
       Map.Entry me        = (Map.Entry)meItr.next();
@@ -2314,8 +2345,8 @@ public class ReachGraph {
       // should have, and it is inefficient to find this again later
       ExistPredSet predsIfSatis =
         hrnCallee.getPreds().isSatisfiedBy(this,
-                                           callerNodeIDsCopiedToCallee
-                                           );
+                                           callerNodeIDsCopiedToCallee,
+                                           null);
 
       if( predsIfSatis != null ) {
         calleeNodesSatisfied.put(hrnCallee, predsIfSatis);
@@ -2334,8 +2365,8 @@ public class ReachGraph {
 
         predsIfSatis =
           stateCallee.getPreds().isSatisfiedBy(this,
-                                               callerNodeIDsCopiedToCallee
-                                               );
+                                               callerNodeIDsCopiedToCallee,
+                                               null);
         if( predsIfSatis != null ) {
 
           Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied =
@@ -2404,8 +2435,8 @@ public class ReachGraph {
 
             predsIfSatis =
               hrnSrcCallee.getPreds().isSatisfiedBy(this,
-                                                    callerNodeIDsCopiedToCallee
-                                                    );
+                                                    callerNodeIDsCopiedToCallee,
+                                                    null);
             if( predsIfSatis != null ) {
               calleeNodesSatisfied.put(hrnSrcCallee, predsIfSatis);
             } else {
@@ -2415,55 +2446,18 @@ public class ReachGraph {
 
           } else {
             // hrnSrcCallee is out-of-context
-
             assert !calleeEdges2oocCallerSrcMatches.containsKey(reCallee);
 
             Set<RefSrcNode> rsnCallers = new HashSet<RefSrcNode>();
 
-            // is the target node in the caller?
-            HeapRegionNode hrnDstCaller = this.id2hrn.get(hrnCallee.getID() );
-            if( hrnDstCaller == null ) {
-              continue;
-            }
-
-            Iterator<RefEdge> reDstItr = hrnDstCaller.iteratorToReferencers();
-            while( reDstItr.hasNext() ) {
-              // the edge and field (either possibly null) must match
-              RefEdge reCaller = reDstItr.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() == null ) {
-                  if( hrnCallerSrc.getType() != null ) {
-                    continue;
-                  }
-                } else {
-                  if( !hrnSrcCallee.getType().equals(hrnCallerSrc.getType() ) ) {
-                    continue;
-                  }
-                }
-              }
-
-              rsnCallers.add(rsnCaller);
-              matchedOutOfContext = true;
-            }
+            // use the isSatisfiedBy with a non-null callers set to capture
+            // nodes in the caller that match the predicates
+            reCallee.getPreds().isSatisfiedBy( this,
+                                               callerNodeIDsCopiedToCallee,
+                                               rsnCallers );
 
             if( !rsnCallers.isEmpty() ) {
+              matchedOutOfContext = true;
               calleeEdges2oocCallerSrcMatches.put(reCallee, rsnCallers);
             }
           }
@@ -2477,8 +2471,9 @@ public class ReachGraph {
 
         predsIfSatis =
           reCallee.getPreds().isSatisfiedBy(this,
-                                            callerNodeIDsCopiedToCallee
-                                            );
+                                            callerNodeIDsCopiedToCallee,
+                                            null);
+
 
         if( predsIfSatis != null ) {
           calleeEdgesSatisfied.put(reCallee, predsIfSatis);
@@ -2493,8 +2488,8 @@ public class ReachGraph {
 
             predsIfSatis =
               stateCallee.getPreds().isSatisfiedBy(this,
-                                                   callerNodeIDsCopiedToCallee
-                                                   );
+                                                   callerNodeIDsCopiedToCallee,
+                                                   null);
             if( predsIfSatis != null ) {
 
               Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied =
@@ -2521,8 +2516,8 @@ public class ReachGraph {
 
             predsIfSatis =
               tCallee.getPreds().isSatisfiedBy(this,
-                                               callerNodeIDsCopiedToCallee
-                                               );
+                                               callerNodeIDsCopiedToCallee,
+                                               null);
             if( predsIfSatis != null ) {
 
               Hashtable<Taint, ExistPredSet> calleeTaintsSatisfied =
@@ -4188,7 +4183,6 @@ public class ReachGraph {
 
     //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();
@@ -4199,14 +4193,6 @@ public class ReachGraph {
         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
@@ -4252,14 +4238,6 @@ public class ReachGraph {
           System.out.println("  edges smaller:");
           return false;
         }
-
-        // REMEMBER, IS NO SMALLER THAN
-        /*
-           System.out.println( "  edges smaller" );
-           return false;
-           }
-         */
-
       }
     }
 
@@ -4436,7 +4414,9 @@ public class ReachGraph {
     try {
       // remove all non-word characters from the graph name so
       // the filename and identifier in dot don't cause errors
-      graphName = graphName.replaceAll("[\\W]", "");
+      // jjenista - also replace underscore '_' to prevent some
+      // really, really long names from IHMS debugging
+      graphName = graphName.replaceAll("[\\W_]", "");
 
       BufferedWriter bw =
         new BufferedWriter(new FileWriter(graphName+".dot") );
@@ -5189,4 +5169,98 @@ public class ReachGraph {
   public Set<TempDescriptor> getInaccessibleVars() {
     return inaccessibleVars;
   }
+
+
+
+
+  public Set<Alloc> canPointTo( TempDescriptor x ) {
+
+    if( !DisjointAnalysis.shouldAnalysisTrack( x.getType() ) ) {
+      // if we don't care to track it, return null which means
+      // "a client of this result shouldn't care either"
+      return HeapAnalysis.DONTCARE_PTR;
+    }
+
+    Set<Alloc> out = new HashSet<Alloc>();
+
+    VariableNode vn = getVariableNodeNoMutation( x );
+    if( vn == null ) {
+      // the empty set means "can't point to anything"
+      return out;
+    }
+
+    Iterator<RefEdge> edgeItr = vn.iteratorToReferencees();
+    while( edgeItr.hasNext() ) {
+      HeapRegionNode hrn = edgeItr.next().getDst();
+      out.add( hrn.getAllocSite() );
+    }
+
+    return out;
+  }
+
+
+
+  public Hashtable< Alloc, Set<Alloc> > canPointTo( TempDescriptor x,
+                                                    String         field,
+                                                    TypeDescriptor fieldType ) {
+
+    if( !DisjointAnalysis.shouldAnalysisTrack( x.getType() ) ) {
+      // if we don't care to track it, return null which means
+      // "a client of this result shouldn't care either"
+      return HeapAnalysis.DONTCARE_DREF;
+    }
+
+    Hashtable< Alloc, Set<Alloc> > out = new Hashtable< Alloc, Set<Alloc> >();
+    
+    VariableNode vn = getVariableNodeNoMutation( x );
+    if( vn == null ) {
+      // the empty table means "x can't point to anything"
+      return out;
+    }
+
+    Iterator<RefEdge> edgeItr = vn.iteratorToReferencees();
+    while( edgeItr.hasNext() ) {
+      HeapRegionNode hrn = edgeItr.next().getDst();
+      Alloc          key = hrn.getAllocSite();
+
+      if( !DisjointAnalysis.shouldAnalysisTrack( fieldType ) ) {
+        // if we don't care to track it, put no entry which means
+        // "a client of this result shouldn't care either"
+        out.put( key, HeapAnalysis.DONTCARE_PTR );
+        continue;
+      }
+
+      Set<Alloc> moreValues = new HashSet<Alloc>();
+      Iterator<RefEdge> edgeItr2 = hrn.iteratorToReferencees();
+      while( edgeItr2.hasNext() ) {
+        RefEdge edge = edgeItr2.next();
+        
+        if( field.equals( edge.getField() ) ) {
+          moreValues.add( edge.getDst().getAllocSite() );
+        }
+      }
+
+      if( out.containsKey( key ) ) {
+        out.get( key ).addAll( moreValues );
+      } else {
+        out.put( key, moreValues );
+      }
+    }
+    
+    return out;
+  }
+
+
+
+  // for debugging
+  public TempDescriptor findVariableByName( String name ) {
+
+    for( TempDescriptor td: td2vn.keySet() ) {
+      if( td.getSymbol().contains( name ) ) {
+        return td;
+      }
+    }
+    
+    return null;
+  }
 }