package Analysis.OwnershipAnalysis;
import Analysis.CallGraph.*;
+import Analysis.Liveness;
+import Analysis.ArrayReferencees;
import IR.*;
import IR.Flat.*;
import IR.Tree.Modifiers;
public HashSet<AllocationSite>
getFlaggedAllocationSitesReachableFromTask(TaskDescriptor td) {
+ checkAnalysisComplete();
return getFlaggedAllocationSitesReachableFromTaskPRIVATE(td);
}
public AllocationSite getAllocationSiteFromFlatNew(FlatNew fn) {
+ checkAnalysisComplete();
return getAllocationSiteFromFlatNewPRIVATE(fn);
}
+ public AllocationSite getAllocationSiteFromHeapRegionNodeID(Integer id) {
+ checkAnalysisComplete();
+ return mapHrnIdToAllocationSite.get(id);
+ }
public Set<HeapRegionNode> createsPotentialAliases(Descriptor taskOrMethod,
- int paramIndex1,
- int paramIndex2) {
-
+ int paramIndex1,
+ int paramIndex2) {
+ checkAnalysisComplete();
OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(paramIndex1, paramIndex2);
}
public Set<HeapRegionNode> createsPotentialAliases(Descriptor taskOrMethod,
- int paramIndex,
- AllocationSite alloc) {
-
+ int paramIndex,
+ AllocationSite alloc) {
+ checkAnalysisComplete();
OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(paramIndex, alloc);
}
public Set<HeapRegionNode> createsPotentialAliases(Descriptor taskOrMethod,
- AllocationSite alloc,
- int paramIndex) {
-
+ AllocationSite alloc,
+ int paramIndex) {
+ checkAnalysisComplete();
OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(paramIndex, alloc);
}
public Set<HeapRegionNode> createsPotentialAliases(Descriptor taskOrMethod,
- AllocationSite alloc1,
- AllocationSite alloc2) {
-
+ AllocationSite alloc1,
+ AllocationSite alloc2) {
+ checkAnalysisComplete();
OwnershipGraph og = getGraphOfAllContextsFromDescriptor(taskOrMethod);
assert(og != null);
return og.hasPotentialAlias(alloc1, alloc2);
protected OwnershipGraph getGraphOfAllContextsFromDescriptor(Descriptor d) {
+ checkAnalysisComplete();
+
assert d != null;
- OwnershipGraph og = new OwnershipGraph( allocationDepth, typeUtil );
+ OwnershipGraph og = new OwnershipGraph();
- assert mapDescriptorToAllMethodContexts.containsKey( d );
- HashSet<MethodContext> contexts = mapDescriptorToAllMethodContexts.get( d );
+ 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 );
+ og.merge(ogContext);
}
return og;
}
- public String prettyPrintNodeSet( Set<HeapRegionNode> s ) {
+ public String prettyPrintNodeSet(Set<HeapRegionNode> s) {
+ checkAnalysisComplete();
+
String out = "{\n";
Iterator<HeapRegionNode> i = s.iterator();
AllocationSite as = n.getAllocationSite();
if( as == null ) {
- out += " "+n.toString()+",\n";
+ out += " "+n.toString()+",\n";
} else {
- out += " "+n.toString()+": "+as.toStringVerbose()+",\n";
+ out += " "+n.toString()+": "+as.toStringVerbose()+",\n";
}
}
// use the methods given above to check every possible alias
// between task parameters and flagged allocation sites reachable
// from the task
- public void writeAllAliases(String outputFile, String timeReport) throws java.io.IOException {
+ public void writeAllAliases(String outputFile,
+ String timeReport,
+ String justTime,
+ boolean tabularOutput,
+ int numLines
+ ) throws java.io.IOException {
+ checkAnalysisComplete();
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile) );
- bw.write("Conducting ownership analysis with allocation depth = "+allocationDepth+"\n");
- bw.write(timeReport+"\n");
+ if( !tabularOutput ) {
+ bw.write("Conducting ownership analysis with allocation depth = "+allocationDepth+"\n");
+ bw.write(timeReport+"\n");
+ }
+
+ int numAlias = 0;
// look through every task for potential aliases
Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
while( taskItr.hasNext() ) {
TaskDescriptor td = (TaskDescriptor) taskItr.next();
- bw.write("\n---------"+td+"--------\n");
+ if( !tabularOutput ) {
+ bw.write("\n---------"+td+"--------\n");
+ }
HashSet<AllocationSite> allocSites = getFlaggedAllocationSitesReachableFromTask(td);
FlatMethod fm = state.getMethodFlat(td);
for( int i = 0; i < fm.numParameters(); ++i ) {
- // for the ith parameter check for aliases to all
- // higher numbered parameters
- for( int j = i + 1; j < fm.numParameters(); ++j ) {
- common = createsPotentialAliases(td, i, j);
- if( !common.isEmpty() ) {
- foundSomeAlias = true;
- bw.write("Potential alias between parameters "+i+" and "+j+".\n");
- bw.write(prettyPrintNodeSet( common )+"\n" );
- }
- }
-
- // for the ith parameter, check for aliases against
- // the set of allocation sites reachable from this
- // task context
- Iterator allocItr = allocSites.iterator();
- while( allocItr.hasNext() ) {
- AllocationSite as = (AllocationSite) allocItr.next();
- common = createsPotentialAliases(td, i, as);
- if( !common.isEmpty() ) {
- foundSomeAlias = true;
- bw.write("Potential alias between parameter "+i+" and "+as.getFlatNew()+".\n");
- bw.write(prettyPrintNodeSet( common )+"\n" );
- }
- }
+ // for the ith parameter check for aliases to all
+ // higher numbered parameters
+ for( int j = i + 1; j < fm.numParameters(); ++j ) {
+ common = createsPotentialAliases(td, i, j);
+ if( !common.isEmpty() ) {
+ foundSomeAlias = true;
+ if( !tabularOutput ) {
+ bw.write("Potential alias between parameters "+i+" and "+j+".\n");
+ bw.write(prettyPrintNodeSet(common)+"\n");
+ } else {
+ ++numAlias;
+ }
+ }
+ }
+
+ // for the ith parameter, check for aliases against
+ // the set of allocation sites reachable from this
+ // task context
+ Iterator allocItr = allocSites.iterator();
+ while( allocItr.hasNext() ) {
+ AllocationSite as = (AllocationSite) allocItr.next();
+ common = createsPotentialAliases(td, i, as);
+ if( !common.isEmpty() ) {
+ foundSomeAlias = true;
+ if( !tabularOutput ) {
+ bw.write("Potential alias between parameter "+i+" and "+as.getFlatNew()+".\n");
+ bw.write(prettyPrintNodeSet(common)+"\n");
+ } else {
+ ++numAlias;
+ }
+ }
+ }
}
// for each allocation site check for aliases with
HashSet<AllocationSite> outerChecked = new HashSet<AllocationSite>();
Iterator allocItr1 = allocSites.iterator();
while( allocItr1.hasNext() ) {
- AllocationSite as1 = (AllocationSite) allocItr1.next();
-
- Iterator allocItr2 = allocSites.iterator();
- while( allocItr2.hasNext() ) {
- AllocationSite as2 = (AllocationSite) allocItr2.next();
-
- if( !outerChecked.contains(as2) ) {
- common = createsPotentialAliases(td, as1, as2);
-
- if( !common.isEmpty() ) {
- foundSomeAlias = true;
- bw.write("Potential alias between "+as1.getFlatNew()+" and "+as2.getFlatNew()+".\n");
- bw.write(prettyPrintNodeSet( common )+"\n" );
- }
- }
- }
-
- outerChecked.add(as1);
+ AllocationSite as1 = (AllocationSite) allocItr1.next();
+
+ Iterator allocItr2 = allocSites.iterator();
+ while( allocItr2.hasNext() ) {
+ AllocationSite as2 = (AllocationSite) allocItr2.next();
+
+ if( !outerChecked.contains(as2) ) {
+ common = createsPotentialAliases(td, as1, as2);
+
+ if( !common.isEmpty() ) {
+ foundSomeAlias = true;
+ if( !tabularOutput ) {
+ bw.write("Potential alias between "+as1.getFlatNew()+" and "+as2.getFlatNew()+".\n");
+ bw.write(prettyPrintNodeSet(common)+"\n");
+ } else {
+ ++numAlias;
+ }
+ }
+ }
+ }
+
+ outerChecked.add(as1);
}
if( !foundSomeAlias ) {
- bw.write("No aliases between flagged objects in Task "+td+".\n");
+ if( !tabularOutput ) {
+ bw.write("No aliases between flagged objects in Task "+td+".\n");
+ }
}
}
- bw.write( "\n"+computeAliasContextHistogram() );
+ if( !tabularOutput ) {
+ bw.write("\n"+computeAliasContextHistogram() );
+ } else {
+ bw.write(" & "+numAlias+
+ " & "+justTime+
+ " & "+numLines+
+ " & "+numMethodsAnalyzed()+
+ " \\\\\n");
+ }
+
bw.close();
}
// this version of writeAllAliases is for Java programs that have no tasks
- public void writeAllAliasesJava(String outputFile, String timeReport) throws java.io.IOException {
- assert !state.TASK;
+ public void writeAllAliasesJava(String outputFile,
+ String timeReport,
+ String justTime,
+ boolean tabularOutput,
+ int numLines
+ ) throws java.io.IOException {
+ checkAnalysisComplete();
+
+ assert !state.TASK;
BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile) );
Iterator allocItr1 = allocSites.iterator();
while( allocItr1.hasNext() ) {
AllocationSite as1 = (AllocationSite) allocItr1.next();
-
+
Iterator allocItr2 = allocSites.iterator();
while( allocItr2.hasNext() ) {
- AllocationSite as2 = (AllocationSite) allocItr2.next();
-
- if( !outerChecked.contains(as2) ) {
- Set<HeapRegionNode> common = createsPotentialAliases(d, as1, as2);
-
- if( !common.isEmpty() ) {
- foundSomeAlias = true;
- bw.write("Potential alias between "+as1.getDisjointId()+" and "+as2.getDisjointId()+".\n");
- bw.write( prettyPrintNodeSet( common )+"\n" );
- }
- }
+ AllocationSite as2 = (AllocationSite) allocItr2.next();
+
+ if( !outerChecked.contains(as2) ) {
+ Set<HeapRegionNode> common = createsPotentialAliases(d, as1, as2);
+
+ if( !common.isEmpty() ) {
+ foundSomeAlias = true;
+ bw.write("Potential alias between "+as1.getDisjointId()+" and "+as2.getDisjointId()+".\n");
+ bw.write(prettyPrintNodeSet(common)+"\n");
+ }
+ }
}
-
+
outerChecked.add(as1);
}
-
+
if( !foundSomeAlias ) {
bw.write("No aliases between flagged objects found.\n");
}
- bw.write( "\n"+computeAliasContextHistogram() );
+ bw.write("\n"+computeAliasContextHistogram() );
bw.close();
}
-
-
-
-
- /*
- getFlaggedAllocationSitesReachableFromTask(TaskDescriptor td) {
- return getFlaggedAllocationSitesReachableFromTaskPRIVATE(td);
- }
-
- public AllocationSite getAllocationSiteFromFlatNew(FlatNew fn) {
- return getAllocationSiteFromFlatNewPRIVATE(fn);
- }
- */
-
- // return the set of allocation sites for the object that the
- // given variable may reference at the given program point
- public Set<AllocationSite> possible( TempDescriptor temp,
- FlatNode ppoint ) {
- assert temp != null;
- assert ppoint != 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;
- */
-
- return null;
- }
///////////////////////////////////////////
//
// end public interface
//
///////////////////////////////////////////
-
-
+ protected void checkAnalysisComplete() {
+ if( !analysisComplete ) {
+ throw new Error("Warning: public interface method called while analysis is running.");
+ }
+ }
// data from the compiler
- private State state;
- private TypeUtil typeUtil;
- private CallGraph callGraph;
- private int allocationDepth;
+ public State state;
+ public CallGraph callGraph;
+ public Liveness liveness;
+ public ArrayReferencees arrayReferencees;
+ public TypeUtil typeUtil;
+ public int allocationDepth;
+
+ // for public interface methods to warn that they
+ // are grabbing results during analysis
+ private boolean analysisComplete;
// used to identify HeapRegionNode objects
// A unique ID equates an object in one
// reserved IDs for special purposes
static private int uniqueIDcount = 10;
-
// Use these data structures to track progress of
// processing all methods in the program, and by methods
// TaskDescriptor and MethodDescriptor are combined
private Hashtable<MethodContext, Integer> mapMethodContextToNumUpdates;
private Hashtable<Descriptor, HashSet<MethodContext> > mapDescriptorToAllMethodContexts;
private Hashtable<MethodContext, HashSet<MethodContext> > mapMethodContextToDependentContexts;
+ private Hashtable<Integer, AllocationSite> mapHrnIdToAllocationSite;
// Use these data structures to track progress of one pass of
// processing the FlatNodes of a particular method
private boolean writeDOTs;
private boolean writeAllDOTs;
+ // for controlling method effects
+ private boolean methodEffects;
+
+ //map each FlatNode to its own internal ownership graph
+ private MethodEffectsAnalysis meAnalysis;
+
+ //keep internal ownership graph by method context and flat node
+ private Hashtable<MethodContext, Hashtable<FlatNode, OwnershipGraph>> mapMethodContextToFlatNodeOwnershipGraph;
+
+ //map method context to a set of allocation sites of live-in vars
+ private Hashtable<MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet;
+
// this analysis generates an ownership graph for every task
public OwnershipAnalysis(State state,
TypeUtil tu,
CallGraph callGraph,
+ Liveness liveness,
+ ArrayReferencees ar,
int allocationDepth,
boolean writeDOTs,
boolean writeAllDOTs,
String aliasFile) throws java.io.IOException {
- double timeStartAnalysis = (double) System.nanoTime();
+ this.methodEffects = false;
+ init(state,tu,callGraph,liveness,ar,allocationDepth,writeDOTs,writeAllDOTs,aliasFile);
+
+ }
+
+ public OwnershipAnalysis(State state,
+ TypeUtil tu,
+ CallGraph callGraph,
+ Liveness liveness,
+ ArrayReferencees ar,
+ int allocationDepth,
+ boolean writeDOTs,
+ boolean writeAllDOTs,
+ String aliasFile,
+ boolean methodEffects) throws java.io.IOException {
+
+ this.methodEffects = methodEffects;
+ init(state,tu,callGraph,liveness,ar,allocationDepth,writeDOTs,writeAllDOTs,aliasFile);
+
+ }
+
+ // new constructor for on-demand disjoint analysis
+ public OwnershipAnalysis(
+ State state,
+ TypeUtil tu,
+ CallGraph callGraph,
+ Liveness liveness,
+ ArrayReferencees ar,
+ int allocationDepth,
+ boolean writeDOTs,
+ boolean writeAllDOTs,
+ String aliasFile,
+ boolean methodEffects,
+ Hashtable<MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet)
+ throws java.io.IOException {
+
+ this.methodEffects = methodEffects;
+ this.mapMethodContextToLiveInAllocationSiteSet=mapMethodContextToLiveInAllocationSiteSet;
+ init(state, tu, callGraph, liveness, ar, allocationDepth, writeDOTs, writeAllDOTs,
+ aliasFile);
- this.state = state;
- this.typeUtil = tu;
- this.callGraph = callGraph;
- this.allocationDepth = allocationDepth;
- this.writeDOTs = writeDOTs;
- this.writeAllDOTs = writeAllDOTs;
+ }
+
+ private void init(State state,
+ TypeUtil tu,
+ CallGraph callGraph,
+ Liveness liveness,
+ ArrayReferencees ar,
+ int allocationDepth,
+ boolean writeDOTs,
+ boolean writeAllDOTs,
+ String aliasFile) throws java.io.IOException {
+
+ analysisComplete = false;
+
+ this.state = state;
+ this.typeUtil = tu;
+ this.callGraph = callGraph;
+ this.liveness = liveness;
+ this.arrayReferencees = ar;
+ this.allocationDepth = allocationDepth;
+ this.writeDOTs = writeDOTs;
+ this.writeAllDOTs = writeAllDOTs;
+
+ // set some static configuration for OwnershipGraphs
+ OwnershipGraph.allocationDepth = allocationDepth;
+ OwnershipGraph.typeUtil = typeUtil;
+ OwnershipGraph.debugCallMapCount = state.OWNERSHIPDEBUGCALLCOUNT;
+ OwnershipGraph.debugCallee = state.OWNERSHIPDEBUGCALLEE;
+ OwnershipGraph.debugCaller = state.OWNERSHIPDEBUGCALLER;
+ if( OwnershipGraph.debugCallee != null &&
+ OwnershipGraph.debugCaller != null ) {
+ OwnershipGraph.debugCallMap = true;
+ }
descriptorsToAnalyze = new HashSet<Descriptor>();
mapDescriptorToAllocationSiteSet =
new Hashtable<Descriptor, HashSet<AllocationSite> >();
- mapDescriptorToAllMethodContexts =
+ mapDescriptorToAllMethodContexts =
new Hashtable<Descriptor, HashSet<MethodContext> >();
mapMethodContextToDependentContexts =
new Hashtable<MethodContext, HashSet<MethodContext> >();
- mapDescriptorToPriority =
+ mapDescriptorToPriority =
new Hashtable<Descriptor, Integer>();
+ mapHrnIdToAllocationSite =
+ new Hashtable<Integer, AllocationSite>();
+
+ if( methodEffects ) {
+ mapMethodContextToFlatNodeOwnershipGraph=new Hashtable<MethodContext, Hashtable<FlatNode, OwnershipGraph>>();
+ }
+
+ meAnalysis=new MethodEffectsAnalysis(methodEffects);
+
if( writeAllDOTs ) {
mapMethodContextToNumUpdates = new Hashtable<MethodContext, Integer>();
}
+ double timeStartAnalysis = (double) System.nanoTime();
+
+
if( state.TASK ) {
// initialize methods to visit as the set of all tasks in the
// program and then any method that could be called starting
// from those tasks
Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
while( taskItr.hasNext() ) {
- Descriptor d = (Descriptor) taskItr.next();
- scheduleAllCallees(d);
+ Descriptor d = (Descriptor) taskItr.next();
+ scheduleAllCallees(d);
}
} else {
Iterator<Descriptor> dItr = descriptorsToAnalyze.iterator();
while( dItr.hasNext() ) {
Descriptor d = dItr.next();
- OwnershipGraph og = new OwnershipGraph(allocationDepth, typeUtil);
+ OwnershipGraph og = new OwnershipGraph();
FlatMethod fm;
if( d instanceof MethodDescriptor ) {
- fm = state.getMethodFlat( (MethodDescriptor) d);
+ fm = state.getMethodFlat( (MethodDescriptor) d);
} else {
- assert d instanceof TaskDescriptor;
- fm = state.getMethodFlat( (TaskDescriptor) d);
+ assert d instanceof TaskDescriptor;
+ fm = state.getMethodFlat( (TaskDescriptor) d);
}
- MethodContext mc = new MethodContext( d );
- assert !mapDescriptorToAllMethodContexts.containsKey( d );
+ MethodContext mc = new MethodContext(d);
+ assert !mapDescriptorToAllMethodContexts.containsKey(d);
HashSet<MethodContext> s = new HashSet<MethodContext>();
- s.add( mc );
- mapDescriptorToAllMethodContexts.put( d, s );
+ s.add(mc);
+ mapDescriptorToAllMethodContexts.put(d, s);
//System.out.println("Previsiting " + mc);
- og = analyzeFlatNode(mc, fm, null, og);
+ meAnalysis.createNewMapping(mc);
+
+ og = analyzeFlatNode(mc, fm, fm, null, og);
setGraphForMethodContext(mc, og);
}
// as mentioned above, analyze methods one-by-one, possibly revisiting
// a method if the methods that it calls are updated
analyzeMethods();
+ analysisComplete = true;
+
double timeEndAnalysis = (double) System.nanoTime();
- double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
- String treport = String.format( "The reachability analysis took %.3f sec.", dt );
- System.out.println( treport );
+ double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow(10.0, 9.0) );
+ String treport = String.format("The reachability analysis took %.3f sec.", dt);
+ String justtime = String.format("%.2f", dt);
+ System.out.println(treport);
if( writeDOTs && !writeAllDOTs ) {
- writeFinalContextGraphs();
- }
+ writeFinalContextGraphs();
+ }
+
+ if(methodEffects) {
+ meAnalysis.writeMethodEffectsResult();
+ }
if( aliasFile != null ) {
if( state.TASK ) {
- writeAllAliases(aliasFile, treport);
+ writeAllAliases(aliasFile, treport, justtime, state.OWNERSHIPALIASTAB, state.lines);
} else {
- writeAllAliasesJava(aliasFile, treport);
+ writeAllAliasesJava(aliasFile, treport, justtime, state.OWNERSHIPALIASTAB, state.lines);
}
}
+
}
// called from the constructor to help initialize the set
// manage the set of tasks and methods to be analyzed
// and be sure to reschedule tasks/methods when the methods
// they call are updated
- private void analyzeMethods() throws java.io.IOException {
+ private void analyzeMethods() throws java.io.IOException {
// first gather all of the method contexts to analyze
HashSet<MethodContext> allContexts = new HashSet<MethodContext>();
Iterator<Descriptor> itrd2a = descriptorsToAnalyze.iterator();
while( itrd2a.hasNext() ) {
- HashSet<MethodContext> mcs = mapDescriptorToAllMethodContexts.get( itrd2a.next() );
+ HashSet<MethodContext> mcs = mapDescriptorToAllMethodContexts.get(itrd2a.next() );
assert mcs != null;
Iterator<MethodContext> itrmc = mcs.iterator();
while( itrmc.hasNext() ) {
- allContexts.add( itrmc.next() );
+ allContexts.add(itrmc.next() );
}
}
// topologically sort them according to the caller graph so leaf calls are
// ordered first; use that ordering to give method contexts priorities
- LinkedList<MethodContext> sortedMethodContexts = topologicalSort( allContexts );
+ LinkedList<MethodContext> sortedMethodContexts = topologicalSort(allContexts);
methodContextsToVisitQ = new PriorityQueue<MethodContextQWrapper>();
methodContextsToVisitSet = new HashSet<MethodContext>();
Iterator<MethodContext> mcItr = sortedMethodContexts.iterator();
while( mcItr.hasNext() ) {
MethodContext mc = mcItr.next();
- mapDescriptorToPriority.put( mc.getDescriptor(), new Integer( p ) );
- methodContextsToVisitQ.add( new MethodContextQWrapper( p, mc ) );
- methodContextsToVisitSet.add( mc );
+ mapDescriptorToPriority.put(mc.getDescriptor(), new Integer(p) );
+ methodContextsToVisitQ.add(new MethodContextQWrapper(p, mc) );
+ methodContextsToVisitSet.add(mc);
++p;
}
// analyze methods from the priority queue until it is empty
while( !methodContextsToVisitQ.isEmpty() ) {
MethodContext mc = methodContextsToVisitQ.poll().getMethodContext();
- assert methodContextsToVisitSet.contains( mc );
- methodContextsToVisitSet.remove( mc );
+ assert methodContextsToVisitSet.contains(mc);
+ methodContextsToVisitSet.remove(mc);
// because the task or method descriptor just extracted
// was in the "to visit" set it either hasn't been analyzed
Descriptor d = mc.getDescriptor();
FlatMethod fm;
if( d instanceof MethodDescriptor ) {
- fm = state.getMethodFlat( (MethodDescriptor) d);
+ fm = state.getMethodFlat( (MethodDescriptor) d);
} else {
- assert d instanceof TaskDescriptor;
- fm = state.getMethodFlat( (TaskDescriptor) d);
+ assert d instanceof TaskDescriptor;
+ fm = state.getMethodFlat( (TaskDescriptor) d);
}
OwnershipGraph og = analyzeFlatMethod(mc, fm);
OwnershipGraph ogPrev = mapMethodContextToCompleteOwnershipGraph.get(mc);
if( !og.equals(ogPrev) ) {
- setGraphForMethodContext(mc, og);
-
- Iterator<MethodContext> depsItr = iteratorDependents( mc );
- while( depsItr.hasNext() ) {
- MethodContext mcNext = depsItr.next();
-
- if( !methodContextsToVisitSet.contains( mcNext ) ) {
- methodContextsToVisitQ.add( new MethodContextQWrapper( mapDescriptorToPriority.get( mcNext.getDescriptor() ),
- mcNext ) );
- methodContextsToVisitSet.add( mcNext );
- }
- }
+ setGraphForMethodContext(mc, og);
+
+ Iterator<MethodContext> depsItr = iteratorDependents(mc);
+ while( depsItr.hasNext() ) {
+ MethodContext mcNext = depsItr.next();
+
+ if( !methodContextsToVisitSet.contains(mcNext) ) {
+ methodContextsToVisitQ.add(new MethodContextQWrapper(mapDescriptorToPriority.get(mcNext.getDescriptor() ),
+ mcNext) );
+ methodContextsToVisitSet.add(mcNext);
+ }
+ }
}
}
// perform this node's contributions to the ownership
// graph on a new copy, then compare it to the old graph
// at this node to see if anything was updated.
- OwnershipGraph og = new OwnershipGraph(allocationDepth, typeUtil);
+ OwnershipGraph og = new OwnershipGraph();
// start by merging all node's parents' graphs
for( int i = 0; i < fn.numPrev(); ++i ) {
- FlatNode pn = fn.getPrev(i);
- if( mapFlatNodeToOwnershipGraph.containsKey(pn) ) {
- OwnershipGraph ogParent = mapFlatNodeToOwnershipGraph.get(pn);
- og.merge(ogParent);
- }
+ FlatNode pn = fn.getPrev(i);
+ if( mapFlatNodeToOwnershipGraph.containsKey(pn) ) {
+ OwnershipGraph ogParent = mapFlatNodeToOwnershipGraph.get(pn);
+ og.merge(ogParent);
+ }
}
// apply the analysis of the flat node to the
// ownership graph made from the merge of the
// parent graphs
og = analyzeFlatNode(mc,
+ flatm,
fn,
returnNodesToCombineForCompleteOwnershipGraph,
og);
-
-
- if( takeDebugSnapshots &&
- mc.getDescriptor().getSymbol().equals( mcDescSymbolDebug ) ) {
- debugSnapshot(og,fn);
+
+
+ if( takeDebugSnapshots &&
+ mc.getDescriptor().getSymbol().equals(mcDescSymbolDebug) ) {
+ debugSnapshot(og,fn);
}
-
// if the results of the new graph are different from
// processing
OwnershipGraph ogPrev = mapFlatNodeToOwnershipGraph.get(fn);
if( !og.equals(ogPrev) ) {
- mapFlatNodeToOwnershipGraph.put(fn, og);
+ mapFlatNodeToOwnershipGraph.put(fn, og);
- for( int i = 0; i < fn.numNext(); i++ ) {
- FlatNode nn = fn.getNext(i);
- flatNodesToVisit.add(nn);
- }
+ for( int i = 0; i < fn.numNext(); i++ ) {
+ FlatNode nn = fn.getNext(i);
+ flatNodesToVisit.add(nn);
+ }
}
}
// end by merging all return nodes into a complete
// ownership graph that represents all possible heap
// states after the flat method returns
- OwnershipGraph completeGraph = new OwnershipGraph(allocationDepth, typeUtil);
+ OwnershipGraph completeGraph = new OwnershipGraph();
Iterator retItr = returnNodesToCombineForCompleteOwnershipGraph.iterator();
while( retItr.hasNext() ) {
FlatReturnNode frn = (FlatReturnNode) retItr.next();
private OwnershipGraph
analyzeFlatNode(MethodContext mc,
+ FlatMethod fmContaining,
FlatNode fn,
HashSet<FlatReturnNode> setRetNodes,
OwnershipGraph og) throws java.io.IOException {
+
+ // any variables that are no longer live should be
+ // nullified in the graph to reduce edges
+ // NOTE: it is not clear we need this. It costs a
+ // liveness calculation for every method, so only
+ // turn it on if we find we actually need it.
+ //og.nullifyDeadVars( liveness.getLiveInTemps( fmContaining, fn ) );
+
+
TempDescriptor lhs;
TempDescriptor rhs;
FieldDescriptor fld;
OwnershipGraph ogInitParamAlloc = mapMethodContextToInitialParamAllocGraph.get(mc);
if( ogInitParamAlloc == null ) {
- // if the method context has aliased parameters, make sure
- // there is a blob region for all those param to reference
- Set<Integer> aliasedParamIndices = mc.getAliasedParamIndices();
-
- if( !aliasedParamIndices.isEmpty() ) {
- og.makeAliasedParamHeapRegionNode();
- }
-
- // set up each parameter
- for( int i = 0; i < fm.numParameters(); ++i ) {
- TempDescriptor tdParam = fm.getParameter( i );
- TypeDescriptor typeParam = tdParam.getType();
- Integer paramIndex = new Integer( i );
-
- if( typeParam.isImmutable() && !typeParam.isArray() ) {
- // don't bother with this primitive parameter, it
- // cannot affect reachability
- continue;
- }
-
- if( aliasedParamIndices.contains( paramIndex ) ) {
- // use the alias blob but give parameters their
- // own primary obj region
- og.assignTempEqualToAliasedParam( tdParam,
- paramIndex );
- } else {
- // this parameter is not aliased to others, give it
- // a fresh primary obj and secondary object
- og.assignTempEqualToParamAlloc( tdParam,
- mc.getDescriptor() instanceof TaskDescriptor,
- paramIndex );
- }
- }
-
- // add additional edges for aliased regions if necessary
- if( !aliasedParamIndices.isEmpty() ) {
- og.addParam2ParamAliasEdges( fm, aliasedParamIndices );
- }
-
- // clean up reachability on initial parameter shapes
- og.globalSweep();
-
- // this maps tokens to parameter indices and vice versa
- // for when this method is a callee
- og.prepareParamTokenMaps( fm );
-
- // cache the graph
- OwnershipGraph ogResult = new OwnershipGraph(allocationDepth, typeUtil);
- ogResult.merge(og);
- mapMethodContextToInitialParamAllocGraph.put(mc, ogResult);
+ // if the method context has aliased parameters, make sure
+ // there is a blob region for all those param to reference
+ Set<Integer> aliasedParamIndices = mc.getAliasedParamIndices();
+
+ if( !aliasedParamIndices.isEmpty() ) {
+ og.makeAliasedParamHeapRegionNode(fm);
+ }
+
+ // set up each parameter
+ for( int i = 0; i < fm.numParameters(); ++i ) {
+ TempDescriptor tdParam = fm.getParameter(i);
+ TypeDescriptor typeParam = tdParam.getType();
+ Integer paramIndex = new Integer(i);
+
+ if( typeParam.isImmutable() && !typeParam.isArray() ) {
+ // don't bother with this primitive parameter, it
+ // cannot affect reachability
+ continue;
+ }
+
+ if( aliasedParamIndices.contains(paramIndex) ) {
+ // use the alias blob but give parameters their
+ // own primary obj region
+ og.assignTempEqualToAliasedParam(tdParam,
+ paramIndex, fm);
+ } else {
+ // this parameter is not aliased to others, give it
+ // a fresh primary obj and secondary object
+ og.assignTempEqualToParamAlloc(tdParam,
+ mc.getDescriptor() instanceof TaskDescriptor,
+ paramIndex, fm);
+ }
+ }
+
+ // add additional edges for aliased regions if necessary
+ if( !aliasedParamIndices.isEmpty() ) {
+ og.addParam2ParamAliasEdges(fm, aliasedParamIndices);
+ }
+
+ // clean up reachability on initial parameter shapes
+ og.globalSweep();
+
+ // this maps tokens to parameter indices and vice versa
+ // for when this method is a callee
+ og.prepareParamTokenMaps(fm);
+
+ // cache the graph
+ OwnershipGraph ogResult = new OwnershipGraph();
+ ogResult.merge(og);
+ mapMethodContextToInitialParamAllocGraph.put(mc, ogResult);
} else {
- // or just leverage the cached copy
- og.merge(ogInitParamAlloc);
+ // or just leverage the cached copy
+ og.merge(ogInitParamAlloc);
}
break;
case FKind.FlatOpNode:
FlatOpNode fon = (FlatOpNode) fn;
if( fon.getOp().getOp() == Operation.ASSIGN ) {
- lhs = fon.getDest();
- rhs = fon.getLeft();
- og.assignTempXEqualToTempY(lhs, rhs);
+ lhs = fon.getDest();
+ rhs = fon.getLeft();
+ og.assignTempXEqualToTempY(lhs, rhs);
}
break;
TypeDescriptor td = fcn.getType();
assert td != null;
-
- og.assignTypedTempXEqualToTempY(lhs, rhs, td);
+
+ og.assignTempXEqualToCastedTempY(lhs, rhs, td);
break;
case FKind.FlatFieldNode:
rhs = ffn.getSrc();
fld = ffn.getField();
if( !fld.getType().isImmutable() || fld.getType().isArray() ) {
- og.assignTempXEqualToTempYFieldF(lhs, rhs, fld);
+ og.assignTempXEqualToTempYFieldF(lhs, rhs, fld);
}
+
+ meAnalysis.analyzeFlatFieldNode(mc, og, rhs, fld);
+
break;
case FKind.FlatSetFieldNode:
fld = fsfn.getField();
rhs = fsfn.getSrc();
if( !fld.getType().isImmutable() || fld.getType().isArray() ) {
- og.assignTempXFieldFEqualToTempY(lhs, fld, rhs);
+ og.assignTempXFieldFEqualToTempY(lhs, fld, rhs);
}
+
+ meAnalysis.analyzeFlatSetFieldNode(mc, og, lhs, fld);
+
break;
case FKind.FlatElementNode:
FlatElementNode fen = (FlatElementNode) fn;
+
lhs = fen.getDst();
rhs = fen.getSrc();
if( !lhs.getType().isImmutable() || lhs.getType().isArray() ) {
- assert rhs.getType() != null;
- assert rhs.getType().isArray();
-
- TypeDescriptor tdElement = rhs.getType().dereference();
- FieldDescriptor fdElement = getArrayField( tdElement );
-
- og.assignTempXEqualToTempYFieldF(lhs, rhs, fdElement);
+ assert rhs.getType() != null;
+ assert rhs.getType().isArray();
+
+ TypeDescriptor tdElement = rhs.getType().dereference();
+ FieldDescriptor fdElement = getArrayField(tdElement);
+ og.assignTempXEqualToTempYFieldF(lhs, rhs, fdElement);
+ meAnalysis.analyzeFlatElementNode(mc, og, lhs, fdElement);
+
}
break;
case FKind.FlatSetElementNode:
FlatSetElementNode fsen = (FlatSetElementNode) fn;
+
+ lhs = fsen.getDst();
+ rhs = fsen.getSrc();
+ if( !lhs.getType().isImmutable() || lhs.getType().isArray() ) {
+ TypeDescriptor tdElement = lhs.getType().dereference();
+ FieldDescriptor fdElement = getArrayField(tdElement);
+ meAnalysis.analyzeFlatSetElementNode(mc, og, lhs, fdElement);
+ }
+
+ if( arrayReferencees.doesNotCreateNewReaching(fsen) ) {
+ // skip this node if it cannot create new reachability paths
+ break;
+ }
+
lhs = fsen.getDst();
rhs = fsen.getSrc();
if( !rhs.getType().isImmutable() || rhs.getType().isArray() ) {
- assert lhs.getType() != null;
- assert lhs.getType().isArray();
-
- TypeDescriptor tdElement = lhs.getType().dereference();
- FieldDescriptor fdElement = getArrayField( tdElement );
+ assert lhs.getType() != null;
+ assert lhs.getType().isArray();
+
+ TypeDescriptor tdElement = lhs.getType().dereference();
+ FieldDescriptor fdElement = getArrayField(tdElement);
+
+ og.assignTempXFieldFEqualToTempY(lhs, fdElement, rhs);
+ meAnalysis.analyzeFlatSetElementNode(mc, og, lhs, fdElement);
- og.assignTempXFieldFEqualToTempY(lhs, fdElement, rhs);
}
break;
FlatNew fnn = (FlatNew) fn;
lhs = fnn.getDst();
if( !lhs.getType().isImmutable() || lhs.getType().isArray() ) {
- AllocationSite as = getAllocationSiteFromFlatNewPRIVATE(fnn);
- og.assignTempEqualToNewAlloc(lhs, as);
+ AllocationSite as = getAllocationSiteFromFlatNewPRIVATE(fnn);
+
+ if (mapMethodContextToLiveInAllocationSiteSet != null) {
+ HashSet<AllocationSite> alllocSet=mapMethodContextToLiveInAllocationSiteSet.get(mc);
+ if(alllocSet!=null) {
+ for (Iterator iterator = alllocSet.iterator(); iterator
+ .hasNext(); ) {
+ AllocationSite allocationSite = (AllocationSite) iterator
+ .next();
+ if(allocationSite.flatNew.equals(as.flatNew)) {
+ as.setFlag(true);
+ }
+ }
+ }
+ }
+
+ og.assignTempEqualToNewAlloc(lhs, as);
}
break;
FlatCall fc = (FlatCall) fn;
MethodDescriptor md = fc.getMethod();
FlatMethod flatm = state.getMethodFlat(md);
- OwnershipGraph ogMergeOfAllPossibleCalleeResults = new OwnershipGraph(allocationDepth, typeUtil);
+ OwnershipGraph ogMergeOfAllPossibleCalleeResults = new OwnershipGraph();
if( md.isStatic() ) {
- // a static method is simply always the same, makes life easy
- ogMergeOfAllPossibleCalleeResults = og;
-
- Set<Integer> aliasedParamIndices =
- ogMergeOfAllPossibleCalleeResults.calculateAliasedParamSet(fc, md.isStatic(), flatm);
-
- MethodContext mcNew = new MethodContext( md, aliasedParamIndices );
- Set contexts = mapDescriptorToAllMethodContexts.get( md );
- assert contexts != null;
- contexts.add( mcNew );
-
- addDependent( mc, mcNew );
-
- 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
- if( !methodContextsToVisitSet.contains( mcNew ) ) {
- methodContextsToVisitQ.add( new MethodContextQWrapper( mapDescriptorToPriority.get( md ),
- mcNew ) );
- methodContextsToVisitSet.add( mcNew );
- }
-
- } else {
- ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee, mc);
- }
+ // a static method is simply always the same, makes life easy
+ ogMergeOfAllPossibleCalleeResults = og;
+
+ Set<Integer> aliasedParamIndices =
+ ogMergeOfAllPossibleCalleeResults.calculateAliasedParamSet(fc, md.isStatic(), flatm);
+
+ MethodContext mcNew = new MethodContext(md, aliasedParamIndices);
+ Set contexts = mapDescriptorToAllMethodContexts.get(md);
+ assert contexts != null;
+ contexts.add(mcNew);
+
+ addDependent(mc, mcNew);
+
+ 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
+ if( !methodContextsToVisitSet.contains(mcNew) ) {
+ methodContextsToVisitQ.add(new MethodContextQWrapper(mapDescriptorToPriority.get(md),
+ mcNew) );
+ methodContextsToVisitSet.add(mcNew);
+ }
+
+ } else {
+ ogMergeOfAllPossibleCalleeResults.resolveMethodCall(fc, md.isStatic(), flatm, onlyPossibleCallee, mc, null);
+ }
+
+ meAnalysis.createNewMapping(mcNew);
+ meAnalysis.analyzeFlatCall(ogMergeOfAllPossibleCalleeResults, mcNew, mc, fc);
+
} else {
- // if the method descriptor is virtual, then there could be a
- // set of possible methods that will actually be invoked, so
- // find all of them and merge all of their results together
- TypeDescriptor typeDesc = fc.getThis().getType();
- Set possibleCallees = callGraph.getMethods(md, typeDesc);
-
- 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);
-
- Set<Integer> aliasedParamIndices =
- ogCopy.calculateAliasedParamSet(fc, possibleMd.isStatic(), pflatm);
-
- MethodContext mcNew = new MethodContext( possibleMd, aliasedParamIndices );
- Set contexts = mapDescriptorToAllMethodContexts.get( md );
- assert contexts != null;
- contexts.add( mcNew );
-
- addDependent( mc, mcNew );
-
- 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
- if( !methodContextsToVisitSet.contains( mcNew ) ) {
- methodContextsToVisitQ.add( new MethodContextQWrapper( mapDescriptorToPriority.get( md ),
- mcNew ) );
- methodContextsToVisitSet.add( mcNew );
- }
-
- } else {
- ogCopy.resolveMethodCall(fc, possibleMd.isStatic(), pflatm, ogPotentialCallee, mc);
- }
-
- ogMergeOfAllPossibleCalleeResults.merge(ogCopy);
- }
+ // if the method descriptor is virtual, then there could be a
+ // set of possible methods that will actually be invoked, so
+ // find all of them and merge all of their results together
+ TypeDescriptor typeDesc = fc.getThis().getType();
+ Set possibleCallees = callGraph.getMethods(md, typeDesc);
+
+ 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();
+ ogCopy.merge(og);
+
+ Set<Integer> aliasedParamIndices =
+ ogCopy.calculateAliasedParamSet(fc, possibleMd.isStatic(), pflatm);
+
+ MethodContext mcNew = new MethodContext(possibleMd, aliasedParamIndices);
+ Set contexts = mapDescriptorToAllMethodContexts.get(md);
+ assert contexts != null;
+ contexts.add(mcNew);
+
+
+ meAnalysis.createNewMapping(mcNew);
+
+
+ addDependent(mc, mcNew);
+
+ 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
+ if( !methodContextsToVisitSet.contains(mcNew) ) {
+ methodContextsToVisitQ.add(new MethodContextQWrapper(mapDescriptorToPriority.get(md),
+ mcNew) );
+ methodContextsToVisitSet.add(mcNew);
+ }
+
+ } else {
+ ogCopy.resolveMethodCall(fc, possibleMd.isStatic(), pflatm, ogPotentialCallee, mc, null);
+ }
+
+ ogMergeOfAllPossibleCalleeResults.merge(ogCopy);
+
+ meAnalysis.analyzeFlatCall(ogMergeOfAllPossibleCalleeResults, mcNew, mc, fc);
+ }
+
}
og = ogMergeOfAllPossibleCalleeResults;
FlatReturnNode frn = (FlatReturnNode) fn;
rhs = frn.getReturnTemp();
if( rhs != null && !rhs.getType().isImmutable() ) {
- og.assignReturnEqualToTemp(rhs);
+ og.assignReturnEqualToTemp(rhs);
}
setRetNodes.add(frn);
break;
}
+
+ if( methodEffects ) {
+ Hashtable<FlatNode, OwnershipGraph> table=mapMethodContextToFlatNodeOwnershipGraph.get(mc);
+ if(table==null) {
+ table=new Hashtable<FlatNode, OwnershipGraph>();
+ }
+ table.put(fn, og);
+ mapMethodContextToFlatNodeOwnershipGraph.put(mc, table);
+ }
+
return og;
}
}
- static public FieldDescriptor getArrayField( TypeDescriptor tdElement ) {
- FieldDescriptor fdElement = mapTypeToArrayField.get( tdElement );
+ static public FieldDescriptor getArrayField(TypeDescriptor tdElement) {
+ FieldDescriptor fdElement = mapTypeToArrayField.get(tdElement);
if( fdElement == null ) {
fdElement = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC),
- tdElement,
- arrayElementFieldName,
- null,
- false);
- mapTypeToArrayField.put( tdElement, fdElement );
+ tdElement,
+ arrayElementFieldName,
+ null,
+ false);
+ mapTypeToArrayField.put(tdElement, fdElement);
}
return fdElement;
}
if( writeDOTs && writeAllDOTs ) {
if( !mapMethodContextToNumUpdates.containsKey(mc) ) {
- mapMethodContextToNumUpdates.put(mc, new Integer(0) );
+ mapMethodContextToNumUpdates.put(mc, new Integer(0) );
}
Integer n = mapMethodContextToNumUpdates.get(mc);
try {
- og.writeGraph(mc, n, true, true, true, false, false);
- } catch( IOException e ) {}
+ og.writeGraph(mc+"COMPLETE"+String.format("%05d", n),
+ true, // write labels (variables)
+ true, // selectively hide intermediate temp vars
+ true, // prune unreachable heap regions
+ false, // show back edges to confirm graph validity
+ false, // show parameter indices (unmaintained!)
+ true, // hide subset reachability states
+ true); // hide edge taints
+ } catch( IOException e ) {
+ }
mapMethodContextToNumUpdates.put(mc, n + 1);
}
}
- private void addDependent( MethodContext caller, MethodContext callee ) {
- HashSet<MethodContext> deps = mapMethodContextToDependentContexts.get( callee );
+ private void addDependent(MethodContext caller, MethodContext callee) {
+ HashSet<MethodContext> deps = mapMethodContextToDependentContexts.get(callee);
if( deps == null ) {
deps = new HashSet<MethodContext>();
}
- deps.add( caller );
- mapMethodContextToDependentContexts.put( callee, deps );
+ deps.add(caller);
+ mapMethodContextToDependentContexts.put(callee, deps);
}
- private Iterator<MethodContext> iteratorDependents( MethodContext callee ) {
- HashSet<MethodContext> deps = mapMethodContextToDependentContexts.get( callee );
+ private Iterator<MethodContext> iteratorDependents(MethodContext callee) {
+ HashSet<MethodContext> deps = mapMethodContextToDependentContexts.get(callee);
if( deps == null ) {
deps = new HashSet<MethodContext>();
- mapMethodContextToDependentContexts.put( callee, deps );
+ mapMethodContextToDependentContexts.put(callee, deps);
}
return deps.iterator();
}
private void writeFinalContextGraphs() {
- // arguments to writeGraph are:
- // boolean writeLabels,
- // boolean labelSelect,
- // boolean pruneGarbage,
- // boolean writeReferencers
- // boolean writeParamMappings
-
Set entrySet = mapMethodContextToCompleteOwnershipGraph.entrySet();
Iterator itr = entrySet.iterator();
while( itr.hasNext() ) {
- Map.Entry me = (Map.Entry) itr.next();
- MethodContext mc = (MethodContext) me.getKey();
+ Map.Entry me = (Map.Entry)itr.next();
+ MethodContext mc = (MethodContext) me.getKey();
OwnershipGraph og = (OwnershipGraph) me.getValue();
try {
- og.writeGraph(mc, true, true, true, false, false);
- } catch( IOException e ) {}
+ og.writeGraph(mc+"COMPLETE",
+ true, // write labels (variables)
+ true, // selectively hide intermediate temp vars
+ true, // prune unreachable heap regions
+ false, // show back edges to confirm graph validity
+ false, // show parameter indices (unmaintained!)
+ true, // hide subset reachability states
+ true); // hide edge taints
+ } catch( IOException e ) {
+ }
}
}
-
+
+
// return just the allocation site associated with one FlatNew node
private AllocationSite getAllocationSiteFromFlatNewPRIVATE(FlatNew fn) {
// the newest nodes are single objects
for( int i = 0; i < allocationDepth; ++i ) {
- Integer id = generateUniqueHeapRegionNodeID();
- as.setIthOldest(i, id);
+ Integer id = generateUniqueHeapRegionNodeID();
+ as.setIthOldest(i, id);
+ mapHrnIdToAllocationSite.put(id, as);
}
// the oldest node is a summary node
FlatNode n = toVisit.iterator().next();
if( n instanceof FlatNew ) {
- s.add(getAllocationSiteFromFlatNewPRIVATE( (FlatNew) n) );
+ s.add(getAllocationSiteFromFlatNewPRIVATE( (FlatNew) n) );
}
toVisit.remove(n);
visited.add(n);
for( int i = 0; i < n.numNext(); ++i ) {
- FlatNode child = n.getNext(i);
- if( !visited.contains(child) ) {
- toVisit.add(child);
- }
+ FlatNode child = n.getNext(i);
+ if( !visited.contains(child) ) {
+ toVisit.add(child);
+ }
}
}
private HashSet<AllocationSite> getFlaggedAllocationSites(Descriptor dIn) {
-
+
HashSet<AllocationSite> out = new HashSet<AllocationSite>();
HashSet<Descriptor> toVisit = new HashSet<Descriptor>();
HashSet<Descriptor> visited = new HashSet<Descriptor>();
HashSet<AllocationSite> asSet = getAllocationSiteSet(d);
Iterator asItr = asSet.iterator();
while( asItr.hasNext() ) {
- AllocationSite as = (AllocationSite) asItr.next();
- if( as.getDisjointId() != null ) {
- out.add(as);
- }
+ AllocationSite as = (AllocationSite) asItr.next();
+ if( as.getDisjointId() != null ) {
+ out.add(as);
+ }
}
// enqueue callees of this method to be searched for
// allocation sites also
Set callees = callGraph.getCalleeSet(d);
if( callees != null ) {
- Iterator methItr = callees.iterator();
- while( methItr.hasNext() ) {
- MethodDescriptor md = (MethodDescriptor) methItr.next();
-
- if( !visited.contains(md) ) {
- toVisit.add(md);
- }
- }
+ Iterator methItr = callees.iterator();
+ while( methItr.hasNext() ) {
+ MethodDescriptor md = (MethodDescriptor) methItr.next();
+
+ if( !visited.contains(md) ) {
+ toVisit.add(md);
+ }
+ }
}
}
-
+
return out;
}
HashSet<AllocationSite> asSet = getAllocationSiteSet(d);
Iterator asItr = asSet.iterator();
while( asItr.hasNext() ) {
- AllocationSite as = (AllocationSite) asItr.next();
- TypeDescriptor typed = as.getType();
- if( typed != null ) {
- ClassDescriptor cd = typed.getClassDesc();
- if( cd != null && cd.hasFlags() ) {
- asSetTotal.add(as);
- }
- }
+ AllocationSite as = (AllocationSite) asItr.next();
+ TypeDescriptor typed = as.getType();
+ if( typed != null ) {
+ ClassDescriptor cd = typed.getClassDesc();
+ if( cd != null && cd.hasFlags() ) {
+ asSetTotal.add(as);
+ }
+ }
}
// enqueue callees of this method to be searched for
// allocation sites also
Set callees = callGraph.getCalleeSet(d);
if( callees != null ) {
- Iterator methItr = callees.iterator();
- while( methItr.hasNext() ) {
- MethodDescriptor md = (MethodDescriptor) methItr.next();
-
- if( !visited.contains(md) ) {
- toVisit.add(md);
- }
- }
+ Iterator methItr = callees.iterator();
+ while( methItr.hasNext() ) {
+ MethodDescriptor md = (MethodDescriptor) methItr.next();
+
+ if( !visited.contains(md) ) {
+ toVisit.add(md);
+ }
+ }
}
}
}
- private LinkedList<MethodContext> topologicalSort( HashSet<MethodContext> set ) {
+ private LinkedList<MethodContext> topologicalSort(HashSet<MethodContext> set) {
HashSet <MethodContext> discovered = new HashSet <MethodContext>();
LinkedList<MethodContext> sorted = new LinkedList<MethodContext>();
-
+
Iterator<MethodContext> itr = set.iterator();
while( itr.hasNext() ) {
MethodContext mc = itr.next();
-
- if( !discovered.contains( mc ) ) {
- dfsVisit( set, mc, sorted, discovered );
+
+ if( !discovered.contains(mc) ) {
+ dfsVisit(set, mc, sorted, discovered);
}
}
-
+
return sorted;
}
-
- private void dfsVisit( HashSet<MethodContext> set,
- MethodContext mc,
- LinkedList<MethodContext> sorted,
- HashSet <MethodContext> discovered ) {
- discovered.add( mc );
-
+
+ private void dfsVisit(HashSet<MethodContext> set,
+ MethodContext mc,
+ LinkedList<MethodContext> sorted,
+ HashSet <MethodContext> discovered) {
+ discovered.add(mc);
+
Descriptor d = mc.getDescriptor();
if( d instanceof MethodDescriptor ) {
- MethodDescriptor md = (MethodDescriptor) d;
- Iterator itr = callGraph.getCallerSet( md ).iterator();
+ MethodDescriptor md = (MethodDescriptor) d;
+ Iterator itr = callGraph.getCallerSet(md).iterator();
while( itr.hasNext() ) {
- Descriptor dCaller = (Descriptor) itr.next();
-
- // only consider the callers in the original set to analyze
- Set<MethodContext> callerContexts = mapDescriptorToAllMethodContexts.get( dCaller );
- if( callerContexts == null )
- continue;
-
- // since the analysis hasn't started, there should be exactly one
- // context if there are any at all
- assert callerContexts.size() == 1;
- MethodContext mcCaller = callerContexts.iterator().next();
- assert set.contains( mcCaller );
-
- if( !discovered.contains( mcCaller ) ) {
- dfsVisit( set, mcCaller, sorted, discovered );
- }
+ Descriptor dCaller = (Descriptor) itr.next();
+
+ // only consider the callers in the original set to analyze
+ Set<MethodContext> callerContexts = mapDescriptorToAllMethodContexts.get(dCaller);
+ if( callerContexts == null )
+ continue;
+
+ // since the analysis hasn't started, there should be exactly one
+ // context if there are any at all
+ assert callerContexts.size() == 1;
+ MethodContext mcCaller = callerContexts.iterator().next();
+ assert set.contains(mcCaller);
+
+ if( !discovered.contains(mcCaller) ) {
+ dfsVisit(set, mcCaller, sorted, discovered);
+ }
}
}
- sorted.addFirst( mc );
+ sorted.addFirst(mc);
}
private String computeAliasContextHistogram() {
-
- Hashtable<Integer, Integer> mapNumContexts2NumDesc =
+
+ Hashtable<Integer, Integer> mapNumContexts2NumDesc =
new Hashtable<Integer, Integer>();
-
+
Iterator itr = mapDescriptorToAllMethodContexts.entrySet().iterator();
while( itr.hasNext() ) {
- Map.Entry me = (Map.Entry) itr.next();
- HashSet<MethodContext> s = (HashSet<MethodContext>) me.getValue();
-
- Integer i = mapNumContexts2NumDesc.get( s.size() );
+ Map.Entry me = (Map.Entry)itr.next();
+ HashSet<MethodContext> s = (HashSet<MethodContext>)me.getValue();
+
+ Integer i = mapNumContexts2NumDesc.get(s.size() );
if( i == null ) {
- i = new Integer( 0 );
+ i = new Integer(0);
}
- mapNumContexts2NumDesc.put( s.size(), i + 1 );
- }
+ mapNumContexts2NumDesc.put(s.size(), i + 1);
+ }
String s = "";
int total = 0;
itr = mapNumContexts2NumDesc.entrySet().iterator();
while( itr.hasNext() ) {
- Map.Entry me = (Map.Entry) itr.next();
+ Map.Entry me = (Map.Entry)itr.next();
Integer c0 = (Integer) me.getKey();
Integer d0 = (Integer) me.getValue();
total += d0;
- s += String.format( "%4d methods had %4d unique alias contexts.\n", d0, c0 );
+ s += String.format("%4d methods had %4d unique alias contexts.\n", d0, c0);
}
- s += String.format( "\n%4d total methods analayzed.\n", total );
+ s += String.format("\n%4d total methods analayzed.\n", total);
return s;
}
+ private int numMethodsAnalyzed() {
+ return descriptorsToAnalyze.size();
+ }
+
- // insert a call to debugSnapshot() somewhere in the analysis
+
+ // insert a call to debugSnapshot() somewhere in the analysis
// to get successive captures of the analysis state
boolean takeDebugSnapshots = false;
- String mcDescSymbolDebug = "addFirst";
+ String mcDescSymbolDebug = "setRoute";
boolean stopAfterCapture = true;
// increments every visit to debugSnapshot, don't fiddle with it
+ // IMPORTANT NOTE FOR SETTING THE FOLLOWING VALUES: this
+ // counter increments just after every node is analyzed
+ // from the body of the method whose symbol is specified
+ // above.
int debugCounter = 0;
// the value of debugCounter to start reporting the debugCounter
int iterStartCapture = 0;
// the number of snapshots to take
- int numIterToCapture = 40;
+ int numIterToCapture = 300;
void debugSnapshot(OwnershipGraph og, FlatNode fn) {
if( debugCounter > iterStartCapture + numIterToCapture ) {
++debugCounter;
if( debugCounter > numStartCountReport &&
- freqCountReport > 0 &&
+ freqCountReport > 0 &&
debugCounter % freqCountReport == 0 ) {
System.out.println(" @@@ debug counter = "+debugCounter);
}
System.out.println(" @@@ capturing debug "+(debugCounter-iterStartCapture)+" @@@");
String graphName = String.format("snap%04d",debugCounter-iterStartCapture);
if( fn != null ) {
- graphName = graphName+fn;
+ graphName = graphName+fn;
}
try {
- // arguments to writeGraph are:
- // boolean writeLabels,
- // boolean labelSelect,
- // boolean pruneGarbage,
- // boolean writeReferencers
- // boolean writeParamMappings
-
- //og.writeGraph(graphName, true, true, true, false, false);
- og.writeGraph(graphName, true, true, true, false, false);
+ og.writeGraph(graphName,
+ true, // write labels (variables)
+ true, // selectively hide intermediate temp vars
+ true, // prune unreachable heap regions
+ false, // show back edges to confirm graph validity
+ false, // show parameter indices (unmaintained!)
+ true, // hide subset reachability states
+ true); // hide edge taints
} catch( Exception e ) {
- System.out.println("Error writing debug capture.");
- System.exit(0);
+ System.out.println("Error writing debug capture.");
+ System.exit(0);
}
}
System.exit(0);
}
}
+
+ public MethodEffectsAnalysis getMethodEffectsAnalysis() {
+ return meAnalysis;
+ }
+
+ public OwnershipGraph getOwnvershipGraphByMethodContext(MethodContext mc) {
+ return mapMethodContextToCompleteOwnershipGraph.get(mc);
+ }
+
+ public HashSet<MethodContext> getAllMethodContextSetByDescriptor(Descriptor d) {
+ return mapDescriptorToAllMethodContexts.get(d);
+ }
+
+ public MethodContext getCalleeMethodContext(MethodContext callerMC, FlatCall fc) {
+
+ Hashtable<FlatNode, OwnershipGraph> table=mapMethodContextToFlatNodeOwnershipGraph.get(callerMC);
+
+ // merge previous ownership graph to calculate corresponding method context
+ OwnershipGraph mergeOG = new OwnershipGraph();
+
+ for(int i=0; i<fc.numPrev(); i++) {
+ FlatNode prevNode=fc.getPrev(i);
+ if(prevNode!=null) {
+ OwnershipGraph prevOG=table.get(prevNode);
+ mergeOG.merge(prevOG);
+ }
+ }
+
+ MethodDescriptor md=fc.getMethod();
+ FlatMethod flatm = state.getMethodFlat(md);
+ Set<Integer> aliasedParamIndices = mergeOG.calculateAliasedParamSet(fc, md.isStatic(), flatm);
+ MethodContext calleeMC = new MethodContext(md, aliasedParamIndices);
+
+ return calleeMC;
+ }
+
+
}