-changes on the potential stall site analysis: propagating the status of callee's return node to the caller region and when current node has a status change, making following nodes updated to get a new potential stall site status.
-changes on liveness analysis of OoOJava: new analysis only covers the task region, not whole region of the flat method.
-changes on disjoint analysis: rather than using reachgraph's inAccessibleSet, using the result of brian's new accessible analysis.
import Analysis.CallGraph.*;
import Analysis.Liveness;
import Analysis.ArrayReferencees;
+import Analysis.OoOJava.Accessible;
import Analysis.OoOJava.RBlockRelationAnalysis;
import IR.*;
import IR.Flat.*;
new Hashtable<FlatNode, ReachGraph>();
private Hashtable<FlatCall, Descriptor> fc2enclosing;
-
+
+ Accessible accessible;
// allocate various structures that are not local
// to a single class method--should be done once
if( rblockRel != null ) {
doEffectsAnalysis = true;
effectsAnalysis = new EffectsAnalysis();
+
+ //note: instead of reachgraph's isAccessible, using the result of accessible analysis
+ //since accessible gives us more accurate results
+ accessible=new Accessible(state, callGraph, rra, liveness);
+ accessible.doAnalysis();
}
-
+
this.allocationDepth = state.DISJOINTALLOCDEPTH;
this.releaseMode = state.DISJOINTRELEASEMODE;
this.determinismDesired = state.DISJOINTDETERMINISM;
if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
if(rblockRel.isPotentialStallSite(fn)){
// x gets status of y
- if(!rg.isAccessible(rhs)){
+// if(!rg.isAccessible(rhs)){
+ if(!accessible.isAccessible(fn, rhs)){
rg.makeInaccessible(lhs);
}
}
if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
if(rblockRel.isPotentialStallSite(fn)){
// x gets status of y
- if(!rg.isAccessible(rhs)){
+// if(!rg.isAccessible(rhs)){
+ if(!accessible.isAccessible(fn,rhs)){
rg.makeInaccessible(lhs);
}
}
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(!rg.isAccessible(rhs)) {
+ if(!accessible.isAccessible(fn,rhs)) {
rg.taintStallSite(fn, rhs);
}
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(!rg.isAccessible(lhs)) {
+ if(!accessible.isAccessible(fn,lhs)) {
rg.taintStallSite(fn, lhs);
}
- if(!rg.isAccessible(rhs)) {
+// if(!rg.isAccessible(rhs)) {
+ if(!accessible.isAccessible(fn,rhs)) {
rg.taintStallSite(fn, rhs);
}
// 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(!rg.isAccessible(rhs)) {
+ if(!accessible.isAccessible(fn,rhs)) {
rg.taintStallSite(fn, rhs);
}
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(!rg.isAccessible(lhs)) {
+ if(!accessible.isAccessible(fn,lhs)) {
rg.taintStallSite(fn, lhs);
}
- if(!rg.isAccessible(rhs)) {
+// if(!rg.isAccessible(rhs)) {
+ if(!accessible.isAccessible(fn,rhs)) {
rg.taintStallSite(fn, rhs);
}
);
if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
- if( !rgPossibleCallee.isAccessible( ReachGraph.tdReturn ) ) {
+// if( !rgPossibleCallee.isAccessible( ReachGraph.tdReturn ) ) {
+ if( !accessible.isAccessible(fn, ReachGraph.tdReturn ) ) {
rgPossibleCaller.makeInaccessible( fc.getReturnTemp() );
}
}
// before transfer, do effects analysis support
if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
- if(!rg.isAccessible(rhs)){
+// if(!rg.isAccessible(rhs)){
+ if(!accessible.isAccessible(fn,rhs)){
rg.makeInaccessible(ReachGraph.tdReturn);
}
}
State.logEvent("OoOJavaAnalysis 1st pass completed");
+
// 2nd pass, liveness, in-set out-set (no virtual reads yet!)
- methItr = descriptorsToAnalyze.iterator();
- while (methItr.hasNext()) {
- Descriptor d = methItr.next();
- FlatMethod fm = state.getMethodFlat(d);
-
- // note we can't use the general liveness analysis already in
- // the compiler because this analysis is task-aware
- livenessAnalysisBackward(fm);
+ Iterator<FlatSESEEnterNode> seseItr = rblockRel.getLocalRootSESEs().iterator();
+ while (seseItr.hasNext()) {
+ FlatSESEEnterNode sese = seseItr.next();
+ livenessAnalysisBackward(sese,liveness);
}
+
State.logEvent("OoOJavaAnalysis 2nd pass completed");
variableAnalysisForward(fm);
}
State.logEvent("OoOJavaAnalysis 3rd pass completed");
+
// 4th pass, compute liveness contribution from
// virtual reads discovered in variable pass
- methItr = descriptorsToAnalyze.iterator();
- while (methItr.hasNext()) {
- Descriptor d = methItr.next();
- FlatMethod fm = state.getMethodFlat(d);
- livenessAnalysisBackward(fm);
+ seseItr = rblockRel.getLocalRootSESEs().iterator();
+ while (seseItr.hasNext()) {
+ FlatSESEEnterNode sese = seseItr.next();
+ livenessAnalysisBackward(sese,liveness);
}
+
State.logEvent("OoOJavaAnalysis 4th pass completed");
// 5th pass, use disjointness with NO FLAGGED REGIONS
while (methItr.hasNext()) {
Descriptor d = methItr.next();
FlatMethod fm = state.getMethodFlat(d);
- codePlansForward(fm);
+ codePlansForward(fm,liveness);
}
State.logEvent("OoOJavaAnalysis 12th pass completed");
}
- private void livenessAnalysisBackward(FlatMethod fm) {
+ private void livenessAnalysisBackward(FlatSESEEnterNode fsen,Liveness liveness) {
// flow backward across nodes to compute liveness, and
// take special care with sese enter/exit nodes that
// alter this from normal liveness analysis
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
- flatNodesToVisit.add( fm.getFlatExit() );
+// flatNodesToVisit.add( fm.getFlatExit() );
+ flatNodesToVisit.add(fsen.getFlatExit());
while( !flatNodesToVisit.isEmpty() ) {
FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
}
}
- Set<TempDescriptor> curr = liveness_nodeActions( fn, livein );
+ Set<TempDescriptor> curr = liveness_nodeActions( fn, livein, liveness );
// if a new result, schedule backward nodes for analysis
if( !curr.equals( prev ) ) {
- livenessGlobalView.put( fn, curr );
- for( int i = 0; i < fn.numPrev(); i++ ) {
- FlatNode nn = fn.getPrev( i );
- flatNodesToVisit.add( nn );
- }
+ if(fn!=fsen){
+ livenessGlobalView.put( fn, curr );
+ for( int i = 0; i < fn.numPrev(); i++ ) {
+ FlatNode nn = fn.getPrev( i );
+ flatNodesToVisit.add( nn );
+ }
+ }
}
}
}
private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
- Set<TempDescriptor> liveIn
+ Set<TempDescriptor> liveIn, Liveness liveness
) {
switch( fn.kind() ) {
// be live-out at the task's exit (and therefore should
// go in the task's out-var set)
FlatSESEExitNode fsexn = fsen.getFlatExit();
- Set<TempDescriptor> livetemps = livenessGlobalView.get( fsexn );
+ //note: liveness analysis can have corresponding decisions
+ Set<TempDescriptor> livetemps= liveness.getLiveInTemps(fsen.getfmEnclosing(), fsexn);
+// Set<TempDescriptor> livetemps = livenessGlobalView.get( fsexn );
if( livetemps != null && livetemps.contains( writeTemps[i] ) ) {
fsen.addOutVar( writeTemps[i] );
}
}
- private void codePlansForward(FlatMethod fm) {
+ private void codePlansForward(FlatMethod fm, Liveness liveness) {
// start from flat method top, visit every node in
// method exactly once
}
codePlans_nodeActions(fm, fn,
- dotSTlive, dotSTtable, dotSTnotAvailSet,
+ /*dotSTlive*/liveness, dotSTtable, dotSTnotAvailSet,
currentSESE);
for (int i = 0; i < fn.numNext(); i++) {
private void codePlans_nodeActions(FlatMethod fm,
FlatNode fn,
- Set<TempDescriptor> liveSetIn,
+// Set<TempDescriptor> liveSetIn,
+ Liveness liveness,
VarSrcTokTable vstTableIn,
Set<TempDescriptor> notAvailSetIn,
FlatSESEEnterNode currentSESE) {
default: {
// a node with no live set has nothing to stall for
- if (liveSetIn == null) {
- break;
- }
+ // note: no reason to check here, remove this....
+// if (liveSetIn == null) {
+// break;
+// }
TempDescriptor[] readarray = fn.readsTemps();
for (int i = 0; i < readarray.length; i++) {
Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
+
while (refVarItr.hasNext()) {
TempDescriptor refVar = refVarItr.next();
- if (liveSetIn.contains(refVar)) {
- copySet.add(refVar);
- }
+ //note: this should just use normal liveness in...only want to copy live variables...
+// if (liveSetIn.contains(refVar)) {
+// copySet.add(refVar);
+// }
+ if(liveness.getLiveInTemps(fm, fn).contains(refVar)){
+ copySet.add(refVar);
+ }
}
if (!copySet.isEmpty()) {
for (int i = 0; i < fn.numNext(); i++) {
FlatNode nn = fn.getNext(i);
VarSrcTokTable nextVstTable = variableResults.get(nn);
- Set<TempDescriptor> nextLiveIn = livenessGlobalView.get(nn);
+ // note: using the result of liveness analysis regardless of task structures
+ // Set<TempDescriptor> nextLiveIn = livenessGlobalView.get(nn);
+ Set<TempDescriptor> nextLiveIn=liveness.getLiveInTemps(fm, nn);
// the table can be null if it is one of the few IR nodes
// completely outside of the root SESE scope
FlatMethod fm,
TempDescriptor var ) {
FlatNode fnContext;
-
- if( fsen.getIsCallerProxySESE() ) {
- // attach the dynamic variable to track to
- // the flat method, so it can be declared at entry
- fnContext = fm;
- } else {
- // otherwise the code context is a task body
- fnContext = fsen;
- }
+
+ // note: dynamic variable declarations are always located in the flat method that encloses task block
+ // there is no need to set fnContext to fsen
+// if( fsen.getIsCallerProxySESE() ) {
+// // attach the dynamic variable to track to
+// // the flat method, so it can be declared at entry
+// fnContext = fm;
+// } else {
+// // otherwise the code context is a task body
+// fnContext = fsen;
+// }
+ fnContext=fm;
ContextTaskNames ctn = fn2contextTaskNames.get( fnContext );
if( ctn == null ) {
ctn.addDynamicVar( var );
fn2contextTaskNames.put( fnContext, ctn );
+
}
private void addNeededStaticName( FlatSESEEnterNode fsen,
import IR.MethodDescriptor;
import IR.TypeDescriptor;
import IR.Flat.*;
+import Util.Pair;
import Analysis.CallGraph.CallGraph;
import java.util.*;
// after some child task definition such that, without looking at
// the flat node itself, the parent might have to stall for child
protected Hashtable<FlatNode, Boolean> fn2isPotentialStallSite;
+
+ HashMap<MethodDescriptor, Set<Pair<FlatCall, MethodDescriptor>>> methodmap=
+ new HashMap<MethodDescriptor, Set<Pair<FlatCall, MethodDescriptor>>>();
+
////////////////////////
Set<FlatNode> visited = new HashSet<FlatNode>();
- while( !flatNodesToVisit.isEmpty() ) {
- Map.Entry me = (Map.Entry) flatNodesToVisit.entrySet().iterator().next();
- FlatNode fn = (FlatNode) me.getKey();
+ while (!flatNodesToVisit.isEmpty()) {
+ Map.Entry me = (Map.Entry) flatNodesToVisit.entrySet().iterator().next();
+ FlatNode fn = (FlatNode) me.getKey();
FlatMethod fm = (FlatMethod) me.getValue();
- flatNodesToVisit.remove( fn );
- visited.add( fn );
+ flatNodesToVisit.remove(fn);
+ visited.add(fn);
// the "is potential stall site" strategy is to propagate
// "false" from the beginning of a task until you hit a
// child, then from the child's exit propagate "true" for
- // the parent statements after children. When you pull a node
+ // the parent statements after children. When you pull a node
// out of the bag for traversal and it happens to be an
// enter or an exit node, fix the dumb propagation that
// your IR predecessor pushed on you
- Boolean isPotentialStallSite = isPotentialStallSite( fn );
+ Boolean isPotentialStallSite = isPotentialStallSite(fn);
- if( fn == fsen.getFlatExit() ) {
- // don't enqueue any futher nodes when you find your exit,
+ if (fn == fsen.getFlatExit()) {
+ // don't enqueue any further nodes when you find your exit,
// NOR mark your own flat as a statement you are currently
// executing, your parent(s) will mark it
continue;
}
- if( fn instanceof FlatSESEExitNode ) {
- setIsPotentialStallSite( fn, false );
- isPotentialStallSite = true;
+ if (fn instanceof FlatSESEExitNode) {
+ setIsPotentialStallSite(fn, false);
+ isPotentialStallSite = true;
}
-
+
// the purpose of this traversal is to find program
// points where rblock 'fsen' might be executing
- addPossibleExecutingRBlock( fn, fsen );
+ addPossibleExecutingRBlock(fn, fsen);
- if( fn instanceof FlatSESEEnterNode ) {
+ if (fn instanceof FlatSESEEnterNode) {
// don't visit internal nodes of child,
// just enqueue the exit node
FlatSESEEnterNode child = (FlatSESEEnterNode) fn;
- assert fsen.getChildren().contains( child );
- assert child.getParents().contains( fsen );
- flatNodesToVisit.put( child.getFlatExit(), fm );
- setIsPotentialStallSite( fn, false );
+ assert fsen.getChildren().contains(child);
+ assert child.getParents().contains(fsen);
+ flatNodesToVisit.put(child.getFlatExit(), fm);
+ setIsPotentialStallSite(fn, false);
// explicitly do this to handle the case that you
- // should mark yourself as possibly executing at
+ // should mark yourself as possibly executing at
// your own exit, because one instance can
// recursively invoke another
- addPossibleExecutingRBlock( child.getFlatExit(), fsen );
+ addPossibleExecutingRBlock(child.getFlatExit(), fsen);
continue;
}
-
-
+
// if previous flat nodes have any changes,,
// propagate predecessor's status of stall site potential
-
- if( fn instanceof FlatCall ) {
+ if (fn instanceof FlatCall) {
+
// start visiting nodes in other contexts
- FlatCall fc = (FlatCall) fn;
+ FlatCall fc = (FlatCall) fn;
MethodDescriptor mdCallee = fc.getMethod();
Set<MethodDescriptor> implementations = new HashSet<MethodDescriptor>();
- if( mdCallee.isStatic() ) {
- implementations.add( mdCallee );
+ if (mdCallee.isStatic()) {
+ implementations.add(mdCallee);
} else {
TypeDescriptor typeDesc = fc.getThis().getType();
- implementations.addAll( callGraph.getMethods( mdCallee, typeDesc ) );
+ implementations.addAll(callGraph.getMethods(mdCallee, typeDesc));
}
- for( Iterator imps = implementations.iterator(); imps.hasNext(); ) {
+ for (Iterator imps = implementations.iterator(); imps.hasNext();) {
MethodDescriptor mdImp = (MethodDescriptor) imps.next();
- FlatMethod fmImp = state.getMethodFlat( mdImp );
- if ((isPotentialStallSite&&!isPotentialStallSite(fmImp))||
- !visited.contains(fmImp)) {
- flatNodesToVisit.put( fmImp, fmImp );
-
- // propagate your IR graph predecessor's stall site potential
- mergeIsPotentialStallSite( fmImp, isPotentialStallSite );
- }
+ FlatMethod fmImp = state.getMethodFlat(mdImp);
+
+ // keep mapping from fc's md to <fc,caller's md>
+ // later, when return node of callee becomes a potential stall site,
+ // following flat nodes of fc should be re-analyzied
+ if(!methodmap.containsKey(fmImp)){
+ methodmap.put(mdImp, new HashSet<Pair<FlatCall,MethodDescriptor>>());
+ }
+ methodmap.get(mdImp).add(new Pair<FlatCall,MethodDescriptor>(fc,fm.getMethod()));
+
+ if ((isPotentialStallSite && !isPotentialStallSite(fmImp)) || !visited.contains(fmImp)) {
+ flatNodesToVisit.put(fmImp, fmImp);
+
+ // propagate your IR graph predecessor's stall site potential
+ mergeIsPotentialStallSite(fmImp, isPotentialStallSite);
+ }
+
}
// don't 'continue' out of this loop, also enqueue
// flat nodes that flow in the current method context
}
+
+ if (fn instanceof FlatReturnNode) {
+ // if return node is potential stall site, need to inform its caller
+ if (isPotentialStallSite) {
+ Set<Pair<FlatCall, MethodDescriptor>> callset = methodmap.get(fm.getMethod());
+ if (callset != null) {
+ for (Pair<FlatCall, MethodDescriptor> fcallpair : callset) {
+ FlatCall fcall = fcallpair.getFirst();
+ MethodDescriptor mdcaller = fcallpair.getSecond();
+ for (int i = 0; i < fcall.numNext(); i++) {
+ FlatNode nn = fcall.getNext(i);
+ if ( visited.contains(nn) && (!isPotentialStallSite(nn)) ) {
+ mergeIsPotentialStallSite(nn, isPotentialStallSite);
+ FlatMethod fmcaller = state.getMethodFlat(mdcaller);
+ flatNodesToVisit.put(nn, fmcaller);
+ }
+ }
+ }
+ }
+ }
+ }
-
- // only when current flat node has a change on the status of potential stall site,
- // need to visit following flat nodes
- for (int i = 0; i < fn.numNext(); i++) {
- FlatNode nn = fn.getNext(i);
- if ((isPotentialStallSite&&!isPotentialStallSite(nn))||
- !visited.contains(nn)) {
- flatNodesToVisit.put(nn, fm);
- mergeIsPotentialStallSite( nn, isPotentialStallSite );
- }
- }
+ // note: only when current flat node has a change on the status of potential
+ // stall site, need to visit following flat nodes
+ for (int i = 0; i < fn.numNext(); i++) {
+ FlatNode nn = fn.getNext(i);
+ if ((isPotentialStallSite && !isPotentialStallSite(nn)) || !visited.contains(nn)) {
+ flatNodesToVisit.put(nn, fm);
+ mergeIsPotentialStallSite(nn, isPotentialStallSite);
+ }
+ }
}
}
}