From: jjenista Date: Fri, 23 Oct 2009 22:12:22 +0000 (+0000) Subject: starting implementation for access paths to improve edge mapping X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=91cf59d77ebf24ac5d5658cb83fdfb73d872bedc;p=IRC.git starting implementation for access paths to improve edge mapping --- diff --git a/Robust/src/Analysis/OwnershipAnalysis/AccessPath.java b/Robust/src/Analysis/OwnershipAnalysis/AccessPath.java new file mode 100644 index 00000000..afab114f --- /dev/null +++ b/Robust/src/Analysis/OwnershipAnalysis/AccessPath.java @@ -0,0 +1,57 @@ +package Analysis.OwnershipAnalysis; + +import IR.*; +import IR.Flat.*; +import java.util.*; + +// An access path is relevant in a callee method to +// a caller's heap. When mapping edges from a callee +// into the caller, if the caller's heap does not have +// any matching access paths, then the edge could not +// exist in that context and is ignored. + +public class AccessPath { + + public AccessPath() { + } + + public boolean equals( Object o ) { + if( o == null ) { + return false; + } + + if( !(o instanceof AccessPath) ) { + return false; + } + + return true; + /* + VariableSourceToken vst = (VariableSourceToken) o; + + // the reference vars have no bearing on equality + return sese.equals( vst.sese ) && + addrVar.equals( vst.addrVar ) && + seseAge.equals( vst.seseAge ); + */ + } + + public int hashCode() { + // the reference vars have no bearing on hashCode + return 1; //(sese.hashCode() << 3) * (addrVar.hashCode() << 4) ^ seseAge.intValue(); + } + + public String toString() { + return "ap"; + } + + public String toStringForDOT() { + /* + if( disjointId != null ) { + return "disjoint "+disjointId+"\\n"+toString()+"\\n"+getType().toPrettyString(); + } else { + return toString()+"\\n"+getType().toPrettyString(); + } + */ + return "do"; + } +} diff --git a/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java b/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java index 6df454bc..feca5776 100644 --- a/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java +++ b/Robust/src/Analysis/OwnershipAnalysis/OwnershipGraph.java @@ -2,6 +2,7 @@ package Analysis.OwnershipAnalysis; import IR.*; import IR.Flat.*; +import Util.UtilAlgorithms; import java.util.*; import java.io.*; @@ -75,6 +76,17 @@ public class OwnershipGraph { public Hashtable paramIndex2paramTokenSecondaryStar; + // consult these sets in algorithms when considering what + // to do with temps or their label nodes found in the graph + public Set outOfScopeTemps; + public Set outOfScopeLabels; + public Set parameterTemps; + public Set parameterLabels; + + // this is kept to allow edges created from variables (a src and dst) + // to know the access paths that allowed it, to prune edges when + // mapping them back into the caller--an access path must appear + public Hashtable< TempDescriptor, Set > temp2accessPaths; @@ -100,6 +112,16 @@ public class OwnershipGraph { paramIndex2paramTokenSecondaryStar = new Hashtable(); allocationSites = new HashSet (); + + outOfScopeTemps = new HashSet(); + outOfScopeLabels = new HashSet(); + parameterTemps = new HashSet(); + parameterLabels = new HashSet(); + + outOfScopeTemps.add( tdReturn ); + outOfScopeLabels.add( getLabelNodeFromTemp( tdReturn ) ); + + temp2accessPaths = new Hashtable< TempDescriptor, Set >(); } @@ -644,12 +666,19 @@ public class OwnershipGraph { null, // reachability set "param"+paramIndex+" obj" ); + parameterTemps.add( td ); + parameterLabels.add( lnParam ); + + // this is a non-program-accessible label that picks up beta // info to be used for fixing a caller of this method TempDescriptor tdParamQ = new TempDescriptor( td+qString ); paramIndex2tdQ.put( paramIndex, tdParamQ ); LabelNode lnParamQ = getLabelNodeFromTemp( tdParamQ ); + outOfScopeTemps.add( tdParamQ ); + outOfScopeLabels.add( lnParamQ ); + // keep track of heap regions that were created for // parameter labels, the index of the parameter they // are for is important when resolving method calls @@ -659,11 +688,11 @@ public class OwnershipGraph { s.add( paramIndex ); idPrimary2paramIndexSet.put( newPrimaryID, s ); paramIndex2idPrimary.put( paramIndex, newPrimaryID ); - TokenTuple ttPrimary = new TokenTuple( newPrimaryID, false, // multi-object TokenTuple.ARITY_ONE ).makeCanonical(); + HeapRegionNode hrnSecondary = null; Integer newSecondaryID = null; @@ -676,6 +705,9 @@ public class OwnershipGraph { paramIndex2tdR.put( paramIndex, tdParamR ); lnParamR = getLabelNodeFromTemp( tdParamR ); + outOfScopeTemps.add( tdParamR ); + outOfScopeLabels.add( lnParamR ); + hrnSecondary = createNewHeapRegionNode( null, // id or null to generate a new one false, // single object? false, // summary? @@ -796,6 +828,10 @@ public class OwnershipGraph { public void makeAliasedParamHeapRegionNode() { LabelNode lnBlob = getLabelNodeFromTemp( tdAliasBlob ); + + outOfScopeTemps.add( tdAliasBlob ); + outOfScopeLabels.add( lnBlob ); + HeapRegionNode hrn = createNewHeapRegionNode( null, // id or null to generate a new one false, // single object? false, // summary? @@ -833,6 +869,9 @@ public class OwnershipGraph { LabelNode lnParam = getLabelNodeFromTemp( tdParam ); LabelNode lnAliased = getLabelNodeFromTemp( tdAliasBlob ); + parameterTemps.add( tdParam ); + parameterLabels.add( lnParam ); + // this is a non-program-accessible label that picks up beta // info to be used for fixing a caller of this method TempDescriptor tdParamQ = new TempDescriptor( tdParam+qString ); @@ -844,6 +883,11 @@ public class OwnershipGraph { LabelNode lnParamQ = getLabelNodeFromTemp( tdParamQ ); LabelNode lnParamR = getLabelNodeFromTemp( tdParamR ); + outOfScopeTemps.add( tdParamR ); + outOfScopeLabels.add( lnParamR ); + outOfScopeTemps.add( tdParamQ ); + outOfScopeLabels.add( lnParamQ ); + // the lnAliased should always only reference one node, and that // heap region node is the aliased param blob assert lnAliased.getNumReferencees() == 1; @@ -3719,6 +3763,8 @@ public class OwnershipGraph { mergeReferenceEdges(og); mergeParamIndexMappings(og); mergeAllocationSites(og); + mergeAccessPaths(og); + mergeTempAndLabelCategories(og); } @@ -3949,6 +3995,18 @@ public class OwnershipGraph { allocationSites.addAll(og.allocationSites); } + protected void mergeAccessPaths(OwnershipGraph og) { + UtilAlgorithms.mergeHashtablesWithHashSetValues(temp2accessPaths, + og.temp2accessPaths); + } + + protected void mergeTempAndLabelCategories(OwnershipGraph og) { + outOfScopeTemps.addAll(og.outOfScopeTemps); + outOfScopeLabels.addAll(og.outOfScopeLabels); + parameterTemps.addAll(og.parameterTemps); + parameterLabels.addAll(og.parameterLabels); + } + // it is necessary in the equals() member functions @@ -3983,10 +4041,18 @@ public class OwnershipGraph { return false; } + if( !areAccessPathsEqual(og) ) { + return false; + } + // if everything is equal up to this point, // assert that allocationSites is also equal-- // this data is redundant and kept for efficiency - assert allocationSites.equals(og.allocationSites); + assert allocationSites .equals(og.allocationSites ); + assert outOfScopeTemps .equals(og.outOfScopeTemps ); + assert outOfScopeLabels.equals(og.outOfScopeLabels); + assert parameterTemps .equals(og.parameterTemps ); + assert parameterLabels .equals(og.parameterLabels ); return true; } @@ -4187,6 +4253,12 @@ public class OwnershipGraph { } + protected boolean areAccessPathsEqual(OwnershipGraph og) { + return temp2accessPaths.equals( og.temp2accessPaths ); + } + + + public Set hasPotentialAlias( HeapRegionNode hrn1, HeapRegionNode hrn2 ) { assert hrn1 != null; assert hrn2 != null; diff --git a/Robust/src/Makefile b/Robust/src/Makefile index 35b1bc32..2c002416 100644 --- a/Robust/src/Makefile +++ b/Robust/src/Makefile @@ -88,12 +88,14 @@ Analysis/OwnershipAnalysis/ChangeTupleSet.class \ Analysis/OwnershipAnalysis/Canonical.class \ Analysis/OwnershipAnalysis/MethodContext.class \ Analysis/OwnershipAnalysis/ParameterDecomposition.class \ +Analysis/OwnershipAnalysis/AccessPath.class \ Analysis/MLP/MLPAnalysis.class \ Analysis/MLP/VariableSourceToken.class \ Analysis/MLP/SVKey.class \ Analysis/MLP/VarSrcTokTable.class \ Analysis/MLP/CodePlan.class \ Util/GraphNode.class Util/Namer.class Util/Relation.class \ +Util/UtilAlgorithms.class \ Interface/HTTPHeader.class Interface/HTTPResponse.class \ Interface/HTTPServices.class Interface/HashStrings.class \ Interface/JhttpServer.class Interface/JhttpWorker.class \ diff --git a/Robust/src/Tests/OwnershipAnalysisTest/mappingWeakness/test.java b/Robust/src/Tests/OwnershipAnalysisTest/mappingWeakness/test.java index b5d6ffa0..e0a29a80 100644 --- a/Robust/src/Tests/OwnershipAnalysisTest/mappingWeakness/test.java +++ b/Robust/src/Tests/OwnershipAnalysisTest/mappingWeakness/test.java @@ -1,5 +1,5 @@ public class Test { - static public void main( String[] args ) { + static public void main( String[] args ) { int n = 10; Vector v1 = new Vector( n ); for( int i = 0; i < n; ++i ) { diff --git a/Robust/src/Util/UtilAlgorithms.java b/Robust/src/Util/UtilAlgorithms.java new file mode 100644 index 00000000..fd021d05 --- /dev/null +++ b/Robust/src/Util/UtilAlgorithms.java @@ -0,0 +1,34 @@ +package Util; +import java.util.*; + +// this class has static methods that implement useful, +// non-trivially algorithms to prevent code duplication +// and reduce bugs + +public class UtilAlgorithms { + + // This method merge hashtable b into a, where the + // tables both have HashSets as the values. If both + // tables have a common key, the new value is the + // union of the sets the key mapped to in each one. + // Note: the reason it must be a HashSet instead of + // a Set is that we want to clone sets of table b, so + // only a is modified. Set does not provide clone(). + static public void mergeHashtablesWithHashSetValues( Hashtable a, + Hashtable b ) { + Iterator itr = b.entrySet().iterator(); + while( itr.hasNext() ) { + Map.Entry me = (Map.Entry) itr.next(); + Object key = (Object) me.getKey(); + HashSet s1 = (HashSet) me.getValue(); + HashSet s2 = (HashSet) a.get( key ); + + if( s2 == null ) { + a.put( key, s1.clone() ); + } else { + s2.addAll( s1 ); + } + } + } + +}