1 package Analysis.OoOJava;
3 import java.io.BufferedWriter;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.util.Enumeration;
7 import java.util.HashSet;
8 import java.util.Hashtable;
9 import java.util.Iterator;
12 import java.util.Stack;
13 import java.util.Map.Entry;
15 import Analysis.ArrayReferencees;
16 import Analysis.Liveness;
17 import Analysis.CallGraph.CallGraph;
18 import Analysis.Disjoint.DisjointAnalysis;
19 import Analysis.Disjoint.Effect;
20 import Analysis.Disjoint.EffectsAnalysis;
21 import Analysis.Disjoint.Taint;
23 import IR.MethodDescriptor;
28 import IR.Flat.FlatCall;
29 import IR.Flat.FlatEdge;
30 import IR.Flat.FlatElementNode;
31 import IR.Flat.FlatFieldNode;
32 import IR.Flat.FlatMethod;
33 import IR.Flat.FlatNew;
34 import IR.Flat.FlatNode;
35 import IR.Flat.FlatOpNode;
36 import IR.Flat.FlatSESEEnterNode;
37 import IR.Flat.FlatSESEExitNode;
38 import IR.Flat.FlatSetElementNode;
39 import IR.Flat.FlatSetFieldNode;
40 import IR.Flat.FlatWriteDynamicVarNode;
41 import IR.Flat.TempDescriptor;
43 public class OoOJavaAnalysis {
45 // data from the compiler
47 private TypeUtil typeUtil;
48 private CallGraph callGraph;
49 private RBlockRelationAnalysis rblockRel;
50 private DisjointAnalysis disjointAnalysisTaints;
51 private DisjointAnalysis disjointAnalysisReach;
53 private Set<MethodDescriptor> descriptorsToAnalyze;
55 private Hashtable<FlatNode, Set<TempDescriptor>> livenessGlobalView;
56 private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
57 private Hashtable<FlatNode, VarSrcTokTable> variableResults;
58 private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
59 private Hashtable<FlatNode, CodePlan> codePlans;
61 private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
63 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
65 private Hashtable<FlatNode, ContextTaskNames> fn2contextTaskNames;
68 // temporal data structures to track analysis progress.
69 static private int uniqueLockSetId = 0;
70 // mapping of a conflict graph to its compiled lock
71 private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
72 // mapping of a sese block to its conflict graph
73 private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
75 public static int maxSESEage = -1;
77 public int getMaxSESEage() {
82 public CodePlan getCodePlan(FlatNode fn) {
83 CodePlan cp = codePlans.get(fn);
87 public Set<FlatNode> getNodesWithPlans() {
88 return codePlans.keySet();
91 public ContextTaskNames getContextTaskNames( FlatMethod fm ) {
92 ContextTaskNames out = fn2contextTaskNames.get( fm );
94 out = new ContextTaskNames();
99 public ContextTaskNames getContextTaskNames( FlatSESEEnterNode fsen ) {
100 ContextTaskNames out = fn2contextTaskNames.get( fsen );
102 out = new ContextTaskNames();
107 public DisjointAnalysis getDisjointAnalysis() {
108 return disjointAnalysisTaints;
112 public OoOJavaAnalysis(State state,
116 ArrayReferencees arrayReferencees) {
118 double timeStartAnalysis = (double) System.nanoTime();
121 this.typeUtil = typeUtil;
122 this.callGraph = callGraph;
123 this.maxSESEage = state.OOO_MAXSESEAGE;
125 livenessGlobalView = new Hashtable<FlatNode, Set<TempDescriptor>>();
126 livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
127 variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
128 notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
129 codePlans = new Hashtable<FlatNode, CodePlan>();
130 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
131 notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
132 sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
133 conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
134 fn2contextTaskNames = new Hashtable<FlatNode, ContextTaskNames>();
136 // add all methods transitively reachable from the
137 // source's main to set for analysis
138 MethodDescriptor mdSourceEntry = typeUtil.getMain();
139 FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
141 descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
143 descriptorsToAnalyze.add(mdSourceEntry);
145 // 1st pass, find basic rblock relations & potential stall sites
146 rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
147 VarSrcTokTable.rblockRel = rblockRel;
149 // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
150 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
151 while (methItr.hasNext()) {
152 Descriptor d = methItr.next();
153 FlatMethod fm = state.getMethodFlat(d);
155 // note we can't use the general liveness analysis already in
156 // the compiler because this analysis is task-aware
157 livenessAnalysisBackward(fm);
160 // 3rd pass, variable analysis
161 methItr = descriptorsToAnalyze.iterator();
162 while (methItr.hasNext()) {
163 Descriptor d = methItr.next();
164 FlatMethod fm = state.getMethodFlat(d);
166 // starting from roots do a forward, fixed-point
167 // variable analysis for refinement and stalls
168 variableAnalysisForward(fm);
171 // 4th pass, compute liveness contribution from
172 // virtual reads discovered in variable pass
173 methItr = descriptorsToAnalyze.iterator();
174 while (methItr.hasNext()) {
175 Descriptor d = methItr.next();
176 FlatMethod fm = state.getMethodFlat(d);
177 livenessAnalysisBackward(fm);
180 // 5th pass, use disjointness with NO FLAGGED REGIONS
181 // to compute taints and effects
182 disjointAnalysisTaints =
183 new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, null,
185 true ); // suppress output--this is an intermediate pass
187 // 6th pass, not available analysis FOR VARIABLES!
188 methItr = descriptorsToAnalyze.iterator();
189 while (methItr.hasNext()) {
190 Descriptor d = methItr.next();
191 FlatMethod fm = state.getMethodFlat(d);
193 // compute what is not available at every program
194 // point, in a forward fixed-point pass
195 notAvailableForward(fm);
198 // 7th pass, make conflict graph
199 // conflict graph is maintained by each parent sese,
200 // where its' own stall sites and children may appear
201 Set<FlatSESEEnterNode> allSESEs=rblockRel.getAllSESEs();
202 for (Iterator iterator = allSESEs.iterator(); iterator.hasNext();) {
204 FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
205 if (!parent.getIsLeafSESE()) {
207 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
208 ConflictGraph conflictGraph = sese2conflictGraph.get(parent);
209 if (conflictGraph == null) {
210 conflictGraph = new ConflictGraph(state);
213 Set<FlatSESEEnterNode> children = parent.getChildren();
214 for (Iterator iterator2 = children.iterator(); iterator2.hasNext();) {
215 FlatSESEEnterNode child = (FlatSESEEnterNode) iterator2.next();
216 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(child);
217 conflictGraph.addLiveIn(taint2Effects);
218 sese2conflictGraph.put(parent, conflictGraph);
223 Iterator descItr = descriptorsToAnalyze.iterator();
224 while (descItr.hasNext()) {
225 Descriptor d = (Descriptor) descItr.next();
226 FlatMethod fm = state.getMethodFlat(d);
228 makeConflictGraph(fm);
233 // 8th pass, calculate all possible conflicts without using
234 // reachability info and identify set of FlatNew that next
235 // disjoint reach. analysis should flag
236 Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
237 calculateConflicts(sitesToFlag, false);
241 // 9th pass, ask disjoint analysis to compute reachability
242 // for objects that may cause heap conflicts so the most
243 // efficient method to deal with conflict can be computed
245 disjointAnalysisReach =
246 new DisjointAnalysis(state, typeUtil, callGraph, liveness,
247 arrayReferencees, sitesToFlag,
248 null // don't do effects analysis again!
251 // 10th pass, calculate conflicts with reachability info
252 calculateConflicts(null, true);
255 // 11th pass, compiling locks
258 // 12th pass, compute a plan for code injections
259 methItr = descriptorsToAnalyze.iterator();
260 while (methItr.hasNext()) {
261 Descriptor d = methItr.next();
262 FlatMethod fm = state.getMethodFlat(d);
263 codePlansForward(fm);
267 // splice new IR nodes into graph after all
268 // analysis passes are complete
269 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
270 while (spliceItr.hasNext()) {
271 Map.Entry me = (Map.Entry) spliceItr.next();
272 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
273 fwdvn.spliceIntoIR();
277 if (state.OOODEBUG) {
280 disjointAnalysisTaints.getEffectsAnalysis().writeEffects("effects.txt");
281 writeConflictGraph();
282 } catch (IOException e) {}
286 System.out.println("\n\n\n##########################################################\n"+
287 "Warning, lots of code changes going on, OoOJava and RCR/DFJ\n"+
288 "systems are being cleaned up. Until the analyses and code gen\n"+
289 "are fully altered and coordinated, these systems will not run\n"+
290 "to completion. Partial stable check-ins are necessary to manage\n"+
291 "the number of files getting touched.\n"+
292 "##########################################################" );
300 * Iterator iter = sese2conflictGraph.entrySet().iterator(); while
301 * (iter.hasNext()) { Entry e = (Entry) iter.next(); FlatNode fn =
302 * (FlatNode) e.getKey(); ConflictGraph conflictGraph = (ConflictGraph)
304 * System.out.println("---------------------------------------");
305 * System.out.println("CONFLICT GRAPH for " + fn); Set<String> keySet =
306 * conflictGraph.id2cn.keySet(); for (Iterator iterator = keySet.iterator();
307 * iterator.hasNext();) { String key = (String) iterator.next();
308 * ConflictNode node = conflictGraph.id2cn.get(key);
309 * System.out.println("key=" + key + " \n" + node.toStringAllEffects()); } }
315 private void writeFile(Set<FlatNew> sitesToFlag) {
318 BufferedWriter bw = new BufferedWriter(new FileWriter("sitesToFlag.txt"));
320 for (Iterator iterator = sitesToFlag.iterator(); iterator.hasNext();) {
321 FlatNew fn = (FlatNew) iterator.next();
325 } catch (IOException e) {
332 private void livenessAnalysisBackward(FlatMethod fm) {
334 // flow backward across nodes to compute liveness, and
335 // take special care with sese enter/exit nodes that
336 // alter this from normal liveness analysis
337 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
338 flatNodesToVisit.add( fm.getFlatExit() );
340 while( !flatNodesToVisit.isEmpty() ) {
341 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
342 flatNodesToVisit.remove( fn );
344 Set<TempDescriptor> prev = livenessGlobalView.get( fn );
346 // merge sets from control flow joins
347 Set<TempDescriptor> livein = new HashSet<TempDescriptor>();
348 for (int i = 0; i < fn.numNext(); i++) {
349 FlatNode nn = fn.getNext( i );
350 Set<TempDescriptor> s = livenessGlobalView.get( nn );
356 Set<TempDescriptor> curr = liveness_nodeActions( fn, livein );
358 // if a new result, schedule backward nodes for analysis
359 if( !curr.equals( prev ) ) {
360 livenessGlobalView.put( fn, curr );
362 for( int i = 0; i < fn.numPrev(); i++ ) {
363 FlatNode nn = fn.getPrev( i );
364 flatNodesToVisit.add( nn );
370 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
371 Set<TempDescriptor> liveIn
373 switch( fn.kind() ) {
375 case FKind.FlatSESEEnterNode: {
376 // add whatever is live-in at a task enter to that
378 FlatSESEEnterNode fsen = (FlatSESEEnterNode)fn;
379 if( liveIn != null ) {
380 fsen.addInVarSet( liveIn );
382 // no break, should also execute default actions
386 // handle effects of statement in reverse, writes then reads
387 TempDescriptor[] writeTemps = fn.writesTemps();
388 for( int i = 0; i < writeTemps.length; ++i ) {
389 liveIn.remove( writeTemps[i] );
391 // if we are analyzing code declared directly in a task,
392 FlatSESEEnterNode fsen = rblockRel.getLocalInnerRBlock( fn );
394 // check to see if we are writing to variables that will
395 // be live-out at the task's exit (and therefore should
396 // go in the task's out-var set)
397 FlatSESEExitNode fsexn = fsen.getFlatExit();
398 Set<TempDescriptor> livetemps = livenessGlobalView.get( fsexn );
399 if( livetemps != null && livetemps.contains( writeTemps[i] ) ) {
400 fsen.addOutVar( writeTemps[i] );
405 TempDescriptor[] readTemps = fn.readsTemps();
406 for( int i = 0; i < readTemps.length; ++i ) {
407 liveIn.add( readTemps[i] );
410 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
411 if( virtualReadTemps != null ) {
412 liveIn.addAll( virtualReadTemps );
422 private void variableAnalysisForward(FlatMethod fm) {
424 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
425 flatNodesToVisit.add(fm);
427 while (!flatNodesToVisit.isEmpty()) {
428 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
429 flatNodesToVisit.remove(fn);
431 VarSrcTokTable prev = variableResults.get(fn);
433 // merge sets from control flow joins
434 VarSrcTokTable curr = new VarSrcTokTable();
435 for (int i = 0; i < fn.numPrev(); i++) {
436 FlatNode nn = fn.getPrev(i);
437 VarSrcTokTable incoming = variableResults.get(nn);
438 curr.merge(incoming);
441 FlatSESEEnterNode currentSESE = rblockRel.getLocalInnerRBlock( fn );
442 if( currentSESE == null ) {
443 currentSESE = rblockRel.getCallerProxySESE();
446 variable_nodeActions(fn, curr, currentSESE);
448 // if a new result, schedule forward nodes for analysis
449 if (!curr.equals(prev)) {
450 variableResults.put(fn, curr);
452 for (int i = 0; i < fn.numNext(); i++) {
453 FlatNode nn = fn.getNext(i);
454 flatNodesToVisit.add(nn);
460 private void variable_nodeActions(FlatNode fn,
461 VarSrcTokTable vstTable,
462 FlatSESEEnterNode currentSESE) {
466 case FKind.FlatSESEEnterNode: {
467 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
468 // ignore currently executing SESE, at this point
469 // the analysis considers a new instance is becoming
472 vstTable.assertConsistency();
476 case FKind.FlatSESEExitNode: {
477 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
479 // fsen is the child of currently executing tasks
480 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
482 // remap all of this child's children tokens to be
483 // from this child as the child exits
484 vstTable.remapChildTokens(fsen);
486 // liveness virtual reads are things that might be
487 // written by an SESE and should be added to the in-set
488 // anything virtually read by this SESE should be pruned
489 // of parent or sibling sources
490 Set<TempDescriptor> liveVars = livenessGlobalView.get(fn);
491 Set<TempDescriptor> fsenVirtReads =
492 vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(fsen,
495 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
496 if (fsenVirtReadsOld != null) {
497 fsenVirtReads.addAll(fsenVirtReadsOld);
499 livenessVirtualReads.put(fn, fsenVirtReads);
501 // then all child out-set tokens are guaranteed
502 // to be filled in, so clobber those entries with
503 // the latest, clean sources
504 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
505 while (outVarItr.hasNext()) {
506 TempDescriptor outVar = outVarItr.next();
507 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
509 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
510 vstTable.remove(outVar);
513 vstTable.assertConsistency();
517 case FKind.FlatOpNode: {
518 FlatOpNode fon = (FlatOpNode) fn;
520 if (fon.getOp().getOp() == Operation.ASSIGN) {
521 TempDescriptor lhs = fon.getDest();
522 TempDescriptor rhs = fon.getLeft();
524 vstTable.remove(lhs);
526 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
528 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
529 while (itr.hasNext()) {
530 VariableSourceToken vst = itr.next();
532 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
535 // when we do x = y for variables, just copy over from a child,
536 // there are two cases:
537 // 1. if the current task is the caller proxy, any local root is a child
539 currentSESE.getIsCallerProxySESE() &&
540 rblockRel.getLocalRootSESEs().contains( vst.getSESE() );
542 // 2. if the child task is a locally-defined child of the current task
543 boolean case2 = currentSESE.getLocalChildren().contains( vst.getSESE() );
545 if( case1 || case2 ) {
546 // if the source comes from a child, copy it over
547 forAddition.add( new VariableSourceToken( ts,
554 // otherwise, stamp it as us as the source
555 forAddition.add( new VariableSourceToken( ts,
564 vstTable.addAll( forAddition );
566 // only break if this is an ASSIGN op node,
567 // otherwise fall through to default case
568 vstTable.assertConsistency();
573 // note that FlatOpNode's that aren't ASSIGN
574 // fall through to this default case
576 TempDescriptor[] writeTemps = fn.writesTemps();
577 if( writeTemps.length > 0 ) {
579 // for now, when writeTemps > 1, make sure
580 // its a call node, programmer enforce only
581 // doing stuff like calling a print routine
582 if( writeTemps.length > 1 ) {
583 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
587 vstTable.remove( writeTemps[0] );
589 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
590 ts.add( writeTemps[0] );
592 vstTable.add( new VariableSourceToken( ts,
600 vstTable.assertConsistency();
607 private void notAvailableForward(FlatMethod fm) {
609 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
610 flatNodesToVisit.add(fm);
612 while (!flatNodesToVisit.isEmpty()) {
613 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
614 flatNodesToVisit.remove(fn);
616 Set<TempDescriptor> prev = notAvailableResults.get(fn);
618 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
619 for (int i = 0; i < fn.numPrev(); i++) {
620 FlatNode nn = fn.getPrev(i);
621 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
622 if (notAvailIn != null) {
623 curr.addAll(notAvailIn);
627 FlatSESEEnterNode currentSESE = rblockRel.getLocalInnerRBlock( fn );
628 if( currentSESE == null ) {
629 currentSESE = rblockRel.getCallerProxySESE();
632 notAvailable_nodeActions(fn, curr, currentSESE);
634 // if a new result, schedule forward nodes for analysis
635 if (!curr.equals(prev)) {
636 notAvailableResults.put(fn, curr);
638 for (int i = 0; i < fn.numNext(); i++) {
639 FlatNode nn = fn.getNext(i);
640 flatNodesToVisit.add(nn);
646 private void notAvailable_nodeActions(FlatNode fn,
647 Set<TempDescriptor> notAvailSet,
648 FlatSESEEnterNode currentSESE
651 // any temps that are removed from the not available set
652 // at this node should be marked in this node's code plan
653 // as temps to be grabbed at runtime!
657 case FKind.FlatSESEEnterNode: {
658 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
660 // keep a copy of what's not available into the SESE
661 // and restore it at the matching exit node
662 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
663 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
664 while (tdItr.hasNext()) {
665 notAvailCopy.add(tdItr.next());
667 notAvailableIntoSESE.put(fsen, notAvailCopy);
672 case FKind.FlatSESEExitNode: {
673 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
674 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
676 notAvailSet.addAll(fsen.getOutVarSet());
678 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
679 assert notAvailIn != null;
680 notAvailSet.addAll(notAvailIn);
683 case FKind.FlatMethod: {
687 case FKind.FlatOpNode: {
688 FlatOpNode fon = (FlatOpNode) fn;
690 if (fon.getOp().getOp() == Operation.ASSIGN) {
691 TempDescriptor lhs = fon.getDest();
692 TempDescriptor rhs = fon.getLeft();
694 // copy makes lhs same availability as rhs
695 if (notAvailSet.contains(rhs)) {
696 notAvailSet.add(lhs);
698 notAvailSet.remove(lhs);
701 // only break if this is an ASSIGN op node,
702 // otherwise fall through to default case
707 // note that FlatOpNode's that aren't ASSIGN
708 // fall through to this default case
710 TempDescriptor[] writeTemps = fn.writesTemps();
711 for (int i = 0; i < writeTemps.length; i++) {
712 TempDescriptor wTemp = writeTemps[i];
713 notAvailSet.remove(wTemp);
715 TempDescriptor[] readTemps = fn.readsTemps();
716 for (int i = 0; i < readTemps.length; i++) {
717 TempDescriptor rTemp = readTemps[i];
718 notAvailSet.remove(rTemp);
720 // if this variable has exactly one source, potentially
721 // get other things from this source as well
722 VarSrcTokTable vstTable = variableResults.get(fn);
724 VSTWrapper vstIfStatic = new VSTWrapper();
725 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
727 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
729 VariableSourceToken vst = vstIfStatic.vst;
731 Iterator<VariableSourceToken> availItr =
732 vstTable.get(vst.getSESE(), vst.getAge()).iterator();
734 // look through things that are also available from same source
735 while (availItr.hasNext()) {
736 VariableSourceToken vstAlsoAvail = availItr.next();
738 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
739 while (refVarItr.hasNext()) {
740 TempDescriptor refVarAlso = refVarItr.next();
742 // if a variable is available from the same source, AND it ALSO
743 // only comes from one statically known source, mark it available
744 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
745 Integer srcTypeAlso =
746 vstTable.getRefVarSrcType(refVarAlso, currentSESE, vstIfStaticNotUsed);
747 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
748 notAvailSet.remove(refVarAlso);
760 private void codePlansForward(FlatMethod fm) {
762 // start from flat method top, visit every node in
763 // method exactly once
764 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
765 flatNodesToVisit.add(fm);
767 Set<FlatNode> visited = new HashSet<FlatNode>();
769 while (!flatNodesToVisit.isEmpty()) {
770 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
771 FlatNode fn = fnItr.next();
773 flatNodesToVisit.remove(fn);
776 // use incoming results as "dot statement" or just
777 // before the current statement
778 VarSrcTokTable dotSTtable = new VarSrcTokTable();
779 for (int i = 0; i < fn.numPrev(); i++) {
780 FlatNode nn = fn.getPrev(i);
781 dotSTtable.merge(variableResults.get(nn));
784 // find dt-st notAvailableSet also
785 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
786 for (int i = 0; i < fn.numPrev(); i++) {
787 FlatNode nn = fn.getPrev(i);
788 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
789 if (notAvailIn != null) {
790 dotSTnotAvailSet.addAll(notAvailIn);
794 Set<TempDescriptor> dotSTlive = livenessGlobalView.get(fn);
796 FlatSESEEnterNode currentSESE = rblockRel.getLocalInnerRBlock( fn );
797 if( currentSESE == null ) {
798 currentSESE = rblockRel.getCallerProxySESE();
801 codePlans_nodeActions(fm, fn,
802 dotSTlive, dotSTtable, dotSTnotAvailSet,
805 for (int i = 0; i < fn.numNext(); i++) {
806 FlatNode nn = fn.getNext(i);
808 if (!visited.contains(nn)) {
809 flatNodesToVisit.add(nn);
815 private void codePlans_nodeActions(FlatMethod fm,
817 Set<TempDescriptor> liveSetIn,
818 VarSrcTokTable vstTableIn,
819 Set<TempDescriptor> notAvailSetIn,
820 FlatSESEEnterNode currentSESE) {
822 CodePlan plan = new CodePlan(currentSESE);
826 case FKind.FlatSESEEnterNode: {
827 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
829 // track the source types of the in-var set so generated
830 // code at this SESE issue can compute the number of
831 // dependencies properly
832 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
833 while (inVarItr.hasNext()) {
834 TempDescriptor inVar = inVarItr.next();
836 // when we get to an SESE enter node we change the
837 // currentSESE variable of this analysis to the
838 // child that is declared by the enter node, so
839 // in order to classify in-vars correctly, pass
840 // the parent SESE in--at other FlatNode types just
841 // use the currentSESE
842 FlatSESEEnterNode parent = rblockRel.getLocalInnerRBlock( fn );
843 if( parent == null ) {
844 parent = rblockRel.getCallerProxySESE();
847 VSTWrapper vstIfStatic = new VSTWrapper();
848 Integer srcType = vstTableIn.getRefVarSrcType(inVar, parent, vstIfStatic);
850 // the current SESE needs a local space to track the dynamic
851 // variable and the child needs space in its SESE record
852 if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
853 fsen.addDynamicInVar(inVar);
854 addDynamicVar( fsen, fm, inVar );
856 } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
857 fsen.addStaticInVar(inVar);
858 VariableSourceToken vst = vstIfStatic.vst;
859 fsen.putStaticInVar2src(inVar, vst);
860 fsen.addStaticInVarSrc(new SESEandAgePair(vst.getSESE(), vst.getAge()));
862 assert srcType.equals(VarSrcTokTable.SrcType_READY);
863 fsen.addReadyInVar(inVar);
868 case FKind.FlatSESEExitNode: {
869 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
870 //TODO! Shouldn't there be a code plan for task exit
871 // where the exiting task calculates whether its own
872 // siblings need variables from its children, so the
873 // exiter should copy those variables into its own out-set
874 // and make the available?
877 case FKind.FlatOpNode: {
878 FlatOpNode fon = (FlatOpNode) fn;
880 if (fon.getOp().getOp() == Operation.ASSIGN) {
881 TempDescriptor lhs = fon.getDest();
882 TempDescriptor rhs = fon.getLeft();
884 // if this is an op node, don't stall, copy
885 // source and delay until we need to use value
887 // ask whether lhs and rhs sources are dynamic, static, etc.
888 VSTWrapper vstIfStatic = new VSTWrapper();
889 Integer lhsSrcType = vstTableIn.getRefVarSrcType(lhs, currentSESE, vstIfStatic);
890 Integer rhsSrcType = vstTableIn.getRefVarSrcType(rhs, currentSESE, vstIfStatic);
892 if (rhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
893 // if rhs is dynamic going in, lhs will definitely be dynamic
894 // going out of this node, so track that here
895 plan.addDynAssign( lhs, rhs );
896 addDynamicVar( currentSESE, fm, lhs );
897 addDynamicVar( currentSESE, fm, rhs );
899 } else if (lhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
900 // otherwise, if the lhs is dynamic, but the rhs is not, we
901 // need to update the variable's dynamic source as "current SESE"
902 plan.addDynAssign(lhs);
905 // only break if this is an ASSIGN op node,
906 // otherwise fall through to default case
911 // note that FlatOpNode's that aren't ASSIGN
912 // fall through to this default case
915 // a node with no live set has nothing to stall for
916 if (liveSetIn == null) {
920 TempDescriptor[] readarray = fn.readsTemps();
921 for (int i = 0; i < readarray.length; i++) {
922 TempDescriptor readtmp = readarray[i];
924 // ignore temps that are definitely available
925 // when considering to stall on it
926 if (!notAvailSetIn.contains(readtmp)) {
930 // check the source type of this variable
931 VSTWrapper vstIfStatic = new VSTWrapper();
932 Integer srcType = vstTableIn.getRefVarSrcType(readtmp, currentSESE, vstIfStatic);
934 if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
935 // 1) It is not clear statically where this variable will
936 // come from, so dynamically we must keep track
937 // along various control paths, and therefore when we stall,
938 // just stall for the exact thing we need and move on
939 plan.addDynamicStall( readtmp );
940 addDynamicVar( currentSESE, fm, readtmp );
942 } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
943 // 2) Single token/age pair: Stall for token/age pair, and copy
944 // all live variables with same token/age pair at the same
945 // time. This is the same stuff that the notavaialable analysis
946 // marks as now available.
947 VariableSourceToken vst = vstIfStatic.vst;
949 Iterator<VariableSourceToken> availItr =
950 vstTableIn.get(vst.getSESE(), vst.getAge()).iterator();
952 while (availItr.hasNext()) {
953 VariableSourceToken vstAlsoAvail = availItr.next();
955 // only grab additional stuff that is live
956 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
958 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
959 while (refVarItr.hasNext()) {
960 TempDescriptor refVar = refVarItr.next();
961 if (liveSetIn.contains(refVar)) {
966 if (!copySet.isEmpty()) {
967 plan.addStall2CopySet(vstAlsoAvail, copySet);
972 // the other case for srcs is READY, so do nothing
975 // assert that everything being stalled for is in the
976 // "not available" set coming into this flat node and
977 // that every VST identified is in the possible "stall set"
978 // that represents VST's from children SESE's
986 // identify sese-age pairs that are statically useful
987 // and should have an associated SESE variable in code
988 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
989 // AND ALWAYS GIVE NAMES TO LOCAL PARENTS
990 Set<VariableSourceToken> staticSet = vstTableIn.get();
991 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
992 while (vstItr.hasNext()) {
993 VariableSourceToken vst = vstItr.next();
995 // the caller proxy generates useful analysis facts, but we
996 // never need to generate another name for it in code (it is
997 // ALWAYS the task executing the local method context)
998 if( vst.getSESE().getIsCallerProxySESE() ) {
1002 SESEandAgePair sap = new SESEandAgePair( vst.getSESE(), vst.getAge() );
1003 sap.getSESE().mustTrackAtLeastAge( sap.getAge() );
1005 FlatSESEEnterNode sese = currentSESE;
1006 while( sese != null ) {
1007 addNeededStaticName( sese, fm, sap );
1008 sese = sese.getLocalParent();
1012 codePlans.put(fn, plan);
1014 // if any variables at this-node-*dot* have a static source (exactly one
1016 // but go to a dynamic source at next-node-*dot*, create a new IR graph
1017 // node on that edge to track the sources dynamically
1018 VarSrcTokTable thisVstTable = variableResults.get(fn);
1019 for (int i = 0; i < fn.numNext(); i++) {
1020 FlatNode nn = fn.getNext(i);
1021 VarSrcTokTable nextVstTable = variableResults.get(nn);
1022 Set<TempDescriptor> nextLiveIn = livenessGlobalView.get(nn);
1024 // the table can be null if it is one of the few IR nodes
1025 // completely outside of the root SESE scope
1026 if (nextVstTable != null && nextLiveIn != null) {
1028 Hashtable<TempDescriptor, VSTWrapper> readyOrStatic2dynamicSet =
1029 thisVstTable.getReadyOrStatic2DynamicSet(nextVstTable, nextLiveIn, currentSESE);
1031 if (!readyOrStatic2dynamicSet.isEmpty()) {
1033 // either add these results to partial fixed-point result
1034 // or make a new one if we haven't made any here yet
1035 FlatEdge fe = new FlatEdge(fn, nn);
1036 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get(fe);
1038 if (fwdvn == null) {
1039 fwdvn = new FlatWriteDynamicVarNode(fn, nn, readyOrStatic2dynamicSet, currentSESE);
1040 wdvNodesToSpliceIn.put(fe, fwdvn);
1042 fwdvn.addMoreVar2Src(readyOrStatic2dynamicSet);
1049 private void addDynamicVar( FlatSESEEnterNode fsen,
1051 TempDescriptor var ) {
1054 if( fsen.getIsCallerProxySESE() ) {
1055 // attach the dynamic variable to track to
1056 // the flat method, so it can be declared at entry
1059 // otherwise the code context is a task body
1063 ContextTaskNames ctn = fn2contextTaskNames.get( fnContext );
1065 ctn = new ContextTaskNames();
1068 ctn.addDynamicVar( var );
1069 fn2contextTaskNames.put( fnContext, ctn );
1072 private void addNeededStaticName( FlatSESEEnterNode fsen,
1074 SESEandAgePair sap ) {
1077 if( fsen.getIsCallerProxySESE() ) {
1078 // attach the dynamic variable to track to
1079 // the flat method, so it can be declared at entry
1082 // otherwise the code context is a task body
1086 ContextTaskNames ctn = fn2contextTaskNames.get( fnContext );
1088 ctn = new ContextTaskNames();
1091 ctn.addNeededStaticName( sap );
1093 fn2contextTaskNames.put( fnContext, ctn );
1097 private void makeConflictGraph(FlatMethod fm) {
1099 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1100 flatNodesToVisit.add(fm);
1102 Set<FlatNode> visited = new HashSet<FlatNode>();
1104 while (!flatNodesToVisit.isEmpty()) {
1105 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
1106 flatNodesToVisit.remove(fn);
1109 Set<FlatSESEEnterNode> currentSESEs =
1110 rblockRel.getPossibleExecutingRBlocks( fn );
1112 conflictGraph_nodeAction(fn, currentSESEs);
1114 // schedule forward nodes for analysis
1115 for (int i = 0; i < fn.numNext(); i++) {
1116 FlatNode nn = fn.getNext(i);
1117 if (!visited.contains(nn)) {
1118 flatNodesToVisit.add(nn);
1126 private void conflictGraph_nodeAction(FlatNode fn,
1127 Set<FlatSESEEnterNode> currentSESEs
1129 ConflictGraph conflictGraph;
1133 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
1136 switch (fn.kind()) {
1139 case FKind.FlatFieldNode:
1140 case FKind.FlatElementNode: {
1142 if (fn instanceof FlatFieldNode) {
1143 FlatFieldNode ffn = (FlatFieldNode) fn;
1146 FlatElementNode fen = (FlatElementNode) fn;
1150 for( Iterator<FlatSESEEnterNode> itr = currentSESEs.iterator();
1153 FlatSESEEnterNode currentSESE = itr.next();
1155 conflictGraph = sese2conflictGraph.get(currentSESE);
1156 if (conflictGraph == null) {
1157 conflictGraph = new ConflictGraph(state);
1161 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1162 conflictGraph.addStallSite(taint2Effects, rhs);
1164 if (conflictGraph.id2cn.size() > 0) {
1165 sese2conflictGraph.put(currentSESE, conflictGraph);
1171 case FKind.FlatSetFieldNode:
1172 case FKind.FlatSetElementNode: {
1174 if (fn instanceof FlatSetFieldNode) {
1175 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
1176 lhs = fsfn.getDst();
1177 rhs = fsfn.getSrc();
1179 FlatSetElementNode fsen = (FlatSetElementNode) fn;
1180 lhs = fsen.getDst();
1181 rhs = fsen.getSrc();
1184 for( Iterator<FlatSESEEnterNode> itr = currentSESEs.iterator();
1187 FlatSESEEnterNode currentSESE = itr.next();
1189 conflictGraph = sese2conflictGraph.get(currentSESE);
1190 if (conflictGraph == null) {
1191 conflictGraph = new ConflictGraph(state);
1194 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1195 conflictGraph.addStallSite(taint2Effects, rhs);
1196 conflictGraph.addStallSite(taint2Effects, lhs);
1198 if (conflictGraph.id2cn.size() > 0) {
1199 sese2conflictGraph.put(currentSESE, conflictGraph);
1205 case FKind.FlatCall: {
1206 FlatCall fc = (FlatCall) fn;
1209 for( Iterator<FlatSESEEnterNode> itr = currentSESEs.iterator();
1212 FlatSESEEnterNode currentSESE = itr.next();
1214 conflictGraph = sese2conflictGraph.get(currentSESE);
1215 if (conflictGraph == null) {
1216 conflictGraph = new ConflictGraph(state);
1219 // collects effects of stall site and generates stall site node
1220 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1222 conflictGraph.addStallSite(taint2Effects, lhs);
1223 if (conflictGraph.id2cn.size() > 0) {
1224 sese2conflictGraph.put(currentSESE, conflictGraph);
1233 private void calculateConflicts( Set<FlatNew> sitesToFlag,
1234 boolean useReachInfo ) {
1236 // decide fine-grain edge or coarse-grain edge among all vertexes by
1237 // pair-wise comparison
1238 Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
1239 while (seseIter.hasNext()) {
1240 FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
1241 ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
1244 // clear current conflict before recalculating with reachability info
1245 conflictGraph.clearAllConflictEdge();
1246 conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
1247 conflictGraph.setFMEnclosing(sese.getfmEnclosing());
1249 conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
1250 sese2conflictGraph.put(sese, conflictGraph);
1255 private void writeConflictGraph() {
1256 Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
1257 while (keyEnum.hasMoreElements()) {
1258 FlatNode key = (FlatNode) keyEnum.nextElement();
1259 ConflictGraph cg = sese2conflictGraph.get(key);
1261 if (cg.hasConflictEdge()) {
1262 cg.writeGraph("ConflictGraphFor" + key, false);
1264 } catch (IOException e) {
1265 System.out.println("Error writing");
1271 private void synthesizeLocks() {
1272 Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
1273 for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
1274 Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
1275 FlatNode sese = graphEntry.getKey();
1276 ConflictGraph conflictGraph = graphEntry.getValue();
1277 calculateCovering(conflictGraph);
1281 private void calculateCovering(ConflictGraph conflictGraph) {
1282 uniqueLockSetId = 0; // reset lock counter for every new conflict graph
1283 HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
1284 HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
1285 HashSet<SESELock> lockSet = new HashSet<SESELock>();
1287 Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
1288 for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
1289 ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
1290 if (conflictEdge.isCoarseEdge()) {
1291 coarseToCover.add(conflictEdge);
1293 fineToCover.add(conflictEdge);
1297 HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
1298 toCover.addAll(fineToCover);
1299 toCover.addAll(coarseToCover);
1301 while (!toCover.isEmpty()) {
1303 SESELock seseLock = new SESELock();
1304 seseLock.setID(uniqueLockSetId++);
1308 do { // fine-grained edge
1312 for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
1315 ConflictEdge edge = (ConflictEdge) iterator.next();
1316 if (seseLock.getConflictNodeSet().size() == 0) {
1318 if (seseLock.isWriteNode(edge.getVertexU())) {
1319 // mark as fine_write
1320 if (edge.getVertexU().isStallSiteNode()) {
1321 type = ConflictNode.PARENT_WRITE;
1323 type = ConflictNode.FINE_WRITE;
1325 seseLock.addConflictNode(edge.getVertexU(), type);
1327 // mark as fine_read
1328 if (edge.getVertexU().isStallSiteNode()) {
1329 type = ConflictNode.PARENT_READ;
1331 type = ConflictNode.FINE_READ;
1333 seseLock.addConflictNode(edge.getVertexU(), type);
1335 if (edge.getVertexV() != edge.getVertexU()) {
1336 if (seseLock.isWriteNode(edge.getVertexV())) {
1337 // mark as fine_write
1338 if (edge.getVertexV().isStallSiteNode()) {
1339 type = ConflictNode.PARENT_WRITE;
1341 type = ConflictNode.FINE_WRITE;
1343 seseLock.addConflictNode(edge.getVertexV(), type);
1345 // mark as fine_read
1346 if (edge.getVertexV().isStallSiteNode()) {
1347 type = ConflictNode.PARENT_READ;
1349 type = ConflictNode.FINE_READ;
1351 seseLock.addConflictNode(edge.getVertexV(), type);
1355 seseLock.addConflictEdge(edge);
1356 fineToCover.remove(edge);
1357 break;// exit iterator loop
1358 }// end of initial setup
1360 ConflictNode newNode;
1361 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1362 // new node has a fine-grained edge to all current node
1363 // If there is a coarse grained edge where need a fine edge, it's
1364 // okay to add the node
1365 // but the edge must remain uncovered.
1369 if (seseLock.containsConflictNode(newNode)) {
1370 seseLock.addEdge(edge);
1371 fineToCover.remove(edge);
1375 if (seseLock.isWriteNode(newNode)) {
1376 if (newNode.isStallSiteNode()) {
1377 type = ConflictNode.PARENT_WRITE;
1379 type = ConflictNode.FINE_WRITE;
1381 seseLock.setNodeType(newNode, type);
1383 if (newNode.isStallSiteNode()) {
1384 type = ConflictNode.PARENT_READ;
1386 type = ConflictNode.FINE_READ;
1388 seseLock.setNodeType(newNode, type);
1391 seseLock.addEdge(edge);
1392 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1393 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1394 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1396 // mark all fine edges between new node and nodes in the group as
1398 if (!conflictEdge.getVertexU().equals(newNode)) {
1399 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1401 seseLock.addConflictEdge(conflictEdge);
1402 fineToCover.remove(conflictEdge);
1404 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1405 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1407 seseLock.addConflictEdge(conflictEdge);
1408 fineToCover.remove(conflictEdge);
1414 break;// exit iterator loop
1419 HashSet<ConflictEdge> notCovered=new HashSet<ConflictEdge>();
1423 for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
1425 ConflictEdge edge = (ConflictEdge) iterator.next();
1426 if (seseLock.getConflictNodeSet().size() == 0) {
1428 if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
1429 // node has a coarse-grained edge with itself
1430 if (!(edge.getVertexU().isStallSiteNode())) {
1431 // and it is not parent
1432 type = ConflictNode.SCC;
1435 type = ConflictNode.PARENT_COARSE;
1437 type = ConflictNode.PARENT_WRITE;
1440 seseLock.addConflictNode(edge.getVertexU(), type);
1442 if (edge.getVertexU().isStallSiteNode()) {
1444 type = ConflictNode.PARENT_COARSE;
1446 if (edge.getVertexU().getWriteEffectSet().isEmpty()) {
1447 type = ConflictNode.PARENT_READ;
1449 type = ConflictNode.PARENT_WRITE;
1453 type = ConflictNode.COARSE;
1455 seseLock.addConflictNode(edge.getVertexU(), type);
1457 if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
1458 // node has a coarse-grained edge with itself
1459 if (!(edge.getVertexV().isStallSiteNode())) {
1460 // and it is not parent
1461 type = ConflictNode.SCC;
1464 type = ConflictNode.PARENT_COARSE;
1466 type = ConflictNode.PARENT_WRITE;
1469 seseLock.addConflictNode(edge.getVertexV(), type);
1471 if (edge.getVertexV().isStallSiteNode()) {
1473 type = ConflictNode.PARENT_COARSE;
1475 if (edge.getVertexV().getWriteEffectSet().isEmpty()) {
1476 type = ConflictNode.PARENT_READ;
1478 type = ConflictNode.PARENT_WRITE;
1482 type = ConflictNode.COARSE;
1484 seseLock.addConflictNode(edge.getVertexV(), type);
1487 coarseToCover.remove(edge);
1488 seseLock.addConflictEdge(edge);
1489 break;// exit iterator loop
1490 }// end of initial setup
1492 ConflictNode newNode;
1493 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1494 // new node has a coarse-grained edge to all fine-read, fine-write,
1498 if (newNode.isInVarNode() && (!seseLock.hasSelfCoarseEdge(newNode))
1499 && seseLock.hasCoarseEdgeWithParentCoarse(newNode)) {
1500 // this case can't be covered by this queue
1501 coarseToCover.remove(edge);
1502 notCovered.add(edge);
1506 if (seseLock.containsConflictNode(newNode)) {
1507 seseLock.addEdge(edge);
1508 coarseToCover.remove(edge);
1512 if (seseLock.hasSelfCoarseEdge(newNode)) {
1514 if (newNode.isStallSiteNode()) {
1515 type = ConflictNode.PARENT_COARSE;
1517 type = ConflictNode.SCC;
1519 seseLock.setNodeType(newNode, type);
1521 if (newNode.isStallSiteNode()) {
1522 type = ConflictNode.PARENT_COARSE;
1524 type = ConflictNode.COARSE;
1526 seseLock.setNodeType(newNode, type);
1529 seseLock.addEdge(edge);
1530 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1531 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1532 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1533 // mark all coarse edges between new node and nodes in the group
1535 if (!conflictEdge.getVertexU().equals(newNode)) {
1536 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1538 seseLock.addConflictEdge(conflictEdge);
1539 coarseToCover.remove(conflictEdge);
1541 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1542 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1544 seseLock.addConflictEdge(conflictEdge);
1545 coarseToCover.remove(conflictEdge);
1550 break;// exit iterator loop
1556 lockSet.add(seseLock);
1559 coarseToCover.addAll(notCovered);
1560 toCover.addAll(fineToCover);
1561 toCover.addAll(coarseToCover);
1565 conflictGraph2SESELock.put(conflictGraph, lockSet);
1568 public ConflictGraph getConflictGraph(FlatNode sese) {
1569 return sese2conflictGraph.get(sese);
1572 public Set<SESELock> getLockMappings(ConflictGraph graph) {
1573 return conflictGraph2SESELock.get(graph);
1576 public Set<FlatSESEEnterNode> getAllSESEs() {
1577 return rblockRel.getAllSESEs();
1580 public FlatSESEEnterNode getMainSESE() {
1581 return rblockRel.getMainSESE();
1584 public FlatSESEEnterNode getCallerProxySESE() {
1585 return rblockRel.getCallerProxySESE();
1589 public void writeReports(String timeReport) throws java.io.IOException {
1591 BufferedWriter bw = new BufferedWriter(new FileWriter("ooojReport_summary.txt"));
1592 bw.write("OoOJava Analysis Results\n\n");
1593 bw.write(timeReport + "\n\n");
1594 printSESEHierarchy(bw);
1599 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
1600 while (methItr.hasNext()) {
1601 MethodDescriptor md = methItr.next();
1602 FlatMethod fm = state.getMethodFlat(md);
1604 bw = new BufferedWriter(new FileWriter("ooojReport_" +
1605 md.getClassMethodName() +
1606 md.getSafeMethodDescriptor() +
1608 bw.write("OoOJava Results for " + md + "\n-------------------\n");
1610 bw.write("Dynamic vars to manage:\n " + getContextTaskNames( fm ).getDynamicVarSet() );
1612 bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessGlobalView));
1613 bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
1614 bw.write("\n\nNot Available Results-Out\n---------------------\n" + fm.printMethod(notAvailableResults));
1615 bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
1621 private void printSESEHierarchy(BufferedWriter bw) throws java.io.IOException {
1622 bw.write("SESE Local Hierarchy\n--------------\n");
1623 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getLocalRootSESEs().iterator();
1624 while (rootItr.hasNext()) {
1625 FlatSESEEnterNode root = rootItr.next();
1626 printSESEHierarchyTree(bw, root, 0);
1630 private void printSESEHierarchyTree(BufferedWriter bw,
1631 FlatSESEEnterNode fsen,
1633 ) throws java.io.IOException {
1634 for (int i = 0; i < depth; ++i) {
1637 bw.write("- " + fsen.getPrettyIdentifier() + "\n");
1639 Iterator<FlatSESEEnterNode> childItr = fsen.getLocalChildren().iterator();
1640 while (childItr.hasNext()) {
1641 FlatSESEEnterNode fsenChild = childItr.next();
1642 printSESEHierarchyTree(bw, fsenChild, depth + 1);
1646 private void printSESEInfo(BufferedWriter bw) throws java.io.IOException {
1647 bw.write("\nSESE info\n-------------\n");
1648 Iterator<FlatSESEEnterNode> fsenItr = rblockRel.getAllSESEs().iterator();
1649 while( fsenItr.hasNext() ) {
1650 FlatSESEEnterNode fsen = fsenItr.next();
1652 bw.write("SESE " + fsen.getPrettyIdentifier());
1653 if( fsen.getIsLeafSESE() ) {
1654 bw.write(" (leaf)");
1658 bw.write(" in-set: " + fsen.getInVarSet() + "\n");
1659 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1660 while (tItr.hasNext()) {
1661 TempDescriptor inVar = tItr.next();
1662 if (fsen.getReadyInVarSet().contains(inVar)) {
1663 bw.write(" (ready) " + inVar + "\n");
1665 if (fsen.getStaticInVarSet().contains(inVar)) {
1666 bw.write(" (static) " + inVar + " from " + fsen.getStaticInVarSrc(inVar) + "\n");
1668 if (fsen.getDynamicInVarSet().contains(inVar)) {
1669 bw.write(" (dynamic)" + inVar + "\n");
1673 bw.write(" Dynamic vars to manage: " + getContextTaskNames( fsen ).getDynamicVarSet() + "\n");
1675 bw.write(" out-set: " + fsen.getOutVarSet() + "\n");
1677 bw.write(" local parent: " + fsen.getLocalParent() + "\n");
1678 bw.write(" local children: " + fsen.getLocalChildren() + "\n");
1680 bw.write(" possible parents: " + fsen.getParents() + "\n");
1681 bw.write(" possible children: " + fsen.getChildren() + "\n");