return getAllocationSiteFromFlatNewPRIVATE(fn);
}
+
public boolean createsPotentialAliases(Descriptor taskOrMethod,
int paramIndex1,
int paramIndex2) {
- OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+ OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(paramIndex1, paramIndex2);
}
int paramIndex,
AllocationSite alloc) {
- OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+ OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(paramIndex, alloc);
}
AllocationSite alloc,
int paramIndex) {
- OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+ OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(paramIndex, alloc);
}
AllocationSite alloc1,
AllocationSite alloc2) {
- OwnershipGraph og = mapDescriptorToCompleteOwnershipGraph.get(taskOrMethod);
+ OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(alloc1, alloc2);
}
+
+ protected OwnershipGraph getGraphOfAllContextsFromDescriptor(Descriptor d) {
+ assert d != null;
+
+ OwnershipGraph og = new OwnershipGraph( allocationDepth, typeUtil );
+
+ assert mapDescriptorToAllMethodContexts.containsKey( d );
+ HashSet<MethodContext> contexts = mapDescriptorToAllMethodContexts.get( d );
+ Iterator<MethodContext> mcItr = contexts.iterator();
+ while( mcItr.hasNext() ) {
+ MethodContext mc = mcItr.next();
+
+ OwnershipGraph ogContext = mapMethodContextToCompleteOwnershipGraph.get(mc);
+ assert ogContext != null;
+
+ og.merge( ogContext );
+ }
+
+ return og;
+ }
+
+
// use the methods given above to check every possible alias
// between task parameters and flagged allocation sites reachable
// from the task
// processing all methods in the program, and by methods
// TaskDescriptor and MethodDescriptor are combined
// together, with a common parent class Descriptor
- private Hashtable<FlatMethod, OwnershipGraph> mapFlatMethodToInitialParamAllocGraph;
- private Hashtable<Descriptor, OwnershipGraph> mapDescriptorToCompleteOwnershipGraph;
- private Hashtable<FlatNew, AllocationSite> mapFlatNewToAllocationSite;
- private Hashtable<Descriptor, HashSet<AllocationSite> > mapDescriptorToAllocationSiteSet;
- private Hashtable<Descriptor, Integer> mapDescriptorToNumUpdates;
+ private Hashtable<MethodContext, OwnershipGraph> mapMethodContextToInitialParamAllocGraph;
+ private Hashtable<MethodContext, OwnershipGraph> mapMethodContextToCompleteOwnershipGraph;
+ private Hashtable<FlatNew, AllocationSite> mapFlatNewToAllocationSite;
+ private Hashtable<Descriptor, HashSet<AllocationSite> > mapDescriptorToAllocationSiteSet;
+ private Hashtable<MethodContext, Integer> mapMethodContextToNumUpdates;
+ private Hashtable<Descriptor, HashSet<MethodContext> > mapDescriptorToAllMethodContexts;
// Use these data structures to track progress of one pass of
// processing the FlatNodes of a particular method
// reduced by visiting a descriptor during analysis. When dependents
// must be scheduled, only those contained in descriptorsToAnalyze
// should be re-added to this set
- private HashSet<Descriptor> descriptorsToVisit;
+ private HashSet<MethodContext> methodContextsToVisit;
// a special field descriptor for all array elements
private static FieldDescriptor fdElement = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC),
"elements",
null,
false);
+
+ // a special temp descriptor for setting more than one parameter label
+ // to the all-aliased-parameters heap region node
+ protected static TempDescriptor tdAliasedParams = new TempDescriptor("_AllAliasedParams___");
+
+
// for controlling DOT file output
private boolean writeDOTs;
private boolean writeAllDOTs;
descriptorsToAnalyze = new HashSet<Descriptor>();
- mapFlatMethodToInitialParamAllocGraph =
- new Hashtable<FlatMethod, OwnershipGraph>();
+ mapMethodContextToInitialParamAllocGraph =
+ new Hashtable<MethodContext, OwnershipGraph>();
- mapDescriptorToCompleteOwnershipGraph =
- new Hashtable<Descriptor, OwnershipGraph>();
+ mapMethodContextToCompleteOwnershipGraph =
+ new Hashtable<MethodContext, OwnershipGraph>();
mapFlatNewToAllocationSite =
new Hashtable<FlatNew, AllocationSite>();
mapDescriptorToAllocationSiteSet =
new Hashtable<Descriptor, HashSet<AllocationSite> >();
+ mapDescriptorToAllMethodContexts =
+ new Hashtable<Descriptor, HashSet<MethodContext> >();
+
+
if( writeAllDOTs ) {
- mapDescriptorToNumUpdates = new Hashtable<Descriptor, Integer>();
+ mapMethodContextToNumUpdates = new Hashtable<MethodContext, Integer>();
}
// initialize methods to visit as the set of all tasks in the
fm = state.getMethodFlat( (TaskDescriptor) d);
}
- System.out.println("Previsiting " + d);
+ MethodContext mc = new MethodContext( d );
+ assert !mapDescriptorToAllMethodContexts.containsKey( d );
+ HashSet<MethodContext> s = new HashSet<MethodContext>();
+ s.add( mc );
+ mapDescriptorToAllMethodContexts.put( d, s );
+
+ System.out.println("Previsiting " + mc);
- og = analyzeFlatNode(d, fm, null, og);
- setGraphForDescriptor(d, og);
+ og = analyzeFlatNode(mc, fm, null, og);
+ setGraphForMethodContext(mc, og);
}
System.out.println("");
// they call are updated
private void analyzeMethods() throws java.io.IOException {
- descriptorsToVisit = (HashSet<Descriptor>)descriptorsToAnalyze.clone();
+ methodContextsToVisit = new HashSet<MethodContext>();
+ Iterator<Descriptor> itrd2a = descriptorsToAnalyze.iterator();
+ while( itrd2a.hasNext() ) {
+ HashSet<MethodContext> mcs = mapDescriptorToAllMethodContexts.get( itrd2a.next() );
+ assert mcs != null;
+
+ Iterator<MethodContext> itrmc = mcs.iterator();
+ while( itrmc.hasNext() ) {
+ methodContextsToVisit.add( itrmc.next() );
+ }
+ }
+
+ while( !methodContextsToVisit.isEmpty() ) {
+ MethodContext mc = methodContextsToVisit.iterator().next();
+ methodContextsToVisit.remove(mc);
- while( !descriptorsToVisit.isEmpty() ) {
- Descriptor d = (Descriptor) descriptorsToVisit.iterator().next();
- descriptorsToVisit.remove(d);
// because the task or method descriptor just extracted
// was in the "to visit" set it either hasn't been analyzed
// If there is a change detected, add any methods/tasks
// that depend on this one to the "to visit" set.
- System.out.println("Analyzing " + d);
+ System.out.println("Analyzing " + mc);
+ Descriptor d = mc.getDescriptor();
FlatMethod fm;
if( d instanceof MethodDescriptor ) {
fm = state.getMethodFlat( (MethodDescriptor) d);
fm = state.getMethodFlat( (TaskDescriptor) d);
}
- OwnershipGraph og = analyzeFlatMethod(d, fm);
- OwnershipGraph ogPrev = mapDescriptorToCompleteOwnershipGraph.get(d);
+ OwnershipGraph og = analyzeFlatMethod(mc, fm);
+ OwnershipGraph ogPrev = mapMethodContextToCompleteOwnershipGraph.get(mc);
if( !og.equals(ogPrev) ) {
- setGraphForDescriptor(d, og);
+ setGraphForMethodContext(mc, og);
// only methods have dependents, tasks cannot
// be invoked by any user program calls
while( depItr.hasNext() ) {
Descriptor dependent = (Descriptor) depItr.next();
if( descriptorsToAnalyze.contains(dependent) ) {
- descriptorsToVisit.add(dependent);
+
+ HashSet<MethodContext> mcs = mapDescriptorToAllMethodContexts.get( dependent );
+ assert mcs != null;
+
+ Iterator<MethodContext> itrmc = mcs.iterator();
+ while( itrmc.hasNext() ) {
+ methodContextsToVisit.add( itrmc.next() );
+ }
}
}
}
// keep passing the Descriptor of the method along for debugging
// and dot file writing
private OwnershipGraph
- analyzeFlatMethod(Descriptor mDesc,
+ analyzeFlatMethod(MethodContext mc,
FlatMethod flatm) throws java.io.IOException {
// initialize flat nodes to visit as the flat method
- // because all other nodes in this flat method are
- // decendents of the flat method itself
+ // because it is the entry point
flatNodesToVisit = new HashSet<FlatNode>();
flatNodesToVisit.add(flatm);
// apply the analysis of the flat node to the
// ownership graph made from the merge of the
// parent graphs
- og = analyzeFlatNode(mDesc,
+ og = analyzeFlatNode(mc,
fn,
returnNodesToCombineForCompleteOwnershipGraph,
og);
private OwnershipGraph
- analyzeFlatNode(Descriptor methodDesc,
+ analyzeFlatNode(MethodContext mc,
FlatNode fn,
HashSet<FlatReturnNode> setRetNodes,
OwnershipGraph og) throws java.io.IOException {
// parameter IDs are consistent between analysis
// iterations, so if this step has been done already
// just merge in the cached version
- OwnershipGraph ogInitParamAlloc = mapFlatMethodToInitialParamAllocGraph.get(fm);
+ OwnershipGraph ogInitParamAlloc = mapMethodContextToInitialParamAllocGraph.get(mc);
if( ogInitParamAlloc == null ) {
- // analyze this node one time globally
- for( int i = 0; i < fm.numParameters(); ++i ) {
- TempDescriptor tdParam = fm.getParameter(i);
- og.assignTempEqualToParamAlloc(tdParam,
- methodDesc instanceof TaskDescriptor,
- new Integer(i) );
+ // if the method context has aliased parameters, make sure
+ // there is a blob region for all those param labels to
+ // reference
+ Set<Integer> aliasedParamIndices = mc.getAliasedParamIndices();
+ if( !aliasedParamIndices.isEmpty() ) {
+ og.makeAliasedParamHeapRegionNode( tdAliasedParams );
}
- // then remember it
+ // set up each parameter
+ for( int i = 0; i < fm.numParameters(); ++i ) {
+ TempDescriptor tdParam = fm.getParameter( i );
+ Integer paramIndex = new Integer( i );
+
+ if( aliasedParamIndices.contains( paramIndex ) ) {
+ // just point this one to the alias blob
+ og.assignTempEqualToAliasedParam( tdParam,
+ tdAliasedParams,
+ paramIndex );
+ } else {
+ // this parameter is not aliased to others, give it
+ // a fresh parameter heap region
+
+ og.assignTempEqualToParamAlloc(tdParam,
+ mc.getDescriptor() instanceof TaskDescriptor,
+ paramIndex );
+ }
+ }
+
+ // cache the graph
OwnershipGraph ogResult = new OwnershipGraph(allocationDepth, typeUtil);
ogResult.merge(og);
- mapFlatMethodToInitialParamAllocGraph.put(fm, ogResult);
+ mapMethodContextToInitialParamAllocGraph.put(mc, ogResult);
} else {
// or just leverage the cached copy
if( md.isStatic() ) {
// a static method is simply always the same, makes life easy
- OwnershipGraph onlyPossibleCallee = mapDescriptorToCompleteOwnershipGraph.get(md);
ogMergeOfAllPossibleCalleeResults = og;
- ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee);
+
+ Set<Integer> aliasedParamIndices =
+ ogMergeOfAllPossibleCalleeResults.calculateAliasedParamSet(fc, md.isStatic(), flatm);
+ MethodContext mcNew = new MethodContext( md, aliasedParamIndices );
+ OwnershipGraph onlyPossibleCallee = mapMethodContextToCompleteOwnershipGraph.get( mcNew );
+
+ if( onlyPossibleCallee == null ) {
+ // if this method context has never been analyzed just schedule it for analysis
+ // and skip over this call site for now
+ methodContextsToVisit.add( mcNew );
+
+ } else {
+ ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee);
+ }
+
} else {
// if the method descriptor is virtual, then there could be a
// set of possible methods that will actually be invoked, so
Iterator i = possibleCallees.iterator();
while( i.hasNext() ) {
MethodDescriptor possibleMd = (MethodDescriptor) i.next();
+ FlatMethod pflatm = state.getMethodFlat(possibleMd);
// don't alter the working graph (og) until we compute a result for every
// possible callee, merge them all together, then set og to that
OwnershipGraph ogCopy = new OwnershipGraph(allocationDepth, typeUtil);
ogCopy.merge(og);
- OwnershipGraph ogPotentialCallee = mapDescriptorToCompleteOwnershipGraph.get(possibleMd);
- ogCopy.resolveMethodCall(fc, md.isStatic(), flatm, ogPotentialCallee);
+ Set<Integer> aliasedParamIndices =
+ ogCopy.calculateAliasedParamSet(fc, possibleMd.isStatic(), pflatm);
+ MethodContext mcNew = new MethodContext( possibleMd, aliasedParamIndices );
+ OwnershipGraph ogPotentialCallee = mapMethodContextToCompleteOwnershipGraph.get( mcNew );
+
+ if( ogPotentialCallee == null ) {
+ // if this method context has never been analyzed just schedule it for analysis
+ // and skip over this call site for now
+ methodContextsToVisit.add( mcNew );
+
+ } else {
+ ogCopy.resolveMethodCall(fc, possibleMd.isStatic(), pflatm, ogPotentialCallee);
+ }
+
ogMergeOfAllPossibleCalleeResults.merge(ogCopy);
}
}
}
- private void setGraphForDescriptor(Descriptor d, OwnershipGraph og)
+ private void setGraphForMethodContext(MethodContext mc, OwnershipGraph og)
throws IOException {
- mapDescriptorToCompleteOwnershipGraph.put(d, og);
+ mapMethodContextToCompleteOwnershipGraph.put(mc, og);
// arguments to writeGraph are:
// boolean writeLabels,
if( writeDOTs ) {
if( !writeAllDOTs ) {
- og.writeGraph(d, true, true, true, false, false);
+ og.writeGraph(mc, true, true, true, false, false);
} else {
- if( !mapDescriptorToNumUpdates.containsKey(d) ) {
- mapDescriptorToNumUpdates.put(d, new Integer(0) );
+ if( !mapMethodContextToNumUpdates.containsKey(mc) ) {
+ mapMethodContextToNumUpdates.put(mc, new Integer(0) );
}
- Integer n = mapDescriptorToNumUpdates.get(d);
- og.writeGraph(d, n, true, true, true, false, false);
- mapDescriptorToNumUpdates.put(d, n + 1);
+ Integer n = mapMethodContextToNumUpdates.get(mc);
+ og.writeGraph(mc, n, true, true, true, false, false);
+ mapMethodContextToNumUpdates.put(mc, n + 1);
}
}
}
protected static TempDescriptor tdReturn = new TempDescriptor("_Return___");
+ protected static final int bogusParamIndexInt = -2;
+
public Hashtable<Integer, HeapRegionNode> id2hrn;
public Hashtable<TempDescriptor, LabelNode > td2ln;
- public Hashtable<Integer, Integer > id2paramIndex;
+ public Hashtable<Integer, Set<Integer> > id2paramIndexSet;
public Hashtable<Integer, Integer > paramIndex2id;
public Hashtable<Integer, TempDescriptor> paramIndex2tdQ;
this.allocationDepth = allocationDepth;
this.typeUtil = typeUtil;
- id2hrn = new Hashtable<Integer, HeapRegionNode>();
- td2ln = new Hashtable<TempDescriptor, LabelNode >();
- id2paramIndex = new Hashtable<Integer, Integer >();
- paramIndex2id = new Hashtable<Integer, Integer >();
- paramIndex2tdQ = new Hashtable<Integer, TempDescriptor>();
+ id2hrn = new Hashtable<Integer, HeapRegionNode>();
+ td2ln = new Hashtable<TempDescriptor, LabelNode >();
+ id2paramIndexSet = new Hashtable<Integer, Set<Integer> >();
+ paramIndex2id = new Hashtable<Integer, Integer >();
+ paramIndex2tdQ = new Hashtable<Integer, TempDescriptor>();
allocationSites = new HashSet <AllocationSite>();
}
// parameter labels, the index of the parameter they
// are for is important when resolving method calls
Integer newID = hrn.getID();
- assert !id2paramIndex.containsKey(newID);
- assert !id2paramIndex.containsValue(paramIndex);
- id2paramIndex.put(newID, paramIndex);
+ assert !id2paramIndexSet.containsKey(newID);
+ Set s = new HashSet<Integer>();
+ s.add( paramIndex );
+ id2paramIndexSet.put(newID, s);
paramIndex2id.put(paramIndex, newID);
paramIndex2tdQ.put(paramIndex, tdParamQ);
addReferenceEdge(hrn, hrn, edgeReflexive);
}
+ public void makeAliasedParamHeapRegionNode(TempDescriptor td) {
+ assert td != null;
+
+ LabelNode lnParam = getLabelNodeFromTemp(td);
+ HeapRegionNode hrn = createNewHeapRegionNode(null,
+ false,
+ false,
+ false,
+ true,
+ null,
+ null,
+ "aliasedParams");
+
+
+ ReachabilitySet beta = new ReachabilitySet(new TokenTuple(hrn.getID(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical()
+ ).makeCanonical();
+
+ // heap regions for parameters are always multiple object (see above)
+ // and have a reference to themselves, because we can't know the
+ // structure of memory that is passed into the method. We're assuming
+ // the worst here.
+
+ ReferenceEdge edgeFromLabel =
+ new ReferenceEdge(lnParam, hrn, null, false, beta);
+
+ ReferenceEdge edgeReflexive =
+ new ReferenceEdge(hrn, hrn, null, true, beta);
+
+ addReferenceEdge(lnParam, hrn, edgeFromLabel);
+ addReferenceEdge(hrn, hrn, edgeReflexive);
+ }
+
+ public void assignTempEqualToAliasedParam(TempDescriptor tdParam,
+ TempDescriptor tdAliased,
+ Integer paramIndex ) {
+
+ assert tdParam != null;
+ assert tdAliased != null;
+
+ LabelNode lnParam = getLabelNodeFromTemp(tdParam);
+ LabelNode lnAliased = getLabelNodeFromTemp(tdAliased);
+
+ // 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+"specialQ");
+ LabelNode lnParamQ = getLabelNodeFromTemp(tdParamQ);
+
+ // the lnAliased should always only reference one node, and that
+ // heap region node is the aliased param blob
+ assert lnAliased.getNumReferencees() == 1;
+ HeapRegionNode hrnAliasBlob = lnAliased.iteratorToReferencees().next().getDst();
+
+ // 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
+ Integer idAliased = hrnAliasBlob.getID();
+ Set s = id2paramIndexSet.get( idAliased );
+ if( s == null ) {
+ s = new HashSet<Integer>();
+ }
+ s.add( paramIndex );
+ id2paramIndexSet.put(idAliased, s);
+ paramIndex2id.put(paramIndex, idAliased);
+ paramIndex2tdQ.put(paramIndex, tdParamQ);
+
+ ReachabilitySet beta = new ReachabilitySet(new TokenTuple(idAliased,
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical()
+ ).makeCanonical();
+
+ // heap regions for parameters are always multiple object (see above)
+ // and have a reference to themselves, because we can't know the
+ // structure of memory that is passed into the method. We're assuming
+ // the worst here.
+
+ ReferenceEdge edgeFromLabel =
+ new ReferenceEdge(lnParam, hrnAliasBlob, null, false, beta);
+
+ ReferenceEdge edgeFromLabelQ =
+ new ReferenceEdge(lnParamQ, hrnAliasBlob, null, false, beta);
+
+ addReferenceEdge(lnParam, hrnAliasBlob, edgeFromLabel);
+ addReferenceEdge(lnParamQ, hrnAliasBlob, edgeFromLabelQ);
+ }
+
+
public void assignReturnEqualToTemp(TempDescriptor x) {
}
+ public Set<Integer> calculateAliasedParamSet(FlatCall fc,
+ boolean isStatic,
+ FlatMethod fm) {
+
+ Hashtable<Integer, LabelNode> paramIndex2ln =
+ new Hashtable<Integer, LabelNode>();
+
+ Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes =
+ new Hashtable<Integer, HashSet<HeapRegionNode> >();
+
+ for( int i = 0; i < fm.numParameters(); ++i ) {
+ Integer paramIndex = new Integer(i);
+
+ // now depending on whether the callee is static or not
+ // we need to account for a "this" argument in order to
+ // find the matching argument in the caller context
+ TempDescriptor argTemp_i;
+ if( isStatic ) {
+ argTemp_i = fc.getArg(paramIndex);
+ } else {
+ if( paramIndex.equals(0) ) {
+ argTemp_i = fc.getThis();
+ } else {
+ argTemp_i = fc.getArg(paramIndex - 1);
+ }
+ }
+
+ // in non-static methods there is a "this" pointer
+ // that should be taken into account
+ if( isStatic ) {
+ assert fc.numArgs() == fm.numParameters();
+ } else {
+ assert fc.numArgs() + 1 == fm.numParameters();
+ }
+
+ LabelNode argLabel_i = getLabelNodeFromTemp(argTemp_i);
+ paramIndex2ln.put(paramIndex, argLabel_i);
+ }
+
+ Iterator lnArgItr = paramIndex2ln.entrySet().iterator();
+ while( lnArgItr.hasNext() ) {
+ Map.Entry me = (Map.Entry)lnArgItr.next();
+ Integer index = (Integer) me.getKey();
+ LabelNode lnArg_i = (LabelNode) me.getValue();
+
+ // rewrite alpha for the nodes reachable from argument label i
+ HashSet<HeapRegionNode> reachableNodes = new HashSet<HeapRegionNode>();
+ HashSet<HeapRegionNode> todoNodes = new HashSet<HeapRegionNode>();
+
+ // to find all reachable nodes, start with label referencees
+ Iterator<ReferenceEdge> edgeArgItr = lnArg_i.iteratorToReferencees();
+ while( edgeArgItr.hasNext() ) {
+ ReferenceEdge edge = edgeArgItr.next();
+ todoNodes.add(edge.getDst() );
+ }
+
+ // then follow links until all reachable nodes have been found
+ while( !todoNodes.isEmpty() ) {
+ HeapRegionNode hrn = todoNodes.iterator().next();
+ todoNodes.remove(hrn);
+ reachableNodes.add(hrn);
+
+ Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencees();
+ while( edgeItr.hasNext() ) {
+ ReferenceEdge edge = edgeItr.next();
+
+ if( !reachableNodes.contains(edge.getDst() ) ) {
+ todoNodes.add(edge.getDst() );
+ }
+ }
+ }
+
+ // save for later
+ paramIndex2reachableCallerNodes.put(index, reachableNodes);
+ }
+
+ Set<Integer> aliasedIndices = new HashSet<Integer>();
+
+ // check for arguments that are aliased
+ for( int i = 0; i < fm.numParameters(); ++i ) {
+ for( int j = 0; j < i; ++j ) {
+ HashSet<HeapRegionNode> s1 = paramIndex2reachableCallerNodes.get( i );
+ HashSet<HeapRegionNode> s2 = paramIndex2reachableCallerNodes.get( j );
+
+ Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(s1);
+ intersection.retainAll(s2);
+
+ if( !intersection.isEmpty() ) {
+ aliasedIndices.add( new Integer( i ) );
+ aliasedIndices.add( new Integer( j ) );
+ }
+ }
+ }
+
+ return aliasedIndices;
+ }
+
+
public void resolveMethodCall(FlatCall fc,
boolean isStatic,
FlatMethod fm,
// add a bogus entry with the identity rule for easy rewrite
// of new callee nodes and edges, doesn't belong to any parameter
- Integer bogusID = new Integer(-1);
- Integer bogusIndex = new Integer(-1);
+ Integer bogusID = new Integer(bogusParamIndexInt);
+ Integer bogusIndex = new Integer(bogusParamIndexInt);
TokenTuple bogusToken = new TokenTuple(bogusID, true, TokenTuple.ARITY_ONE).makeCanonical();
TokenTuple bogusTokenPlus = new TokenTuple(bogusID, true, TokenTuple.ARITY_ONEORMORE).makeCanonical();
ReachabilitySet rsIdentity =
}
-
-
- // check for parameters that are aliased prior to this call site
- // if so, come to a grinding halt. Later, we should move this
- // up before doing any alpha/beta updates
- for( int i = 0; i < fm.numParameters(); ++i ) {
- for( int j = 0; j < i; ++j ) {
- HashSet<HeapRegionNode> s1 = paramIndex2reachableCallerNodes.get( i );
- HashSet<HeapRegionNode> s2 = paramIndex2reachableCallerNodes.get( j );
-
- Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(s1);
- intersection.retainAll(s2);
-
- if( !intersection.isEmpty() ) {
- // uh oh
- System.out.println( " Arguments "+j+" and "+i+" are aliased just before" );
- System.out.println( " "+fc+" calls "+fm+"\n" );
- //System.exit( -1 );
- }
- }
- }
-
-
-
-
// verify the existence of allocation sites and their
// shadows from the callee in the context of this caller graph
// then map allocated nodes of callee onto the caller shadows
HashSet<HeapRegionNode> possibleCallerHRNs = new HashSet<HeapRegionNode>();
- Integer paramIndexCallee = ogCallee.id2paramIndex.get(hrnCallee.getID() );
+ Set<Integer> paramIndicesCallee = ogCallee.id2paramIndexSet.get( hrnCallee.getID() );
- if( paramIndexCallee == null ) {
+ if( paramIndicesCallee == null ) {
// this is a node allocated in the callee then and it has
// exactly one shadow node in the caller to map to
AllocationSite as = hrnCallee.getAllocationSite();
} else {
// this is a node that was created to represent a parameter
// so it maps to a whole mess of heap regions
- assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee);
- possibleCallerHRNs = paramIndex2reachableCallerNodes.get(paramIndexCallee);
+ Iterator<Integer> itrIndex = paramIndicesCallee.iterator();
+ while( itrIndex.hasNext() ) {
+ Integer paramIndexCallee = itrIndex.next();
+ assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee);
+ possibleCallerHRNs.addAll( paramIndex2reachableCallerNodes.get(paramIndexCallee) );
+ }
}
return possibleCallerHRNs;
// same number of parameters, or if one or both parameter
// index tables are empty
protected void mergeId2paramIndex(OwnershipGraph og) {
- if( id2paramIndex.size() == 0 ) {
- id2paramIndex = og.id2paramIndex;
- paramIndex2id = og.paramIndex2id;
- paramIndex2tdQ = og.paramIndex2tdQ;
+ if( id2paramIndexSet.size() == 0 ) {
+ id2paramIndexSet = og.id2paramIndexSet;
+ paramIndex2id = og.paramIndex2id;
+ paramIndex2tdQ = og.paramIndex2tdQ;
return;
}
- if( og.id2paramIndex.size() == 0 ) {
+ if( og.id2paramIndexSet.size() == 0 ) {
return;
}
- assert id2paramIndex.size() == og.id2paramIndex.size();
+ assert id2paramIndexSet.size() == og.id2paramIndexSet.size();
}
protected void mergeAllocationSites(OwnershipGraph og) {
protected boolean areId2paramIndexEqual(OwnershipGraph og) {
- return id2paramIndex.size() == og.id2paramIndex.size();
+ return id2paramIndexSet.size() == og.id2paramIndexSet.size();
}
public boolean hasPotentialAlias(Integer paramIndex1, Integer paramIndex2) {
// for writing ownership graphs to dot files
- public void writeGraph(Descriptor methodDesc,
+ public void writeGraph(MethodContext mc,
FlatNode fn,
boolean writeLabels,
boolean labelSelect,
boolean writeParamMappings
) throws java.io.IOException {
writeGraph(
- methodDesc.getSymbol() +
- methodDesc.getNum() +
+ mc.toString() +
fn.toString(),
writeLabels,
labelSelect,
);
}
- public void writeGraph(Descriptor methodDesc,
+ public void writeGraph(MethodContext mc,
boolean writeLabels,
boolean labelSelect,
boolean pruneGarbage,
boolean writeParamMappings
) throws java.io.IOException {
- writeGraph(methodDesc+"COMPLETE",
+ writeGraph(mc+"COMPLETE",
writeLabels,
labelSelect,
pruneGarbage,
);
}
- public void writeGraph(Descriptor methodDesc,
+ public void writeGraph(MethodContext mc,
Integer numUpdate,
boolean writeLabels,
boolean labelSelect,
boolean writeParamMappings
) throws java.io.IOException {
- writeGraph(methodDesc+"COMPLETE"+String.format("%05d", numUpdate),
+ writeGraph(mc+"COMPLETE"+String.format("%05d", numUpdate),
writeLabels,
labelSelect,
pruneGarbage,
Analysis/OwnershipAnalysis/ChangeTuple.class \
Analysis/OwnershipAnalysis/ChangeTupleSet.class \
Analysis/OwnershipAnalysis/Canonical.class \
+Analysis/OwnershipAnalysis/MethodContext.class \
Util/GraphNode.class Util/Namer.class Util/Relation.class \
Interface/HTTPHeader.class Interface/HTTPResponse.class \
Interface/HTTPServices.class Interface/HashStrings.class \
--- /dev/null
+PROGRAM=testMethodContexts
+
+SOURCE_FILES=$(PROGRAM).java
+
+BUILDSCRIPT=~/research/Robust/src/buildscript
+BSFLAGS= -recover -ownership -ownaliasfile aliases.txt -enable-assertions -ownwritedots final -ownallocdepth 1 #-flatirtasks
+
+
+all: $(PROGRAM).bin
+
+view: PNGs
+ eog *.png &
+
+PNGs: DOTs
+ d2p *COMPLETE*.dot
+
+DOTs: $(PROGRAM).bin
+
+$(PROGRAM).bin: $(SOURCE_FILES)
+ $(BUILDSCRIPT) $(BSFLAGS) -o $(PROGRAM) $(SOURCE_FILES)
+
+clean:
+ rm -f $(PROGRAM).bin
+ rm -fr tmpbuilddirectory
+ rm -f *~
+ rm -f *.dot
+ rm -f *.png
+ rm -f *.ps
+ rm -f *.eps
+ rm -f aliases.txt
--- /dev/null
+public class Foo { flag f; Foo x; public Foo(){} }
+
+public class Plane {
+ public Plane(){}
+
+ public void fly( Foo p0, Foo p1 ) {
+ p0.x = new Foo(){f};
+ }
+}
+
+public class SpitFire extends Plane {
+ public SpitFire(){}
+
+ public void fly( Foo p0, Foo p1 ) {
+ p1.x = new Foo(){f};
+ }
+}
+
+public class Jet extends Plane {
+ public Jet(){}
+
+ public void fly( Foo p0, Foo p1 ) {
+ Foo jet = new Foo(){f};
+ jet.x = p0;
+ }
+}
+
+public class F14 extends Jet {
+ public F14(){}
+
+ public void fly( Foo p0, Foo p1 ) {
+ Foo f14 = new Foo(){f};
+ f14.x = p1;
+ }
+}
+
+task Startup( StartupObject s{ initialstate } ) {
+
+ Foo a0 = new Foo(){f};
+ Foo a1 = new Foo(){f};
+
+ Plane p;
+
+ if( false ) {
+ p = new Plane();
+ } else if( false ) {
+ p = new SpitFire();
+ } else if( false ) {
+ p = new Jet();
+ } else {
+ p = new F14();
+ }
+
+ p.fly( a0, a1 );
+
+ taskexit( s{ !initialstate } );
+}
+
+
+task SomeOtherTask( Foo foo{f} ) {
+
+ Foo a0 = new Foo(){f};
+ Foo a1 = new Foo(){f};
+
+ Plane p;
+
+ if( false ) {
+ p = new Plane();
+ } else if( false ) {
+ p = new SpitFire();
+ } else if( false ) {
+ p = new Jet();
+ } else {
+ p = new F14();
+ }
+
+ a0.x = a1;
+ p.fly( a0, a1 );
+
+ taskexit( foo{!f} );
+}