--- /dev/null
+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";
+ }
+}
import IR.*;
import IR.Flat.*;
+import Util.UtilAlgorithms;
import java.util.*;
import java.io.*;
public Hashtable<Integer, TokenTuple> paramIndex2paramTokenSecondaryStar;
+ // consult these sets in algorithms when considering what
+ // to do with temps or their label nodes found in the graph
+ public Set<TempDescriptor> outOfScopeTemps;
+ public Set<LabelNode> outOfScopeLabels;
+ public Set<TempDescriptor> parameterTemps;
+ public Set<LabelNode> 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<AccessPath> > temp2accessPaths;
paramIndex2paramTokenSecondaryStar = new Hashtable<Integer, TokenTuple >();
allocationSites = new HashSet <AllocationSite>();
+
+ outOfScopeTemps = new HashSet<TempDescriptor>();
+ outOfScopeLabels = new HashSet<LabelNode>();
+ parameterTemps = new HashSet<TempDescriptor>();
+ parameterLabels = new HashSet<LabelNode>();
+
+ outOfScopeTemps.add( tdReturn );
+ outOfScopeLabels.add( getLabelNodeFromTemp( tdReturn ) );
+
+ temp2accessPaths = new Hashtable< TempDescriptor, Set<AccessPath> >();
}
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
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;
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?
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?
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 );
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;
mergeReferenceEdges(og);
mergeParamIndexMappings(og);
mergeAllocationSites(og);
+ mergeAccessPaths(og);
+ mergeTempAndLabelCategories(og);
}
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
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;
}
}
+ protected boolean areAccessPathsEqual(OwnershipGraph og) {
+ return temp2accessPaths.equals( og.temp2accessPaths );
+ }
+
+
+
public Set<HeapRegionNode> hasPotentialAlias( HeapRegionNode hrn1, HeapRegionNode hrn2 ) {
assert hrn1 != null;
assert hrn2 != null;
--- /dev/null
+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 );
+ }
+ }
+ }
+
+}