--- /dev/null
+package Analysis.Disjoint;
+
+import IR.*;
+import IR.Flat.*;
+import java.util.*;
+import java.io.*;
+
+public class DescriptorComparator implements Comparator {
+
+ public int compare( Object o1, Object o2 ) {
+
+ assert o1 instanceof Descriptor;
+ assert o2 instanceof Descriptor;
+
+ Descriptor d1 = (Descriptor) o1;
+ Descriptor d2 = (Descriptor) o2;
+
+ return d1.getNum() - d2.getNum();
+ }
+
+}
// 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>( new DescriptorComparator() );
+
+ } else {
+ // otherwise use a speedy hashset
+ descriptorsToAnalyze = new HashSet<Descriptor>();
+ }
mapDescriptorToCompleteReachGraph =
new Hashtable<Descriptor, ReachGraph>();
mapDescriptorToReachGraph =
new Hashtable<Descriptor, ReachGraph>();
+
+ pm = new PointerMethod();
}
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
- this.pm=new PointerMethod();
assert
state.DISJOINTDVISITSTACK ||
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();
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( 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;
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>( new DescriptorComparator() );
+
+ } else {
+ // otherwise use a speedy hashset
+ discovered = new HashSet<Descriptor>();
+ }
+
+ LinkedList<Descriptor> sorted = new LinkedList<Descriptor>();
Iterator<Descriptor> itr = toSort.iterator();
while( itr.hasNext() ) {
if( writeDebugDOTs ) {
- debugGraphPrefix = String.format( "call%02d", debugCallSiteVisits );
+ debugGraphPrefix = String.format( "call%02d", debugCallSiteVisitCounter );
rg.writeGraph( debugGraphPrefix+"calleeview",
resolveMethodDebugDOTwriteLabels,
resolveMethodDebugDOTselectTemps,
private static boolean resolveMethodDebugDOThideEdgeTaints = true;
static String debugGraphPrefix;
- static int debugCallSiteVisits = 0;
- static int debugCallSiteVisitsUntilExit = 0;
+ static int debugCallSiteVisitCounter;
+ static int debugCallSiteVisitStartCapture;
+ static int debugCallSiteNumVisitsToCapture;
+ static boolean debugCallSiteStopAfter;
public void
if( writeDebugDOTs ) {
System.out.println( " Writing out visit "+
- debugCallSiteVisits+
+ debugCallSiteVisitCounter+
" to debug call site" );
debugGraphPrefix = String.format( "call%02d",
- debugCallSiteVisits );
+ debugCallSiteVisitCounter );
rgCallee.writeGraph( debugGraphPrefix+"callee",
resolveMethodDebugDOTwriteLabels,
}
-
-
-
if( writeDebugDOTs ) {
writeGraph( debugGraphPrefix+"caller90AfterTransfer",
resolveMethodDebugDOTwriteLabels,
resolveMethodDebugDOTselectTemps,
resolveMethodDebugDOTpruneGarbage,
resolveMethodDebugDOThideSubsetReach,
- resolveMethodDebugDOThideEdgeTaints );
-
- ++debugCallSiteVisits;
- if( debugCallSiteVisits >= debugCallSiteVisitsUntilExit ) {
- System.out.println( "!!! Exiting after requested visits to call site. !!!" );
- System.exit( 0 );
- }
+ resolveMethodDebugDOThideEdgeTaints );
}
}
#################################################
##
-## To debug a call site, supply the symbols for
-## the callee, then caller, then max number of
-## analysis visits to the call site to write out
+## To debug a call site supply:
+## 1. callee symbol
+## 2. caller symbol
+## 3. number of analysis call site visits to skip,
+## before starting to capture (early visits
+## are usually uninteresting)
+## 4. number of call site visits to capture
+## 5. whether to halt analysis immediately
+## after capture (or let it run on normally)
##
#################################################
-#DEBUGFLAGS= -disjoint-debug-callsite setClusters innerKMeansSetting 20
-#DEBUGFLAGS= -disjoint-debug-callsite ensureCapacity addElement 100
-#DEBUGFLAGS= -disjoint-debug-callsite setPartial reduceOutput 100
+#DEBUGFLAGS= -disjoint-debug-callsite addInterOutput t6 50 5 false
+
#################################################
##
## To get snapshots (graphs) for the exit of every
-## node in a method, supply method symbol then the
-## number of analysis visits to the method to skip
-## (early visits usually uninteresting), then the
-## number of visits to take snapshots for, finally
-## a boolean value indicating if the analysis should
-## immediately terminate after the last snapshot visit
+## node in a method, supply:
+## 1. method symbol
+## 2. number of methods visits to skip,
+## before starting to capture (early visits
+## are usually uninteresting)
+## 3. number of analysis method visits to capture
+## 4. whether to halt analysis immediately
+## after capture (or let it run on normally)
##
#################################################
#SNAPFLAGS= -disjoint-debug-snap-method calcGoodFeatureTask 5 10 true
#SNAPFLAGS= -disjoint-debug-snap-method calcGoodFeature 5 1 true
-SNAPFLAGS= -disjoint-debug-snap-method t6 20 5 true
+SNAPFLAGS= -disjoint-debug-snap-method t6 30 1 false
#SNAPFLAGS= -disjoint-debug-snap-method reduceOutput 5 50 true
#SNAPFLAGS= -disjoint-debug-snap-method setReduceFinish 5 50 true
#SNAPFLAGS= -disjoint-debug-snap-method setPartial 1 50 true
JAVAFLAGS= -mainclass test
#VISITMODE= -disjoint-dvisit-stack
-VISITMODE= -disjoint-dvisit-pqueue
-#VISITMODE= -disjoint-dvisit-stack-callees-on-top
+#VISITMODE= -disjoint-dvisit-pqueue
+VISITMODE= -disjoint-dvisit-stack-callees-on-top
DEBUGMODE= -enable-assertions -disjoint-write-dots final -disjoint-alias-file aliases.txt normal -disjoint-desire-determinism
RELEASEMODE= -disjoint-release-mode -disjoint-alias-file aliases.txt tabbed
public boolean DISJOINTWRITEIHMS=false;
public String DISJOINTALIASFILE=null;
public boolean DISJOINTALIASTAB=false;
- public int DISJOINTDEBUGCALLCOUNT=0;
+
public String DISJOINTDEBUGCALLEE=null;
public String DISJOINTDEBUGCALLER=null;
+ public int DISJOINTDEBUGCALLVISITTOSTART=0;
+ public int DISJOINTDEBUGCALLNUMVISITS=0;
+ public boolean DISJOINTDEBUGCALLSTOPAFTER=false;
+
public String DISJOINTSNAPSYMBOL=null;
public int DISJOINTSNAPVISITTOSTART=0;
public int DISJOINTSNAPNUMVISITS=0;
public boolean DISJOINTSNAPSTOPAFTER=false;
+
public boolean DISJOINTDVISITSTACK=true;
public boolean DISJOINTDVISITPQUE=false;
public boolean DISJOINTDVISITSTACKEESONTOP=false;
} else if( arg.equals("tabbed") ) {
state.DISJOINTALIASTAB = true;
} else {
- throw new Error("disjoint-alias-file requires arguments <filename> <normal/tabbed>");
+ throw new Error("disjoint-alias-file requires arguments: <filename> <normal/tabbed>");
}
} else if (option.equals("-disjoint-debug-callsite")) {
state.DISJOINTDEBUGCALLEE=args[++i];
state.DISJOINTDEBUGCALLER=args[++i];
- state.DISJOINTDEBUGCALLCOUNT=Integer.parseInt(args[++i]);
+ state.DISJOINTDEBUGCALLVISITTOSTART=Integer.parseInt(args[++i]);
+ state.DISJOINTDEBUGCALLNUMVISITS=Integer.parseInt(args[++i]);
+ String arg = args[++i];
+ if( arg.equals("true") ) {
+ state.DISJOINTDEBUGCALLSTOPAFTER = true;
+ } else if( arg.equals("false") ) {
+ state.DISJOINTDEBUGCALLSTOPAFTER = false;
+ } else {
+ throw new Error("disjoint-debug-callsite requires arguments:\n"+
+ " <callee symbol> <caller symbol> <# visit to start> <# visits to capture> <T/F stop after>");
+ }
} else if (option.equals("-disjoint-debug-snap-method")) {
state.DISJOINTSNAPSYMBOL=args[++i];
} else if( arg.equals("false") ) {
state.DISJOINTSNAPSTOPAFTER = false;
} else {
- throw new Error("disjoint-debug-snap-method requires arguments <method symbol> <# visit to start> <# visits to snap> <T/F stop after>");
+ throw new Error("disjoint-debug-snap-method requires arguments:\n"+
+ " <method symbol> <# visit to start> <# visits to snap> <T/F stop after>");
}
} else if( option.equals( "-disjoint-release-mode" ) ) {
state.DISJOINTRELEASEMODE = true;
- } else if( option.equals( "-disjoint-desire-determinism" ) ) {
- state.DISJOINTDETERMINISM = true;
-
} else if( option.equals( "-disjoint-dvisit-stack" ) ) {
state.DISJOINTDVISITSTACK = true;
state.DISJOINTDVISITPQUE = false;
state.DISJOINTDVISITSTACKEESONTOP = true;
state.DISJOINTDVISITPQUE = false;
state.DISJOINTDVISITSTACK = false;
+
+ } else if( option.equals( "-disjoint-desire-determinism" ) ) {
+ state.DISJOINTDETERMINISM = true;
+
+ // when asking analysis for a deterministic result, force
+ // a stack-based visiting scheme, because the priority queue
+ // requires a non-deterministic topological sort
+ state.DISJOINTDVISITSTACKEESONTOP = true;
+ state.DISJOINTDVISITPQUE = false;
+ state.DISJOINTDVISITSTACK = false;
}