From: jjenista Date: Mon, 15 Mar 2010 19:55:17 +0000 (+0000) Subject: most of the missing context-rewriting code X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e2acd9a1ec5b1bce1b2c2e00ad373837cbbe7887;p=IRC.git most of the missing context-rewriting code --- diff --git a/Robust/src/Analysis/Disjoint/Canonical.java b/Robust/src/Analysis/Disjoint/Canonical.java index 7c913fbc..23c39bb6 100644 --- a/Robust/src/Analysis/Disjoint/Canonical.java +++ b/Robust/src/Analysis/Disjoint/Canonical.java @@ -942,6 +942,290 @@ abstract public class Canonical { op2result.put( op, out ); return out; } - + + + public static ReachSet toCallerContext( ReachSet rs, + AllocSite as ) { + assert rs != null; + assert as != null; + assert rs.isCanonical(); + assert as.isCanonical(); + + CanonicalOp op = + new CanonicalOp( CanonicalOp.REACHSET_TOCALLERCONTEXT_ALLOCSITE, + rs, + as ); + + Canonical result = op2result.get( op ); + if( result != null ) { + return (ReachSet) result; + } + + // otherwise, no cached result... + ReachSet out = ReachSet.factory(); + Iterator itr = rs.iterator(); + while( itr.hasNext() ) { + ReachState state = itr.next(); + out = Canonical.union( out, + Canonical.toCallerContext( state, as ) + ); + } + + assert out.isCanonical(); + op2result.put( op, out ); + return out; + } + + public static ReachSet toCallerContext( ReachState state, + AllocSite as ) { + assert state != null; + assert as != null; + assert state.isCanonical(); + assert as.isCanonical(); + + CanonicalOp op = + new CanonicalOp( CanonicalOp.REACHSTATE_TOCALLERCONTEXT_ALLOCSITE, + state, + as ); + + Canonical result = op2result.get( op ); + if( result != null ) { + return (ReachSet) result; + } + + // otherwise, no cached result... + ReachSet out = ReachSet.factory(); + + // this method returns a ReachSet instead of a ReachState + // because the companion method, toCallee, translates + // symbols many-to-one, so state->state + // but this method does an ~inverse mapping, one-to-many + // so one state can split into a set of branched states + + // 0 -> -0 + // 1 -> -1 + // 2S -> -2S + // 2S* -> -2S* + // + // 0? -> 0 + // 1? -> 1 + // 2S? -> 2S + // -> 0? + // -> 1? + // -> 2S? + // 2S?* -> {2S*, 2S?*} + + boolean found2Sooc = false; + + ReachState baseState = ReachState.factory(); + + Iterator itr = state.iterator(); + while( itr.hasNext() ) { + ReachTuple rt = itr.next(); + + int age = as.getAgeCategory( rt.getHrnID() ); + + if( age == AllocSite.AGE_notInThisSite ) { + // things not from the site just go back in + baseState = Canonical.union( baseState, rt ); + + } else if( age == AllocSite.AGE_summary ) { + + if( rt.isOutOfContext() ) { + // if its out-of-context, we only deal here with the ZERO-OR-MORE + // arity, if ARITY-ONE we'll branch the base state after the loop + if( rt.getArity() == ReachTuple.ARITY_ZEROORMORE ) { + // add two overly conservative symbols to reach state (PUNTING) + baseState = Canonical.union( baseState, + ReachTuple.factory( as.getSummary(), + true, // multi + ReachTuple.ARITY_ZEROORMORE, + false // out-of-context + ) + ); + baseState = Canonical.union( baseState, + ReachTuple.factory( as.getSummary(), + true, // multi + ReachTuple.ARITY_ZEROORMORE, + true // out-of-context + ) + ); + } else { + assert rt.getArity() == ReachTuple.ARITY_ONE; + found2Sooc = true; + } + + } else { + // the in-context just becomes shadow + baseState = Canonical.union( baseState, + ReachTuple.factory( as.getSummaryShadow(), + true, // multi + rt.getArity(), + false // out-of-context + ) + ); + } + + } else { + // otherwise the ith symbol becomes shadowed + Integer I = as.getAge( rt.getHrnID() ); + assert I != null; + + assert !rt.isMultiObject(); + + baseState = Canonical.union( baseState, + ReachTuple.factory( -rt.getHrnID(), + false, // multi + rt.getArity(), + false // out-of-context + ) + ); + } + } + + // now either make branches if we have 2S?, or + // the current baseState is the only state we need + if( found2Sooc ) { + // make a branch with every possibility of the one-to-many + // mapping for 2S? appended to the baseState + out = Canonical.union( out, + Canonical.union( baseState, + ReachTuple.factory( as.getSummary(), + true, // multi + ReachTuple.ARITY_ONE, + false // out-of-context + ) + ) + ); + + out = Canonical.union( out, + Canonical.union( baseState, + ReachTuple.factory( as.getSummary(), + true, // multi + ReachTuple.ARITY_ONE, + true // out-of-context + ) + ) + ); + + for( int i = 0; i < as.getAllocationDepth(); ++i ) { + out = Canonical.union( out, + Canonical.union( baseState, + ReachTuple.factory( as.getIthOldest( i ), + false, // multi + ReachTuple.ARITY_ONE, + true // out-of-context + ) + ) + ); + } + + } else { + // just use current baseState + out = Canonical.union( out, + baseState ); + } + + + assert out.isCanonical(); + op2result.put( op, out ); + return out; + } + + + + + + + + + + public static ReachSet unshadow( ReachSet rs, + AllocSite as ) { + assert rs != null; + assert as != null; + assert rs.isCanonical(); + assert as.isCanonical(); + + CanonicalOp op = + new CanonicalOp( CanonicalOp.REACHSET_UNSHADOW_ALLOCSITE, + rs, + as ); + + Canonical result = op2result.get( op ); + if( result != null ) { + return (ReachSet) result; + } + + // otherwise, no cached result... + ReachSet out = ReachSet.factory(); + Iterator itr = rs.iterator(); + while( itr.hasNext() ) { + ReachState state = itr.next(); + out = Canonical.add( out, + Canonical.unshadow( state, as ) + ); + } + + assert out.isCanonical(); + op2result.put( op, out ); + return out; + } + + public static ReachState unshadow( ReachState state, + AllocSite as ) { + assert state != null; + assert as != null; + assert state.isCanonical(); + assert as.isCanonical(); + + CanonicalOp op = + new CanonicalOp( CanonicalOp.REACHSTATE_UNSHADOW_ALLOCSITE, + state, + as ); + + Canonical result = op2result.get( op ); + if( result != null ) { + return (ReachState) result; + } + + // this is the current mapping, where 0, 1, 2S were allocated + // in the current context, 0?, 1? and 2S? were allocated in a + // previous context, and we're translating to a future context + // + // -0 -> 0 + // -1 -> 1 + // -2S -> 2S + + // otherwise, no cached result... + ReachState out = ReachState.factory(); + Iterator itr = state.iterator(); + while( itr.hasNext() ) { + ReachTuple rt = itr.next(); + + int age = as.getShadowAgeCategory( rt.getHrnID() ); + + if( age == AllocSite.SHADOWAGE_notInThisSite ) { + // things not from the site just go back in + out = Canonical.union( out, rt ); + + } else { + assert !rt.isOutOfContext(); + + // otherwise unshadow it + out = Canonical.union( out, + ReachTuple.factory( -rt.getHrnID(), + rt.isMultiObject(), + rt.getArity(), + false + ) + ); + } + } + + assert out.isCanonical(); + op2result.put( op, out ); + return out; + } } diff --git a/Robust/src/Analysis/Disjoint/CanonicalOp.java b/Robust/src/Analysis/Disjoint/CanonicalOp.java index b9e8a155..7f5dd6cf 100644 --- a/Robust/src/Analysis/Disjoint/CanonicalOp.java +++ b/Robust/src/Analysis/Disjoint/CanonicalOp.java @@ -8,27 +8,31 @@ package Analysis.Disjoint; // first and do a result look-up public class CanonicalOp { - public static final int REACHTUPLE_UNIONARITY_REACHTUPLE = 0x1a34; - public static final int REACHSTATE_UNION_REACHSTATE = 0x5678; - public static final int REACHSTATE_UNION_REACHTUPLE = 0x32b6; - public static final int REACHSTATE_UNIONUPARITY_REACHSTATE = 0x9152; - public static final int REACHSTATE_REMOVE_REACHTUPLE = 0x8173; - public static final int REACHSTATE_AGETUPLESFROM_ALLOCSITE = 0x4f65; - public static final int REACHSET_UNION_REACHSET = 0x2131; - public static final int REACHSET_UNION_REACHSTATE = 0xe3c8; - public static final int REACHSET_INTERSECTION_REACHSET = 0x3361; - public static final int REACHSET_REMOVE_REACHSTATE = 0x9391; - public static final int REACHSET_APPLY_CHANGESET = 0x1d55; - public static final int REACHSET_UNIONTOCHANGESET_REACHSET = 0x46a9; - public static final int REACHSET_AGETUPLESFROM_ALLOCSITE = 0x22bb; - public static final int REACHSET_PRUNEBY_REACHSET = 0xd774; - public static final int CHANGESET_UNION_CHANGESET = 0x53b3; - public static final int CHANGESET_UNION_CHANGETUPLE = 0x9ee4; - public static final int EXISTPREDSET_JOIN_EXISTPREDSET = 0x8a21; - public static final int EXISTPREDSET_ADD_EXISTPRED = 0xba5f; - public static final int PRIM_OP_UNUSED = 0xef01; - public static final int REACHSET_TOCALLEECONTEXT_ALLOCSITE = 0x56f6; + public static final int REACHTUPLE_UNIONARITY_REACHTUPLE = 0x1a34; + public static final int REACHSTATE_UNION_REACHSTATE = 0x5678; + public static final int REACHSTATE_UNION_REACHTUPLE = 0x32b6; + public static final int REACHSTATE_UNIONUPARITY_REACHSTATE = 0x9152; + public static final int REACHSTATE_REMOVE_REACHTUPLE = 0x8173; + public static final int REACHSTATE_AGETUPLESFROM_ALLOCSITE = 0x4f65; + public static final int REACHSET_UNION_REACHSET = 0x2131; + public static final int REACHSET_UNION_REACHSTATE = 0xe3c8; + public static final int REACHSET_INTERSECTION_REACHSET = 0x3361; + public static final int REACHSET_REMOVE_REACHSTATE = 0x9391; + public static final int REACHSET_APPLY_CHANGESET = 0x1d55; + public static final int REACHSET_UNIONTOCHANGESET_REACHSET = 0x46a9; + public static final int REACHSET_AGETUPLESFROM_ALLOCSITE = 0x22bb; + public static final int REACHSET_PRUNEBY_REACHSET = 0xd774; + public static final int CHANGESET_UNION_CHANGESET = 0x53b3; + public static final int CHANGESET_UNION_CHANGETUPLE = 0x9ee4; + public static final int EXISTPREDSET_JOIN_EXISTPREDSET = 0x8a21; + public static final int EXISTPREDSET_ADD_EXISTPRED = 0xba5f; + public static final int PRIM_OP_UNUSED = 0xef01; + public static final int REACHSET_TOCALLEECONTEXT_ALLOCSITE = 0x56f6; public static final int REACHSTATE_TOCALLEECONTEXT_ALLOCSITE = 0x7faf; + public static final int REACHSET_TOCALLERCONTEXT_ALLOCSITE = 0x2f6a; + public static final int REACHSTATE_TOCALLERCONTEXT_ALLOCSITE = 0xb2b1; + public static final int REACHSET_UNSHADOW_ALLOCSITE = 0x1049; + public static final int REACHSTATE_UNSHADOW_ALLOCSITE = 0x08ef; protected int opCode; protected Canonical operand1; diff --git a/Robust/src/Analysis/Disjoint/ReachGraph.java b/Robust/src/Analysis/Disjoint/ReachGraph.java index ff811bc4..c8a63bf0 100644 --- a/Robust/src/Analysis/Disjoint/ReachGraph.java +++ b/Robust/src/Analysis/Disjoint/ReachGraph.java @@ -1291,6 +1291,32 @@ public class ReachGraph { return out; } + // used below to convert a ReachSet to its caller-context + // equivalent with respect to allocation sites in this graph + protected ReachSet toCallerContext( ReachSet rs ) { + ReachSet out = rs; + Iterator asItr = allocSites.iterator(); + while( asItr.hasNext() ) { + AllocSite as = asItr.next(); + out = Canonical.toCallerContext( out, as ); + } + assert out.isCanonical(); + return out; + } + + // used below to convert a ReachSet to an equivalent + // version with shadow IDs merged into unshadowed IDs + protected ReachSet unshadow( ReachSet rs ) { + ReachSet out = rs; + Iterator asItr = allocSites.iterator(); + while( asItr.hasNext() ) { + AllocSite as = asItr.next(); + out = Canonical.unshadow( out, as ); + } + assert out.isCanonical(); + return out; + } + // use this method to make a new reach graph that is // what heap the FlatMethod callee from the FlatCall @@ -1903,7 +1929,7 @@ public class ReachGraph { false, // out-of-context? hrnCallee.getType(), // type hrnCallee.getAllocSite(), // allocation site - hrnCallee.getInherent(), // inherent reach + toCallerContext( hrnCallee.getInherent() ), // inherent reach null, // current reach predsEmpty, // predicates hrnCallee.getDescription() // description @@ -1913,7 +1939,7 @@ public class ReachGraph { } // TODO: alpha should be some rewritten version of callee in caller context - hrnCaller.setAlpha( hrnCallee.getAlpha() ); + hrnCaller.setAlpha( toCallerContext( hrnCallee.getAlpha() ) ); hrnCaller.setPreds( preds ); } @@ -1996,8 +2022,8 @@ public class ReachGraph { false, // out-of-context? hrnSrcCallee.getType(), // type hrnSrcCallee.getAllocSite(), // allocation site - hrnSrcCallee.getInherent(), // inherent reach - hrnSrcCallee.getAlpha(), // current reach + toCallerContext( hrnSrcCallee.getInherent() ), // inherent reach + toCallerContext( hrnSrcCallee.getAlpha() ), // current reach predsEmpty, // predicates hrnSrcCallee.getDescription() // description ); @@ -2025,7 +2051,7 @@ public class ReachGraph { hrnDstCaller, reCallee.getType(), reCallee.getField(), - reCallee.getBeta(), + toCallerContext( reCallee.getBeta() ), preds ); @@ -2107,8 +2133,8 @@ public class ReachGraph { false, // out-of-context? hrnDstCallee.getType(), // type hrnDstCallee.getAllocSite(), // allocation site - hrnDstCallee.getInherent(), // inherent reach - hrnDstCallee.getAlpha(), // current reach + toCallerContext( hrnDstCallee.getInherent() ), // inherent reach + toCallerContext( hrnDstCallee.getAlpha() ), // current reach predsTrue, // predicates hrnDstCallee.getDescription() // description ); @@ -2126,7 +2152,7 @@ public class ReachGraph { hrnDstCaller, tdNewEdge, null, - reCallee.getBeta(), + toCallerContext( reCallee.getBeta() ), predsTrue ); @@ -2233,6 +2259,30 @@ public class ReachGraph { } + if( writeDebugDOTs ) { + try { + writeGraph( "caller45BeforeUnshadow", + true, false, false, false, true, true ); + } catch( IOException e ) {} + } + + + Iterator itrAllHRNodes = id2hrn.entrySet().iterator(); + while( itrAllHRNodes.hasNext() ) { + Map.Entry me = (Map.Entry) itrAllHRNodes.next(); + HeapRegionNode hrn = (HeapRegionNode) me.getValue(); + + hrn.setAlpha( unshadow( hrn.getAlpha() ) ); + + Iterator itrEdges = hrn.iteratorToReferencers(); + while( itrEdges.hasNext() ) { + RefEdge re = itrEdges.next(); + re.setBeta( unshadow( re.getBeta() ) ); + } + } + + + if( writeDebugDOTs ) { try { writeGraph( "caller50BeforeGlobalSweep", diff --git a/Robust/src/Tests/disjoint/predicateTest3/test.java b/Robust/src/Tests/disjoint/predicateTest3/test.java index 256cbdda..f8b640b9 100644 --- a/Robust/src/Tests/disjoint/predicateTest3/test.java +++ b/Robust/src/Tests/disjoint/predicateTest3/test.java @@ -1,40 +1,17 @@ public class Foo { public Foo() {} public Foo f; - public Bar b; -} - -public class Bar { - public Bar() {} } public class Test { static public void main( String[] args ) { - - Foo f1 = disjoint high1 new Foo(); - Foo extraVar = f1; - addSomething( f1 ); - - Foo f2 = disjoint high2 new Foo(); - addSomething( f2 ); - - - Foo f3 = getAFoo(); - Foo f4 = getAFoo(); - f3.f = f4; + Foo top = disjoint inMain new Foo(); + addSomething( top ); } - public static void addSomething( Foo f ) { - addBar( f ); - } - - public static void addBar( Foo g ) { - if( true ) { - g.b = disjoint low1 new Bar(); - } else { - g.b = disjoint low2 new Bar(); - } + public static void addSomething( Foo x ) { + x.f = new Foo(); } public static Foo getAFoo() {