private Stack<FlatSESEEnterNode> seseStack;
private Set<FlatSESEEnterNode> seseRoots;
+ private Hashtable< FlatNode, Set<VariableSourceToken> > pointResults;
+
public MLPAnalysis( State state,
TypeUtil tu,
seseStack = new Stack <FlatSESEEnterNode>();
seseRoots = new HashSet<FlatSESEEnterNode>();
+ pointResults = new Hashtable< FlatNode, Set<VariableSourceToken> >();
+
+
// run analysis on each method that is actually called
// reachability analysis already computed this so reuse
Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
private void buildForestForward( FlatMethod fm ) {
-
+
+ // start from flat method top, visit every node in
+ // method exactly once, find SESEs and remember
+ // roots and child relationships
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
flatNodesToVisit.add( fm );
Set<FlatNode> visited = new HashSet<FlatNode>();
while( !flatNodesToVisit.isEmpty() ) {
- FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+ Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
+ FlatNode fn = fnItr.next();
+
+ System.out.println( " considering "+fn );
+
+ // only analyze sese exit nodes when all the nodes between
+ // it and its matching enter have been analyzed
+ if( !seseStack.empty() &&
+ fn.equals( seseStack.peek().getFlatExit() ) &&
+ flatNodesToVisit.size() != 1 ) {
+ // not ready for this exit node yet, just grab another
+ fn = fnItr.next();
+ }
+
flatNodesToVisit.remove( fn );
- visited.add( fn );
+ visited.add( fn );
+
+ System.out.println( " visiting "+fn );
- //System.out.println( " "+fn );
+ analyzeFlatNode( fn, true, null, null );
- analyzeFlatNode( fn, true );
+ // initialize for backward computation in next step
+ pointResults.put( fn, new HashSet<VariableSourceToken>() );
for( int i = 0; i < fn.numNext(); i++ ) {
FlatNode nn = fn.getNext( i );
private void computeReadAndWriteSetBackward( FlatSESEEnterNode fsen ) {
-
- }
+ // start from an SESE exit, visit nodes in reverse up to
+ // SESE enter in a fixed-point scheme, where children SESEs
+ // should already be analyzed and therefore can be skipped
+ // because child SESE enter node has all necessary info
+ Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+ flatNodesToVisit.add( fsen.getFlatExit() );
+
+ while( !flatNodesToVisit.isEmpty() ) {
+ FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+ flatNodesToVisit.remove( fn );
+
+ Set<VariableSourceToken> prev = pointResults.get( fn );
+
+ // merge sets from control flow joins
+ Set<VariableSourceToken> merge = new HashSet<VariableSourceToken>();
+ for( int i = 0; i < fn.numNext(); i++ ) {
+ FlatNode nn = fn.getNext( i );
+ merge = mergeVSTsets( merge, pointResults.get( nn ) );
+ }
+
+ Set<VariableSourceToken> curr = analyzeFlatNode( fn, false, merge, fsen );
+
+ // if a new result, schedule backward nodes for analysis
+ if( !prev.equals( curr ) ) {
+
+ System.out.println( " "+fn+":" );
+ System.out.println( " prev ="+prev );
+ System.out.println( " merge="+merge );
+ System.out.println( " curr ="+curr );
+ System.out.println( "" );
+
+ pointResults.put( fn, curr );
+
+ // don't flow backwards past SESE enter
+ if( !fn.equals( fsen ) ) {
+ for( int i = 0; i < fn.numPrev(); i++ ) {
+ FlatNode nn = fn.getPrev( i );
+ flatNodesToVisit.add( nn );
+ }
+ }
+ }
+ }
+
+ if( state.MLPDEBUG ) {
+ System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
+ Iterator<VariableSourceToken> tItr = pointResults.get( fsen ).iterator();
+ while( tItr.hasNext() ) {
+ System.out.println( " "+tItr.next() );
+ }
+ }
+ }
- private void analyzeFlatNode( FlatNode fn, boolean buildForest ) {
- TempDescriptor lhs;
- TempDescriptor rhs;
- FieldDescriptor fld;
+ private Set<VariableSourceToken> analyzeFlatNode( FlatNode fn,
+ boolean buildForest,
+ Set<VariableSourceToken> vstSet,
+ FlatSESEEnterNode currentSESE ) {
// use node type to decide what alterations to make
// to the ownership graph
seseStack.peek().addChild( fsen );
}
seseStack.push( fsen );
+ System.out.println( " pushed "+fsen );
}
} break;
case FKind.FlatSESEExitNode: {
- FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+ FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
if( buildForest ) {
assert !seseStack.empty();
- seseStack.pop();
+ FlatSESEEnterNode fsen = seseStack.pop();
+ System.out.println( " popped "+fsen );
}
//FlatSESEEnterNode fsen = fsexn.getFlatEnter();
//seseStack.peek().addOutVarSet( fsen.getOutVarSet() );
} break;
- /*
+ /*
case FKind.FlatMethod: {
FlatMethod fm = (FlatMethod) fn;
} break;
+ */
- case FKind.FlatOpNode: {
- FlatOpNode fon = (FlatOpNode) fn;
- if( fon.getOp().getOp() == Operation.ASSIGN ) {
- lhs = fon.getDest();
- rhs = fon.getLeft();
-
- }
- } break;
-
- case FKind.FlatCastNode: {
- FlatCastNode fcn = (FlatCastNode) fn;
- lhs = fcn.getDst();
- rhs = fcn.getSrc();
-
- TypeDescriptor td = fcn.getType();
- assert td != null;
-
- } break;
-
- case FKind.FlatFieldNode: {
- FlatFieldNode ffn = (FlatFieldNode) fn;
- lhs = ffn.getDst();
- rhs = ffn.getSrc();
- fld = ffn.getField();
- if( !fld.getType().isImmutable() || fld.getType().isArray() ) {
-
- }
- } break;
-
- case FKind.FlatSetFieldNode: {
- FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
- lhs = fsfn.getDst();
- fld = fsfn.getField();
- rhs = fsfn.getSrc();
- if( !fld.getType().isImmutable() || fld.getType().isArray() ) {
-
- }
- } break;
-
- case FKind.FlatElementNode: {
- FlatElementNode fen = (FlatElementNode) fn;
- lhs = fen.getDst();
- rhs = fen.getSrc();
- if( !lhs.getType().isImmutable() || lhs.getType().isArray() ) {
-
- assert rhs.getType() != null;
- assert rhs.getType().isArray();
-
- TypeDescriptor tdElement = rhs.getType().dereference();
- //FieldDescriptor fdElement = getArrayField( tdElement );
-
- }
- } break;
-
+ case FKind.FlatOpNode:
+ case FKind.FlatCastNode:
+ case FKind.FlatFieldNode:
+ case FKind.FlatSetFieldNode:
+ case FKind.FlatElementNode:
case FKind.FlatSetElementNode: {
- FlatSetElementNode fsen = (FlatSetElementNode) fn;
- lhs = fsen.getDst();
- rhs = fsen.getSrc();
- if( !rhs.getType().isImmutable() || rhs.getType().isArray() ) {
+ if( !buildForest ) {
+ // handle effects of statement in reverse, writes then reads
+ TempDescriptor [] writeTemps = fn.writesTemps();
+ for( int i = 0; i < writeTemps.length; ++i ) {
+ vstSet = killTemp( vstSet, writeTemps[i] );
+ }
- assert lhs.getType() != null;
- assert lhs.getType().isArray();
-
- TypeDescriptor tdElement = lhs.getType().dereference();
- //FieldDescriptor fdElement = getArrayField( tdElement );
+ TempDescriptor [] readTemps = fn.readsTemps();
+ for( int i = 0; i < readTemps.length; ++i ) {
+ Set<VariableSourceToken> vstNew = new HashSet<VariableSourceToken>();
+ vstNew.add( new VariableSourceToken( currentSESE,
+ readTemps[i],
+ new Integer( 0 ) ) );
+ vstSet = mergeVSTsets( vstSet, vstNew );
+ }
}
} break;
+ /*
case FKind.FlatNew: {
FlatNew fnn = (FlatNew) fn;
lhs = fnn.getDst();
//AllocationSite as = getAllocationSiteFromFlatNewPRIVATE( fnn );
}
} break;
+ */
+ /*
case FKind.FlatCall: {
FlatCall fc = (FlatCall) fn;
MethodDescriptor md = fc.getMethod();
}
} break;
+ */
case FKind.FlatReturnNode: {
FlatReturnNode frn = (FlatReturnNode) fn;
- rhs = frn.getReturnTemp();
- if( rhs != null && !rhs.getType().isImmutable() ) {
-
- }
- if( !seseStack.empty() ) {
- throw new Error( "Error: return statement enclosed within SESE "+seseStack.peek() );
+ if( buildForest && !seseStack.empty() ) {
+ throw new Error( "Error: return statement enclosed within "+seseStack.peek() );
}
} break;
- */
+
} // end switch
+
+
+ return vstSet;
+ }
+
+
+ private Set<VariableSourceToken> killTemp( Set<VariableSourceToken> s,
+ TempDescriptor t ) {
+ Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
+
+ Iterator<VariableSourceToken> vstitr = s.iterator();
+ while( vstitr.hasNext() ) {
+ VariableSourceToken vst = vstitr.next();
+
+ if( !vst.getVar().equals( t ) ) {
+ out.add( vst );
+ }
+ }
+
+ return out;
+ }
+
+
+ private Set<VariableSourceToken> mergeVSTsets( Set<VariableSourceToken> s1,
+ Set<VariableSourceToken> s2 ) {
+
+ Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
+
+ Iterator<VariableSourceToken> vst1itr = s1.iterator();
+ while( vst1itr.hasNext() ) {
+ VariableSourceToken vst1 = vst1itr.next();
+
+ int changeAge = -1;
+
+ Iterator<VariableSourceToken> vst2itr = s2.iterator();
+ while( vst2itr.hasNext() ) {
+ VariableSourceToken vst2 = vst2itr.next();
+
+ if( vst1.getSESE().equals( vst2.getSESE() ) &&
+ vst1.getVar() .equals( vst2.getVar() ) ) {
+ changeAge = vst1.getAge();
+ int a = vst2.getAge();
+ if( a < changeAge ) {
+ changeAge = a;
+ }
+ break;
+ }
+ }
+
+ if( changeAge < 0 ) {
+ out.add( vst1 );
+ } else {
+ out.add( new VariableSourceToken( vst1.getSESE(),
+ vst1.getVar(),
+ new Integer( changeAge ) ) );
+ }
+ }
+
+
+ Iterator<VariableSourceToken> vst2itr = s2.iterator();
+ while( vst2itr.hasNext() ) {
+ VariableSourceToken vst2 = vst2itr.next();
+
+ boolean matchSESEandVar = false;
+
+ vst1itr = s1.iterator();
+ while( vst1itr.hasNext() ) {
+ VariableSourceToken vst1 = vst1itr.next();
+
+ if( vst1.getSESE().equals( vst2.getSESE() ) &&
+ vst1.getVar() .equals( vst2.getVar() ) ) {
+ matchSESEandVar = true;
+ break;
+ }
+ }
+
+ if( !matchSESEandVar ) {
+ out.add( vst2 );
+ }
+ }
+
+
+ return out;
}
}
+
+