From 2c0ef63ca84728e9310f99e19bd5742082946d45 Mon Sep 17 00:00:00 2001 From: jjenista Date: Wed, 18 May 2011 23:47:59 +0000 Subject: [PATCH] bug fix: heap contexts for call sites were propgated from caller to callee incorrectly. A heap context should propagate from the caller to each possible callee at virtual dispatch... how did this ever work?? --- .../Analysis/Disjoint/DisjointAnalysis.java | 304 ++++++++++-------- Robust/src/Analysis/Disjoint/ReachGraph.java | 4 +- Robust/src/Benchmarks/oooJava/master-makefile | 20 +- .../src/IR/Flat/BCXPointsToCheckVRuntime.java | 16 + 4 files changed, 209 insertions(+), 135 deletions(-) diff --git a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java index c8bde2d8..4e851640 100644 --- a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java +++ b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java @@ -1237,7 +1237,7 @@ public class DisjointAnalysis implements HeapAnalysis { stopAfterCapture ) { System.out.println("!!! Stopping analysis after debug snap captures. !!!"); - System.exit(0); + System.exit(-1); } } @@ -1287,7 +1287,7 @@ public class DisjointAnalysis implements HeapAnalysis { rg.writeGraph("genReach"+fgrn.getGraphName(), true, // write labels (variables) false, //true, // selectively hide intermediate temp vars - false, //true, // prune unreachable heap regions + true, // prune unreachable heap regions true, // hide reachability altogether true, // hide subset reachability states true, // hide predicates @@ -1310,8 +1310,10 @@ public class DisjointAnalysis implements HeapAnalysis { FlatCall fc = (FlatCall) me.getKey(); ReachGraph rgContrib = (ReachGraph) me.getValue(); - assert fc.getMethod().equals(d); - + // note that "fc.getMethod()" like (Object.toString) + // might not be equal to "d" like (String.toString) + // because the mapping gets set up when we resolve + // virtual dispatch rg.merge(rgContrib); } @@ -1621,122 +1623,7 @@ public class DisjointAnalysis implements HeapAnalysis { FlatMethod fmCallee = state.getMethodFlat(mdCallee); - - // all this jimma jamma to debug call sites is WELL WORTH the - // effort, so so so many bugs or buggy info appears through call - // sites - boolean debugCallSite = false; - if( state.DISJOINTDEBUGCALLEE != null && - state.DISJOINTDEBUGCALLER != null ) { - - boolean debugCalleeMatches = false; - boolean debugCallerMatches = false; - - ClassDescriptor cdCallee = mdCallee.getClassDesc(); - if( cdCallee != null ) { - debugCalleeMatches = - state.DISJOINTDEBUGCALLEE.equals( cdCallee.getSymbol()+ - "."+ - mdCallee.getSymbol() - ); - } - - - if( mdCaller instanceof MethodDescriptor ) { - ClassDescriptor cdCaller = ((MethodDescriptor)mdCaller).getClassDesc(); - if( cdCaller != null ) { - debugCallerMatches = - state.DISJOINTDEBUGCALLER.equals( cdCaller.getSymbol()+ - "."+ - mdCaller.getSymbol() - ); - } - } else { - // for bristlecone style tasks - debugCallerMatches = - state.DISJOINTDEBUGCALLER.equals( mdCaller.getSymbol() ); - } - - debugCallSite = debugCalleeMatches && debugCallerMatches; - } - - - - 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 - // not used for the current call site transform, we are - // grabbing this heap model for future analysis of the callees, - // so if different results emerge we will return to this site - ReachGraph heapForThisCall_old = - getIHMcontribution(mdCallee, fc); - - // the computation of the callee-reachable heap - // is useful for making the callee starting point - // and for applying the call site transfer function - Set callerNodeIDsCopiedToCallee = - new HashSet(); - - ReachGraph heapForThisCall_cur = - rg.makeCalleeView(fc, - fmCallee, - callerNodeIDsCopiedToCallee, - writeDebugDOTs - ); - - // enforce that a call site contribution can only - // monotonically increase - heapForThisCall_cur.merge(heapForThisCall_old); - - if( !heapForThisCall_cur.equals(heapForThisCall_old) ) { - // if heap at call site changed, update the contribution, - // and reschedule the callee for analysis - addIHMcontribution(mdCallee, fc, heapForThisCall_cur); - - // 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 @@ -1760,9 +1647,11 @@ public class DisjointAnalysis implements HeapAnalysis { } - + DebugCallSiteData dcsd = new DebugCallSiteData(); + ReachGraph rgMergeOfPossibleCallers = new ReachGraph(); + Iterator mdItr = setPossibleCallees.iterator(); while( mdItr.hasNext() ) { MethodDescriptor mdPossible = mdItr.next(); @@ -1771,6 +1660,60 @@ public class DisjointAnalysis implements HeapAnalysis { addDependent(mdPossible, // callee d); // caller + + // decide for each possible resolution of the method whether we + // want to debug this call site + decideDebugCallSite( dcsd, mdCaller, mdPossible ); + + + + // calculate the heap this call site can reach--note this is + // not used for the current call site transform, we are + // grabbing this heap model for future analysis of the callees, + // so if different results emerge we will return to this site + ReachGraph heapForThisCall_old = + getIHMcontribution(mdPossible, fc); + + // the computation of the callee-reachable heap + // is useful for making the callee starting point + // and for applying the call site transfer function + Set callerNodeIDsCopiedToCallee = + new HashSet(); + + ReachGraph heapForThisCall_cur = + rg.makeCalleeView(fc, + fmPossible, + callerNodeIDsCopiedToCallee, + dcsd.writeDebugDOTs + ); + + // enforce that a call site contribution can only + // monotonically increase + heapForThisCall_cur.merge(heapForThisCall_old); + + if( !heapForThisCall_cur.equals(heapForThisCall_old) ) { + // if heap at call site changed, update the contribution, + // and reschedule the callee for analysis + addIHMcontribution(mdPossible, fc, heapForThisCall_cur); + + // 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: "+mdPossible); + } + + if( state.DISJOINTDVISITSTACKEESONTOP ) { + calleesToEnqueue.add(mdPossible); + } else { + enqueue(mdPossible); + } + } + + + + // don't alter the working graph (rg) until we compute a // result for every possible callee, merge them all together, // then set rg to that @@ -1792,17 +1735,19 @@ public class DisjointAnalysis implements HeapAnalysis { System.out.println(" callee hasn't been analyzed, scheduling: "+mdPossible); } + } else { + // calculate the method call transform rgPossibleCaller.resolveMethodCall(fc, fmPossible, rgPossibleCallee, callerNodeIDsCopiedToCallee, - writeDebugDOTs + dcsd.writeDebugDOTs ); + if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) { -// if( !rgPossibleCallee.isAccessible( ReachGraph.tdReturn ) ) { if( !accessible.isAccessible(fn, ReachGraph.tdReturn) ) { rgPossibleCaller.makeInaccessible(fc.getReturnTemp() ); } @@ -1812,12 +1757,9 @@ public class DisjointAnalysis implements HeapAnalysis { rgMergeOfPossibleCallers.merge(rgPossibleCaller); } + - - if( stopAfter ) { - System.out.println("$$$ Exiting after requested captures of call site. $$$"); - System.exit(0); - } + statusDebugCallSite( dcsd ); // now that we've taken care of building heap models for @@ -2872,6 +2814,114 @@ public class DisjointAnalysis implements HeapAnalysis { return fn2rgAtEnter.get(fn); } + + + protected class DebugCallSiteData { + public boolean debugCallSite; + public boolean didOneDebug; + public boolean writeDebugDOTs; + public boolean stopAfter; + + public DebugCallSiteData() { + debugCallSite = false; + didOneDebug = false; + writeDebugDOTs = false; + stopAfter = false; + } + } + + protected void decideDebugCallSite( DebugCallSiteData dcsd, + Descriptor taskOrMethodCaller, + MethodDescriptor mdCallee ) { + + // all this jimma jamma to debug call sites is WELL WORTH the + // effort, so so so many bugs or buggy info appears through call + // sites + + if( state.DISJOINTDEBUGCALLEE == null || + state.DISJOINTDEBUGCALLER == null ) { + return; + } + + + boolean debugCalleeMatches = false; + boolean debugCallerMatches = false; + + ClassDescriptor cdCallee = mdCallee.getClassDesc(); + if( cdCallee != null ) { + debugCalleeMatches = + state.DISJOINTDEBUGCALLEE.equals( cdCallee.getSymbol()+ + "."+ + mdCallee.getSymbol() + ); + } + + + if( taskOrMethodCaller instanceof MethodDescriptor ) { + ClassDescriptor cdCaller = ((MethodDescriptor)taskOrMethodCaller).getClassDesc(); + if( cdCaller != null ) { + debugCallerMatches = + state.DISJOINTDEBUGCALLER.equals( cdCaller.getSymbol()+ + "."+ + taskOrMethodCaller.getSymbol() + ); + } + } else { + // for bristlecone style tasks + debugCallerMatches = + state.DISJOINTDEBUGCALLER.equals( taskOrMethodCaller.getSymbol() ); + } + + dcsd.debugCallSite = debugCalleeMatches && debugCallerMatches; + dcsd.writeDebugDOTs = dcsd.debugCallSite; + + if( dcsd.debugCallSite ) { + dcsd.didOneDebug = true; + System.out.println( " --> Debugging "+taskOrMethodCaller+" calling "+mdCallee ); + } + } + + protected void statusDebugCallSite( DebugCallSiteData dcsd ) { + + dcsd.writeDebugDOTs = false; + dcsd.stopAfter = false; + + if( dcsd.didOneDebug ) { + ++ReachGraph.debugCallSiteVisitCounter; + System.out.println(" $$$ Debug call site visit "+ + ReachGraph.debugCallSiteVisitCounter+ + " $$$" + ); + if( + (ReachGraph.debugCallSiteVisitCounter >= + ReachGraph.debugCallSiteVisitStartCapture) && + + (ReachGraph.debugCallSiteVisitCounter < + ReachGraph.debugCallSiteVisitStartCapture + + ReachGraph.debugCallSiteNumVisitsToCapture) + ) { + dcsd.writeDebugDOTs = true; + System.out.println(" $$$ Capturing this call site visit $$$"); + if( ReachGraph.debugCallSiteStopAfter && + (ReachGraph.debugCallSiteVisitCounter == + ReachGraph.debugCallSiteVisitStartCapture + + ReachGraph.debugCallSiteNumVisitsToCapture - 1) + ) { + dcsd.stopAfter = true; + } + } + } + + if( dcsd.stopAfter ) { + System.out.println("$$$ Exiting after requested captures of call site. $$$"); + System.exit(-1); + } + } + + + + + // get successive captures of the analysis state, use compiler // flags to control boolean takeDebugSnapshots = false; diff --git a/Robust/src/Analysis/Disjoint/ReachGraph.java b/Robust/src/Analysis/Disjoint/ReachGraph.java index 6eedd6ba..c64b2abe 100644 --- a/Robust/src/Analysis/Disjoint/ReachGraph.java +++ b/Robust/src/Analysis/Disjoint/ReachGraph.java @@ -4466,7 +4466,9 @@ public class ReachGraph { try { // remove all non-word characters from the graph name so // the filename and identifier in dot don't cause errors - graphName = graphName.replaceAll("[\\W]", ""); + // jjenista - also replace underscore '_' to prevent some + // really, really long names from IHMS debugging + graphName = graphName.replaceAll("[\\W_]", ""); BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+".dot") ); diff --git a/Robust/src/Benchmarks/oooJava/master-makefile b/Robust/src/Benchmarks/oooJava/master-makefile index debd68cf..2f741510 100644 --- a/Robust/src/Benchmarks/oooJava/master-makefile +++ b/Robust/src/Benchmarks/oooJava/master-makefile @@ -40,7 +40,7 @@ RCRDEBUGV= -rcr_debug_verbose -printlinenum BSFLAGS= -64bit -mainclass $(PROGRAM) -heapsize-mb 5000 -garbagestats -joptimize -noloop -optimize -nolock -debug #-nooptimize #src-after-pp -CHECKPOINTSTO= -printlinenum -pointsto-check-v-runtime +CHECKPOINTSTO= -printlinenum -pointsto-check-v-runtime -debug DRELEASEMODE=-disjoint-release-mode -disjoint-dvisit-stack-callees-on-top -disjoint-alias-file aliases.txt tabbed @@ -76,16 +76,18 @@ DISJOINT= -disjoint -disjoint-k 1 -enable-assertions $(DRELEASEMODE) #-disjoint- # EX: (skip first 10 visits, capture the next 3, then halt) # -disjoint-debug-snap-method Remove 10 3 true -DISJOINTDEBUG= -disjoint -disjoint-k 1 -enable-assertions \ - -disjoint-write-dots final \ - -flatirusermethods -# -disjoint-debug-callsite String.valueOf Power.main 1 1000 true \ +DISJOINTDEBUG= -disjoint -disjoint-k 1 -enable-assertions +# -disjoint-debug-callsite String.toString String.valueOf 1 1000 true \ +# -disjoint-debug-snap-method String.toString 1 1000 true \ +# -disjoint-write-initial-contexts \ +# -disjoint-write-dots final +# -disjoint-debug-scheduling \ +# -disjoint-write-ihms +# -flatirusermethods # -justanalyze # -disjoint-desire-determinism # -disjoint-debug-callsite Demand.add Lateral.compute 1 1000 true # -disjoint-debug-snap-method ComputeCenterOfMass 6 2 true -# -disjoint-debug-scheduling - @@ -99,6 +101,10 @@ single-remake-c: rcr-remake-c: $(BUILDSCRIPT) -nojava $(BMFLAGS) $(BSFLAGS) $(USECOREPROF) $(USERCR) $(DISJOINT) -o $(PROGRAM)r -builddir rcr $(SOURCE_FILES) +check-remake-c: + $(BUILDSCRIPT) -nojava $(BMFLAGS) $(BSFLAGS) $(USECOREPROF) $(DISJOINTDEBUG) $(CHECKPOINTSTO) -o $(PROGRAM)c -builddir chk $(SOURCE_FILES) + + single: $(PROGRAM)s.bin diff --git a/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java b/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java index 2ab300ac..6f8a9879 100644 --- a/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java +++ b/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java @@ -34,6 +34,7 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { public void additionalIncludesMethodsHeader(PrintWriter outmethodheader) { outmethodheader.println( "#include" ); + outmethodheader.println( "#include" ); } @@ -216,6 +217,21 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { condition+" ) allocsite=%d at %s:%d\\n\", ((struct "+ cdObject.getSafeSymbol()+"*)"+ pointer+")->allocsite, __FILE__, __LINE__ );" ); + + // spit out the stack trace (so fancy!) + output.println( "{" ); + output.println( "void* buffer[100];" ); + output.println( "char** strings;" ); + output.println( "int nptrs,j;" ); + output.println( "nptrs = backtrace(buffer, 100);" ); + output.println( "strings = backtrace_symbols(buffer, nptrs);" ); + output.println( "if (strings == NULL) {" ); + output.println( " perror(\"backtrace_symbols\");" ); + output.println( "}" ); + output.println( "for (j = 0; j < nptrs; j++) {" ); + output.println( " printf(\"%s\\n\", strings[j]);" ); + output.println( "}" ); + output.println( "}" ); } -- 2.34.1