return out;
}
- // 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,
- String justTime,
- boolean tabularOutput,
- int numLines
-)
- throws java.io.IOException {
- checkAnalysisComplete();
+ // use the methods given above to check every possible sharing class
+ // between task parameters and flagged allocation sites reachable
+ // from the task
+ public void writeAllSharing(String outputFile,
+ String timeReport,
+ String justTime,
+ boolean tabularOutput,
+ int numLines
+ )
+ throws java.io.IOException {
+ checkAnalysisComplete();
- BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
+ BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
- if (!tabularOutput) {
- 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;
+ int numSharing = 0;
- // look through every task for potential aliases
- Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
- while (taskItr.hasNext()) {
- TaskDescriptor td = (TaskDescriptor) taskItr.next();
+ // look through every task for potential sharing
+ Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
+ while (taskItr.hasNext()) {
+ TaskDescriptor td = (TaskDescriptor) taskItr.next();
- if (!tabularOutput) {
- bw.write("\n---------" + td + "--------\n");
- }
+ if (!tabularOutput) {
+ bw.write("\n---------" + td + "--------\n");
+ }
- HashSet<AllocSite> allocSites = getFlaggedAllocationSitesReachableFromTask(td);
+ HashSet<AllocSite> allocSites = getFlaggedAllocationSitesReachableFromTask(td);
- Set<HeapRegionNode> common;
+ Set<HeapRegionNode> common;
- // for each task parameter, check for aliases with
- // other task parameters and every allocation site
- // reachable from this task
- boolean foundSomeAlias = false;
+ // for each task parameter, check for sharing classes with
+ // other task parameters and every allocation site
+ // reachable from this task
+ boolean foundSomeSharing = false;
- FlatMethod fm = state.getMethodFlat(td);
- for (int i = 0; i < fm.numParameters(); ++i) {
+ FlatMethod fm = state.getMethodFlat(td);
+ for (int i = 0; i < fm.numParameters(); ++i) {
- // skip parameters with types that cannot reference
- // into the heap
- if( !shouldAnalysisTrack( fm.getParameter( i ).getType() ) ) {
- continue;
- }
+ // skip parameters with types that cannot reference
+ // into the heap
+ if( !shouldAnalysisTrack( fm.getParameter( i ).getType() ) ) {
+ continue;
+ }
- // for the ith parameter check for aliases to all
- // higher numbered parameters
- for (int j = i + 1; j < fm.numParameters(); ++j) {
-
- // skip parameters with types that cannot reference
- // into the heap
- if( !shouldAnalysisTrack( fm.getParameter( j ).getType() ) ) {
- continue;
- }
-
-
- common = hasPotentialSharing(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 sharing classes to all
+ // higher numbered parameters
+ for (int j = i + 1; j < fm.numParameters(); ++j) {
+
+ // skip parameters with types that cannot reference
+ // into the heap
+ if( !shouldAnalysisTrack( fm.getParameter( j ).getType() ) ) {
+ continue;
+ }
+
+
+ common = hasPotentialSharing(td, i, j);
+ if (!common.isEmpty()) {
+ foundSomeSharing = true;
+ ++numSharing;
+ if (!tabularOutput) {
+ bw.write("Potential sharing 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()) {
- AllocSite as = (AllocSite) allocItr.next();
- common = hasPotentialSharing(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 the ith parameter, check for sharing classes against
+ // the set of allocation sites reachable from this
+ // task context
+ Iterator allocItr = allocSites.iterator();
+ while (allocItr.hasNext()) {
+ AllocSite as = (AllocSite) allocItr.next();
+ common = hasPotentialSharing(td, i, as);
+ if (!common.isEmpty()) {
+ foundSomeSharing = true;
+ ++numSharing;
+ if (!tabularOutput) {
+ bw.write("Potential sharing between parameter " + i
+ + " and " + as.getFlatNew() + ".\n");
+ bw.write(prettyPrintNodeSet(common) + "\n");
+ }
+ }
+ }
+ }
- // for each allocation site check for aliases with
- // other allocation sites in the context of execution
- // of this task
- HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
- Iterator allocItr1 = allocSites.iterator();
- while (allocItr1.hasNext()) {
- AllocSite as1 = (AllocSite) allocItr1.next();
-
- Iterator allocItr2 = allocSites.iterator();
- while (allocItr2.hasNext()) {
- AllocSite as2 = (AllocSite) allocItr2.next();
-
- if (!outerChecked.contains(as2)) {
- common = hasPotentialSharing(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;
- }
- }
- }
- }
+ // for each allocation site check for sharing classes with
+ // other allocation sites in the context of execution
+ // of this task
+ HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
+ Iterator allocItr1 = allocSites.iterator();
+ while (allocItr1.hasNext()) {
+ AllocSite as1 = (AllocSite) allocItr1.next();
+
+ Iterator allocItr2 = allocSites.iterator();
+ while (allocItr2.hasNext()) {
+ AllocSite as2 = (AllocSite) allocItr2.next();
+
+ if (!outerChecked.contains(as2)) {
+ common = hasPotentialSharing(td, as1, as2);
+
+ if (!common.isEmpty()) {
+ foundSomeSharing = true;
+ ++numSharing;
+ if (!tabularOutput) {
+ bw.write("Potential sharing between "
+ + as1.getFlatNew() + " and "
+ + as2.getFlatNew() + ".\n");
+ bw.write(prettyPrintNodeSet(common) + "\n");
+ }
+ }
+ }
+ }
- outerChecked.add(as1);
- }
+ outerChecked.add(as1);
+ }
- if (!foundSomeAlias) {
- if (!tabularOutput) {
- bw.write("No aliases between flagged objects in Task " + td
- + ".\n");
- }
- }
- }
+ if (!foundSomeSharing) {
+ if (!tabularOutput) {
+ bw.write("No sharing between flagged objects in Task " + td
+ + ".\n");
+ }
+ }
+ }
- /*
- if (!tabularOutput) {
- bw.write("\n" + computeAliasContextHistogram());
- } else {
- bw.write(" & " + numAlias + " & " + justTime + " & " + numLines
- + " & " + numMethodsAnalyzed() + " \\\\\n");
- }
- */
+
+ if (tabularOutput) {
+ bw.write(" & " + numSharing + " & " + justTime + " & " + numLines
+ + " & " + numMethodsAnalyzed() + " \\\\\n");
+ } else {
+ bw.write("\nNumber sharing classes: "+numSharing);
+ }
- bw.close();
- }
+ bw.close();
+ }
- // this version of writeAllAliases is for Java programs that have no tasks
- public void writeAllAliasesJava(String outputFile,
- String timeReport,
- String justTime,
- boolean tabularOutput,
- int numLines
-)
- throws java.io.IOException {
- checkAnalysisComplete();
-
- assert !state.TASK;
+ // this version of writeAllSharing is for Java programs that have no tasks
+ public void writeAllSharingJava(String outputFile,
+ String timeReport,
+ String justTime,
+ boolean tabularOutput,
+ int numLines
+ )
+ throws java.io.IOException {
+ checkAnalysisComplete();
- BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
+ assert !state.TASK;
- bw.write("Conducting disjoint reachability analysis with allocation depth = "
- + allocationDepth + "\n");
- bw.write(timeReport + "\n\n");
+ int numSharing = 0;
- boolean foundSomeAlias = false;
+ BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
+
+ bw.write("Conducting disjoint reachability analysis with allocation depth = "
+ + allocationDepth + "\n");
+ bw.write(timeReport + "\n\n");
+
+ boolean foundSomeSharing = false;
+
+ Descriptor d = typeUtil.getMain();
+ HashSet<AllocSite> allocSites = getFlaggedAllocationSites(d);
+
+ // for each allocation site check for sharing classes with
+ // other allocation sites in the context of execution
+ // of this task
+ HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
+ Iterator allocItr1 = allocSites.iterator();
+ while (allocItr1.hasNext()) {
+ AllocSite as1 = (AllocSite) allocItr1.next();
+
+ Iterator allocItr2 = allocSites.iterator();
+ while (allocItr2.hasNext()) {
+ AllocSite as2 = (AllocSite) allocItr2.next();
+
+ if (!outerChecked.contains(as2)) {
+ Set<HeapRegionNode> common = hasPotentialSharing(d,
+ as1, as2);
+
+ if (!common.isEmpty()) {
+ foundSomeSharing = true;
+ bw.write("Potential sharing between "
+ + as1.getDisjointAnalysisId() + " and "
+ + as2.getDisjointAnalysisId() + ".\n");
+ bw.write(prettyPrintNodeSet(common) + "\n");
+ ++numSharing;
+ }
+ }
+ }
- Descriptor d = typeUtil.getMain();
- HashSet<AllocSite> allocSites = getFlaggedAllocationSites(d);
+ outerChecked.add(as1);
+ }
- // for each allocation site check for aliases with
- // other allocation sites in the context of execution
- // of this task
- HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
- Iterator allocItr1 = allocSites.iterator();
- while (allocItr1.hasNext()) {
- AllocSite as1 = (AllocSite) allocItr1.next();
+ if (!foundSomeSharing) {
+ bw.write("No sharing classes between flagged objects found.\n");
+ } else {
+ bw.write("\nNumber sharing classes: "+numSharing);
+ }
- Iterator allocItr2 = allocSites.iterator();
- while (allocItr2.hasNext()) {
- AllocSite as2 = (AllocSite) allocItr2.next();
+ bw.write("Number of methods analyzed: "+numMethodsAnalyzed()+"\n");
- if (!outerChecked.contains(as2)) {
- Set<HeapRegionNode> common = hasPotentialSharing(d,
- as1, as2);
+ bw.close();
+ }
+
+ ///////////////////////////////////////////
+ //
+ // end public interface
+ //
+ ///////////////////////////////////////////
- if (!common.isEmpty()) {
- foundSomeAlias = true;
- bw.write("Potential alias between "
- + as1.getDisjointAnalysisId() + " and "
- + as2.getDisjointAnalysisId() + ".\n");
- bw.write(prettyPrintNodeSet(common) + "\n");
- }
- }
- }
+ protected void checkAnalysisComplete() {
+ if( !analysisComplete ) {
+ throw new Error("Warning: public interface method called while analysis is running.");
+ }
+ }
- outerChecked.add(as1);
- }
- if (!foundSomeAlias) {
- bw.write("No aliases between flagged objects found.\n");
- }
+ // run in faster mode, only when bugs wrung out!
+ public static boolean releaseMode;
-// bw.write("\n" + computeAliasContextHistogram());
- bw.close();
- }
-
- ///////////////////////////////////////////
- //
- // end public interface
- //
- ///////////////////////////////////////////
+ // use command line option to set this, analysis
+ // should attempt to be deterministic
+ public static boolean determinismDesired;
- protected void checkAnalysisComplete() {
- if( !analysisComplete ) {
- throw new Error("Warning: public interface method called while analysis is running.");
- }
- }
+ // when we want to enforce determinism in the
+ // analysis we need to sort descriptors rather
+ // than toss them in efficient sets, use this
+ public static DescriptorComparator dComp =
+ new DescriptorComparator();
// data from the compiler
public int allocationDepth;
// data structure for public interface
- private Hashtable<Descriptor, HashSet<AllocSite> > mapDescriptorToAllocSiteSet;
+ private Hashtable< Descriptor, HashSet<AllocSite> >
+ mapDescriptorToAllocSiteSet;
// for public interface methods to warn that they
// current descriptors to visit in fixed-point
// interprocedural analysis, prioritized by
// dependency in the call graph
+ protected Stack<Descriptor>
+ descriptorsToVisitStack;
protected PriorityQueue<DescriptorQWrapper>
descriptorsToVisitQ;
protected Hashtable<Descriptor, Integer>
mapDescriptorToPriority;
+ // when analyzing a method and scheduling more:
+ // remember set of callee's enqueued for analysis
+ // so they can be put on top of the callers in
+ // the stack-visit mode
+ protected Set<Descriptor>
+ calleesToEnqueue;
// maps a descriptor to its current partial result
// from the intraprocedural fixed-point analysis--
protected Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >
mapDescriptorToIHMcontributions;
- // TODO -- CHANGE EDGE/TYPE/FIELD storage!
+ // additionally, keep a mapping from descriptors to the
+ // merged in-coming initial context, because we want this
+ // initial context to be STRICTLY MONOTONIC
+ protected Hashtable<Descriptor, ReachGraph>
+ mapDescriptorToInitialContext;
+
+ // make the result for back edges analysis-wide STRICTLY
+ // MONOTONIC as well, but notice we use FlatNode as the
+ // key for this map: in case we want to consider other
+ // nodes as back edge's in future implementations
+ protected Hashtable<FlatNode, ReachGraph>
+ mapBackEdgeToMonotone;
+
+
public static final String arrayElementFieldName = "___element_";
static protected Hashtable<TypeDescriptor, FieldDescriptor>
mapTypeToArrayField;
//map task descriptor to initial task parameter
protected Hashtable<Descriptor, ReachGraph>
- mapDescriptorToReachGraph;
+ mapDescriptorToReachGraph;
+
+ protected PointerMethod pm;
+
+ static protected Hashtable<FlatNode, ReachGraph> fn2rg =
+ new Hashtable<FlatNode, ReachGraph>();
+
+ private Hashtable<FlatCall, Descriptor> fc2enclosing;
+
// allocate various structures that are not local
// to a single class method--should be done once
- protected void allocateStructures() {
- descriptorsToAnalyze = new HashSet<Descriptor>();
+ protected void allocateStructures() {
+
+ if( determinismDesired ) {
+ // use an ordered set
+ descriptorsToAnalyze = new TreeSet<Descriptor>( dComp );
+ } else {
+ // otherwise use a speedy hashset
+ descriptorsToAnalyze = new HashSet<Descriptor>();
+ }
mapDescriptorToCompleteReachGraph =
new Hashtable<Descriptor, ReachGraph>();
mapDescriptorToIHMcontributions =
new Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >();
+ mapDescriptorToInitialContext =
+ new Hashtable<Descriptor, ReachGraph>();
+
+ mapBackEdgeToMonotone =
+ new Hashtable<FlatNode, ReachGraph>();
+
mapHrnIdToAllocSite =
new Hashtable<Integer, AllocSite>();
mapTypeToArrayField =
new Hashtable <TypeDescriptor, FieldDescriptor>();
- descriptorsToVisitQ =
- new PriorityQueue<DescriptorQWrapper>();
+ if( state.DISJOINTDVISITSTACK ||
+ state.DISJOINTDVISITSTACKEESONTOP
+ ) {
+ descriptorsToVisitStack =
+ new Stack<Descriptor>();
+ }
+
+ if( state.DISJOINTDVISITPQUE ) {
+ descriptorsToVisitQ =
+ new PriorityQueue<DescriptorQWrapper>();
+ }
descriptorsToVisitSet =
new HashSet<Descriptor>();
mapDescriptorToPriority =
new Hashtable<Descriptor, Integer>();
+ calleesToEnqueue =
+ new HashSet<Descriptor>();
+
mapDescriptorToAllocSiteSet =
new Hashtable<Descriptor, HashSet<AllocSite> >();
mapDescriptorToReachGraph =
new Hashtable<Descriptor, ReachGraph>();
+
+ pm = new PointerMethod();
+
+ fc2enclosing = new Hashtable<FlatCall, Descriptor>();
}
ArrayReferencees arrayReferencees
) throws java.io.IOException {
- analysisComplete = false;
+ analysisComplete = false;
this.state = state;
this.typeUtil = typeUtil;
this.liveness = liveness;
this.arrayReferencees = arrayReferencees;
this.allocationDepth = state.DISJOINTALLOCDEPTH;
+ this.releaseMode = state.DISJOINTRELEASEMODE;
+ this.determinismDesired = state.DISJOINTDETERMINISM;
this.writeFinalDOTs = state.DISJOINTWRITEDOTS && !state.DISJOINTWRITEALL;
this.writeAllIncrementalDOTs = state.DISJOINTWRITEDOTS && state.DISJOINTWRITEALL;
this.stopAfterCapture = state.DISJOINTSNAPSTOPAFTER;
this.snapVisitCounter = 1; // count visits from 1 (user will write 1, means 1st visit)
this.snapNodeCounter = 0; // count nodes from 0
+
+ assert
+ state.DISJOINTDVISITSTACK ||
+ state.DISJOINTDVISITPQUE ||
+ state.DISJOINTDVISITSTACKEESONTOP;
+ assert !(state.DISJOINTDVISITSTACK && state.DISJOINTDVISITPQUE);
+ assert !(state.DISJOINTDVISITSTACK && state.DISJOINTDVISITSTACKEESONTOP);
+ assert !(state.DISJOINTDVISITPQUE && state.DISJOINTDVISITSTACKEESONTOP);
// set some static configuration for ReachGraphs
ReachGraph.allocationDepth = allocationDepth;
ReachGraph.typeUtil = typeUtil;
- ReachGraph.debugCallSiteVisitsUntilExit = state.DISJOINTDEBUGCALLCOUNT;
+ ReachGraph.debugCallSiteVisitStartCapture
+ = state.DISJOINTDEBUGCALLVISITTOSTART;
+
+ ReachGraph.debugCallSiteNumVisitsToCapture
+ = state.DISJOINTDEBUGCALLNUMVISITS;
+
+ ReachGraph.debugCallSiteStopAfter
+ = state.DISJOINTDEBUGCALLSTOPAFTER;
+
+ ReachGraph.debugCallSiteVisitCounter
+ = 0; // count visits from 1, is incremented before first visit
+
+
allocateStructures();
writeFinalIHMs();
}
+ if( state.DISJOINTWRITEINITCONTEXTS ) {
+ writeInitialContexts();
+ }
+
if( state.DISJOINTALIASFILE != null ) {
if( state.TASK ) {
- writeAllAliases(state.DISJOINTALIASFILE, treport, justtime, state.DISJOINTALIASTAB, state.lines);
+ writeAllSharing(state.DISJOINTALIASFILE, treport, justtime, state.DISJOINTALIASTAB, state.lines);
} else {
- /*
- writeAllAliasesJava( aliasFile,
- treport,
- justtime,
- state.DISJOINTALIASTAB,
- state.lines );
- */
+ writeAllSharingJava(state.DISJOINTALIASFILE,
+ treport,
+ justtime,
+ state.DISJOINTALIASTAB,
+ state.lines
+ );
}
}
}
+ protected boolean moreDescriptorsToVisit() {
+ if( state.DISJOINTDVISITSTACK ||
+ state.DISJOINTDVISITSTACKEESONTOP
+ ) {
+ return !descriptorsToVisitStack.isEmpty();
+
+ } else if( state.DISJOINTDVISITPQUE ) {
+ return !descriptorsToVisitQ.isEmpty();
+ }
+
+ throw new Error( "Neither descriptor visiting mode set" );
+ }
+
+
// fixed-point computation over the call graph--when a
// method's callees are updated, it must be reanalyzed
protected void analyzeMethods() throws java.io.IOException {
+ // task or non-task (java) mode determines what the roots
+ // of the call chain are, and establishes the set of methods
+ // reachable from the roots that will be analyzed
+
if( state.TASK ) {
- // This analysis does not support Bamboo at the moment,
- // but if it does in the future we would initialize the
- // set of descriptors to analyze as the program-reachable
- // tasks and the methods callable by them. For Java,
- // just methods reachable from the main method.
- System.out.println( "Bamboo..." );
- Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
+ System.out.println( "Bamboo mode..." );
- while (taskItr.hasNext()) {
- TaskDescriptor td = (TaskDescriptor) taskItr.next();
- if (!descriptorsToAnalyze.contains(td)) {
- descriptorsToAnalyze.add(td);
- descriptorsToAnalyze.addAll(callGraph.getAllMethods(td));
- }
+ Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
+ while( taskItr.hasNext() ) {
+ TaskDescriptor td = (TaskDescriptor) taskItr.next();
+ if( !descriptorsToAnalyze.contains( td ) ) {
+ // add all methods transitively reachable from the
+ // tasks as well
+ descriptorsToAnalyze.add( td );
+ descriptorsToAnalyze.addAll( callGraph.getAllMethods( td ) );
+ }
}
-
+
} else {
+ System.out.println( "Java mode..." );
+
// add all methods transitively reachable from the
// source's main to set for analysis
mdSourceEntry = typeUtil.getMain();
descriptorsToAnalyze.add( mdSourceEntry );
- descriptorsToAnalyze.addAll(
- callGraph.getAllMethods( mdSourceEntry )
- );
-
+ descriptorsToAnalyze.addAll( callGraph.getAllMethods( mdSourceEntry ) );
+
// fabricate an empty calling context that will call
// the source's main, but call graph doesn't know
// about it, so explicitly add it
descriptorsToAnalyze.add( mdAnalysisEntry );
}
- // topologically sort according to the call graph so
- // leaf calls are ordered first, smarter analysis order
- // CHANGED: order leaf calls last!!
- LinkedList<Descriptor> sortedDescriptors =
- topologicalSort( descriptorsToAnalyze );
-
- // add sorted descriptors to priority queue, and duplicate
- // the queue as a set for efficiently testing whether some
- // method is marked for analysis
- int p = 0;
- Iterator<Descriptor> dItr = sortedDescriptors.iterator();
- while( dItr.hasNext() ) {
- Descriptor d = dItr.next();
- mapDescriptorToPriority.put( d, new Integer( p ) );
- descriptorsToVisitQ.add( new DescriptorQWrapper( p, d ) );
- descriptorsToVisitSet.add( d );
- ++p;
+
+ // now, depending on the interprocedural mode for visiting
+ // methods, set up the needed data structures
+
+ if( state.DISJOINTDVISITPQUE ) {
+
+ // topologically sort according to the call graph so
+ // leaf calls are last, helps build contexts up first
+ LinkedList<Descriptor> sortedDescriptors =
+ topologicalSort( descriptorsToAnalyze );
+
+ // add sorted descriptors to priority queue, and duplicate
+ // the queue as a set for efficiently testing whether some
+ // method is marked for analysis
+ int p = 0;
+ Iterator<Descriptor> dItr;
+
+ // for the priority queue, give items at the head
+ // of the sorted list a low number (highest priority)
+ while( !sortedDescriptors.isEmpty() ) {
+ Descriptor d = sortedDescriptors.removeFirst();
+ mapDescriptorToPriority.put( d, new Integer( p ) );
+ descriptorsToVisitQ.add( new DescriptorQWrapper( p, d ) );
+ descriptorsToVisitSet.add( d );
+ ++p;
+ }
+
+ } else if( state.DISJOINTDVISITSTACK ||
+ state.DISJOINTDVISITSTACKEESONTOP
+ ) {
+ // if we're doing the stack scheme, just throw the root
+ // method or tasks on the stack
+ if( state.TASK ) {
+ Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
+ while( taskItr.hasNext() ) {
+ TaskDescriptor td = (TaskDescriptor) taskItr.next();
+ descriptorsToVisitStack.add( td );
+ descriptorsToVisitSet.add( td );
+ }
+
+ } else {
+ descriptorsToVisitStack.add( mdAnalysisEntry );
+ descriptorsToVisitSet.add( mdAnalysisEntry );
+ }
+
+ } else {
+ throw new Error( "Unknown method scheduling mode" );
}
- // analyze methods from the priority queue until it is empty
- while( !descriptorsToVisitQ.isEmpty() ) {
- Descriptor d = descriptorsToVisitQ.poll().getDescriptor();
+
+ // analyze scheduled methods until there are no more to visit
+ while( moreDescriptorsToVisit() ) {
+ Descriptor d = null;
+
+ if( state.DISJOINTDVISITSTACK ||
+ state.DISJOINTDVISITSTACKEESONTOP
+ ) {
+ d = descriptorsToVisitStack.pop();
+
+ } else if( state.DISJOINTDVISITPQUE ) {
+ d = descriptorsToVisitQ.poll().getDescriptor();
+ }
+
assert descriptorsToVisitSet.contains( d );
descriptorsToVisitSet.remove( d );
System.out.println( "Analyzing " + d );
+ if( state.DISJOINTDVISITSTACKEESONTOP ) {
+ assert calleesToEnqueue.isEmpty();
+ }
+
ReachGraph rg = analyzeMethod( d );
ReachGraph rgPrev = getPartial( d );
if( !rg.equals( rgPrev ) ) {
setPartial( d, rg );
+ if( state.DISJOINTDEBUGSCHEDULING ) {
+ System.out.println( " complete graph changed, scheduling callers for analysis:" );
+ }
+
// results for d changed, so enqueue dependents
// of d for further analysis
Iterator<Descriptor> depsItr = getDependents( d ).iterator();
while( depsItr.hasNext() ) {
Descriptor dNext = depsItr.next();
enqueue( dNext );
+
+ if( state.DISJOINTDEBUGSCHEDULING ) {
+ System.out.println( " "+dNext );
+ }
}
- }
- }
+ }
+
+ // whether or not the method under analysis changed,
+ // we may have some callees that are scheduled for
+ // more analysis, and they should go on the top of
+ // the stack now (in other method-visiting modes they
+ // are already enqueued at this point
+ if( state.DISJOINTDVISITSTACKEESONTOP ) {
+ Iterator<Descriptor> depsItr = calleesToEnqueue.iterator();
+ while( depsItr.hasNext() ) {
+ Descriptor dNext = depsItr.next();
+ enqueue( dNext );
+ }
+ calleesToEnqueue.clear();
+ }
+
+ }
}
protected ReachGraph analyzeMethod( Descriptor d )
} else {
fm = state.getMethodFlat( d );
}
-
+ pm.analyzeMethod( fm );
+
// intraprocedural work set
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
flatNodesToVisit.add( fm );
+
+ // if determinism is desired by client, shadow the
+ // set with a queue to make visit order deterministic
+ Queue<FlatNode> flatNodesToVisitQ = null;
+ if( determinismDesired ) {
+ flatNodesToVisitQ = new LinkedList<FlatNode>();
+ flatNodesToVisitQ.add( fm );
+ }
// mapping of current partial results
Hashtable<FlatNode, ReachGraph> mapFlatNodeToReachGraph =
HashSet<FlatReturnNode> setReturns = new HashSet<FlatReturnNode>();
while( !flatNodesToVisit.isEmpty() ) {
- FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+
+ FlatNode fn;
+ if( determinismDesired ) {
+ assert !flatNodesToVisitQ.isEmpty();
+ fn = flatNodesToVisitQ.remove();
+ } else {
+ fn = flatNodesToVisit.iterator().next();
+ }
flatNodesToVisit.remove( fn );
// effect transfer function defined by this node,
}
// start by merging all node's parents' graphs
- for( int i = 0; i < fn.numPrev(); ++i ) {
- FlatNode pn = fn.getPrev( i );
+ for( int i = 0; i < pm.numPrev(fn); ++i ) {
+ FlatNode pn = pm.getPrev(fn,i);
if( mapFlatNodeToReachGraph.containsKey( pn ) ) {
ReachGraph rgParent = mapFlatNodeToReachGraph.get( pn );
rg.merge( rgParent );
if( !rg.equals( rgPrev ) ) {
mapFlatNodeToReachGraph.put( fn, rg );
- for( int i = 0; i < fn.numNext(); i++ ) {
- FlatNode nn = fn.getNext( i );
+ for( int i = 0; i < pm.numNext( fn ); i++ ) {
+ FlatNode nn = pm.getNext( fn, i );
+
flatNodesToVisit.add( nn );
+ if( determinismDesired ) {
+ flatNodesToVisitQ.add( nn );
+ }
}
}
}
+
// end by merging all return nodes into a complete
- // ownership graph that represents all possible heap
+ // reach graph that represents all possible heap
// states after the flat method returns
ReachGraph completeGraph = new ReachGraph();
assert fc.getMethod().equals( d );
- // some call sites are in same method context though,
- // and all of them should be merged together first,
- // then heaps from different contexts should be merged
- // THIS ASSUMES DIFFERENT CONTEXTS NEED SPECIAL CONSIDERATION!
- // such as, do allocation sites need to be aged?
+ rg.merge( rgContrib );
+ }
+
+ // additionally, we are enforcing STRICT MONOTONICITY for the
+ // method's initial context, so grow the context by whatever
+ // the previously computed context was, and put the most
+ // up-to-date context back in the map
+ ReachGraph rgPrevContext = mapDescriptorToInitialContext.get( d );
+ rg.merge( rgPrevContext );
+ mapDescriptorToInitialContext.put( d, rg );
- rg.merge_diffMethodContext( rgContrib );
- }
} break;
case FKind.FlatOpNode:
break;
case FKind.FlatCall: {
- //TODO: temporal fix for task descriptor case
- //MethodDescriptor mdCaller = fmContaining.getMethod();
Descriptor mdCaller;
- if(fmContaining.getMethod()!=null){
- mdCaller = fmContaining.getMethod();
- }else{
- mdCaller = fmContaining.getTask();
+ if( fmContaining.getMethod() != null ){
+ mdCaller = fmContaining.getMethod();
+ } else {
+ mdCaller = fmContaining.getTask();
}
FlatCall fc = (FlatCall) fn;
MethodDescriptor mdCallee = fc.getMethod();
FlatMethod fmCallee = state.getMethodFlat( mdCallee );
- boolean writeDebugDOTs =
+
+ boolean debugCallSite =
mdCaller.getSymbol().equals( state.DISJOINTDEBUGCALLER ) &&
- mdCallee.getSymbol().equals( state.DISJOINTDEBUGCALLEE );
+ mdCallee.getSymbol().equals( state.DISJOINTDEBUGCALLEE );
+
+ boolean writeDebugDOTs = false;
+ boolean stopAfter = false;
+ if( debugCallSite ) {
+ ++ReachGraph.debugCallSiteVisitCounter;
+ System.out.println( " $$$ Debug call site visit "+
+ ReachGraph.debugCallSiteVisitCounter+
+ " $$$"
+ );
+ if(
+ (ReachGraph.debugCallSiteVisitCounter >=
+ ReachGraph.debugCallSiteVisitStartCapture) &&
+
+ (ReachGraph.debugCallSiteVisitCounter <
+ ReachGraph.debugCallSiteVisitStartCapture +
+ ReachGraph.debugCallSiteNumVisitsToCapture)
+ ) {
+ writeDebugDOTs = true;
+ System.out.println( " $$$ Capturing this call site visit $$$" );
+ if( ReachGraph.debugCallSiteStopAfter &&
+ (ReachGraph.debugCallSiteVisitCounter ==
+ ReachGraph.debugCallSiteVisitStartCapture +
+ ReachGraph.debugCallSiteNumVisitsToCapture - 1)
+ ) {
+ stopAfter = true;
+ }
+ }
+ }
// calculate the heap this call site can reach--note this is
// if heap at call site changed, update the contribution,
// and reschedule the callee for analysis
addIHMcontribution( mdCallee, fc, heapForThisCall_cur );
- enqueue( mdCallee );
- }
+ // map a FlatCall to its enclosing method/task descriptor
+ // so we can write that info out later
+ fc2enclosing.put( fc, mdCaller );
+ if( state.DISJOINTDEBUGSCHEDULING ) {
+ System.out.println( " context changed, scheduling callee: "+mdCallee );
+ }
+
+ if( state.DISJOINTDVISITSTACKEESONTOP ) {
+ calleesToEnqueue.add( mdCallee );
+ } else {
+ enqueue( mdCallee );
+ }
+
+ }
// the transformation for a call site should update the
// current heap abstraction with any effects from the callee,
// or if the method is virtual, the effects from any possible
// callees, so find the set of callees...
- Set<MethodDescriptor> setPossibleCallees =
- new HashSet<MethodDescriptor>();
+ Set<MethodDescriptor> setPossibleCallees;
+ if( determinismDesired ) {
+ // use an ordered set
+ setPossibleCallees = new TreeSet<MethodDescriptor>( dComp );
+ } else {
+ // otherwise use a speedy hashset
+ setPossibleCallees = new HashSet<MethodDescriptor>();
+ }
if( mdCallee.isStatic() ) {
setPossibleCallees.add( mdCallee );
if( rgEffect == null ) {
// if this method has never been analyzed just schedule it
// for analysis and skip over this call site for now
- enqueue( mdPossible );
+ if( state.DISJOINTDVISITSTACKEESONTOP ) {
+ calleesToEnqueue.add( mdPossible );
+ } else {
+ enqueue( mdPossible );
+ }
+
+ if( state.DISJOINTDEBUGSCHEDULING ) {
+ System.out.println( " callee hasn't been analyzed, scheduling: "+mdPossible );
+ }
+
+
} else {
rgCopy.resolveMethodCall( fc,
fmPossible,
}
+ if( stopAfter ) {
+ System.out.println( "$$$ Exiting after requested captures of call site. $$$" );
+ System.exit( 0 );
+ }
+
+
// now that we've taken care of building heap models for
// callee analysis, finish this transformation
rg = rgMergeOfEffects;
//rg.globalSweep();
+ // back edges are strictly monotonic
+ if( pm.isBackEdge( fn ) ) {
+ ReachGraph rgPrevResult = mapBackEdgeToMonotone.get( fn );
+ rg.merge( rgPrevResult );
+ mapBackEdgeToMonotone.put( fn, rg );
+ }
+
// at this point rg should be the correct update
// by an above transfer function, or untouched if
// the flat node type doesn't affect the heap
return rg;
}
+
// this method should generate integers strictly greater than zero!
// special "shadow" regions are made from a heap region by negating
ReachGraph rg = (ReachGraph) me.getValue();
rg.writeGraph( "COMPLETE"+d,
- true, // write labels (variables)
- true, // selectively hide intermediate temp vars
- true, // prune unreachable heap regions
- false, // hide subset reachability states
- true ); // hide edge taints
+ true, // write labels (variables)
+ true, // selectively hide intermediate temp vars
+ true, // prune unreachable heap regions
+ false, // hide reachability altogether
+ true, // hide subset reachability states
+ true, // hide predicates
+ false ); // hide edge taints
}
}
FlatCall fc = (FlatCall) me2.getKey();
ReachGraph rg = (ReachGraph) me2.getValue();
- rg.writeGraph( "IHMPARTFOR"+d+"FROM"+fc,
+ rg.writeGraph( "IHMPARTFOR"+d+"FROM"+fc2enclosing.get( fc )+fc,
true, // write labels (variables)
- false, // selectively hide intermediate temp vars
- false, // prune unreachable heap regions
- false, // hide subset reachability states
+ true, // selectively hide intermediate temp vars
+ true, // hide reachability altogether
+ true, // prune unreachable heap regions
+ true, // hide subset reachability states
+ false, // hide predicates
true ); // hide edge taints
}
}
}
+
+ private void writeInitialContexts() {
+ Set entrySet = mapDescriptorToInitialContext.entrySet();
+ Iterator itr = entrySet.iterator();
+ while( itr.hasNext() ) {
+ Map.Entry me = (Map.Entry) itr.next();
+ Descriptor d = (Descriptor) me.getKey();
+ ReachGraph rg = (ReachGraph) me.getValue();
+
+ rg.writeGraph( "INITIAL"+d,
+ true, // write labels (variables)
+ true, // selectively hide intermediate temp vars
+ true, // prune unreachable heap regions
+ false, // hide all reachability
+ true, // hide subset reachability states
+ true, // hide predicates
+ false );// hide edge taints
+ }
+ }
protected ReachGraph getPartial( Descriptor d ) {
rg.writeGraph( d+"COMPLETE"+String.format( "%05d", n ),
true, // write labels (variables)
true, // selectively hide intermediate temp vars
- false, // prune unreachable heap regions
- false, // hide subset reachability states
- true ); // hide edge taints
+ true, // prune unreachable heap regions
+ false, // hide all reachability
+ true, // hide subset reachability states
+ false, // hide predicates
+ false); // hide edge taints
mapDescriptorToNumUpdates.put( d, n + 1 );
}
protected AllocSite getAllocSiteFromFlatNewPRIVATE( FlatNew fnew ) {
if( !mapFlatNewToAllocSite.containsKey( fnew ) ) {
- AllocSite as =
- (AllocSite) Canonical.makeCanonical( new AllocSite( allocationDepth,
- fnew,
- fnew.getDisjointId()
- )
- );
+ AllocSite as = AllocSite.factory( allocationDepth,
+ fnew,
+ fnew.getDisjointId(),
+ false
+ );
// the newest nodes are single objects
for( int i = 0; i < allocationDepth; ++i ) {
return true;
}
-
- /*
- // return all allocation sites in the method (there is one allocation
- // site per FlatNew node in a method)
- protected HashSet<AllocSite> getAllocSiteSet(Descriptor d) {
- if( !mapDescriptorToAllocSiteSet.containsKey(d) ) {
- buildAllocSiteSet(d);
- }
-
- return mapDescriptorToAllocSiteSet.get(d);
-
- }
- */
-
- /*
- protected void buildAllocSiteSet(Descriptor d) {
- HashSet<AllocSite> s = new HashSet<AllocSite>();
-
- FlatMethod fm = state.getMethodFlat( d );
-
- // visit every node in this FlatMethod's IR graph
- // and make a set of the allocation sites from the
- // FlatNew node's visited
- HashSet<FlatNode> visited = new HashSet<FlatNode>();
- HashSet<FlatNode> toVisit = new HashSet<FlatNode>();
- toVisit.add( fm );
-
- while( !toVisit.isEmpty() ) {
- FlatNode n = toVisit.iterator().next();
-
- if( n instanceof FlatNew ) {
- s.add(getAllocSiteFromFlatNewPRIVATE( (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 );
- }
- }
- }
-
- mapDescriptorToAllocSiteSet.put( d, s );
- }
- */
- /*
- protected HashSet<AllocSite> getFlaggedAllocSites(Descriptor dIn) {
-
- HashSet<AllocSite> out = new HashSet<AllocSite>();
- HashSet<Descriptor> toVisit = new HashSet<Descriptor>();
- HashSet<Descriptor> visited = new HashSet<Descriptor>();
-
- toVisit.add(dIn);
-
- while( !toVisit.isEmpty() ) {
- Descriptor d = toVisit.iterator().next();
- toVisit.remove(d);
- visited.add(d);
-
- HashSet<AllocSite> asSet = getAllocSiteSet(d);
- Iterator asItr = asSet.iterator();
- while( asItr.hasNext() ) {
- AllocSite as = (AllocSite) asItr.next();
- if( as.getDisjointAnalysisId() != 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);
- }
- }
- }
- }
-
- return out;
- }
- */
-
- /*
- protected HashSet<AllocSite>
- getFlaggedAllocSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
-
- HashSet<AllocSite> asSetTotal = new HashSet<AllocSite>();
- HashSet<Descriptor> toVisit = new HashSet<Descriptor>();
- HashSet<Descriptor> visited = new HashSet<Descriptor>();
-
- toVisit.add(td);
-
- // traverse this task and all methods reachable from this task
- while( !toVisit.isEmpty() ) {
- Descriptor d = toVisit.iterator().next();
- toVisit.remove(d);
- visited.add(d);
-
- HashSet<AllocSite> asSet = getAllocSiteSet(d);
- Iterator asItr = asSet.iterator();
- while( asItr.hasNext() ) {
- AllocSite as = (AllocSite) 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);
- }
- }
- }
- }
-
-
- return asSetTotal;
- }
- */
-
-
- /*
- protected String computeAliasContextHistogram() {
-
- Hashtable<Integer, Integer> mapNumContexts2NumDesc =
- new Hashtable<Integer, Integer>();
-
- Iterator itr = mapDescriptorToAllDescriptors.entrySet().iterator();
- while( itr.hasNext() ) {
- Map.Entry me = (Map.Entry) itr.next();
- HashSet<Descriptor> s = (HashSet<Descriptor>) me.getValue();
-
- Integer i = mapNumContexts2NumDesc.get( s.size() );
- if( i == null ) {
- i = new Integer( 0 );
- }
- 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();
- 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( "\n%4d total methods analayzed.\n", total );
-
- return s;
- }
-
protected int numMethodsAnalyzed() {
return descriptorsToAnalyze.size();
}
- */
+
protected LinkedList<Descriptor> topologicalSort( Set<Descriptor> toSort ) {
- Set <Descriptor> discovered = new HashSet <Descriptor>();
- LinkedList<Descriptor> sorted = new LinkedList<Descriptor>();
+ Set<Descriptor> discovered;
+
+ if( determinismDesired ) {
+ // use an ordered set
+ discovered = new TreeSet<Descriptor>( dComp );
+ } else {
+ // otherwise use a speedy hashset
+ discovered = new HashSet<Descriptor>();
+ }
+
+ LinkedList<Descriptor> sorted = new LinkedList<Descriptor>();
Iterator<Descriptor> itr = toSort.iterator();
while( itr.hasNext() ) {
protected void enqueue( Descriptor d ) {
+
if( !descriptorsToVisitSet.contains( d ) ) {
- Integer priority = mapDescriptorToPriority.get( d );
- descriptorsToVisitQ.add( new DescriptorQWrapper( priority,
- d )
- );
+
+ if( state.DISJOINTDVISITSTACK ||
+ state.DISJOINTDVISITSTACKEESONTOP
+ ) {
+ descriptorsToVisitStack.add( d );
+
+ } else if( state.DISJOINTDVISITPQUE ) {
+ Integer priority = mapDescriptorToPriority.get( d );
+ descriptorsToVisitQ.add( new DescriptorQWrapper( priority,
+ d )
+ );
+ }
+
descriptorsToVisitSet.add( d );
}
}
getIHMcontributions( d );
if( !heapsFromCallers.containsKey( fc ) ) {
- heapsFromCallers.put( fc, new ReachGraph() );
+ return null;
}
return heapsFromCallers.get( fc );
}
+
public void addIHMcontribution( Descriptor d,
FlatCall fc,
ReachGraph rg
heapsFromCallers.put( fc, rg );
}
-private AllocSite createParameterAllocSite(ReachGraph rg, TempDescriptor tempDesc) {
+
+ private AllocSite createParameterAllocSite( ReachGraph rg,
+ TempDescriptor tempDesc,
+ boolean flagRegions
+ ) {
- // create temp descriptor for each parameter variable
- FlatNew flatNew = new FlatNew(tempDesc.getType(), tempDesc, false);
+ FlatNew flatNew;
+ if( flagRegions ) {
+ flatNew = new FlatNew( tempDesc.getType(), // type
+ tempDesc, // param temp
+ false, // global alloc?
+ "param"+tempDesc // disjoint site ID string
+ );
+ } else {
+ flatNew = new FlatNew( tempDesc.getType(), // type
+ tempDesc, // param temp
+ false, // global alloc?
+ null // disjoint site ID string
+ );
+ }
+
// create allocation site
- AllocSite as = (AllocSite) Canonical.makeCanonical(new AllocSite( allocationDepth, flatNew, flatNew.getDisjointId()));
+ AllocSite as = AllocSite.factory( allocationDepth,
+ flatNew,
+ flatNew.getDisjointId(),
+ false
+ );
for (int i = 0; i < allocationDepth; ++i) {
Integer id = generateUniqueHeapRegionNodeID();
as.setIthOldest(i, id);
return as;
-}
+ }
private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
}
-private HeapRegionNode createMultiDeimensionalArrayHRN(ReachGraph rg, AllocSite alloc, HeapRegionNode srcHRN, FieldDescriptor fd, Hashtable<HeapRegionNode, HeapRegionNode> map, Hashtable<TypeDescriptor, HeapRegionNode> mapToExistingNode ){
+ private HeapRegionNode createMultiDeimensionalArrayHRN(ReachGraph rg, AllocSite alloc, HeapRegionNode srcHRN, FieldDescriptor fd, Hashtable<HeapRegionNode, HeapRegionNode> map, Hashtable<TypeDescriptor, HeapRegionNode> mapToExistingNode, ReachSet alpha ){
int dimCount=fd.getType().getArrayCount();
HeapRegionNode prevNode=null;
if(i==dimCount){
as = alloc;
}else{
- as = createParameterAllocSite(rg, tempDesc);
+ as = createParameterAllocSite(rg, tempDesc, false);
}
// make a new reference to allocated node
hrnSummary =
rg.createNewHeapRegionNode(as.getSummary(), // id or null to generate a new one
false, // single object?
true, // summary?
- false, // flagged?
false, // out-of-context?
as.getType(), // type
as, // allocation site
- null, // inherent reach
- null, // current reach
- ExistPredSet.factory(), // predicates
+ alpha, // inherent reach
+ alpha, // current reach
+ ExistPredSet.factory(rg.predTrue), // predicates
tempDesc.toString() // description
);
rg.id2hrn.put(as.getSummary(),hrnSummary);
if(prevNode==null){
// make a new reference between new summary node and source
- RefEdge edgeToSummary = new RefEdge(srcHRN, // source
+ RefEdge edgeToSummary = new RefEdge(srcHRN, // source
hrnSummary, // dest
typeDesc, // type
fd.getSymbol(), // field name
- srcHRN.getAlpha(), // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ alpha, // beta
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
hrnSummary, // dest
typeDesc, // type
arrayElementFieldName, // field name
- srcHRN.getAlpha(), // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ alpha, // beta
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
typeDesc.setArrayCount(0);
if(!mapToExistingNode.containsKey(typeDesc)){
TempDescriptor tempDesc=new TempDescriptor(type.getSymbol(),typeDesc);
- AllocSite as = createParameterAllocSite(rg, tempDesc);
+ AllocSite as = createParameterAllocSite(rg, tempDesc, false);
// make a new reference to allocated node
HeapRegionNode hrnSummary =
rg.createNewHeapRegionNode(as.getSummary(), // id or null to generate a new one
false, // single object?
true, // summary?
- false, // flagged?
false, // out-of-context?
typeDesc, // type
as, // allocation site
- null, // inherent reach
- null, // current reach
- ExistPredSet.factory(), // predicates
+ alpha, // inherent reach
+ alpha, // current reach
+ ExistPredSet.factory(rg.predTrue), // predicates
tempDesc.toString() // description
);
rg.id2hrn.put(as.getSummary(),hrnSummary);
hrnSummary, // dest
typeDesc, // type
arrayElementFieldName, // field name
- null, // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ alpha, // beta
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
prevNode=hrnSummary;
}else{
- HeapRegionNode hrnSummary=mapToExistingNode.get(typeDesc);
+ HeapRegionNode hrnSummary=mapToExistingNode.get(typeDesc);
if(prevNode.getReferenceTo(hrnSummary, typeDesc, arrayElementFieldName)==null){
RefEdge edgeToSummary = new RefEdge(prevNode, // source
hrnSummary, // dest
typeDesc, // type
arrayElementFieldName, // field name
- null, // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ alpha, // beta
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
}
TempDescriptor tempDesc = fm.getParameter(idx);
- AllocSite as = createParameterAllocSite(rg, tempDesc);
+ AllocSite as = createParameterAllocSite(rg, tempDesc, true);
VariableNode lnX = rg.getVariableNodeFromTemp(tempDesc);
Integer idNewest = as.getIthOldest(0);
HeapRegionNode hrnNewest = rg.id2hrn.get(idNewest);
+
// make a new reference to allocated node
RefEdge edgeNew = new RefEdge(lnX, // source
hrnNewest, // dest
taskDesc.getParamType(idx), // type
null, // field name
hrnNewest.getAlpha(), // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(lnX, hrnNewest, edgeNew);
-
+
// set-up a work set for class field
ClassDescriptor classDesc = paramTypeDesc.getClassDesc();
for (Iterator it = classDesc.getFields(); it.hasNext();) {
//corresponding allocsite has already been created for a parameter variable.
allocSite=as;
}else{
- allocSite = createParameterAllocSite(rg, td);
+ allocSite = createParameterAllocSite(rg, td, false);
}
String strDesc = allocSite.toStringForDOT()
+ "\\nsummary";
HeapRegionNode hrnSummary;
if(allocType.isArray() && allocType.getArrayCount()>0){
- hrnSummary=createMultiDeimensionalArrayHRN(rg,allocSite,srcHRN,fd,mapToFirstDimensionArrayNode,mapTypeToExistingSummaryNode);
+ hrnSummary=createMultiDeimensionalArrayHRN(rg,allocSite,srcHRN,fd,mapToFirstDimensionArrayNode,mapTypeToExistingSummaryNode,hrnNewest.getAlpha());
}else{
hrnSummary =
rg.createNewHeapRegionNode(allocSite.getSummary(), // id or null to generate a new one
false, // single object?
true, // summary?
- false, // flagged?
false, // out-of-context?
allocSite.getType(), // type
allocSite, // allocation site
- null, // inherent reach
- srcHRN.getAlpha(), // current reach
- ExistPredSet.factory(), // predicates
+ hrnNewest.getAlpha(), // inherent reach
+ hrnNewest.getAlpha(), // current reach
+ ExistPredSet.factory(rg.predTrue), // predicates
strDesc // description
);
rg.id2hrn.put(allocSite.getSummary(),hrnSummary);
hrnSummary, // dest
type, // type
fd.getSymbol(), // field name
- srcHRN.getAlpha(), // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ hrnNewest.getAlpha(), // beta
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
fd.getType(), // type
fd.getSymbol(), // field name
srcHRN.getAlpha(), // beta
- ExistPredSet.factory(rg.predTrue) // predicates
+ ExistPredSet.factory(rg.predTrue), // predicates
+ null
);
rg.addRefEdge(srcHRN, hrnDst, edgeToSummary);
assert d instanceof TaskDescriptor;
fm = state.getMethodFlat( (TaskDescriptor) d);
}
+ pm.analyzeMethod(fm);
// visit every node in this FlatMethod's IR graph
// and make a set of the allocation sites from the
toVisit.remove(n);
visited.add(n);
- for( int i = 0; i < n.numNext(); ++i ) {
- FlatNode child = n.getNext(i);
+ for( int i = 0; i < pm.numNext(n); ++i ) {
+ FlatNode child = pm.getNext(n, i);
if( !visited.contains(child) ) {
toVisit.add(child);
}
" @@@" );
String graphName;
if( in ) {
- graphName = String.format( "snap%02d_%04din",
+ graphName = String.format( "snap%03d_%04din",
snapVisitCounter,
snapNodeCounter );
} else {
- graphName = String.format( "snap%02d_%04dout",
+ graphName = String.format( "snap%03d_%04dout",
snapVisitCounter,
snapNodeCounter );
}
graphName = graphName + fn;
}
rg.writeGraph( graphName,
- true, // write labels (variables)
- true, // selectively hide intermediate temp vars
- false, // prune unreachable heap regions
- false, // hide subset reachability states
- true );// hide edge taints
+ true, // write labels (variables)
+ true, // selectively hide intermediate temp vars
+ true, // prune unreachable heap regions
+ false, // hide reachability
+ true, // hide subset reachability states
+ true, // hide predicates
+ false );// hide edge taints
}
}