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;
22 import Analysis.MLP.CodePlan;
23 import Analysis.MLP.SESEandAgePair;
24 import Analysis.MLP.VSTWrapper;
25 import Analysis.MLP.VarSrcTokTable;
26 import Analysis.MLP.VariableSourceToken;
28 import IR.MethodDescriptor;
33 import IR.Flat.FlatCall;
34 import IR.Flat.FlatEdge;
35 import IR.Flat.FlatElementNode;
36 import IR.Flat.FlatFieldNode;
37 import IR.Flat.FlatMethod;
38 import IR.Flat.FlatNew;
39 import IR.Flat.FlatNode;
40 import IR.Flat.FlatOpNode;
41 import IR.Flat.FlatSESEEnterNode;
42 import IR.Flat.FlatSESEExitNode;
43 import IR.Flat.FlatSetElementNode;
44 import IR.Flat.FlatSetFieldNode;
45 import IR.Flat.FlatWriteDynamicVarNode;
46 import IR.Flat.TempDescriptor;
48 public class OoOJavaAnalysis {
50 // data from the compiler
52 private TypeUtil typeUtil;
53 private CallGraph callGraph;
54 private RBlockRelationAnalysis rblockRel;
55 private RBlockStatusAnalysis rblockStatus;
56 private DisjointAnalysis disjointAnalysisTaints;
57 private DisjointAnalysis disjointAnalysisReach;
59 private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
60 private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
61 private Hashtable<FlatNode, VarSrcTokTable> variableResults;
62 private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
63 private Hashtable<FlatNode, CodePlan> codePlans;
65 private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
67 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
69 // temporal data structures to track analysis progress.
70 static private int uniqueLockSetId = 0;
71 // mapping of a conflict graph to its compiled lock
72 private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
73 // mapping of a sese block to its conflict graph
74 private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
76 public static int maxSESEage = -1;
78 public int getMaxSESEage() {
83 public CodePlan getCodePlan(FlatNode fn) {
84 CodePlan cp = codePlans.get(fn);
88 public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
89 ArrayReferencees arrayReferencees) {
91 double timeStartAnalysis = (double) System.nanoTime();
94 this.typeUtil = typeUtil;
95 this.callGraph = callGraph;
96 this.maxSESEage = state.MLP_MAXSESEAGE;
98 livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
99 livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
100 variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
101 notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
102 codePlans = new Hashtable<FlatNode, CodePlan>();
103 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
105 notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
107 sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
108 conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
110 // add all methods transitively reachable from the
111 // source's main to set for analysis
112 MethodDescriptor mdSourceEntry = typeUtil.getMain();
113 FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
115 Set<MethodDescriptor> descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
117 descriptorsToAnalyze.add(mdSourceEntry);
119 // 1st pass, find basic rblock relations & status
120 rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
121 rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
123 // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
124 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
125 while (rootItr.hasNext()) {
126 FlatSESEEnterNode root = rootItr.next();
127 livenessAnalysisBackward(root, true, null);
130 // 3rd pass, variable analysis
131 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
132 while (methItr.hasNext()) {
133 Descriptor d = methItr.next();
134 FlatMethod fm = state.getMethodFlat(d);
136 // starting from roots do a forward, fixed-point
137 // variable analysis for refinement and stalls
138 variableAnalysisForward(fm);
141 // 4th pass, compute liveness contribution from
142 // virtual reads discovered in variable pass
143 rootItr = rblockRel.getRootSESEs().iterator();
144 while (rootItr.hasNext()) {
145 FlatSESEEnterNode root = rootItr.next();
146 livenessAnalysisBackward(root, true, null);
149 // 5th pass, use disjointness with NO FLAGGED REGIONS
150 // to compute taints and effects
151 disjointAnalysisTaints =
152 new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, null,
153 rblockRel, rblockStatus,
154 true ); // suppress output--this is an intermediate pass
156 // 6th pass, not available analysis FOR VARIABLES!
157 methItr = descriptorsToAnalyze.iterator();
158 while (methItr.hasNext()) {
159 Descriptor d = methItr.next();
160 FlatMethod fm = state.getMethodFlat(d);
162 // compute what is not available at every program
163 // point, in a forward fixed-point pass
164 notAvailableForward(fm);
167 // 7th pass, make conflict graph
168 // conflict graph is maintained by each parent sese,
169 Iterator descItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
170 while (descItr.hasNext()) {
171 Descriptor d = (Descriptor) descItr.next();
172 FlatMethod fm = state.getMethodFlat(d);
174 makeConflictGraph(fm);
179 * Iterator iter = sese2conflictGraph.entrySet().iterator(); while
180 * (iter.hasNext()) { Entry e = (Entry) iter.next(); FlatNode fn =
181 * (FlatNode) e.getKey(); ConflictGraph conflictGraph = (ConflictGraph)
183 * System.out.println("---------------------------------------");
184 * System.out.println("CONFLICT GRAPH for " + fn); Set<String> keySet =
185 * conflictGraph.id2cn.keySet(); for (Iterator iterator = keySet.iterator();
186 * iterator.hasNext();) { String key = (String) iterator.next();
187 * ConflictNode node = conflictGraph.id2cn.get(key);
188 * System.out.println("key=" + key + " \n" + node.toStringAllEffects()); } }
191 // 8th pass, calculate all possible conflicts without using reachability
193 // and identify set of FlatNew that next disjoint reach. analysis should
195 Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
196 calculateConflicts(sitesToFlag, false);
200 // 9th pass, ask disjoint analysis to compute reachability
201 // for objects that may cause heap conflicts so the most
202 // efficient method to deal with conflict can be computed
205 disjointAnalysisReach =
206 new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, sitesToFlag,
207 null, // don't do effects analysis again!
208 null // don't do effects analysis again!
210 // 10th pass, calculate conflicts with reachability info
211 calculateConflicts(null, true);
213 // 11th pass, compiling locks
216 // 12th pass, compute a plan for code injections
217 methItr = descriptorsToAnalyze.iterator();
218 while (methItr.hasNext()) {
219 Descriptor d = methItr.next();
220 FlatMethod fm = state.getMethodFlat(d);
221 codePlansForward(fm);
225 // splice new IR nodes into graph after all
226 // analysis passes are complete
227 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
228 while (spliceItr.hasNext()) {
229 Map.Entry me = (Map.Entry) spliceItr.next();
230 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
231 fwdvn.spliceIntoIR();
234 if (state.OOODEBUG) {
237 disjointAnalysisTaints.getEffectsAnalysis().writeEffects("effects.txt");
238 writeConflictGraph();
239 } catch (IOException e) {
245 private void writeFile(Set<FlatNew> sitesToFlag) {
248 BufferedWriter bw = new BufferedWriter(new FileWriter("sitesToFlag.txt"));
250 for (Iterator iterator = sitesToFlag.iterator(); iterator.hasNext();) {
251 FlatNew fn = (FlatNew) iterator.next();
255 } catch (IOException e) {
261 private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
262 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
264 // start from an SESE exit, visit nodes in reverse up to
265 // SESE enter in a fixed-point scheme, where children SESEs
266 // should already be analyzed and therefore can be skipped
267 // because child SESE enter node has all necessary info
268 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
271 flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
273 flatNodesToVisit.add(fsen.getFlatExit());
276 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
277 new Hashtable<FlatNode, Set<TempDescriptor>>();
280 liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
283 while (!flatNodesToVisit.isEmpty()) {
284 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
285 flatNodesToVisit.remove(fn);
287 Set<TempDescriptor> prev = livenessResults.get(fn);
289 // merge sets from control flow joins
290 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
291 for (int i = 0; i < fn.numNext(); i++) {
292 FlatNode nn = fn.getNext(i);
293 Set<TempDescriptor> s = livenessResults.get(nn);
299 Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
301 // if a new result, schedule backward nodes for analysis
302 if (!curr.equals(prev)) {
303 livenessResults.put(fn, curr);
305 // don't flow backwards past current SESE enter
306 if (!fn.equals(fsen)) {
307 for (int i = 0; i < fn.numPrev(); i++) {
308 FlatNode nn = fn.getPrev(i);
309 flatNodesToVisit.add(nn);
315 Set<TempDescriptor> s = livenessResults.get(fsen);
320 // remember liveness per node from the root view as the
321 // global liveness of variables for later passes to use
323 livenessRootView.putAll(livenessResults);
326 // post-order traversal, so do children first
327 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
328 while (childItr.hasNext()) {
329 FlatSESEEnterNode fsenChild = childItr.next();
330 livenessAnalysisBackward(fsenChild, false, liveout);
334 private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
335 FlatSESEEnterNode currentSESE, boolean toplevel,
336 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
339 case FKind.FlatSESEExitNode:
341 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
342 if (!liveout.containsKey(fsexn)) {
343 liveout.put(fsexn, new HashSet<TempDescriptor>());
345 liveout.get(fsexn).addAll(liveIn);
347 // no break, sese exits should also execute default actions
350 // handle effects of statement in reverse, writes then reads
351 TempDescriptor[] writeTemps = fn.writesTemps();
352 for (int i = 0; i < writeTemps.length; ++i) {
353 liveIn.remove(writeTemps[i]);
356 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
357 Set<TempDescriptor> livetemps = liveout.get(fsexn);
358 if (livetemps != null && livetemps.contains(writeTemps[i])) {
359 // write to a live out temp...
360 // need to put in SESE liveout set
361 currentSESE.addOutVar(writeTemps[i]);
366 TempDescriptor[] readTemps = fn.readsTemps();
367 for (int i = 0; i < readTemps.length; ++i) {
368 liveIn.add(readTemps[i]);
371 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
372 if (virtualReadTemps != null) {
373 liveIn.addAll(virtualReadTemps);
384 private void variableAnalysisForward(FlatMethod fm) {
386 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
387 flatNodesToVisit.add(fm);
389 while (!flatNodesToVisit.isEmpty()) {
390 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
391 flatNodesToVisit.remove(fn);
393 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
394 assert seseStack != null;
396 VarSrcTokTable prev = variableResults.get(fn);
398 // merge sets from control flow joins
399 VarSrcTokTable curr = new VarSrcTokTable();
400 for (int i = 0; i < fn.numPrev(); i++) {
401 FlatNode nn = fn.getPrev(i);
402 VarSrcTokTable incoming = variableResults.get(nn);
403 curr.merge(incoming);
406 if (!seseStack.empty()) {
407 variable_nodeActions(fn, curr, seseStack.peek());
410 // if a new result, schedule forward nodes for analysis
411 if (!curr.equals(prev)) {
412 variableResults.put(fn, curr);
414 for (int i = 0; i < fn.numNext(); i++) {
415 FlatNode nn = fn.getNext(i);
416 flatNodesToVisit.add(nn);
422 private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
423 FlatSESEEnterNode currentSESE) {
426 case FKind.FlatSESEEnterNode: {
427 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
428 assert fsen.equals(currentSESE);
430 vstTable.age(currentSESE);
431 vstTable.assertConsistency();
435 case FKind.FlatSESEExitNode: {
436 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
437 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
438 assert currentSESE.getChildren().contains(fsen);
440 // remap all of this child's children tokens to be
441 // from this child as the child exits
442 vstTable.remapChildTokens(fsen);
444 // liveness virtual reads are things that might be
445 // written by an SESE and should be added to the in-set
446 // anything virtually read by this SESE should be pruned
447 // of parent or sibling sources
448 Set<TempDescriptor> liveVars = livenessRootView.get(fn);
449 Set<TempDescriptor> fsenVirtReads =
450 vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(fsen, liveVars);
451 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
452 if (fsenVirtReadsOld != null) {
453 fsenVirtReads.addAll(fsenVirtReadsOld);
455 livenessVirtualReads.put(fn, fsenVirtReads);
457 // then all child out-set tokens are guaranteed
458 // to be filled in, so clobber those entries with
459 // the latest, clean sources
460 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
461 while (outVarItr.hasNext()) {
462 TempDescriptor outVar = outVarItr.next();
463 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
465 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
466 vstTable.remove(outVar);
469 vstTable.assertConsistency();
474 case FKind.FlatOpNode: {
475 FlatOpNode fon = (FlatOpNode) fn;
477 if (fon.getOp().getOp() == Operation.ASSIGN) {
478 TempDescriptor lhs = fon.getDest();
479 TempDescriptor rhs = fon.getLeft();
481 vstTable.remove(lhs);
483 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
485 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
486 while (itr.hasNext()) {
487 VariableSourceToken vst = itr.next();
489 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
492 if (currentSESE.getChildren().contains(vst.getSESE())) {
493 // if the source comes from a child, copy it over
494 forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
497 // otherwise, stamp it as us as the source
498 forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
502 vstTable.addAll(forAddition);
504 // only break if this is an ASSIGN op node,
505 // otherwise fall through to default case
506 vstTable.assertConsistency();
511 // note that FlatOpNode's that aren't ASSIGN
512 // fall through to this default case
514 TempDescriptor[] writeTemps = fn.writesTemps();
515 if (writeTemps.length > 0) {
517 // for now, when writeTemps > 1, make sure
518 // its a call node, programmer enforce only
519 // doing stuff like calling a print routine
520 // assert writeTemps.length == 1;
521 if (writeTemps.length > 1) {
522 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
526 vstTable.remove(writeTemps[0]);
528 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
529 ts.add(writeTemps[0]);
531 vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
534 vstTable.assertConsistency();
541 private void notAvailableForward(FlatMethod fm) {
543 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
544 flatNodesToVisit.add(fm);
546 while (!flatNodesToVisit.isEmpty()) {
547 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
548 flatNodesToVisit.remove(fn);
550 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
551 assert seseStack != null;
553 Set<TempDescriptor> prev = notAvailableResults.get(fn);
555 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
556 for (int i = 0; i < fn.numPrev(); i++) {
557 FlatNode nn = fn.getPrev(i);
558 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
559 if (notAvailIn != null) {
560 curr.addAll(notAvailIn);
564 if (!seseStack.empty()) {
565 notAvailable_nodeActions(fn, curr, seseStack.peek());
568 // if a new result, schedule forward nodes for analysis
569 if (!curr.equals(prev)) {
570 notAvailableResults.put(fn, curr);
572 for (int i = 0; i < fn.numNext(); i++) {
573 FlatNode nn = fn.getNext(i);
574 flatNodesToVisit.add(nn);
580 private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
581 FlatSESEEnterNode currentSESE) {
583 // any temps that are removed from the not available set
584 // at this node should be marked in this node's code plan
585 // as temps to be grabbed at runtime!
589 case FKind.FlatSESEEnterNode: {
590 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
591 assert fsen.equals(currentSESE);
593 // keep a copy of what's not available into the SESE
594 // and restore it at the matching exit node
595 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
596 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
597 while (tdItr.hasNext()) {
598 notAvailCopy.add(tdItr.next());
600 notAvailableIntoSESE.put(fsen, notAvailCopy);
606 case FKind.FlatSESEExitNode: {
607 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
608 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
609 assert currentSESE.getChildren().contains(fsen);
611 notAvailSet.addAll(fsen.getOutVarSet());
613 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
614 assert notAvailIn != null;
615 notAvailSet.addAll(notAvailIn);
620 case FKind.FlatMethod: {
624 case FKind.FlatOpNode: {
625 FlatOpNode fon = (FlatOpNode) fn;
627 if (fon.getOp().getOp() == Operation.ASSIGN) {
628 TempDescriptor lhs = fon.getDest();
629 TempDescriptor rhs = fon.getLeft();
631 // copy makes lhs same availability as rhs
632 if (notAvailSet.contains(rhs)) {
633 notAvailSet.add(lhs);
635 notAvailSet.remove(lhs);
638 // only break if this is an ASSIGN op node,
639 // otherwise fall through to default case
644 // note that FlatOpNode's that aren't ASSIGN
645 // fall through to this default case
647 TempDescriptor[] writeTemps = fn.writesTemps();
648 for (int i = 0; i < writeTemps.length; i++) {
649 TempDescriptor wTemp = writeTemps[i];
650 notAvailSet.remove(wTemp);
652 TempDescriptor[] readTemps = fn.readsTemps();
653 for (int i = 0; i < readTemps.length; i++) {
654 TempDescriptor rTemp = readTemps[i];
655 notAvailSet.remove(rTemp);
657 // if this variable has exactly one source, potentially
658 // get other things from this source as well
659 VarSrcTokTable vstTable = variableResults.get(fn);
661 VSTWrapper vstIfStatic = new VSTWrapper();
662 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
664 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
666 VariableSourceToken vst = vstIfStatic.vst;
668 Iterator<VariableSourceToken> availItr =
669 vstTable.get(vst.getSESE(), vst.getAge()).iterator();
671 // look through things that are also available from same source
672 while (availItr.hasNext()) {
673 VariableSourceToken vstAlsoAvail = availItr.next();
675 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
676 while (refVarItr.hasNext()) {
677 TempDescriptor refVarAlso = refVarItr.next();
679 // if a variable is available from the same source, AND it ALSO
680 // only comes from one statically known source, mark it available
681 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
682 Integer srcTypeAlso =
683 vstTable.getRefVarSrcType(refVarAlso, currentSESE, vstIfStaticNotUsed);
684 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
685 notAvailSet.remove(refVarAlso);
697 private void codePlansForward(FlatMethod fm) {
699 // start from flat method top, visit every node in
700 // method exactly once
701 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
702 flatNodesToVisit.add(fm);
704 Set<FlatNode> visited = new HashSet<FlatNode>();
706 while (!flatNodesToVisit.isEmpty()) {
707 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
708 FlatNode fn = fnItr.next();
710 flatNodesToVisit.remove(fn);
713 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
714 assert seseStack != null;
716 // use incoming results as "dot statement" or just
717 // before the current statement
718 VarSrcTokTable dotSTtable = new VarSrcTokTable();
719 for (int i = 0; i < fn.numPrev(); i++) {
720 FlatNode nn = fn.getPrev(i);
721 dotSTtable.merge(variableResults.get(nn));
724 // find dt-st notAvailableSet also
725 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
726 for (int i = 0; i < fn.numPrev(); i++) {
727 FlatNode nn = fn.getPrev(i);
728 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
729 if (notAvailIn != null) {
730 dotSTnotAvailSet.addAll(notAvailIn);
734 Set<TempDescriptor> dotSTlive = livenessRootView.get(fn);
736 if (!seseStack.empty()) {
737 codePlans_nodeActions(fn, dotSTlive, dotSTtable, dotSTnotAvailSet, seseStack.peek());
740 for (int i = 0; i < fn.numNext(); i++) {
741 FlatNode nn = fn.getNext(i);
743 if (!visited.contains(nn)) {
744 flatNodesToVisit.add(nn);
750 private void codePlans_nodeActions(FlatNode fn, Set<TempDescriptor> liveSetIn,
751 VarSrcTokTable vstTableIn, Set<TempDescriptor> notAvailSetIn, FlatSESEEnterNode currentSESE) {
753 CodePlan plan = new CodePlan(currentSESE);
757 case FKind.FlatSESEEnterNode: {
758 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
759 assert fsen.equals(currentSESE);
761 // track the source types of the in-var set so generated
762 // code at this SESE issue can compute the number of
763 // dependencies properly
764 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
765 while (inVarItr.hasNext()) {
766 TempDescriptor inVar = inVarItr.next();
768 // when we get to an SESE enter node we change the
769 // currentSESE variable of this analysis to the
770 // child that is declared by the enter node, so
771 // in order to classify in-vars correctly, pass
772 // the parent SESE in--at other FlatNode types just
773 // use the currentSESE
774 VSTWrapper vstIfStatic = new VSTWrapper();
775 Integer srcType = vstTableIn.getRefVarSrcType(inVar, fsen.getParent(), vstIfStatic);
777 // the current SESE needs a local space to track the dynamic
778 // variable and the child needs space in its SESE record
779 if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
780 fsen.addDynamicInVar(inVar);
781 fsen.getParent().addDynamicVar(inVar);
783 } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
784 fsen.addStaticInVar(inVar);
785 VariableSourceToken vst = vstIfStatic.vst;
786 fsen.putStaticInVar2src(inVar, vst);
787 fsen.addStaticInVarSrc(new SESEandAgePair(vst.getSESE(), vst.getAge()));
789 assert srcType.equals(VarSrcTokTable.SrcType_READY);
790 fsen.addReadyInVar(inVar);
797 case FKind.FlatSESEExitNode: {
798 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
802 case FKind.FlatOpNode: {
803 FlatOpNode fon = (FlatOpNode) fn;
805 if (fon.getOp().getOp() == Operation.ASSIGN) {
806 TempDescriptor lhs = fon.getDest();
807 TempDescriptor rhs = fon.getLeft();
809 // if this is an op node, don't stall, copy
810 // source and delay until we need to use value
812 // ask whether lhs and rhs sources are dynamic, static, etc.
813 VSTWrapper vstIfStatic = new VSTWrapper();
814 Integer lhsSrcType = vstTableIn.getRefVarSrcType(lhs, currentSESE, vstIfStatic);
815 Integer rhsSrcType = vstTableIn.getRefVarSrcType(rhs, currentSESE, vstIfStatic);
817 if (rhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
818 // if rhs is dynamic going in, lhs will definitely be dynamic
819 // going out of this node, so track that here
820 plan.addDynAssign(lhs, rhs);
821 currentSESE.addDynamicVar(lhs);
822 currentSESE.addDynamicVar(rhs);
824 } else if (lhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
825 // otherwise, if the lhs is dynamic, but the rhs is not, we
826 // need to update the variable's dynamic source as "current SESE"
827 plan.addDynAssign(lhs);
830 // only break if this is an ASSIGN op node,
831 // otherwise fall through to default case
836 // note that FlatOpNode's that aren't ASSIGN
837 // fall through to this default case
840 // a node with no live set has nothing to stall for
841 if (liveSetIn == null) {
845 TempDescriptor[] readarray = fn.readsTemps();
846 for (int i = 0; i < readarray.length; i++) {
847 TempDescriptor readtmp = readarray[i];
849 // ignore temps that are definitely available
850 // when considering to stall on it
851 if (!notAvailSetIn.contains(readtmp)) {
855 // check the source type of this variable
856 VSTWrapper vstIfStatic = new VSTWrapper();
857 Integer srcType = vstTableIn.getRefVarSrcType(readtmp, currentSESE, vstIfStatic);
859 if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
860 // 1) It is not clear statically where this variable will
861 // come from, so dynamically we must keep track
862 // along various control paths, and therefore when we stall,
863 // just stall for the exact thing we need and move on
864 plan.addDynamicStall(readtmp);
865 currentSESE.addDynamicVar(readtmp);
867 } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
868 // 2) Single token/age pair: Stall for token/age pair, and copy
869 // all live variables with same token/age pair at the same
870 // time. This is the same stuff that the notavaialable analysis
871 // marks as now available.
872 VariableSourceToken vst = vstIfStatic.vst;
874 Iterator<VariableSourceToken> availItr =
875 vstTableIn.get(vst.getSESE(), vst.getAge()).iterator();
877 while (availItr.hasNext()) {
878 VariableSourceToken vstAlsoAvail = availItr.next();
880 // only grab additional stuff that is live
881 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
883 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
884 while (refVarItr.hasNext()) {
885 TempDescriptor refVar = refVarItr.next();
886 if (liveSetIn.contains(refVar)) {
891 if (!copySet.isEmpty()) {
892 plan.addStall2CopySet(vstAlsoAvail, copySet);
897 // the other case for srcs is READY, so do nothing
900 // assert that everything being stalled for is in the
901 // "not available" set coming into this flat node and
902 // that every VST identified is in the possible "stall set"
903 // that represents VST's from children SESE's
911 // identify sese-age pairs that are statically useful
912 // and should have an associated SESE variable in code
913 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
914 // AND ALWAYS GIVE NAMES TO PARENTS
915 Set<VariableSourceToken> staticSet = vstTableIn.get();
916 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
917 while (vstItr.hasNext()) {
918 VariableSourceToken vst = vstItr.next();
920 // placeholder source tokens are useful results, but
921 // the placeholder static name is never needed
922 if (vst.getSESE().getIsCallerSESEplaceholder()) {
926 FlatSESEEnterNode sese = currentSESE;
927 while (sese != null) {
928 sese.addNeededStaticName(new SESEandAgePair(vst.getSESE(), vst.getAge()));
929 sese.mustTrackAtLeastAge(vst.getAge());
931 sese = sese.getParent();
935 codePlans.put(fn, plan);
937 // if any variables at this-node-*dot* have a static source (exactly one
939 // but go to a dynamic source at next-node-*dot*, create a new IR graph
940 // node on that edge to track the sources dynamically
941 VarSrcTokTable thisVstTable = variableResults.get(fn);
942 for (int i = 0; i < fn.numNext(); i++) {
943 FlatNode nn = fn.getNext(i);
944 VarSrcTokTable nextVstTable = variableResults.get(nn);
945 Set<TempDescriptor> nextLiveIn = livenessRootView.get(nn);
947 // the table can be null if it is one of the few IR nodes
948 // completely outside of the root SESE scope
949 if (nextVstTable != null && nextLiveIn != null) {
951 Hashtable<TempDescriptor, VSTWrapper> readyOrStatic2dynamicSet =
952 thisVstTable.getReadyOrStatic2DynamicSet(nextVstTable, nextLiveIn, currentSESE);
954 if (!readyOrStatic2dynamicSet.isEmpty()) {
956 // either add these results to partial fixed-point result
957 // or make a new one if we haven't made any here yet
958 FlatEdge fe = new FlatEdge(fn, nn);
959 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get(fe);
962 fwdvn = new FlatWriteDynamicVarNode(fn, nn, readyOrStatic2dynamicSet, currentSESE);
963 wdvNodesToSpliceIn.put(fe, fwdvn);
965 fwdvn.addMoreVar2Src(readyOrStatic2dynamicSet);
972 private void makeConflictGraph(FlatMethod fm) {
974 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
975 flatNodesToVisit.add(fm);
977 Set<FlatNode> visited = new HashSet<FlatNode>();
979 while (!flatNodesToVisit.isEmpty()) {
980 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
981 flatNodesToVisit.remove(fn);
984 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
985 assert seseStack != null;
987 if (!seseStack.isEmpty()) {
989 ConflictGraph conflictGraph = sese2conflictGraph.get(seseStack.peek());
990 if (conflictGraph == null) {
991 conflictGraph = new ConflictGraph(state);
994 conflictGraph_nodeAction(fn, seseStack.peek());
997 // schedule forward nodes for analysis
998 for (int i = 0; i < fn.numNext(); i++) {
999 FlatNode nn = fn.getNext(i);
1000 if (!visited.contains(nn)) {
1001 flatNodesToVisit.add(nn);
1009 private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
1011 ConflictGraph conflictGraph;
1015 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
1017 switch (fn.kind()) {
1019 case FKind.FlatSESEEnterNode: {
1021 if (currentSESE.getParent() == null) {
1024 conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
1025 if (conflictGraph == null) {
1026 conflictGraph = new ConflictGraph(state);
1029 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1031 if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
1032 // collects effects set of invar set and generates invar node
1033 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(currentSESE);
1034 conflictGraph.addLiveIn(taint2Effects);
1037 if (conflictGraph.id2cn.size() > 0) {
1038 sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
1044 case FKind.FlatFieldNode:
1045 case FKind.FlatElementNode: {
1047 conflictGraph = sese2conflictGraph.get(currentSESE);
1048 if (conflictGraph == null) {
1049 conflictGraph = new ConflictGraph(state);
1052 if (fn instanceof FlatFieldNode) {
1053 FlatFieldNode ffn = (FlatFieldNode) fn;
1056 FlatElementNode fen = (FlatElementNode) fn;
1061 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1062 conflictGraph.addStallSite(taint2Effects, rhs);
1064 if (conflictGraph.id2cn.size() > 0) {
1065 sese2conflictGraph.put(currentSESE, conflictGraph);
1070 case FKind.FlatSetFieldNode:
1071 case FKind.FlatSetElementNode: {
1073 conflictGraph = sese2conflictGraph.get(currentSESE);
1074 if (conflictGraph == null) {
1075 conflictGraph = new ConflictGraph(state);
1078 if (fn instanceof FlatSetFieldNode) {
1079 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
1080 lhs = fsfn.getDst();
1081 rhs = fsfn.getSrc();
1083 FlatSetElementNode fsen = (FlatSetElementNode) fn;
1084 lhs = fsen.getDst();
1085 rhs = fsen.getSrc();
1088 // collects effects of stall site and generates stall site node
1089 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1090 conflictGraph.addStallSite(taint2Effects, rhs);
1091 conflictGraph.addStallSite(taint2Effects, lhs);
1093 if (conflictGraph.id2cn.size() > 0) {
1094 sese2conflictGraph.put(currentSESE, conflictGraph);
1099 case FKind.FlatCall: {
1100 conflictGraph = sese2conflictGraph.get(currentSESE);
1101 if (conflictGraph == null) {
1102 conflictGraph = new ConflictGraph(state);
1105 FlatCall fc = (FlatCall) fn;
1108 // collects effects of stall site and generates stall site node
1109 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1110 conflictGraph.addStallSite(taint2Effects, lhs);
1111 if (conflictGraph.id2cn.size() > 0) {
1112 sese2conflictGraph.put(currentSESE, conflictGraph);
1122 private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
1123 // decide fine-grain edge or coarse-grain edge among all vertexes by
1124 // pair-wise comparison
1125 Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
1126 while (seseIter.hasNext()) {
1127 FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
1128 ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
1130 // clear current conflict before recalculating with reachability info
1131 conflictGraph.clearAllConflictEdge();
1132 conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
1133 conflictGraph.setFMEnclosing(sese.getfmEnclosing());
1135 conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
1136 sese2conflictGraph.put(sese, conflictGraph);
1140 private void writeConflictGraph() {
1141 Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
1142 while (keyEnum.hasMoreElements()) {
1143 FlatNode key = (FlatNode) keyEnum.nextElement();
1144 ConflictGraph cg = sese2conflictGraph.get(key);
1146 if (cg.hasConflictEdge()) {
1147 cg.writeGraph("ConflictGraphFor" + key, false);
1149 } catch (IOException e) {
1150 System.out.println("Error writing");
1156 private void synthesizeLocks() {
1157 Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
1158 for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
1159 Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
1160 FlatNode sese = graphEntry.getKey();
1161 ConflictGraph conflictGraph = graphEntry.getValue();
1162 calculateCovering(conflictGraph);
1166 private void calculateCovering(ConflictGraph conflictGraph) {
1167 uniqueLockSetId = 0; // reset lock counter for every new conflict graph
1168 HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
1169 HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
1170 HashSet<SESELock> lockSet = new HashSet<SESELock>();
1172 Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
1173 for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
1174 ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
1175 if (conflictEdge.isCoarseEdge()) {
1176 coarseToCover.add(conflictEdge);
1178 fineToCover.add(conflictEdge);
1182 HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
1183 toCover.addAll(fineToCover);
1184 toCover.addAll(coarseToCover);
1186 while (!toCover.isEmpty()) {
1188 SESELock seseLock = new SESELock();
1189 seseLock.setID(uniqueLockSetId++);
1193 do { // fine-grained edge
1197 for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
1200 ConflictEdge edge = (ConflictEdge) iterator.next();
1201 if (seseLock.getConflictNodeSet().size() == 0) {
1203 if (seseLock.isWriteNode(edge.getVertexU())) {
1204 // mark as fine_write
1205 if (edge.getVertexU().isStallSiteNode()) {
1206 type = ConflictNode.PARENT_WRITE;
1208 type = ConflictNode.FINE_WRITE;
1210 seseLock.addConflictNode(edge.getVertexU(), type);
1212 // mark as fine_read
1213 if (edge.getVertexU().isStallSiteNode()) {
1214 type = ConflictNode.PARENT_READ;
1216 type = ConflictNode.FINE_READ;
1218 seseLock.addConflictNode(edge.getVertexU(), type);
1220 if (edge.getVertexV() != edge.getVertexU()) {
1221 if (seseLock.isWriteNode(edge.getVertexV())) {
1222 // mark as fine_write
1223 if (edge.getVertexV().isStallSiteNode()) {
1224 type = ConflictNode.PARENT_WRITE;
1226 type = ConflictNode.FINE_WRITE;
1228 seseLock.addConflictNode(edge.getVertexV(), type);
1230 // mark as fine_read
1231 if (edge.getVertexV().isStallSiteNode()) {
1232 type = ConflictNode.PARENT_READ;
1234 type = ConflictNode.FINE_READ;
1236 seseLock.addConflictNode(edge.getVertexV(), type);
1240 seseLock.addConflictEdge(edge);
1241 fineToCover.remove(edge);
1242 break;// exit iterator loop
1243 }// end of initial setup
1245 ConflictNode newNode;
1246 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1247 // new node has a fine-grained edge to all current node
1248 // If there is a coarse grained edge where need a fine edge, it's
1249 // okay to add the node
1250 // but the edge must remain uncovered.
1254 if (seseLock.containsConflictNode(newNode)) {
1255 seseLock.addEdge(edge);
1256 fineToCover.remove(edge);
1260 if (seseLock.isWriteNode(newNode)) {
1261 if (newNode.isStallSiteNode()) {
1262 type = ConflictNode.PARENT_WRITE;
1264 type = ConflictNode.FINE_WRITE;
1266 seseLock.setNodeType(newNode, type);
1268 if (newNode.isStallSiteNode()) {
1269 type = ConflictNode.PARENT_READ;
1271 type = ConflictNode.FINE_READ;
1273 seseLock.setNodeType(newNode, type);
1276 seseLock.addEdge(edge);
1277 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1278 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1279 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1281 // mark all fine edges between new node and nodes in the group as
1283 if (!conflictEdge.getVertexU().equals(newNode)) {
1284 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1286 seseLock.addConflictEdge(conflictEdge);
1287 fineToCover.remove(conflictEdge);
1289 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1290 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1292 seseLock.addConflictEdge(conflictEdge);
1293 fineToCover.remove(conflictEdge);
1299 break;// exit iterator loop
1304 HashSet<ConflictEdge> notCovered=new HashSet<ConflictEdge>();
1308 for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
1310 ConflictEdge edge = (ConflictEdge) iterator.next();
1311 if (seseLock.getConflictNodeSet().size() == 0) {
1313 if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
1314 // node has a coarse-grained edge with itself
1315 if (!(edge.getVertexU().isStallSiteNode())) {
1316 // and it is not parent
1317 type = ConflictNode.SCC;
1319 type = ConflictNode.PARENT_WRITE;
1321 seseLock.addConflictNode(edge.getVertexU(), type);
1323 if (edge.getVertexU().isStallSiteNode()) {
1324 if (edge.getVertexU().getWriteEffectSet().isEmpty()) {
1325 type = ConflictNode.PARENT_READ;
1327 type = ConflictNode.PARENT_WRITE;
1330 type = ConflictNode.COARSE;
1332 seseLock.addConflictNode(edge.getVertexU(), type);
1334 if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
1335 // node has a coarse-grained edge with itself
1336 if (!(edge.getVertexV().isStallSiteNode())) {
1337 // and it is not parent
1338 type = ConflictNode.SCC;
1340 type = ConflictNode.PARENT_WRITE;
1342 seseLock.addConflictNode(edge.getVertexV(), type);
1344 if (edge.getVertexV().isStallSiteNode()) {
1345 if (edge.getVertexV().getWriteEffectSet().isEmpty()) {
1346 type = ConflictNode.PARENT_READ;
1348 type = ConflictNode.PARENT_WRITE;
1351 type = ConflictNode.COARSE;
1353 seseLock.addConflictNode(edge.getVertexV(), type);
1356 coarseToCover.remove(edge);
1357 seseLock.addConflictEdge(edge);
1358 break;// exit iterator loop
1359 }// end of initial setup
1361 ConflictNode newNode;
1362 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1363 // new node has a coarse-grained edge to all fine-read, fine-write,
1367 if (newNode.isInVarNode() && (!seseLock.hasSelfCoarseEdge(newNode))
1368 && seseLock.hasCoarseEdgeWithParentCoarse(newNode)) {
1369 // this case can't be covered by this queue
1370 coarseToCover.remove(edge);
1371 notCovered.add(edge);
1375 if (seseLock.containsConflictNode(newNode)) {
1376 seseLock.addEdge(edge);
1377 coarseToCover.remove(edge);
1381 if (seseLock.hasSelfCoarseEdge(newNode)) {
1383 if (newNode.isStallSiteNode()) {
1384 type = ConflictNode.PARENT_COARSE;
1386 type = ConflictNode.SCC;
1388 seseLock.setNodeType(newNode, type);
1390 if (newNode.isStallSiteNode()) {
1391 type = ConflictNode.PARENT_COARSE;
1393 type = ConflictNode.COARSE;
1395 seseLock.setNodeType(newNode, type);
1398 seseLock.addEdge(edge);
1399 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1400 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1401 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1402 // mark all coarse edges between new node and nodes in the group
1404 if (!conflictEdge.getVertexU().equals(newNode)) {
1405 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1407 seseLock.addConflictEdge(conflictEdge);
1408 coarseToCover.remove(conflictEdge);
1410 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1411 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1413 seseLock.addConflictEdge(conflictEdge);
1414 coarseToCover.remove(conflictEdge);
1419 break;// exit iterator loop
1425 lockSet.add(seseLock);
1428 coarseToCover.addAll(notCovered);
1429 toCover.addAll(fineToCover);
1430 toCover.addAll(coarseToCover);
1434 conflictGraph2SESELock.put(conflictGraph, lockSet);
1437 public ConflictGraph getConflictGraph(FlatNode sese) {
1438 return sese2conflictGraph.get(sese);
1441 public Set<SESELock> getLockMappings(ConflictGraph graph) {
1442 return conflictGraph2SESELock.get(graph);
1445 public Set<FlatSESEEnterNode> getAllSESEs() {
1446 return rblockRel.getAllSESEs();
1449 public FlatSESEEnterNode getMainSESE() {
1450 return rblockRel.getMainSESE();
1453 public void writeReports(String timeReport) throws java.io.IOException {
1455 BufferedWriter bw = new BufferedWriter(new FileWriter("mlpReport_summary.txt"));
1456 bw.write("MLP Analysis Results\n\n");
1457 bw.write(timeReport + "\n\n");
1458 printSESEHierarchy(bw);
1463 Iterator<Descriptor> methItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
1464 while (methItr.hasNext()) {
1465 MethodDescriptor md = (MethodDescriptor) methItr.next();
1466 FlatMethod fm = state.getMethodFlat(md);
1469 new BufferedWriter(new FileWriter("mlpReport_" + md.getClassMethodName()
1470 + md.getSafeMethodDescriptor() + ".txt"));
1471 bw.write("MLP Results for " + md + "\n-------------------\n");
1473 FlatSESEEnterNode implicitSESE = (FlatSESEEnterNode) fm.getNext(0);
1474 if (!implicitSESE.getIsCallerSESEplaceholder() && implicitSESE != rblockRel.getMainSESE()) {
1475 System.out.println(implicitSESE + " is not implicit?!");
1478 bw.write("Dynamic vars to manage:\n " + implicitSESE.getDynamicVarSet());
1480 bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessRootView));
1481 bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
1482 bw.write("\n\nNot Available Results-Out\n---------------------\n"
1483 + fm.printMethod(notAvailableResults));
1484 bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
1490 private void printSESEHierarchy(BufferedWriter bw) throws java.io.IOException {
1491 bw.write("SESE Hierarchy\n--------------\n");
1492 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1493 while (rootItr.hasNext()) {
1494 FlatSESEEnterNode root = rootItr.next();
1495 if (root.getIsCallerSESEplaceholder()) {
1496 if (!root.getChildren().isEmpty()) {
1497 printSESEHierarchyTree(bw, root, 0);
1500 printSESEHierarchyTree(bw, root, 0);
1505 private void printSESEHierarchyTree(BufferedWriter bw, FlatSESEEnterNode fsen, int depth)
1506 throws java.io.IOException {
1507 for (int i = 0; i < depth; ++i) {
1510 bw.write("- " + fsen.getPrettyIdentifier() + "\n");
1512 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1513 while (childItr.hasNext()) {
1514 FlatSESEEnterNode fsenChild = childItr.next();
1515 printSESEHierarchyTree(bw, fsenChild, depth + 1);
1519 private void printSESEInfo(BufferedWriter bw) throws java.io.IOException {
1520 bw.write("\nSESE info\n-------------\n");
1521 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1522 while (rootItr.hasNext()) {
1523 FlatSESEEnterNode root = rootItr.next();
1524 if (root.getIsCallerSESEplaceholder()) {
1525 if (!root.getChildren().isEmpty()) {
1526 printSESEInfoTree(bw, root);
1529 printSESEInfoTree(bw, root);
1534 public DisjointAnalysis getDisjointAnalysis() {
1535 return disjointAnalysisTaints;
1538 private void printSESEInfoTree(BufferedWriter bw, FlatSESEEnterNode fsen)
1539 throws java.io.IOException {
1541 if (!fsen.getIsCallerSESEplaceholder()) {
1542 bw.write("SESE " + fsen.getPrettyIdentifier());
1543 if( fsen.getIsLeafSESE() ) {
1544 bw.write(" (leaf)");
1548 bw.write(" in-set: " + fsen.getInVarSet() + "\n");
1549 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1550 while (tItr.hasNext()) {
1551 TempDescriptor inVar = tItr.next();
1552 if (fsen.getReadyInVarSet().contains(inVar)) {
1553 bw.write(" (ready) " + inVar + "\n");
1555 if (fsen.getStaticInVarSet().contains(inVar)) {
1556 bw.write(" (static) " + inVar + " from " + fsen.getStaticInVarSrc(inVar) + "\n");
1558 if (fsen.getDynamicInVarSet().contains(inVar)) {
1559 bw.write(" (dynamic)" + inVar + "\n");
1563 bw.write(" Dynamic vars to manage: " + fsen.getDynamicVarSet() + "\n");
1565 bw.write(" out-set: " + fsen.getOutVarSet() + "\n");
1569 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1570 while (childItr.hasNext()) {
1571 FlatSESEEnterNode fsenChild = childItr.next();
1572 printSESEInfoTree(bw, fsenChild);