From: jjenista Date: Wed, 1 Jun 2011 19:12:01 +0000 (+0000) Subject: check points-to module improvements along with a bug fix for disjoint call transfer... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0aca2e6f413de8a76c4726a00c0004db3717366e;p=IRC.git check points-to module improvements along with a bug fix for disjoint call transfer func. The bug was when considering callee edges to bring to the caller, use the predicates of the edge only to decide --- diff --git a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java index 4e851640..0617600c 100644 --- a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java +++ b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java @@ -521,6 +521,17 @@ public class DisjointAnalysis implements HeapAnalysis { protected Hashtable mapDescriptorToInitialContext; + // mapping of current partial results for a given node. Note that + // to reanalyze a method we discard all partial results because a + // null reach graph indicates the node needs to be visited on the + // way to the fixed point. + // The reason for a persistent mapping is so after the analysis we + // can ask for the graph of any node at the fixed point, but this + // option is only enabled with a compiler flag. + protected Hashtable mapFlatNodeToReachGraphPersist; + protected Hashtable mapFlatNodeToReachGraph; + + // 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 @@ -673,6 +684,9 @@ public class DisjointAnalysis implements HeapAnalysis { mapDescriptorToInitialContext = new Hashtable(); + mapFlatNodeToReachGraphPersist = + new Hashtable(); + mapBackEdgeToMonotone = new Hashtable(); @@ -877,14 +891,18 @@ public class DisjointAnalysis implements HeapAnalysis { writeFinalGraphs(); } - if( state.DISJOINTWRITEIHMS && !suppressOutput ) { + if( state.DISJOINTWRITEIHMS ) { writeFinalIHMs(); } - if( state.DISJOINTWRITEINITCONTEXTS && !suppressOutput ) { + if( state.DISJOINTWRITEINITCONTEXTS ) { writeInitialContexts(); } + if( state.DISJOINT_WRITE_ALL_NODE_FINAL_GRAPHS ) { + writeFinalGraphsForEveryNode(); + } + if( state.DISJOINTALIASFILE != null && !suppressOutput ) { if( state.TASK ) { writeAllSharing(state.DISJOINTALIASFILE, treport, justtime, state.DISJOINTALIASTAB, state.lines); @@ -1111,8 +1129,8 @@ public class DisjointAnalysis implements HeapAnalysis { flatNodesToVisitQ.add(fm); } - // mapping of current partial results - Hashtable mapFlatNodeToReachGraph = + // start a new mapping of partial results + mapFlatNodeToReachGraph = new Hashtable(); // the set of return nodes partial results that will be combined as @@ -1197,6 +1215,12 @@ public class DisjointAnalysis implements HeapAnalysis { if( !rg.equals(rgPrev) ) { mapFlatNodeToReachGraph.put(fn, rg); + // we don't necessarily want to keep the reach graph for every + // node in the program unless a client or the user wants it + if( state.DISJOINT_WRITE_ALL_NODE_FINAL_GRAPHS ) { + mapFlatNodeToReachGraphPersist.put(fn, rg); + } + for( int i = 0; i < pm.numNext(fn); i++ ) { FlatNode nn = pm.getNext(fn, i); @@ -1214,6 +1238,10 @@ public class DisjointAnalysis implements HeapAnalysis { // states after the flat method returns ReachGraph completeGraph = new ReachGraph(); + if( setReturns.isEmpty() ) { + System.out.println( "d = "+d ); + + } assert !setReturns.isEmpty(); Iterator retItr = setReturns.iterator(); while( retItr.hasNext() ) { @@ -1337,7 +1365,6 @@ public class DisjointAnalysis implements HeapAnalysis { if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) { if(rblockRel.isPotentialStallSite(fn)) { // x gets status of y -// if(!rg.isAccessible(rhs)){ if(!accessible.isAccessible(fn, rhs)) { rg.makeInaccessible(lhs); } @@ -1361,7 +1388,6 @@ public class DisjointAnalysis implements HeapAnalysis { if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) { if(rblockRel.isPotentialStallSite(fn)) { // x gets status of y -// if(!rg.isAccessible(rhs)){ if(!accessible.isAccessible(fn,rhs)) { rg.makeInaccessible(lhs); } @@ -1386,7 +1412,6 @@ public class DisjointAnalysis implements HeapAnalysis { if(rblockRel.isPotentialStallSite(fn)) { // x=y.f, stall y if not accessible // contributes read effects on stall site of y -// if(!rg.isAccessible(rhs)) { if(!accessible.isAccessible(fn,rhs)) { rg.taintStallSite(fn, rhs); } @@ -1425,12 +1450,10 @@ public class DisjointAnalysis implements HeapAnalysis { if(rblockRel.isPotentialStallSite(fn)) { // x.y=f , stall x and y if they are not accessible // also contribute write effects on stall site of x -// if(!rg.isAccessible(lhs)) { if(!accessible.isAccessible(fn,lhs)) { rg.taintStallSite(fn, lhs); } -// if(!rg.isAccessible(rhs)) { if(!accessible.isAccessible(fn,rhs)) { rg.taintStallSite(fn, rhs); } @@ -1471,7 +1494,6 @@ public class DisjointAnalysis implements HeapAnalysis { // x=y.f, stall y if not accessible // contributes read effects on stall site of y // after this, x and y are accessbile. -// if(!rg.isAccessible(rhs)) { if(!accessible.isAccessible(fn,rhs)) { rg.taintStallSite(fn, rhs); } @@ -1511,12 +1533,10 @@ public class DisjointAnalysis implements HeapAnalysis { if(rblockRel.isPotentialStallSite(fn)) { // x.y=f , stall x and y if they are not accessible // also contribute write effects on stall site of x -// if(!rg.isAccessible(lhs)) { if(!accessible.isAccessible(fn,lhs)) { rg.taintStallSite(fn, lhs); } -// if(!rg.isAccessible(rhs)) { if(!accessible.isAccessible(fn,rhs)) { rg.taintStallSite(fn, rhs); } @@ -1623,6 +1643,12 @@ public class DisjointAnalysis implements HeapAnalysis { FlatMethod fmCallee = state.getMethodFlat(mdCallee); + + + + + + // the transformation for a call site should update the // current heap abstraction with any effects from the callee, @@ -1790,7 +1816,6 @@ public class DisjointAnalysis implements HeapAnalysis { // before transfer, do effects analysis support if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) { -// if(!rg.isAccessible(rhs)){ if(!accessible.isAccessible(fn,rhs)) { rg.makeInaccessible(ReachGraph.tdReturn); } @@ -1930,6 +1955,25 @@ public class DisjointAnalysis implements HeapAnalysis { } } + private void writeFinalGraphsForEveryNode() { + Set entrySet = mapFlatNodeToReachGraphPersist.entrySet(); + Iterator itr = entrySet.iterator(); + while( itr.hasNext() ) { + Map.Entry me = (Map.Entry) itr.next(); + FlatNode fn = (FlatNode) me.getKey(); + ReachGraph rg = (ReachGraph) me.getValue(); + + rg.writeGraph("NODEFINAL"+fn, + true, // write labels (variables) + false, // selectively hide intermediate temp vars + true, // prune unreachable heap regions + true, // hide all reachability + true, // hide subset reachability states + true, // hide predicates + true); // hide edge taints + } + } + protected ReachGraph getPartial(Descriptor d) { return mapDescriptorToCompleteReachGraph.get(d); @@ -2983,18 +3027,6 @@ public class DisjointAnalysis implements HeapAnalysis { return rgAtEnter.canPointTo( x ); } - - - public Set canPointToAfter( TempDescriptor x, - FlatNode programPoint ) { - - ReachGraph rgAtExit = fn2rgAtExit.get( programPoint ); - if( rgAtExit == null ) { - return null; - } - - return rgAtExit.canPointTo( x ); - } public Hashtable< Alloc, Set > canPointToAt( TempDescriptor x, @@ -3023,4 +3055,45 @@ public class DisjointAnalysis implements HeapAnalysis { return rgAtEnter.canPointTo( x, arrayElementFieldName, x.getType().dereference() ); } + + + public Set canPointToAfter( TempDescriptor x, + FlatNode programPoint ) { + + ReachGraph rgAtExit = fn2rgAtExit.get( programPoint ); + + if( rgAtExit == null ) { + return null; + } + + return rgAtExit.canPointTo( x ); + } + + + public Hashtable< Alloc, Set > canPointToAfter( TempDescriptor x, + FieldDescriptor f, + FlatNode programPoint ) { + + ReachGraph rgAtExit = fn2rgAtExit.get( programPoint ); + if( rgAtExit == null ) { + return null; + } + + return rgAtExit.canPointTo( x, f.getSymbol(), f.getType() ); + } + + + public Hashtable< Alloc, Set > canPointToAfterElement( TempDescriptor x, + FlatNode programPoint ) { + + ReachGraph rgAtExit = fn2rgAtExit.get( programPoint ); + if( rgAtExit == null ) { + return null; + } + + assert x.getType() != null; + assert x.getType().isArray(); + + return rgAtExit.canPointTo( x, arrayElementFieldName, x.getType().dereference() ); + } } diff --git a/Robust/src/Analysis/Disjoint/ExistPred.java b/Robust/src/Analysis/Disjoint/ExistPred.java index fc34a97c..d1aef27b 100644 --- a/Robust/src/Analysis/Disjoint/ExistPred.java +++ b/Robust/src/Analysis/Disjoint/ExistPred.java @@ -232,14 +232,14 @@ public class ExistPred extends Canonical { // predicate is satisfied, return the predicate set of the // element that satisfied it, or null for false public ExistPredSet isSatisfiedBy(ReachGraph rg, - Set calleeReachableNodes + Set calleeReachableNodes, + Set callerSrcMatches ) { if( predType == TYPE_TRUE ) { return ExistPredSet.factory(ExistPred.factory() ); } if( predType == TYPE_NODE ) { - // first find node HeapRegionNode hrn = rg.id2hrn.get(n_hrnID); if( hrn == null ) { @@ -348,8 +348,14 @@ public class ExistPred extends Canonical { // when the state and taint are null we're done! if( ne_state == null && e_taint == null ) { + + if( callerSrcMatches != null ) { + callerSrcMatches.add( rsn ); + } + return edge.getPreds(); + } else if( ne_state != null ) { // otherwise look for state too @@ -374,6 +380,10 @@ public class ExistPred extends Canonical { } else { // it was here, return the predicates on the taint!! + if( callerSrcMatches != null ) { + callerSrcMatches.add( rsn ); + } + return tCaller.getPreds(); } } @@ -386,6 +396,26 @@ public class ExistPred extends Canonical { + // if this pred is an edge type pred, then given + // a reach graph, find the element of the graph that + // may exist and represents the source of the edge + public RefSrcNode getEdgeSource( ReachGraph rg ) { + if( predType != TYPE_EDGE ) { + return null; + } + + if( e_tdSrc != null ) { + // variable node is the source, look for it in the graph + return rg.getVariableNodeNoMutation( e_tdSrc ); + } + + // otherwise a heap region node is the source, look for it + assert e_hrnDstID != null; + return rg.id2hrn.get( e_hrnDstID ); + } + + + public boolean equalsSpecific(Object o) { if( o == null ) { return false; diff --git a/Robust/src/Analysis/Disjoint/ExistPredSet.java b/Robust/src/Analysis/Disjoint/ExistPredSet.java index d2fa2865..76cb5182 100644 --- a/Robust/src/Analysis/Disjoint/ExistPredSet.java +++ b/Robust/src/Analysis/Disjoint/ExistPredSet.java @@ -60,7 +60,8 @@ public class ExistPredSet extends Canonical { // only consider the subest of the caller elements that // are reachable by callee when testing predicates public ExistPredSet isSatisfiedBy(ReachGraph rg, - Set calleeReachableNodes + Set calleeReachableNodes, + Set callerSrcMatches ) { ExistPredSet predsOut = null; @@ -68,7 +69,8 @@ public class ExistPredSet extends Canonical { while( predItr.hasNext() ) { ExistPredSet predsFromSatisfier = predItr.next().isSatisfiedBy(rg, - calleeReachableNodes); + calleeReachableNodes, + callerSrcMatches); if( predsFromSatisfier != null ) { if( predsOut == null ) { @@ -84,6 +86,23 @@ public class ExistPredSet extends Canonical { } + // this method returns the source node of any + // edge predicates in the set for the given graph + public Set getEdgeSources( ReachGraph rg ) { + Set out = new HashSet(); + + for( ExistPred pred: preds ) { + RefSrcNode rsn = pred.getEdgeSource( rg ); + if( rsn != null ) { + out.add( rsn ); + } + } + + return out; + } + + + public boolean isEmpty() { return preds.isEmpty(); } diff --git a/Robust/src/Analysis/Disjoint/HeapAnalysis.java b/Robust/src/Analysis/Disjoint/HeapAnalysis.java index 53c816d1..cb4c99d7 100644 --- a/Robust/src/Analysis/Disjoint/HeapAnalysis.java +++ b/Robust/src/Analysis/Disjoint/HeapAnalysis.java @@ -49,14 +49,21 @@ public interface HeapAnalysis { public Set canPointToAt( TempDescriptor x, FlatNode programPoint ); - public Set canPointToAfter( TempDescriptor x, - FlatNode programPoint ); - public Hashtable< Alloc, Set > canPointToAt( TempDescriptor x, FieldDescriptor f, FlatNode programPoint ); public Hashtable< Alloc, Set > canPointToAtElement( TempDescriptor x, // x[i] FlatNode programPoint ); + + public Set canPointToAfter( TempDescriptor x, + FlatNode programPoint ); + + public Hashtable< Alloc, Set > canPointToAfter( TempDescriptor x, + FieldDescriptor f, + FlatNode programPoint ); + + public Hashtable< Alloc, Set > canPointToAfterElement( TempDescriptor x, // x[i] + FlatNode programPoint ); } diff --git a/Robust/src/Analysis/Disjoint/ReachGraph.java b/Robust/src/Analysis/Disjoint/ReachGraph.java index c64b2abe..86550e67 100644 --- a/Robust/src/Analysis/Disjoint/ReachGraph.java +++ b/Robust/src/Analysis/Disjoint/ReachGraph.java @@ -2247,8 +2247,8 @@ public class ReachGraph { private static boolean resolveMethodDebugDOTpruneGarbage = true; private static boolean resolveMethodDebugDOThideReach = true; private static boolean resolveMethodDebugDOThideSubsetReach = true; - private static boolean resolveMethodDebugDOThidePreds = true; - private static boolean resolveMethodDebugDOThideEdgeTaints = false; + private static boolean resolveMethodDebugDOThidePreds = false; + private static boolean resolveMethodDebugDOThideEdgeTaints = true; static String debugGraphPrefix; static int debugCallSiteVisitCounter; @@ -2332,6 +2332,7 @@ public class ReachGraph { new Hashtable< RefEdge, Set >(); + Iterator meItr = rgCallee.id2hrn.entrySet().iterator(); while( meItr.hasNext() ) { Map.Entry me = (Map.Entry)meItr.next(); @@ -2344,8 +2345,8 @@ public class ReachGraph { // should have, and it is inefficient to find this again later ExistPredSet predsIfSatis = hrnCallee.getPreds().isSatisfiedBy(this, - callerNodeIDsCopiedToCallee - ); + callerNodeIDsCopiedToCallee, + null); if( predsIfSatis != null ) { calleeNodesSatisfied.put(hrnCallee, predsIfSatis); @@ -2364,8 +2365,8 @@ public class ReachGraph { predsIfSatis = stateCallee.getPreds().isSatisfiedBy(this, - callerNodeIDsCopiedToCallee - ); + callerNodeIDsCopiedToCallee, + null); if( predsIfSatis != null ) { Hashtable calleeStatesSatisfied = @@ -2434,8 +2435,8 @@ public class ReachGraph { predsIfSatis = hrnSrcCallee.getPreds().isSatisfiedBy(this, - callerNodeIDsCopiedToCallee - ); + callerNodeIDsCopiedToCallee, + null); if( predsIfSatis != null ) { calleeNodesSatisfied.put(hrnSrcCallee, predsIfSatis); } else { @@ -2445,55 +2446,18 @@ public class ReachGraph { } else { // hrnSrcCallee is out-of-context - assert !calleeEdges2oocCallerSrcMatches.containsKey(reCallee); Set rsnCallers = new HashSet(); - // is the target node in the caller? - HeapRegionNode hrnDstCaller = this.id2hrn.get(hrnCallee.getID() ); - if( hrnDstCaller == null ) { - continue; - } - - Iterator reDstItr = hrnDstCaller.iteratorToReferencers(); - while( reDstItr.hasNext() ) { - // the edge and field (either possibly null) must match - RefEdge reCaller = reDstItr.next(); - - if( !reCaller.typeEquals(reCallee.getType() ) || - !reCaller.fieldEquals(reCallee.getField() ) - ) { - continue; - } - - RefSrcNode rsnCaller = reCaller.getSrc(); - if( rsnCaller instanceof VariableNode ) { - - // a variable node matches an OOC region with null type - if( hrnSrcCallee.getType() != null ) { - continue; - } - - } else { - // otherwise types should match - HeapRegionNode hrnCallerSrc = (HeapRegionNode) rsnCaller; - if( hrnSrcCallee.getType() == null ) { - if( hrnCallerSrc.getType() != null ) { - continue; - } - } else { - if( !hrnSrcCallee.getType().equals(hrnCallerSrc.getType() ) ) { - continue; - } - } - } - - rsnCallers.add(rsnCaller); - matchedOutOfContext = true; - } + // use the isSatisfiedBy with a non-null callers set to capture + // nodes in the caller that match the predicates + reCallee.getPreds().isSatisfiedBy( this, + callerNodeIDsCopiedToCallee, + rsnCallers ); if( !rsnCallers.isEmpty() ) { + matchedOutOfContext = true; calleeEdges2oocCallerSrcMatches.put(reCallee, rsnCallers); } } @@ -2507,8 +2471,9 @@ public class ReachGraph { predsIfSatis = reCallee.getPreds().isSatisfiedBy(this, - callerNodeIDsCopiedToCallee - ); + callerNodeIDsCopiedToCallee, + null); + if( predsIfSatis != null ) { calleeEdgesSatisfied.put(reCallee, predsIfSatis); @@ -2523,8 +2488,8 @@ public class ReachGraph { predsIfSatis = stateCallee.getPreds().isSatisfiedBy(this, - callerNodeIDsCopiedToCallee - ); + callerNodeIDsCopiedToCallee, + null); if( predsIfSatis != null ) { Hashtable calleeStatesSatisfied = @@ -2551,8 +2516,8 @@ public class ReachGraph { predsIfSatis = tCallee.getPreds().isSatisfiedBy(this, - callerNodeIDsCopiedToCallee - ); + callerNodeIDsCopiedToCallee, + null); if( predsIfSatis != null ) { Hashtable calleeTaintsSatisfied = @@ -4218,7 +4183,6 @@ public class ReachGraph { //System.out.println( "*** Asking if A is no smaller than B ***" ); - Iterator iA = rgA.id2hrn.entrySet().iterator(); while( iA.hasNext() ) { Map.Entry meA = (Map.Entry)iA.next(); @@ -4229,14 +4193,6 @@ public class ReachGraph { System.out.println(" regions smaller"); return false; } - - //HeapRegionNode hrnB = rgB.id2hrn.get( idA ); - /* NOT EQUALS, NO SMALLER THAN! - if( !hrnA.equalsIncludingAlphaAndPreds( hrnB ) ) { - System.out.println( " regions smaller" ); - return false; - } - */ } // this works just fine, no smaller than @@ -4282,14 +4238,6 @@ public class ReachGraph { System.out.println(" edges smaller:"); return false; } - - // REMEMBER, IS NO SMALLER THAN - /* - System.out.println( " edges smaller" ); - return false; - } - */ - } } diff --git a/Robust/src/Analysis/Pointer/Pointer.java b/Robust/src/Analysis/Pointer/Pointer.java index 2bf65e11..5a648767 100644 --- a/Robust/src/Analysis/Pointer/Pointer.java +++ b/Robust/src/Analysis/Pointer/Pointer.java @@ -2125,11 +2125,6 @@ nextdelta: return null; } - public Set canPointToAfter( TempDescriptor x, - FlatNode programPoint ) { - return null; - } - public Hashtable< Alloc, Set > canPointToAt( TempDescriptor x, FieldDescriptor f, FlatNode programPoint ) { @@ -2140,4 +2135,20 @@ nextdelta: FlatNode programPoint ) { return null; } + + public Set canPointToAfter( TempDescriptor x, + FlatNode programPoint ) { + return null; + } + + public Hashtable< Alloc, Set > canPointToAfter( TempDescriptor x, + FieldDescriptor f, + FlatNode programPoint ) { + return null; + } + + public Hashtable< Alloc, Set > canPointToAfterElement( TempDescriptor x, // x[i] + FlatNode programPoint ) { + return null; + } } diff --git a/Robust/src/Benchmarks/oooJava/master-makefile b/Robust/src/Benchmarks/oooJava/master-makefile index 2f741510..797e0556 100644 --- a/Robust/src/Benchmarks/oooJava/master-makefile +++ b/Robust/src/Benchmarks/oooJava/master-makefile @@ -77,14 +77,21 @@ DISJOINT= -disjoint -disjoint-k 1 -enable-assertions $(DRELEASEMODE) #-disjoint- # -disjoint-debug-snap-method Remove 10 3 true DISJOINTDEBUG= -disjoint -disjoint-k 1 -enable-assertions +# -disjoint-write-dots final \ +# -flatirusermethods \ +# -disjoint-debug-callsite System.println Barneshut.run 1 1000 true \ +# -disjoint-debug-snap-method Barneshut.run 1 1000 false +# -disjoint-debug-snap-method String.indexOf 1 1000 true +# -disjoint-debug-callsite String.concat2 FileInputStream.readLine 1 1000 true \ +# -disjoint-debug-snap-method String.concat2 1 1000 true +# -disjoint-debug-snap-method FileInputStream.readLine 1 1000 true +# -disjoint-write-all-node-graphs +# +# -justanalyze \ # -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 diff --git a/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java b/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java index 6f8a9879..d5439f03 100644 --- a/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java +++ b/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java @@ -16,19 +16,31 @@ import java.util.*; public class BCXPointsToCheckVRuntime implements BuildCodeExtension { + protected State state; protected BuildCode buildCode; protected TypeUtil typeUtil; protected HeapAnalysis heapAnalysis; protected ClassDescriptor cdObject; + protected TypeDescriptor stringType; - public BCXPointsToCheckVRuntime( BuildCode buildCode, + private boolean DEBUG = false; + + + + public BCXPointsToCheckVRuntime( State state, + BuildCode buildCode, TypeUtil typeUtil, HeapAnalysis heapAnalysis ) { + this.state = state; this.buildCode = buildCode; this.typeUtil = typeUtil; this.heapAnalysis = heapAnalysis; + + ClassDescriptor cdString = typeUtil.getClass( typeUtil.StringClass ); + assert cdString != null; + stringType = new TypeDescriptor( cdString ); } @@ -44,11 +56,20 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { TempDescriptor td = fm.getParameter( i ); TypeDescriptor type = td.getType(); if( type.isPtr() ) { + output.println( "// Generating points-to checks for method params" ); + genAssertRuntimePtrVsHeapResults( output, fm, td, heapAnalysis.canPointToAfter( td, fm ) ); + + output.println( "// end method params" ); + + if( DEBUG ) { + System.out.println( "\nGenerating code for "+fm ); + System.out.println( " arg "+td+" can point to "+heapAnalysis.canPointToAfter( td, fm ) ); + } } } } @@ -61,10 +82,42 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { FieldDescriptor fld; TempDescriptor idx; TypeDescriptor type; + TempDescriptor arg; + TempDescriptor ret; + + // for PRE-NODE checks, only look at pointers we are reading from because + // pointers about to be set may be undefined and don't pass runtime checks nicely + switch( fn.kind() ) { + /* + case FKind.FlatLiteralNode: { + FlatLiteralNode fln = (FlatLiteralNode) fn; + + if( fln.getType().equals( stringType ) ) { + lhs = fln.getDst(); + + output.println( "// Generating points-to checks for pre-node string literal" ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAt( lhs, fn ) + ); + + output.println( "// end pre-node string literal" ); + + + if( DEBUG ) { + System.out.println( " before "+fn ); + System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAt( lhs, fn ) ); + } + } + } break; + */ + case FKind.FlatOpNode: { FlatOpNode fon = (FlatOpNode) fn; if( fon.getOp().getOp() == Operation.ASSIGN ) { @@ -73,17 +126,30 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { type = lhs.getType(); if( type.isPtr() ) { - genAssertRuntimePtrVsHeapResults( output, - fm, - lhs, - heapAnalysis.canPointToAt( lhs, fn ) - ); + + output.println( "// Generating points-to checks for pre-node op assign" ); + + + //genAssertRuntimePtrVsHeapResults( output, + // fm, + // lhs, + // heapAnalysis.canPointToAt( lhs, fn ) + // ); genAssertRuntimePtrVsHeapResults( output, fm, rhs, heapAnalysis.canPointToAt( rhs, fn ) ); + + output.println( "// end pre-node op assign" ); + + + if( DEBUG ) { + System.out.println( " before "+fn ); + //System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAt( lhs, fn ) ); + System.out.println( " "+rhs+" can point to "+heapAnalysis.canPointToAt( rhs, fn ) ); + } } } } break; @@ -96,17 +162,29 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { type = fcn.getType(); if( type.isPtr() ) { - genAssertRuntimePtrVsHeapResults( output, - fm, - lhs, - heapAnalysis.canPointToAt( lhs, fn ) - ); + + output.println( "// Generating points-to checks for pre-node cast" ); + + //genAssertRuntimePtrVsHeapResults( output, + // fm, + // lhs, + // heapAnalysis.canPointToAt( lhs, fn ) + // ); genAssertRuntimePtrVsHeapResults( output, fm, rhs, heapAnalysis.canPointToAt( rhs, fn ) ); + + output.println( "// end pre-node cast" ); + + + if( DEBUG ) { + System.out.println( " before "+fn ); + //System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAt( lhs, fn ) ); + System.out.println( " "+rhs+" can point to "+heapAnalysis.canPointToAt( rhs, fn ) ); + } } } break; @@ -119,11 +197,14 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { type = lhs.getType(); if( type.isPtr() ) { - genAssertRuntimePtrVsHeapResults( output, - fm, - lhs, - heapAnalysis.canPointToAt( lhs, fn ) - ); + + output.println( "// Generating points-to checks for pre-node field" ); + + //genAssertRuntimePtrVsHeapResults( output, + // fm, + // lhs, + // heapAnalysis.canPointToAt( lhs, fn ) + // ); genAssertRuntimePtrVsHeapResults( output, fm, @@ -138,6 +219,16 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { null, heapAnalysis.canPointToAt( rhs, fld, fn ) ); + + output.println( "// end pre-node field" ); + + + if( DEBUG ) { + System.out.println( " before "+fn ); + //System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAt( lhs, fn ) ); + System.out.println( " "+rhs+" can point to "+heapAnalysis.canPointToAt( rhs, fn ) ); + System.out.println( " "+rhs+"."+fld+" can point to "+heapAnalysis.canPointToAt( rhs, fld, fn ) ); + } } } break; @@ -150,11 +241,14 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { type = lhs.getType(); if( type.isPtr() ) { - genAssertRuntimePtrVsHeapResults( output, - fm, - lhs, - heapAnalysis.canPointToAt( lhs, fn ) - ); + + output.println( "// Generating points-to checks for pre-node element" ); + + //genAssertRuntimePtrVsHeapResults( output, + // fm, + // lhs, + // heapAnalysis.canPointToAt( lhs, fn ) + // ); genAssertRuntimePtrVsHeapResults( output, fm, @@ -169,31 +263,287 @@ public class BCXPointsToCheckVRuntime implements BuildCodeExtension { idx, heapAnalysis.canPointToAtElement( rhs, fn ) ); + + output.println( "// end pre-node element" ); + + + if( DEBUG ) { + System.out.println( " before "+fn ); + //System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAt( lhs, fn ) ); + System.out.println( " "+rhs+" can point to "+heapAnalysis.canPointToAt( rhs, fn ) ); + System.out.println( " "+rhs+"["+idx+"] can point to "+heapAnalysis.canPointToAtElement( rhs, fn ) ); + } } } break; - - } + + case FKind.FlatCall: { + FlatCall fc = (FlatCall) fn; + //ret = fc.getReturnTemp(); + + FlatMethod fmCallee = state.getMethodFlat( fc.getMethod() ); + + boolean somethingChecked = false; + + output.println( "// Generating points-to checks for pre-node call" ); + + for( int i = 0; i < fmCallee.numParameters(); ++i ) { + arg = fc.getArgMatchingParamIndex( fmCallee, i ); + type = arg.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + arg, + heapAnalysis.canPointToAt( arg, fn ) + ); + somethingChecked = true; + } + } + + //if( ret != null ) { + // type = ret.getType(); + // if( type.isPtr() ) { + // genAssertRuntimePtrVsHeapResults( output, + // fm, + // ret, + // heapAnalysis.canPointToAt( ret, fn ) + // ); + // somethingChecked = true; + // } + //} + + output.println( "// end pre-node call" ); + + if( DEBUG && somethingChecked ) { + + System.out.println( " before "+fn+":" ); + + for( int i = 0; i < fmCallee.numParameters(); ++i ) { + arg = fc.getArgMatchingParamIndex( fmCallee, i ); + type = arg.getType(); + if( type.isPtr() ) { + System.out.println( " arg "+arg+" can point to "+heapAnalysis.canPointToAt( arg, fn ) ); + } + } + + //if( ret != null ) { + // type = ret.getType(); + // if( type.isPtr() ) { + // System.out.println( " return temp "+ret+" can point to "+heapAnalysis.canPointToAt( ret, fn ) ); + // } + //} + + } + } break; + } } + public void additionalCodePostNode(FlatMethod fm, FlatNode fn, PrintWriter output) { + + TempDescriptor lhs; + TempDescriptor rhs; + FieldDescriptor fld; + TempDescriptor idx; + TypeDescriptor type; + TempDescriptor arg; + TempDescriptor ret; + + + switch( fn.kind() ) { + + + case FKind.FlatLiteralNode: { + FlatLiteralNode fln = (FlatLiteralNode) fn; + + if( fln.getType().equals( stringType ) ) { + lhs = fln.getDst(); + + output.println( "// Generating points-to checks for post-node string literal" ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAfter( lhs, fn ) + ); + + output.println( "// end post-node string literal" ); + + + if( DEBUG ) { + System.out.println( " after "+fn ); + System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAfter( lhs, fn ) ); + } + } + } break; + + + case FKind.FlatOpNode: { + FlatOpNode fon = (FlatOpNode) fn; + if( fon.getOp().getOp() == Operation.ASSIGN ) { + lhs = fon.getDest(); + + type = lhs.getType(); + if( type.isPtr() ) { + + output.println( "// Generating points-to checks for post-node op assign" ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAfter( lhs, fn ) + ); + + output.println( "// end post-node op assign" ); + + + if( DEBUG ) { + System.out.println( " after "+fn ); + System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAfter( lhs, fn ) ); + } + } + } + } break; + + + case FKind.FlatCastNode: { + FlatCastNode fcn = (FlatCastNode) fn; + lhs = fcn.getDst(); + + type = fcn.getType(); + if( type.isPtr() ) { + + output.println( "// Generating points-to checks for post-node cast" ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAfter( lhs, fn ) + ); + + output.println( "// end post-node cast" ); + + + if( DEBUG ) { + System.out.println( " after "+fn ); + System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAfter( lhs, fn ) ); + } + } + } break; + + + case FKind.FlatFieldNode: { + FlatFieldNode ffn = (FlatFieldNode) fn; + lhs = ffn.getDst(); + + type = lhs.getType(); + if( type.isPtr() ) { + + output.println( "// Generating points-to checks for post-node field" ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAfter( lhs, fn ) + ); + + output.println( "// end post-node field" ); + + + if( DEBUG ) { + System.out.println( " after "+fn ); + System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAfter( lhs, fn ) ); + } + } + } break; + + + case FKind.FlatElementNode: { + FlatElementNode fen = (FlatElementNode) fn; + lhs = fen.getDst(); + + type = lhs.getType(); + if( type.isPtr() ) { + + output.println( "// Generating points-to checks for post-node element" ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAfter( lhs, fn ) + ); + + output.println( "// end post-node element" ); + + + if( DEBUG ) { + System.out.println( " after "+fn ); + System.out.println( " "+lhs+" can point to "+heapAnalysis.canPointToAfter( lhs, fn ) ); + } + } + } break; + + case FKind.FlatCall: { - FlatCall fc = (FlatCall) fn; - TempDescriptor td = fc.getReturnTemp(); - - if( td != null ) { - TypeDescriptor type = td.getType(); + FlatCall fc = (FlatCall) fn; + ret = fc.getReturnTemp(); + + FlatMethod fmCallee = state.getMethodFlat( fc.getMethod() ); + + boolean somethingChecked = false; + + output.println( "// Generating points-to checks for post-node call" ); + + for( int i = 0; i < fmCallee.numParameters(); ++i ) { + arg = fc.getArgMatchingParamIndex( fmCallee, i ); + type = arg.getType(); if( type.isPtr() ) { genAssertRuntimePtrVsHeapResults( output, fm, - td, - heapAnalysis.canPointToAfter( td, fn ) + arg, + heapAnalysis.canPointToAfter( arg, fn ) ); + somethingChecked = true; + } + } + + if( ret != null ) { + type = ret.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + ret, + heapAnalysis.canPointToAfter( ret, fn ) + ); + somethingChecked = true; + } + } + + output.println( "// end post-node call" ); + + if( DEBUG && somethingChecked ) { + + System.out.println( " after "+fn+":" ); + + for( int i = 0; i < fmCallee.numParameters(); ++i ) { + arg = fc.getArgMatchingParamIndex( fmCallee, i ); + type = arg.getType(); + if( type.isPtr() ) { + System.out.println( " arg "+arg+" can point to "+heapAnalysis.canPointToAfter( arg, fn ) ); + } + } + + if( ret != null ) { + type = ret.getType(); + if( type.isPtr() ) { + System.out.println( " return temp "+ret+" can point to "+heapAnalysis.canPointToAfter( ret, fn ) ); + } } + } } break; } diff --git a/Robust/src/IR/State.java b/Robust/src/IR/State.java index b8f30f6d..bb692cd4 100644 --- a/Robust/src/IR/State.java +++ b/Robust/src/IR/State.java @@ -126,6 +126,7 @@ public class State { public boolean DISJOINTDEBUGSCHEDULING=false; + public boolean DISJOINT_WRITE_ALL_NODE_FINAL_GRAPHS=false; public boolean POINTSTO_CHECK_V_RUNTIME=false; diff --git a/Robust/src/Main/Main.java b/Robust/src/Main/Main.java index 0bb5c21a..8f30c5a6 100644 --- a/Robust/src/Main/Main.java +++ b/Robust/src/Main/Main.java @@ -204,6 +204,9 @@ public class Main { } else if (option.equals("-disjoint-write-ihms")) { state.DISJOINTWRITEIHMS = true; + } else if (option.equals("-disjoint-write-all-node-graphs")) { + state.DISJOINT_WRITE_ALL_NODE_FINAL_GRAPHS = true; + } else if (option.equals("-disjoint-alias-file")) { state.DISJOINTALIASFILE = args[++i]; String arg = args[++i]; @@ -678,7 +681,7 @@ public class Main { if( state.POINTSTO_CHECK_V_RUNTIME && heapAnalysis != null ) { - BCXPointsToCheckVRuntime bcx = new BCXPointsToCheckVRuntime( bc, tu, heapAnalysis ); + BCXPointsToCheckVRuntime bcx = new BCXPointsToCheckVRuntime( state, bc, tu, heapAnalysis ); bc.registerExtension( bcx ); }