analysis collects effects per method and interprocedurally
authorjjenista <jjenista>
Fri, 25 Jun 2010 18:18:50 +0000 (18:18 +0000)
committerjjenista <jjenista>
Fri, 25 Jun 2010 18:18:50 +0000 (18:18 +0000)
Robust/src/Analysis/Disjoint/DisjointAnalysis.java
Robust/src/Analysis/Disjoint/Effect.java
Robust/src/Analysis/Disjoint/EffectSet.java
Robust/src/Analysis/Disjoint/EffectsAnalysis.java
Robust/src/Analysis/Disjoint/ReachGraph.java
Robust/src/Tests/disjoint/taintTest1/makefile
Robust/src/Tests/disjoint/taintTest1/test.java

index 03bfb6d4ddb657f58f939167629e163a98e9f356..e4dbabfc764e4f992adffe78ec5647c0e7d87d3a 100644 (file)
@@ -338,7 +338,7 @@ public class DisjointAnalysis {
   public int              allocationDepth;
 
   protected boolean doEffectsAnalysis = false;
-
+  protected EffectsAnalysis effectsAnalysis;
   
   // data structure for public interface
   private Hashtable< Descriptor, HashSet<AllocSite> > 
@@ -581,6 +581,7 @@ public class DisjointAnalysis {
 
     if( rblockRel != null ) {
       doEffectsAnalysis = true;
+      effectsAnalysis   = new EffectsAnalysis();
     }
 
     this.allocationDepth         = state.DISJOINTALLOCDEPTH;
@@ -671,6 +672,10 @@ public class DisjointAnalysis {
     } catch( IOException e ) {
       throw new Error( "IO Exception while writing disjointness analysis output." );
     }
+
+    if( doEffectsAnalysis ) {
+      effectsAnalysis.writeEffectsPerMethod( "effects-per-method.txt" );
+    }
   }
 
 
@@ -1098,6 +1103,10 @@ public class DisjointAnalysis {
       fld = ffn.getField();
       if( shouldAnalysisTrack( fld.getType() ) ) {
        rg.assignTempXEqualToTempYFieldF( lhs, rhs, fld );
+
+        if( doEffectsAnalysis ) {
+          effectsAnalysis.analyzeFlatFieldNode( fmContaining, rg, rhs, fld );          
+        }
       }          
       break;
 
@@ -1106,8 +1115,13 @@ public class DisjointAnalysis {
       lhs = fsfn.getDst();
       fld = fsfn.getField();
       rhs = fsfn.getSrc();
+
       if( shouldAnalysisTrack( fld.getType() ) ) {
-       rg.assignTempXFieldFEqualToTempY( lhs, fld, rhs );
+        boolean strongUpdate = rg.assignTempXFieldFEqualToTempY( lhs, fld, rhs );
+
+        if( doEffectsAnalysis ) {
+          effectsAnalysis.analyzeFlatSetFieldNode( fmContaining, rg, lhs, fld, strongUpdate );
+        }
       }           
       break;
 
@@ -1259,7 +1273,6 @@ public class DisjointAnalysis {
 
       }
 
-
       // the transformation for a call site should update the
       // current heap abstraction with any effects from the callee,
       // or if the method is virtual, the effects from any possible
@@ -1315,15 +1328,30 @@ public class DisjointAnalysis {
 
 
         } else {
+          // calculate the method call transform
+          
+          Hashtable<Taint, TaintSet> tCallee2tsCaller = null;
+
+          if( doEffectsAnalysis ) {
+            tCallee2tsCaller = new Hashtable<Taint, TaintSet>();
+          }        
+
           rgCopy.resolveMethodCall( fc, 
                                     fmPossible, 
                                     rgEffect,
                                     callerNodeIDsCopiedToCallee,
+                                    tCallee2tsCaller,
                                     writeDebugDOTs
                                     );
+
+          if( doEffectsAnalysis ) {
+            effectsAnalysis.analyzeFlatCall( fmContaining,
+                                             fmPossible, 
+                                             tCallee2tsCaller );
+          }        
         }
         
-        rgMergeOfEffects.merge( rgCopy );
+        rgMergeOfEffects.merge( rgCopy );        
       }
 
 
index f53cff2e6d5300afc9f231e41fcdc8fbbc99a865..658c648283f02ac389bfd0c4ed37e53463c85ca3 100644 (file)
@@ -1,6 +1,5 @@
 package Analysis.Disjoint;
 
-import Analysis.OwnershipAnalysis.EffectsKey;
 import IR.FieldDescriptor;
 import IR.Flat.TempDescriptor;
 
@@ -11,15 +10,6 @@ public class Effect {
   public static final int write = 2;
   public static final int strongupdate = 3;
 
-  // identify a parameter index
-  protected Integer paramIndex;
-
-  // identify an inset var
-  protected TempDescriptor insetVar;
-
-  // identify an allocation site of inset var
-  protected AllocSite insetAllocSite;
-
   // identify an allocation site of affected object
   protected AllocSite affectedAllocSite;
 
@@ -29,38 +19,12 @@ public class Effect {
   // identify a field
   protected FieldDescriptor field;
 
-  public Effect(Integer pi, AllocSite insetAS, AllocSite affectedAS, int type, FieldDescriptor field) {
-    this.paramIndex = pi;
-    this.insetAllocSite = insetAS;
+  public Effect(AllocSite affectedAS, int type, FieldDescriptor field) {
     this.affectedAllocSite = affectedAS;
     this.type = type;
     this.field = field;
   }
 
-  public Integer getParamIndex() {
-    return paramIndex;
-  }
-
-  public void setParamIndex(Integer paramIndex) {
-    this.paramIndex = paramIndex;
-  }
-
-  public TempDescriptor getInsetVar() {
-    return insetVar;
-  }
-
-  public void setInsetVar(TempDescriptor insetVar) {
-    this.insetVar = insetVar;
-  }
-
-  public AllocSite getInsetAllocSite() {
-    return insetAllocSite;
-  }
-
-  public void setInsetAllocSite(AllocSite insetAllocSite) {
-    this.insetAllocSite = insetAllocSite;
-  }
-
   public AllocSite getAffectedAllocSite() {
     return affectedAllocSite;
   }
@@ -96,18 +60,7 @@ public class Effect {
     }
 
     Effect in = (Effect) o;
-
-    if (paramIndex != null) {
-      if (!paramIndex.equals(in.getParamIndex())) {
-        return false;
-      }
-    } else {
-      if (!insetVar.equals(in.getInsetVar()) 
-          && !insetAllocSite.equals(in.getInsetAllocSite())) {
-        return false;
-      }
-    }
-
+    
     if (affectedAllocSite.equals(in.getAffectedAllocSite()) 
         && type == in.getType() 
         && field.equals(in.getField())) {
@@ -121,12 +74,6 @@ public class Effect {
 
     int hash = affectedAllocSite.hashCode();
 
-    if (paramIndex != null) {
-      hash = hash ^ paramIndex.hashCode();
-    } else if (insetAllocSite != null) {
-      hash = hash ^ insetAllocSite.hashCode();
-    }
-
     hash = hash + type;
 
     if (field != null) {
@@ -140,14 +87,7 @@ public class Effect {
   public String toString() {
     String s = "(";
 
-    if (paramIndex != null) {
-      s += "param" + paramIndex;
-    } else {
-      s += insetVar;
-      s += ", " + insetAllocSite.toStringBrief();
-    }
-
-    s += ", " + affectedAllocSite.toStringBrief();
+    s += affectedAllocSite.toStringBrief();
     s += ", ";
     if (type == read) {
       s += "read";
index cbddc2a39b6bbde25f0500a7d75a1f64dc12d29d..12d12089ced87768ced61b61146355cbac03c761 100644 (file)
@@ -2,33 +2,36 @@ package Analysis.Disjoint;
 
 import java.util.HashSet;
 import java.util.Hashtable;
-
+import java.util.Set;
+import java.util.Iterator;
 import IR.Flat.TempDescriptor;
 
 public class EffectSet {
 
-  private Hashtable<Integer, HashSet<Effect>> methodEffectSet;
-  private Hashtable<TempDescriptor, HashSet<Effect>> rblockEffectSet;
+  private Hashtable<Taint, HashSet<Effect>> taint2effects;
 
   public EffectSet() {
-    methodEffectSet = new Hashtable<Integer, HashSet<Effect>>();
+    taint2effects = new Hashtable<Taint, HashSet<Effect>>();
   }
 
-  public void addMethodEffect(Integer paramIdx, Effect e) {
-    HashSet<Effect> effectSet = methodEffectSet.get(paramIdx);
+  public void addEffect(Taint t, Effect e) {
+    HashSet<Effect> effectSet = taint2effects.get(t);
     if (effectSet == null) {
       effectSet = new HashSet<Effect>();
     }
     effectSet.add(e);
-    methodEffectSet.put(paramIdx, effectSet);
+    taint2effects.put(t, effectSet);
   }
 
-  public String toString() {
-    if (methodEffectSet != null) {
-      return methodEffectSet.toString();
-    } else {
-      return rblockEffectSet.toString();
-    }
+  public Set<Effect> getEffects(Taint t) {
+    return taint2effects.get(t);
   }
 
+  public Iterator getAllEffectPairs() {
+    return taint2effects.entrySet().iterator();
+  }
+
+  public String toString() {
+    return taint2effects.toString();    
+  }
 }
index 043d6ddee0aa8dc6824e89a83903da4eb8a2bdb8..0e81f1b84111db6ddae6f56386898f5cb516bc8f 100644 (file)
@@ -1,12 +1,13 @@
 package Analysis.Disjoint;
 
-import java.util.Hashtable;
-import java.util.Iterator;
+import java.util.*;
+import java.io.*;
 
 import IR.FieldDescriptor;
 import IR.Flat.FlatCall;
 import IR.Flat.FlatMethod;
 import IR.Flat.TempDescriptor;
+import IR.Flat.FlatSESEEnterNode;
 
 /////////////////////////////////////////////
 // 
@@ -26,25 +27,16 @@ import IR.Flat.TempDescriptor;
 
 public class EffectsAnalysis {
 
-  private Hashtable<FlatMethod, EffectSet> mapFlatmethodToEffectset;
+  private Hashtable<FlatMethod, EffectSet> fm2effectSet;
 
-  // private Hashtable<MethodContext, MethodEffects>
-  // mapMethodContextToMethodEffects;
-  // boolean methodeffects = false;
-
-  public EffectsAnalysis(boolean methodeffects) {
-    mapFlatmethodToEffectset = new Hashtable<FlatMethod, EffectSet>();
+  public EffectsAnalysis() {
+    fm2effectSet = new Hashtable<FlatMethod, EffectSet>();
   }
 
   public void analyzeFlatFieldNode(FlatMethod fmContaining, ReachGraph rg, TempDescriptor rhs, FieldDescriptor fld) {
 
     VariableNode vn = rg.td2vn.get(rhs);
 
-    EffectSet effectSet = mapFlatmethodToEffectset.get(fmContaining);
-    if (effectSet == null) {
-      effectSet = new EffectSet();
-    }
-
     for (Iterator<RefEdge> iterator = vn.iteratorToReferencees(); iterator.hasNext();) {
       RefEdge edge = iterator.next();
       TaintSet taintSet = edge.getTaints();
@@ -52,25 +44,23 @@ public class EffectsAnalysis {
       for (Iterator<Taint> taintSetIter = taintSet.iterator(); taintSetIter.hasNext();) {
         Taint taint = taintSetIter.next();
 
-//        Effect effect = new Effect(taint.getParamIndex(), taint.getAllocSite(), affectedAlloc, Effect.read, fld);
-//        effectSet.addMethodEffect(taint.getParamIndex(), effect);
+        EffectSet effectSet = fm2effectSet.get(fmContaining);
+        if (effectSet == null) {
+          effectSet = new EffectSet();
+        }
+        
+        Effect effect = new Effect(affectedAlloc, Effect.read, fld);
+        effectSet.addEffect(taint, effect);
 
+        fm2effectSet.put(fmContaining, effectSet);
       }
     }
-
-    mapFlatmethodToEffectset.put(fmContaining, effectSet);
-
   }
 
-  public void analyzeFlatSetFieldNode(FlatMethod fmContaining, ReachGraph rg, TempDescriptor lhs, FieldDescriptor fld) {
+  public void analyzeFlatSetFieldNode(FlatMethod fmContaining, ReachGraph rg, TempDescriptor lhs, FieldDescriptor fld, boolean strongUpdate) {
 
     VariableNode vn = rg.td2vn.get(lhs);
 
-    EffectSet effectSet = mapFlatmethodToEffectset.get(fmContaining);
-    if (effectSet == null) {
-      effectSet = new EffectSet();
-    }
-
     for (Iterator<RefEdge> iterator = vn.iteratorToReferencees(); iterator.hasNext();) {
       RefEdge edge = iterator.next();
       TaintSet taintSet = edge.getTaints();
@@ -78,18 +68,99 @@ public class EffectsAnalysis {
       for (Iterator<Taint> taintSetIter = taintSet.iterator(); taintSetIter.hasNext();) {
         Taint taint = taintSetIter.next();
 
-//        Effect effect = new Effect(taint.getParamIndex(), taint.getAllocSite(), affectedAlloc, Effect.write, fld);
-//        effectSet.addMethodEffect(taint.getParamIndex(), effect);
-
+        EffectSet effectSet = fm2effectSet.get(fmContaining);
+        if (effectSet == null) {
+          effectSet = new EffectSet();
+        }
+        
+        Effect effect = new Effect(affectedAlloc, Effect.write, fld);
+        effectSet.addEffect(taint, effect);
+
+        if (strongUpdate) {
+          effectSet.addEffect(taint, 
+                              new Effect(affectedAlloc,
+                                         Effect.strongupdate,
+                                         fld)
+                              );
+        }
+
+        fm2effectSet.put(fmContaining, effectSet);
       }
     }
+  }
 
-    mapFlatmethodToEffectset.put(fmContaining, effectSet);
+  public void analyzeFlatCall(FlatMethod fmContaining, FlatMethod fmCallee, Hashtable<Taint, TaintSet> tCallee2tsCaller) {
+    
+    EffectSet esCaller = getEffectSet(fmContaining);
+    if( esCaller == null ) {
+      esCaller = new EffectSet();
+    }
     
+    EffectSet esCallee = getEffectSet(fmCallee);
+    if( esCallee == null ) {
+      esCallee = new EffectSet();
+    }
+
+    Iterator meItr = esCallee.getAllEffectPairs();
+    while( meItr.hasNext() ) {
+      Map.Entry       me      = (Map.Entry)       meItr.next();
+      Taint           tCallee = (Taint)           me.getKey();
+      HashSet<Effect> effects = (HashSet<Effect>) me.getValue();
+
+      if( tCallee2tsCaller.containsKey( tCallee ) ) {
+
+        Iterator<Taint> tItr = tCallee2tsCaller.get( tCallee ).iterator();
+        while( tItr.hasNext() ) {
+          Taint tCaller = tItr.next();
+
+          Iterator<Effect> eItr = effects.iterator();
+          while( eItr.hasNext() ) {
+            Effect e = eItr.next();
+            
+            esCaller.addEffect( tCaller, e );
+          }
+        }
+      }
+    }
+
+    fm2effectSet.put(fmContaining, esCaller);    
   }
 
   public EffectSet getEffectSet(FlatMethod fm) {
-    return mapFlatmethodToEffectset.get(fm);
+    return fm2effectSet.get(fm);
+  }
+
+  public void writeEffectsPerMethod( String outfile ) {
+    try {
+      BufferedWriter bw = new BufferedWriter(new FileWriter(outfile));
+      
+      bw.write( "Effects\n\n" );
+
+      Iterator meItr1 = fm2effectSet.entrySet().iterator();
+      while( meItr1.hasNext() ) {
+        Map.Entry  me1 = (Map.Entry)  meItr1.next();
+        FlatMethod fm  = (FlatMethod) me1.getKey();
+        EffectSet  es  = (EffectSet)  me1.getValue();
+
+        bw.write( "\n"+fm+"\n--------------\n" );
+
+        Iterator meItr2 = es.getAllEffectPairs();
+        while( meItr2.hasNext() ) {
+          Map.Entry       me2     = (Map.Entry)       meItr2.next();
+          Taint           taint   = (Taint)           me2.getKey();
+          HashSet<Effect> effects = (HashSet<Effect>) me2.getValue();
+
+          Iterator<Effect> eItr = effects.iterator();
+          while( eItr.hasNext() ) {
+            Effect e = eItr.next();
+            
+            bw.write( "  "+taint+"-->"+e+"\n" );
+          }
+        }
+      }
+
+      bw.close();
+    } catch( IOException e ) {}
   }
 
   /*
index c2cab6890520a02f65222d0c78994f24c503e553..dbb1d4ed71e779b83b5abc8fb7f991ffbc66d71f 100644 (file)
@@ -241,12 +241,15 @@ public class ReachGraph {
 
   }
 
-  protected void clearRefEdgesFrom( RefSrcNode     referencer,
-                                    TypeDescriptor type,
-                                    String         field,
-                                    boolean        removeAll ) {
+  // return whether at least one edge was removed
+  protected boolean clearRefEdgesFrom( RefSrcNode     referencer,
+                                       TypeDescriptor type,
+                                       String         field,
+                                       boolean        removeAll ) {
     assert referencer != null;
 
+    boolean atLeastOneEdgeRemoved = false;
+
     // get a copy of the set to iterate over, otherwise
     // we will be trying to take apart the set as we
     // are iterating over it, which won't work
@@ -264,8 +267,12 @@ public class ReachGraph {
                        referencee,
                        edge.getType(),
                        edge.getField() );
+
+        atLeastOneEdgeRemoved = true;
       }
     }
+
+    return atLeastOneEdgeRemoved;
   }
 
   protected void clearRefEdgesTo( HeapRegionNode referencee,
@@ -510,9 +517,10 @@ public class ReachGraph {
   }
 
 
-  public void assignTempXFieldFEqualToTempY( TempDescriptor  x,
-                                            FieldDescriptor f,
-                                            TempDescriptor  y ) {
+  // return whether a strong update was actually effected
+  public boolean assignTempXFieldFEqualToTempY( TempDescriptor  x,
+                                                FieldDescriptor f,
+                                                TempDescriptor  y ) {
 
     VariableNode lnX = getVariableNodeFromTemp( x );
     VariableNode lnY = getVariableNodeFromTemp( y );
@@ -526,7 +534,8 @@ public class ReachGraph {
     Set<RefEdge> impossibleEdges = new HashSet<RefEdge>();
 
     // first look for possible strong updates and remove those edges
-    boolean strongUpdate = false;
+    boolean strongUpdateCond          = false;
+    boolean edgeRemovedByStrongUpdate = false;
 
     Iterator<RefEdge> itrXhrn = lnX.iteratorToReferencees();
     while( itrXhrn.hasNext() ) {
@@ -541,8 +550,16 @@ public class ReachGraph {
              )
          ) {
         if( !DISABLE_STRONG_UPDATES ) {
-          strongUpdate = true;
-          clearRefEdgesFrom( hrnX, f.getType(), f.getSymbol(), false );
+          strongUpdateCond = true;
+
+          boolean atLeastOne = 
+            clearRefEdgesFrom( hrnX, 
+                               f.getType(), 
+                               f.getSymbol(), 
+                               false );
+          if( atLeastOne ) {
+            edgeRemovedByStrongUpdate = true;
+          }
         }
       }
     }
@@ -657,19 +674,21 @@ public class ReachGraph {
 
     // if there was a strong update, make sure to improve
     // reachability with a global sweep    
-    if( strongUpdate || !impossibleEdges.isEmpty() ) {    
+    if( edgeRemovedByStrongUpdate || !impossibleEdges.isEmpty() ) {    
       if( !DISABLE_GLOBAL_SWEEP ) {
         globalSweep();
       }
     }    
     
+
     // after x.y=f , stall x and y if they are not accessible
     // also contribute write effects on stall site of x
     // accessible status update
     // if it is in region
     //accessibleVars.add(x);
     //accessibleVars.add(y);
-    
+
+    return edgeRemovedByStrongUpdate;
   }
 
 
@@ -1565,8 +1584,10 @@ public class ReachGraph {
   // equivalent, just eliminate Taints with bad preds
   protected TaintSet 
     toCallerContext( TaintSet                       ts,
-                     Hashtable<Taint, ExistPredSet> calleeTaintsSatisfied 
+                     Hashtable<Taint, ExistPredSet> calleeTaintsSatisfied,
+                     Hashtable<Taint, TaintSet>     tCallee2tsCaller
                      ) {
+
     TaintSet out = TaintSet.factory();
 
     // when the mapping is null it means there were no
@@ -1592,6 +1613,17 @@ public class ReachGraph {
         out = Canonical.add( out,
                              tCaller
                              );
+
+        // this mapping aids the effects analysis--
+        // ONLY DO IF MASTER MAP IS NOT NULL
+        if( tCallee2tsCaller != null ) {
+          TaintSet tsCaller = tCallee2tsCaller.get( tCallee );
+          if( tsCaller == null ) {
+            tsCaller = TaintSet.factory();
+          }
+          tsCaller = Canonical.add( tsCaller, tCaller );
+          tCallee2tsCaller.put( tCallee, tsCaller );
+        }
       }     
     }    
     
@@ -2092,6 +2124,7 @@ public class ReachGraph {
                        FlatMethod   fmCallee,        
                        ReachGraph   rgCallee,
                        Set<Integer> callerNodeIDsCopiedToCallee,
+                       Hashtable<Taint, TaintSet> tCallee2tsCaller,
                        boolean      writeDebugDOTs
                        ) {
 
@@ -2629,7 +2662,8 @@ public class ReachGraph {
                                                          calleeEdge2calleeStatesSatisfied.get( reCallee ) ),
                                         preds,
                                         toCallerContext( reCallee.getTaints(),
-                                                         calleeEdge2calleeTaintsSatisfied.get( reCallee ) )
+                                                         calleeEdge2calleeTaintsSatisfied.get( reCallee ),
+                                                         tCallee2tsCaller )
                                         );
 
         ChangeSet cs = ChangeSet.factory();
index fa76629b1897b32d972b107a078932b4c70aaaa8..b000dbb238bcbc3a1567017acfa2818cb7e8b991 100644 (file)
@@ -5,7 +5,7 @@ SOURCE_FILES=$(PROGRAM).java
 BUILDSCRIPT=~/research/Robust/src/buildscript
 
 BSFLAGS= -mainclass Test -justanalyze -ooojava -disjoint -disjoint-k 1 -enable-assertions
-DEBUGFLAGS= -disjoint-write-dots final -disjoint-write-initial-contexts -disjoint-write-ihms -disjoint-debug-snap-method main 0 10 true
+#DEBUGFLAGS= -disjoint-write-dots final -disjoint-write-initial-contexts -disjoint-write-ihms -disjoint-debug-snap-method main 0 10 true
 
 all: $(PROGRAM).bin
 
@@ -27,3 +27,4 @@ clean:
        rm -f  *.dot
        rm -f  *.png
        rm -f  aliases.txt
+       rm -f  effects-per-method.txt
index 4ec6d2ab2a8f9217564ae4b0aaaa473aca149f44..f0f9b02a3a4993c475d625979f5a0a82ec9e1d06 100644 (file)
@@ -12,19 +12,17 @@ public class Test {
     Foo b = new Foo();
 
     /*
-    if( false ) {
-      a = new Foo();
+    rblock r1 {
+      a.f = new Foo();
     }
     */
-
+    
     rblock r1 {
       a.f = new Foo();
-
       b.f = new Foo();
 
       doSomething( a, b );
     }
-   
   }
 
   static void doSomething( Foo a, Foo b ) {