From: jjenista Date: Fri, 25 Jun 2010 18:18:50 +0000 (+0000) Subject: analysis collects effects per method and interprocedurally X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=5fdf584dd337b73e7af7dd6c32bb4fff3c2135d5;p=IRC.git analysis collects effects per method and interprocedurally --- diff --git a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java index 03bfb6d4..e4dbabfc 100644 --- a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java +++ b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java @@ -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 > @@ -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 tCallee2tsCaller = null; + + if( doEffectsAnalysis ) { + tCallee2tsCaller = new Hashtable(); + } + rgCopy.resolveMethodCall( fc, fmPossible, rgEffect, callerNodeIDsCopiedToCallee, + tCallee2tsCaller, writeDebugDOTs ); + + if( doEffectsAnalysis ) { + effectsAnalysis.analyzeFlatCall( fmContaining, + fmPossible, + tCallee2tsCaller ); + } } - rgMergeOfEffects.merge( rgCopy ); + rgMergeOfEffects.merge( rgCopy ); } diff --git a/Robust/src/Analysis/Disjoint/Effect.java b/Robust/src/Analysis/Disjoint/Effect.java index f53cff2e..658c6482 100644 --- a/Robust/src/Analysis/Disjoint/Effect.java +++ b/Robust/src/Analysis/Disjoint/Effect.java @@ -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"; diff --git a/Robust/src/Analysis/Disjoint/EffectSet.java b/Robust/src/Analysis/Disjoint/EffectSet.java index cbddc2a3..12d12089 100644 --- a/Robust/src/Analysis/Disjoint/EffectSet.java +++ b/Robust/src/Analysis/Disjoint/EffectSet.java @@ -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> methodEffectSet; - private Hashtable> rblockEffectSet; + private Hashtable> taint2effects; public EffectSet() { - methodEffectSet = new Hashtable>(); + taint2effects = new Hashtable>(); } - public void addMethodEffect(Integer paramIdx, Effect e) { - HashSet effectSet = methodEffectSet.get(paramIdx); + public void addEffect(Taint t, Effect e) { + HashSet effectSet = taint2effects.get(t); if (effectSet == null) { effectSet = new HashSet(); } 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 getEffects(Taint t) { + return taint2effects.get(t); } + public Iterator getAllEffectPairs() { + return taint2effects.entrySet().iterator(); + } + + public String toString() { + return taint2effects.toString(); + } } diff --git a/Robust/src/Analysis/Disjoint/EffectsAnalysis.java b/Robust/src/Analysis/Disjoint/EffectsAnalysis.java index 043d6dde..0e81f1b8 100644 --- a/Robust/src/Analysis/Disjoint/EffectsAnalysis.java +++ b/Robust/src/Analysis/Disjoint/EffectsAnalysis.java @@ -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 mapFlatmethodToEffectset; + private Hashtable fm2effectSet; - // private Hashtable - // mapMethodContextToMethodEffects; - // boolean methodeffects = false; - - public EffectsAnalysis(boolean methodeffects) { - mapFlatmethodToEffectset = new Hashtable(); + public EffectsAnalysis() { + fm2effectSet = new Hashtable(); } 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 iterator = vn.iteratorToReferencees(); iterator.hasNext();) { RefEdge edge = iterator.next(); TaintSet taintSet = edge.getTaints(); @@ -52,25 +44,23 @@ public class EffectsAnalysis { for (Iterator 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 iterator = vn.iteratorToReferencees(); iterator.hasNext();) { RefEdge edge = iterator.next(); TaintSet taintSet = edge.getTaints(); @@ -78,18 +68,99 @@ public class EffectsAnalysis { for (Iterator 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 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 effects = (HashSet) me.getValue(); + + if( tCallee2tsCaller.containsKey( tCallee ) ) { + + Iterator tItr = tCallee2tsCaller.get( tCallee ).iterator(); + while( tItr.hasNext() ) { + Taint tCaller = tItr.next(); + + Iterator 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 effects = (HashSet) me2.getValue(); + + Iterator eItr = effects.iterator(); + while( eItr.hasNext() ) { + Effect e = eItr.next(); + + bw.write( " "+taint+"-->"+e+"\n" ); + } + } + } + + bw.close(); + } catch( IOException e ) {} } /* diff --git a/Robust/src/Analysis/Disjoint/ReachGraph.java b/Robust/src/Analysis/Disjoint/ReachGraph.java index c2cab689..dbb1d4ed 100644 --- a/Robust/src/Analysis/Disjoint/ReachGraph.java +++ b/Robust/src/Analysis/Disjoint/ReachGraph.java @@ -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 impossibleEdges = new HashSet(); // first look for possible strong updates and remove those edges - boolean strongUpdate = false; + boolean strongUpdateCond = false; + boolean edgeRemovedByStrongUpdate = false; Iterator 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 calleeTaintsSatisfied + Hashtable calleeTaintsSatisfied, + Hashtable 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 callerNodeIDsCopiedToCallee, + Hashtable 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(); diff --git a/Robust/src/Tests/disjoint/taintTest1/makefile b/Robust/src/Tests/disjoint/taintTest1/makefile index fa76629b..b000dbb2 100644 --- a/Robust/src/Tests/disjoint/taintTest1/makefile +++ b/Robust/src/Tests/disjoint/taintTest1/makefile @@ -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 diff --git a/Robust/src/Tests/disjoint/taintTest1/test.java b/Robust/src/Tests/disjoint/taintTest1/test.java index 4ec6d2ab..f0f9b02a 100644 --- a/Robust/src/Tests/disjoint/taintTest1/test.java +++ b/Robust/src/Tests/disjoint/taintTest1/test.java @@ -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 ) {