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 Set<FlatNode> getNodesWithPlans() {
89 return codePlans.keySet();
92 public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
93 ArrayReferencees arrayReferencees) {
95 double timeStartAnalysis = (double) System.nanoTime();
98 this.typeUtil = typeUtil;
99 this.callGraph = callGraph;
100 this.maxSESEage = state.MLP_MAXSESEAGE;
102 livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
103 livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
104 variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
105 notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
106 codePlans = new Hashtable<FlatNode, CodePlan>();
107 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
109 notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
111 sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
112 conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
114 // add all methods transitively reachable from the
115 // source's main to set for analysis
116 MethodDescriptor mdSourceEntry = typeUtil.getMain();
117 FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
119 Set<MethodDescriptor> descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
121 descriptorsToAnalyze.add(mdSourceEntry);
123 // 1st pass, find basic rblock relations & status
124 rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
125 rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
127 // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
128 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
129 while (rootItr.hasNext()) {
130 FlatSESEEnterNode root = rootItr.next();
131 livenessAnalysisBackward(root, true, null);
134 // 3rd pass, variable analysis
135 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
136 while (methItr.hasNext()) {
137 Descriptor d = methItr.next();
138 FlatMethod fm = state.getMethodFlat(d);
140 // starting from roots do a forward, fixed-point
141 // variable analysis for refinement and stalls
142 variableAnalysisForward(fm);
145 // 4th pass, compute liveness contribution from
146 // virtual reads discovered in variable pass
147 rootItr = rblockRel.getRootSESEs().iterator();
148 while (rootItr.hasNext()) {
149 FlatSESEEnterNode root = rootItr.next();
150 livenessAnalysisBackward(root, true, null);
153 // 5th pass, use disjointness with NO FLAGGED REGIONS
154 // to compute taints and effects
155 disjointAnalysisTaints =
156 new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, null,
157 rblockRel, rblockStatus,
158 true ); // suppress output--this is an intermediate pass
160 // 6th pass, not available analysis FOR VARIABLES!
161 methItr = descriptorsToAnalyze.iterator();
162 while (methItr.hasNext()) {
163 Descriptor d = methItr.next();
164 FlatMethod fm = state.getMethodFlat(d);
166 // compute what is not available at every program
167 // point, in a forward fixed-point pass
168 notAvailableForward(fm);
171 // 7th pass, make conflict graph
172 // conflict graph is maintained by each parent sese,
174 Set<FlatSESEEnterNode> allSESEs=rblockRel.getAllSESEs();
175 for (Iterator iterator = allSESEs.iterator(); iterator.hasNext();) {
177 FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
178 if (!parent.getIsLeafSESE()) {
180 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
181 ConflictGraph conflictGraph = sese2conflictGraph.get(parent);
182 if (conflictGraph == null) {
183 conflictGraph = new ConflictGraph(state);
186 Set<FlatSESEEnterNode> children = parent.getSESEChildren();
187 for (Iterator iterator2 = children.iterator(); iterator2.hasNext();) {
188 FlatSESEEnterNode child = (FlatSESEEnterNode) iterator2.next();
189 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(child);
190 conflictGraph.addLiveIn(taint2Effects);
191 sese2conflictGraph.put(parent, conflictGraph);
196 Iterator descItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
197 while (descItr.hasNext()) {
198 Descriptor d = (Descriptor) descItr.next();
199 FlatMethod fm = state.getMethodFlat(d);
201 makeConflictGraph(fm);
208 * Iterator iter = sese2conflictGraph.entrySet().iterator(); while
209 * (iter.hasNext()) { Entry e = (Entry) iter.next(); FlatNode fn =
210 * (FlatNode) e.getKey(); ConflictGraph conflictGraph = (ConflictGraph)
212 * System.out.println("---------------------------------------");
213 * System.out.println("CONFLICT GRAPH for " + fn); Set<String> keySet =
214 * conflictGraph.id2cn.keySet(); for (Iterator iterator = keySet.iterator();
215 * iterator.hasNext();) { String key = (String) iterator.next();
216 * ConflictNode node = conflictGraph.id2cn.get(key);
217 * System.out.println("key=" + key + " \n" + node.toStringAllEffects()); } }
220 // 8th pass, calculate all possible conflicts without using reachability
222 // and identify set of FlatNew that next disjoint reach. analysis should
224 Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
225 calculateConflicts(sitesToFlag, false);
229 // 9th pass, ask disjoint analysis to compute reachability
230 // for objects that may cause heap conflicts so the most
231 // efficient method to deal with conflict can be computed
233 disjointAnalysisReach =
234 new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, sitesToFlag,
235 null, // don't do effects analysis again!
236 null // don't do effects analysis again!
238 // 10th pass, calculate conflicts with reachability info
239 calculateConflicts(null, true);
241 // 11th pass, compiling locks
244 // 12th pass, compute a plan for code injections
245 methItr = descriptorsToAnalyze.iterator();
246 while (methItr.hasNext()) {
247 Descriptor d = methItr.next();
248 FlatMethod fm = state.getMethodFlat(d);
249 codePlansForward(fm);
253 // splice new IR nodes into graph after all
254 // analysis passes are complete
255 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
256 while (spliceItr.hasNext()) {
257 Map.Entry me = (Map.Entry) spliceItr.next();
258 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
259 fwdvn.spliceIntoIR();
262 if (state.OOODEBUG) {
265 disjointAnalysisTaints.getEffectsAnalysis().writeEffects("effects.txt");
266 writeConflictGraph();
267 } catch (IOException e) {
274 private void writeFile(Set<FlatNew> sitesToFlag) {
277 BufferedWriter bw = new BufferedWriter(new FileWriter("sitesToFlag.txt"));
279 for (Iterator iterator = sitesToFlag.iterator(); iterator.hasNext();) {
280 FlatNew fn = (FlatNew) iterator.next();
284 } catch (IOException e) {
290 private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
291 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
293 // start from an SESE exit, visit nodes in reverse up to
294 // SESE enter in a fixed-point scheme, where children SESEs
295 // should already be analyzed and therefore can be skipped
296 // because child SESE enter node has all necessary info
297 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
300 flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
302 flatNodesToVisit.add(fsen.getFlatExit());
305 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
306 new Hashtable<FlatNode, Set<TempDescriptor>>();
309 liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
312 while (!flatNodesToVisit.isEmpty()) {
313 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
314 flatNodesToVisit.remove(fn);
316 Set<TempDescriptor> prev = livenessResults.get(fn);
318 // merge sets from control flow joins
319 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
320 for (int i = 0; i < fn.numNext(); i++) {
321 FlatNode nn = fn.getNext(i);
322 Set<TempDescriptor> s = livenessResults.get(nn);
328 Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
330 // if a new result, schedule backward nodes for analysis
331 if (!curr.equals(prev)) {
332 livenessResults.put(fn, curr);
334 // don't flow backwards past current SESE enter
335 if (!fn.equals(fsen)) {
336 for (int i = 0; i < fn.numPrev(); i++) {
337 FlatNode nn = fn.getPrev(i);
338 flatNodesToVisit.add(nn);
344 Set<TempDescriptor> s = livenessResults.get(fsen);
349 // remember liveness per node from the root view as the
350 // global liveness of variables for later passes to use
352 livenessRootView.putAll(livenessResults);
355 // post-order traversal, so do children first
356 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
357 while (childItr.hasNext()) {
358 FlatSESEEnterNode fsenChild = childItr.next();
359 livenessAnalysisBackward(fsenChild, false, liveout);
363 private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
364 FlatSESEEnterNode currentSESE, boolean toplevel,
365 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
368 case FKind.FlatSESEExitNode:
370 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
371 if (!liveout.containsKey(fsexn)) {
372 liveout.put(fsexn, new HashSet<TempDescriptor>());
374 liveout.get(fsexn).addAll(liveIn);
376 // no break, sese exits should also execute default actions
379 // handle effects of statement in reverse, writes then reads
380 TempDescriptor[] writeTemps = fn.writesTemps();
381 for (int i = 0; i < writeTemps.length; ++i) {
382 liveIn.remove(writeTemps[i]);
385 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
386 Set<TempDescriptor> livetemps = liveout.get(fsexn);
387 if (livetemps != null && livetemps.contains(writeTemps[i])) {
388 // write to a live out temp...
389 // need to put in SESE liveout set
390 currentSESE.addOutVar(writeTemps[i]);
395 TempDescriptor[] readTemps = fn.readsTemps();
396 for (int i = 0; i < readTemps.length; ++i) {
397 liveIn.add(readTemps[i]);
400 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
401 if (virtualReadTemps != null) {
402 liveIn.addAll(virtualReadTemps);
413 private void variableAnalysisForward(FlatMethod fm) {
415 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
416 flatNodesToVisit.add(fm);
418 while (!flatNodesToVisit.isEmpty()) {
419 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
420 flatNodesToVisit.remove(fn);
422 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
423 assert seseStack != null;
425 VarSrcTokTable prev = variableResults.get(fn);
427 // merge sets from control flow joins
428 VarSrcTokTable curr = new VarSrcTokTable();
429 for (int i = 0; i < fn.numPrev(); i++) {
430 FlatNode nn = fn.getPrev(i);
431 VarSrcTokTable incoming = variableResults.get(nn);
432 curr.merge(incoming);
435 if (!seseStack.empty()) {
436 variable_nodeActions(fn, curr, seseStack.peek());
439 // if a new result, schedule forward nodes for analysis
440 if (!curr.equals(prev)) {
441 variableResults.put(fn, curr);
443 for (int i = 0; i < fn.numNext(); i++) {
444 FlatNode nn = fn.getNext(i);
445 flatNodesToVisit.add(nn);
451 private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
452 FlatSESEEnterNode currentSESE) {
455 case FKind.FlatSESEEnterNode: {
456 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
457 assert fsen.equals(currentSESE);
459 vstTable.age(currentSESE);
460 vstTable.assertConsistency();
464 case FKind.FlatSESEExitNode: {
465 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
466 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
467 assert currentSESE.getChildren().contains(fsen);
469 // remap all of this child's children tokens to be
470 // from this child as the child exits
471 vstTable.remapChildTokens(fsen);
473 // liveness virtual reads are things that might be
474 // written by an SESE and should be added to the in-set
475 // anything virtually read by this SESE should be pruned
476 // of parent or sibling sources
477 Set<TempDescriptor> liveVars = livenessRootView.get(fn);
478 Set<TempDescriptor> fsenVirtReads =
479 vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(fsen, liveVars);
480 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
481 if (fsenVirtReadsOld != null) {
482 fsenVirtReads.addAll(fsenVirtReadsOld);
484 livenessVirtualReads.put(fn, fsenVirtReads);
486 // then all child out-set tokens are guaranteed
487 // to be filled in, so clobber those entries with
488 // the latest, clean sources
489 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
490 while (outVarItr.hasNext()) {
491 TempDescriptor outVar = outVarItr.next();
492 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
494 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
495 vstTable.remove(outVar);
498 vstTable.assertConsistency();
503 case FKind.FlatOpNode: {
504 FlatOpNode fon = (FlatOpNode) fn;
506 if (fon.getOp().getOp() == Operation.ASSIGN) {
507 TempDescriptor lhs = fon.getDest();
508 TempDescriptor rhs = fon.getLeft();
510 vstTable.remove(lhs);
512 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
514 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
515 while (itr.hasNext()) {
516 VariableSourceToken vst = itr.next();
518 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
521 if (currentSESE.getChildren().contains(vst.getSESE())) {
522 // if the source comes from a child, copy it over
523 forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
526 // otherwise, stamp it as us as the source
527 forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
531 vstTable.addAll(forAddition);
533 // only break if this is an ASSIGN op node,
534 // otherwise fall through to default case
535 vstTable.assertConsistency();
540 // note that FlatOpNode's that aren't ASSIGN
541 // fall through to this default case
543 TempDescriptor[] writeTemps = fn.writesTemps();
544 if (writeTemps.length > 0) {
546 // for now, when writeTemps > 1, make sure
547 // its a call node, programmer enforce only
548 // doing stuff like calling a print routine
549 // assert writeTemps.length == 1;
550 if (writeTemps.length > 1) {
551 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
555 vstTable.remove(writeTemps[0]);
557 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
558 ts.add(writeTemps[0]);
560 vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
563 vstTable.assertConsistency();
570 private void notAvailableForward(FlatMethod fm) {
572 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
573 flatNodesToVisit.add(fm);
575 while (!flatNodesToVisit.isEmpty()) {
576 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
577 flatNodesToVisit.remove(fn);
579 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
580 assert seseStack != null;
582 Set<TempDescriptor> prev = notAvailableResults.get(fn);
584 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
585 for (int i = 0; i < fn.numPrev(); i++) {
586 FlatNode nn = fn.getPrev(i);
587 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
588 if (notAvailIn != null) {
589 curr.addAll(notAvailIn);
593 if (!seseStack.empty()) {
594 notAvailable_nodeActions(fn, curr, seseStack.peek());
597 // if a new result, schedule forward nodes for analysis
598 if (!curr.equals(prev)) {
599 notAvailableResults.put(fn, curr);
601 for (int i = 0; i < fn.numNext(); i++) {
602 FlatNode nn = fn.getNext(i);
603 flatNodesToVisit.add(nn);
609 private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
610 FlatSESEEnterNode currentSESE) {
612 // any temps that are removed from the not available set
613 // at this node should be marked in this node's code plan
614 // as temps to be grabbed at runtime!
618 case FKind.FlatSESEEnterNode: {
619 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
620 assert fsen.equals(currentSESE);
622 // keep a copy of what's not available into the SESE
623 // and restore it at the matching exit node
624 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
625 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
626 while (tdItr.hasNext()) {
627 notAvailCopy.add(tdItr.next());
629 notAvailableIntoSESE.put(fsen, notAvailCopy);
635 case FKind.FlatSESEExitNode: {
636 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
637 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
638 assert currentSESE.getChildren().contains(fsen);
640 notAvailSet.addAll(fsen.getOutVarSet());
642 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
643 assert notAvailIn != null;
644 notAvailSet.addAll(notAvailIn);
649 case FKind.FlatMethod: {
653 case FKind.FlatOpNode: {
654 FlatOpNode fon = (FlatOpNode) fn;
656 if (fon.getOp().getOp() == Operation.ASSIGN) {
657 TempDescriptor lhs = fon.getDest();
658 TempDescriptor rhs = fon.getLeft();
660 // copy makes lhs same availability as rhs
661 if (notAvailSet.contains(rhs)) {
662 notAvailSet.add(lhs);
664 notAvailSet.remove(lhs);
667 // only break if this is an ASSIGN op node,
668 // otherwise fall through to default case
673 // note that FlatOpNode's that aren't ASSIGN
674 // fall through to this default case
676 TempDescriptor[] writeTemps = fn.writesTemps();
677 for (int i = 0; i < writeTemps.length; i++) {
678 TempDescriptor wTemp = writeTemps[i];
679 notAvailSet.remove(wTemp);
681 TempDescriptor[] readTemps = fn.readsTemps();
682 for (int i = 0; i < readTemps.length; i++) {
683 TempDescriptor rTemp = readTemps[i];
684 notAvailSet.remove(rTemp);
686 // if this variable has exactly one source, potentially
687 // get other things from this source as well
688 VarSrcTokTable vstTable = variableResults.get(fn);
690 VSTWrapper vstIfStatic = new VSTWrapper();
691 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
693 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
695 VariableSourceToken vst = vstIfStatic.vst;
697 Iterator<VariableSourceToken> availItr =
698 vstTable.get(vst.getSESE(), vst.getAge()).iterator();
700 // look through things that are also available from same source
701 while (availItr.hasNext()) {
702 VariableSourceToken vstAlsoAvail = availItr.next();
704 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
705 while (refVarItr.hasNext()) {
706 TempDescriptor refVarAlso = refVarItr.next();
708 // if a variable is available from the same source, AND it ALSO
709 // only comes from one statically known source, mark it available
710 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
711 Integer srcTypeAlso =
712 vstTable.getRefVarSrcType(refVarAlso, currentSESE, vstIfStaticNotUsed);
713 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
714 notAvailSet.remove(refVarAlso);
726 private void codePlansForward(FlatMethod fm) {
728 // start from flat method top, visit every node in
729 // method exactly once
730 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
731 flatNodesToVisit.add(fm);
733 Set<FlatNode> visited = new HashSet<FlatNode>();
735 while (!flatNodesToVisit.isEmpty()) {
736 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
737 FlatNode fn = fnItr.next();
739 flatNodesToVisit.remove(fn);
742 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
743 assert seseStack != null;
745 // use incoming results as "dot statement" or just
746 // before the current statement
747 VarSrcTokTable dotSTtable = new VarSrcTokTable();
748 for (int i = 0; i < fn.numPrev(); i++) {
749 FlatNode nn = fn.getPrev(i);
750 dotSTtable.merge(variableResults.get(nn));
753 // find dt-st notAvailableSet also
754 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
755 for (int i = 0; i < fn.numPrev(); i++) {
756 FlatNode nn = fn.getPrev(i);
757 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
758 if (notAvailIn != null) {
759 dotSTnotAvailSet.addAll(notAvailIn);
763 Set<TempDescriptor> dotSTlive = livenessRootView.get(fn);
765 if (!seseStack.empty()) {
766 codePlans_nodeActions(fn, dotSTlive, dotSTtable, dotSTnotAvailSet, seseStack.peek());
769 for (int i = 0; i < fn.numNext(); i++) {
770 FlatNode nn = fn.getNext(i);
772 if (!visited.contains(nn)) {
773 flatNodesToVisit.add(nn);
779 private void codePlans_nodeActions(FlatNode fn, Set<TempDescriptor> liveSetIn,
780 VarSrcTokTable vstTableIn, Set<TempDescriptor> notAvailSetIn, FlatSESEEnterNode currentSESE) {
782 CodePlan plan = new CodePlan(currentSESE);
786 case FKind.FlatSESEEnterNode: {
787 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
788 assert fsen.equals(currentSESE);
790 // track the source types of the in-var set so generated
791 // code at this SESE issue can compute the number of
792 // dependencies properly
793 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
794 while (inVarItr.hasNext()) {
795 TempDescriptor inVar = inVarItr.next();
797 // when we get to an SESE enter node we change the
798 // currentSESE variable of this analysis to the
799 // child that is declared by the enter node, so
800 // in order to classify in-vars correctly, pass
801 // the parent SESE in--at other FlatNode types just
802 // use the currentSESE
803 VSTWrapper vstIfStatic = new VSTWrapper();
804 Integer srcType = vstTableIn.getRefVarSrcType(inVar, fsen.getParent(), vstIfStatic);
806 // the current SESE needs a local space to track the dynamic
807 // variable and the child needs space in its SESE record
808 if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
809 fsen.addDynamicInVar(inVar);
810 fsen.getParent().addDynamicVar(inVar);
812 } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
813 fsen.addStaticInVar(inVar);
814 VariableSourceToken vst = vstIfStatic.vst;
815 fsen.putStaticInVar2src(inVar, vst);
816 fsen.addStaticInVarSrc(new SESEandAgePair(vst.getSESE(), vst.getAge()));
818 assert srcType.equals(VarSrcTokTable.SrcType_READY);
819 fsen.addReadyInVar(inVar);
826 case FKind.FlatSESEExitNode: {
827 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
831 case FKind.FlatOpNode: {
832 FlatOpNode fon = (FlatOpNode) fn;
834 if (fon.getOp().getOp() == Operation.ASSIGN) {
835 TempDescriptor lhs = fon.getDest();
836 TempDescriptor rhs = fon.getLeft();
838 // if this is an op node, don't stall, copy
839 // source and delay until we need to use value
841 // ask whether lhs and rhs sources are dynamic, static, etc.
842 VSTWrapper vstIfStatic = new VSTWrapper();
843 Integer lhsSrcType = vstTableIn.getRefVarSrcType(lhs, currentSESE, vstIfStatic);
844 Integer rhsSrcType = vstTableIn.getRefVarSrcType(rhs, currentSESE, vstIfStatic);
846 if (rhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
847 // if rhs is dynamic going in, lhs will definitely be dynamic
848 // going out of this node, so track that here
849 plan.addDynAssign(lhs, rhs);
850 currentSESE.addDynamicVar(lhs);
851 currentSESE.addDynamicVar(rhs);
853 } else if (lhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
854 // otherwise, if the lhs is dynamic, but the rhs is not, we
855 // need to update the variable's dynamic source as "current SESE"
856 plan.addDynAssign(lhs);
859 // only break if this is an ASSIGN op node,
860 // otherwise fall through to default case
865 // note that FlatOpNode's that aren't ASSIGN
866 // fall through to this default case
869 // a node with no live set has nothing to stall for
870 if (liveSetIn == null) {
874 TempDescriptor[] readarray = fn.readsTemps();
875 for (int i = 0; i < readarray.length; i++) {
876 TempDescriptor readtmp = readarray[i];
878 // ignore temps that are definitely available
879 // when considering to stall on it
880 if (!notAvailSetIn.contains(readtmp)) {
884 // check the source type of this variable
885 VSTWrapper vstIfStatic = new VSTWrapper();
886 Integer srcType = vstTableIn.getRefVarSrcType(readtmp, currentSESE, vstIfStatic);
888 if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
889 // 1) It is not clear statically where this variable will
890 // come from, so dynamically we must keep track
891 // along various control paths, and therefore when we stall,
892 // just stall for the exact thing we need and move on
893 plan.addDynamicStall(readtmp);
894 currentSESE.addDynamicVar(readtmp);
896 } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
897 // 2) Single token/age pair: Stall for token/age pair, and copy
898 // all live variables with same token/age pair at the same
899 // time. This is the same stuff that the notavaialable analysis
900 // marks as now available.
901 VariableSourceToken vst = vstIfStatic.vst;
903 Iterator<VariableSourceToken> availItr =
904 vstTableIn.get(vst.getSESE(), vst.getAge()).iterator();
906 while (availItr.hasNext()) {
907 VariableSourceToken vstAlsoAvail = availItr.next();
909 // only grab additional stuff that is live
910 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
912 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
913 while (refVarItr.hasNext()) {
914 TempDescriptor refVar = refVarItr.next();
915 if (liveSetIn.contains(refVar)) {
920 if (!copySet.isEmpty()) {
921 plan.addStall2CopySet(vstAlsoAvail, copySet);
926 // the other case for srcs is READY, so do nothing
929 // assert that everything being stalled for is in the
930 // "not available" set coming into this flat node and
931 // that every VST identified is in the possible "stall set"
932 // that represents VST's from children SESE's
940 // identify sese-age pairs that are statically useful
941 // and should have an associated SESE variable in code
942 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
943 // AND ALWAYS GIVE NAMES TO PARENTS
944 Set<VariableSourceToken> staticSet = vstTableIn.get();
945 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
946 while (vstItr.hasNext()) {
947 VariableSourceToken vst = vstItr.next();
949 // placeholder source tokens are useful results, but
950 // the placeholder static name is never needed
951 if (vst.getSESE().getIsCallerSESEplaceholder()) {
955 FlatSESEEnterNode sese = currentSESE;
956 while (sese != null) {
957 sese.addNeededStaticName(new SESEandAgePair(vst.getSESE(), vst.getAge()));
958 sese.mustTrackAtLeastAge(vst.getAge());
960 sese = sese.getParent();
964 codePlans.put(fn, plan);
966 // if any variables at this-node-*dot* have a static source (exactly one
968 // but go to a dynamic source at next-node-*dot*, create a new IR graph
969 // node on that edge to track the sources dynamically
970 VarSrcTokTable thisVstTable = variableResults.get(fn);
971 for (int i = 0; i < fn.numNext(); i++) {
972 FlatNode nn = fn.getNext(i);
973 VarSrcTokTable nextVstTable = variableResults.get(nn);
974 Set<TempDescriptor> nextLiveIn = livenessRootView.get(nn);
976 // the table can be null if it is one of the few IR nodes
977 // completely outside of the root SESE scope
978 if (nextVstTable != null && nextLiveIn != null) {
980 Hashtable<TempDescriptor, VSTWrapper> readyOrStatic2dynamicSet =
981 thisVstTable.getReadyOrStatic2DynamicSet(nextVstTable, nextLiveIn, currentSESE);
983 if (!readyOrStatic2dynamicSet.isEmpty()) {
985 // either add these results to partial fixed-point result
986 // or make a new one if we haven't made any here yet
987 FlatEdge fe = new FlatEdge(fn, nn);
988 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get(fe);
991 fwdvn = new FlatWriteDynamicVarNode(fn, nn, readyOrStatic2dynamicSet, currentSESE);
992 wdvNodesToSpliceIn.put(fe, fwdvn);
994 fwdvn.addMoreVar2Src(readyOrStatic2dynamicSet);
1001 private void makeConflictGraph(FlatMethod fm) {
1003 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1004 flatNodesToVisit.add(fm);
1006 Set<FlatNode> visited = new HashSet<FlatNode>();
1008 while (!flatNodesToVisit.isEmpty()) {
1009 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
1010 flatNodesToVisit.remove(fn);
1013 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
1014 assert seseStack != null;
1016 if (!seseStack.isEmpty()) {
1017 conflictGraph_nodeAction(fn, seseStack.peek());
1020 // schedule forward nodes for analysis
1021 for (int i = 0; i < fn.numNext(); i++) {
1022 FlatNode nn = fn.getNext(i);
1023 if (!visited.contains(nn)) {
1024 flatNodesToVisit.add(nn);
1032 private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
1034 ConflictGraph conflictGraph;
1038 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
1040 switch (fn.kind()) {
1042 case FKind.FlatFieldNode:
1043 case FKind.FlatElementNode: {
1045 if (fn instanceof FlatFieldNode) {
1046 FlatFieldNode ffn = (FlatFieldNode) fn;
1049 FlatElementNode fen = (FlatElementNode) fn;
1053 // jjenista - I think the following code is WRONG!!!
1054 // We are looking at some non-task FlatNode fn that is a stall site and
1055 // considering what conflicts it might have with CHILDREN of the CURRENT TASK
1056 // that contains fn. WE SHOULD NOT BE GETTING THE PARENT OF currentSESE
1057 // because in this scenario currentSESE IS the parent in relation to other
1058 // tasks that might conflict with this fn.
1059 // OK, why not fix it? Because code all over the place is built on
1060 // being able to retrieve the correct conflict graph, which is associated
1061 // with the wrong task, but at least consistently, SO LEAVE IT BUT REALIZE
1062 // WHAT IS HAPPENING
1064 Set<FlatSESEEnterNode> parentSet = currentSESE.getSESEParent();
1065 for (Iterator iterator = parentSet.iterator(); iterator.hasNext();) {
1066 FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
1067 // System.out.println("##current="+currentSESE.getmdEnclosing()+" PARENT=" + parent);
1068 conflictGraph = sese2conflictGraph.get(parent);
1069 if (conflictGraph == null) {
1070 conflictGraph = new ConflictGraph(state);
1074 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1075 conflictGraph.addStallSite(taint2Effects, rhs);
1076 if (taint2Effects != null)
1077 // System.out.println("add =" + taint2Effects + "currentSESE=" + parent
1078 // + " into conflictGraph=" + conflictGraph);
1080 if (conflictGraph.id2cn.size() > 0) {
1081 sese2conflictGraph.put(parent, conflictGraph);
1088 case FKind.FlatSetFieldNode:
1089 case FKind.FlatSetElementNode: {
1091 if (fn instanceof FlatSetFieldNode) {
1092 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
1093 lhs = fsfn.getDst();
1094 rhs = fsfn.getSrc();
1096 FlatSetElementNode fsen = (FlatSetElementNode) fn;
1097 lhs = fsen.getDst();
1098 rhs = fsen.getSrc();
1101 // jjenista - I think the following code is WRONG!!!
1102 // We are looking at some non-task FlatNode fn that is a stall site and
1103 // considering what conflicts it might have with CHILDREN of the CURRENT TASK
1104 // that contains fn. WE SHOULD NOT BE GETTING THE PARENT OF currentSESE
1105 // because in this scenario currentSESE IS the parent in relation to other
1106 // tasks that might conflict with this fn.
1107 // OK, why not fix it? Because code all over the place is built on
1108 // being able to retrieve the correct conflict graph, which is associated
1109 // with the wrong task, but at least consistently, SO LEAVE IT BUT REALIZE
1110 // WHAT IS HAPPENING
1112 // collects effects of stall site and generates stall site node
1113 Set<FlatSESEEnterNode> parentSet = currentSESE.getSESEParent();
1114 for (Iterator iterator = parentSet.iterator(); iterator.hasNext();) {
1115 FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
1116 conflictGraph = sese2conflictGraph.get(parent);
1117 if (conflictGraph == null) {
1118 conflictGraph = new ConflictGraph(state);
1121 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1122 conflictGraph.addStallSite(taint2Effects, rhs);
1123 conflictGraph.addStallSite(taint2Effects, lhs);
1125 if (conflictGraph.id2cn.size() > 0) {
1126 sese2conflictGraph.put(parent, conflictGraph);
1133 case FKind.FlatCall: {
1134 conflictGraph = sese2conflictGraph.get(currentSESE);
1135 if (conflictGraph == null) {
1136 conflictGraph = new ConflictGraph(state);
1139 FlatCall fc = (FlatCall) fn;
1142 // collects effects of stall site and generates stall site node
1143 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1145 // jjenista - I think the following code is WRONG!!!
1146 // We are looking at some non-task FlatNode fn that is a stall site and
1147 // considering what conflicts it might have with CHILDREN of the CURRENT TASK
1148 // that contains fn. WE SHOULD NOT BE GETTING THE PARENT OF currentSESE
1149 // because in this scenario currentSESE IS the parent in relation to other
1150 // tasks that might conflict with this fn.
1151 // OK, why not fix it? Because code all over the place is built on
1152 // being able to retrieve the correct conflict graph, which is associated
1153 // with the wrong task, but at least consistently, SO LEAVE IT BUT REALIZE
1154 // WHAT IS HAPPENING
1156 Set<FlatSESEEnterNode> parentSet = currentSESE.getSESEParent();
1157 for (Iterator iterator = parentSet.iterator(); iterator.hasNext();) {
1158 FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
1159 conflictGraph = sese2conflictGraph.get(parent);
1160 if (conflictGraph == null) {
1161 conflictGraph = new ConflictGraph(state);
1164 conflictGraph.addStallSite(taint2Effects, lhs);
1165 if (conflictGraph.id2cn.size() > 0) {
1166 sese2conflictGraph.put(parent, conflictGraph);
1179 private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
1180 // decide fine-grain edge or coarse-grain edge among all vertexes by
1181 // pair-wise comparison
1182 Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
1183 while (seseIter.hasNext()) {
1184 FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
1185 ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
1186 // System.out.println("# CALCULATING SESE CONFLICT="+sese);
1188 // clear current conflict before recalculating with reachability info
1189 conflictGraph.clearAllConflictEdge();
1190 conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
1191 conflictGraph.setFMEnclosing(sese.getfmEnclosing());
1193 conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
1194 sese2conflictGraph.put(sese, conflictGraph);
1198 private void writeConflictGraph() {
1199 Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
1200 while (keyEnum.hasMoreElements()) {
1201 FlatNode key = (FlatNode) keyEnum.nextElement();
1202 ConflictGraph cg = sese2conflictGraph.get(key);
1204 if (cg.hasConflictEdge()) {
1205 cg.writeGraph("ConflictGraphFor" + key, false);
1207 } catch (IOException e) {
1208 System.out.println("Error writing");
1214 private void synthesizeLocks() {
1215 Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
1216 for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
1217 Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
1218 FlatNode sese = graphEntry.getKey();
1219 ConflictGraph conflictGraph = graphEntry.getValue();
1220 calculateCovering(conflictGraph);
1224 private void calculateCovering(ConflictGraph conflictGraph) {
1225 uniqueLockSetId = 0; // reset lock counter for every new conflict graph
1226 HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
1227 HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
1228 HashSet<SESELock> lockSet = new HashSet<SESELock>();
1230 Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
1231 for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
1232 ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
1233 if (conflictEdge.isCoarseEdge()) {
1234 coarseToCover.add(conflictEdge);
1236 fineToCover.add(conflictEdge);
1240 HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
1241 toCover.addAll(fineToCover);
1242 toCover.addAll(coarseToCover);
1244 while (!toCover.isEmpty()) {
1246 SESELock seseLock = new SESELock();
1247 seseLock.setID(uniqueLockSetId++);
1251 do { // fine-grained edge
1255 for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
1258 ConflictEdge edge = (ConflictEdge) iterator.next();
1259 if (seseLock.getConflictNodeSet().size() == 0) {
1261 if (seseLock.isWriteNode(edge.getVertexU())) {
1262 // mark as fine_write
1263 if (edge.getVertexU().isStallSiteNode()) {
1264 type = ConflictNode.PARENT_WRITE;
1266 type = ConflictNode.FINE_WRITE;
1268 seseLock.addConflictNode(edge.getVertexU(), type);
1270 // mark as fine_read
1271 if (edge.getVertexU().isStallSiteNode()) {
1272 type = ConflictNode.PARENT_READ;
1274 type = ConflictNode.FINE_READ;
1276 seseLock.addConflictNode(edge.getVertexU(), type);
1278 if (edge.getVertexV() != edge.getVertexU()) {
1279 if (seseLock.isWriteNode(edge.getVertexV())) {
1280 // mark as fine_write
1281 if (edge.getVertexV().isStallSiteNode()) {
1282 type = ConflictNode.PARENT_WRITE;
1284 type = ConflictNode.FINE_WRITE;
1286 seseLock.addConflictNode(edge.getVertexV(), type);
1288 // mark as fine_read
1289 if (edge.getVertexV().isStallSiteNode()) {
1290 type = ConflictNode.PARENT_READ;
1292 type = ConflictNode.FINE_READ;
1294 seseLock.addConflictNode(edge.getVertexV(), type);
1298 seseLock.addConflictEdge(edge);
1299 fineToCover.remove(edge);
1300 break;// exit iterator loop
1301 }// end of initial setup
1303 ConflictNode newNode;
1304 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1305 // new node has a fine-grained edge to all current node
1306 // If there is a coarse grained edge where need a fine edge, it's
1307 // okay to add the node
1308 // but the edge must remain uncovered.
1312 if (seseLock.containsConflictNode(newNode)) {
1313 seseLock.addEdge(edge);
1314 fineToCover.remove(edge);
1318 if (seseLock.isWriteNode(newNode)) {
1319 if (newNode.isStallSiteNode()) {
1320 type = ConflictNode.PARENT_WRITE;
1322 type = ConflictNode.FINE_WRITE;
1324 seseLock.setNodeType(newNode, type);
1326 if (newNode.isStallSiteNode()) {
1327 type = ConflictNode.PARENT_READ;
1329 type = ConflictNode.FINE_READ;
1331 seseLock.setNodeType(newNode, type);
1334 seseLock.addEdge(edge);
1335 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1336 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1337 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1339 // mark all fine edges between new node and nodes in the group as
1341 if (!conflictEdge.getVertexU().equals(newNode)) {
1342 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1344 seseLock.addConflictEdge(conflictEdge);
1345 fineToCover.remove(conflictEdge);
1347 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1348 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1350 seseLock.addConflictEdge(conflictEdge);
1351 fineToCover.remove(conflictEdge);
1357 break;// exit iterator loop
1362 HashSet<ConflictEdge> notCovered=new HashSet<ConflictEdge>();
1366 for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
1368 ConflictEdge edge = (ConflictEdge) iterator.next();
1369 if (seseLock.getConflictNodeSet().size() == 0) {
1371 if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
1372 // node has a coarse-grained edge with itself
1373 if (!(edge.getVertexU().isStallSiteNode())) {
1374 // and it is not parent
1375 type = ConflictNode.SCC;
1378 type = ConflictNode.PARENT_COARSE;
1380 type = ConflictNode.PARENT_WRITE;
1383 seseLock.addConflictNode(edge.getVertexU(), type);
1385 if (edge.getVertexU().isStallSiteNode()) {
1387 type = ConflictNode.PARENT_COARSE;
1389 if (edge.getVertexU().getWriteEffectSet().isEmpty()) {
1390 type = ConflictNode.PARENT_READ;
1392 type = ConflictNode.PARENT_WRITE;
1396 type = ConflictNode.COARSE;
1398 seseLock.addConflictNode(edge.getVertexU(), type);
1400 if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
1401 // node has a coarse-grained edge with itself
1402 if (!(edge.getVertexV().isStallSiteNode())) {
1403 // and it is not parent
1404 type = ConflictNode.SCC;
1407 type = ConflictNode.PARENT_COARSE;
1409 type = ConflictNode.PARENT_WRITE;
1412 seseLock.addConflictNode(edge.getVertexV(), type);
1414 if (edge.getVertexV().isStallSiteNode()) {
1416 type = ConflictNode.PARENT_COARSE;
1418 if (edge.getVertexV().getWriteEffectSet().isEmpty()) {
1419 type = ConflictNode.PARENT_READ;
1421 type = ConflictNode.PARENT_WRITE;
1425 type = ConflictNode.COARSE;
1427 seseLock.addConflictNode(edge.getVertexV(), type);
1430 coarseToCover.remove(edge);
1431 seseLock.addConflictEdge(edge);
1432 break;// exit iterator loop
1433 }// end of initial setup
1435 ConflictNode newNode;
1436 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1437 // new node has a coarse-grained edge to all fine-read, fine-write,
1441 if (newNode.isInVarNode() && (!seseLock.hasSelfCoarseEdge(newNode))
1442 && seseLock.hasCoarseEdgeWithParentCoarse(newNode)) {
1443 // this case can't be covered by this queue
1444 coarseToCover.remove(edge);
1445 notCovered.add(edge);
1449 if (seseLock.containsConflictNode(newNode)) {
1450 seseLock.addEdge(edge);
1451 coarseToCover.remove(edge);
1455 if (seseLock.hasSelfCoarseEdge(newNode)) {
1457 if (newNode.isStallSiteNode()) {
1458 type = ConflictNode.PARENT_COARSE;
1460 type = ConflictNode.SCC;
1462 seseLock.setNodeType(newNode, type);
1464 if (newNode.isStallSiteNode()) {
1465 type = ConflictNode.PARENT_COARSE;
1467 type = ConflictNode.COARSE;
1469 seseLock.setNodeType(newNode, type);
1472 seseLock.addEdge(edge);
1473 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1474 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1475 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1476 // mark all coarse edges between new node and nodes in the group
1478 if (!conflictEdge.getVertexU().equals(newNode)) {
1479 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1481 seseLock.addConflictEdge(conflictEdge);
1482 coarseToCover.remove(conflictEdge);
1484 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1485 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1487 seseLock.addConflictEdge(conflictEdge);
1488 coarseToCover.remove(conflictEdge);
1493 break;// exit iterator loop
1499 lockSet.add(seseLock);
1502 coarseToCover.addAll(notCovered);
1503 toCover.addAll(fineToCover);
1504 toCover.addAll(coarseToCover);
1508 conflictGraph2SESELock.put(conflictGraph, lockSet);
1511 public ConflictGraph getConflictGraph(FlatNode sese) {
1512 return sese2conflictGraph.get(sese);
1515 public Set<SESELock> getLockMappings(ConflictGraph graph) {
1516 return conflictGraph2SESELock.get(graph);
1519 public Set<FlatSESEEnterNode> getAllSESEs() {
1520 return rblockRel.getAllSESEs();
1523 public FlatSESEEnterNode getMainSESE() {
1524 return rblockRel.getMainSESE();
1527 public void writeReports(String timeReport) throws java.io.IOException {
1529 BufferedWriter bw = new BufferedWriter(new FileWriter("mlpReport_summary.txt"));
1530 bw.write("MLP Analysis Results\n\n");
1531 bw.write(timeReport + "\n\n");
1532 printSESEHierarchy(bw);
1537 Iterator<Descriptor> methItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
1538 while (methItr.hasNext()) {
1539 MethodDescriptor md = (MethodDescriptor) methItr.next();
1540 FlatMethod fm = state.getMethodFlat(md);
1543 new BufferedWriter(new FileWriter("mlpReport_" + md.getClassMethodName()
1544 + md.getSafeMethodDescriptor() + ".txt"));
1545 bw.write("MLP Results for " + md + "\n-------------------\n");
1547 FlatSESEEnterNode implicitSESE = (FlatSESEEnterNode) fm.getNext(0);
1548 if (!implicitSESE.getIsCallerSESEplaceholder() && implicitSESE != rblockRel.getMainSESE()) {
1549 System.out.println(implicitSESE + " is not implicit?!");
1552 bw.write("Dynamic vars to manage:\n " + implicitSESE.getDynamicVarSet());
1554 bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessRootView));
1555 bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
1556 bw.write("\n\nNot Available Results-Out\n---------------------\n"
1557 + fm.printMethod(notAvailableResults));
1558 bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
1564 private void printSESEHierarchy(BufferedWriter bw) throws java.io.IOException {
1565 bw.write("SESE Hierarchy\n--------------\n");
1566 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1567 while (rootItr.hasNext()) {
1568 FlatSESEEnterNode root = rootItr.next();
1569 if (root.getIsCallerSESEplaceholder()) {
1570 if (!root.getChildren().isEmpty()) {
1571 printSESEHierarchyTree(bw, root, 0);
1574 printSESEHierarchyTree(bw, root, 0);
1579 private void printSESEHierarchyTree(BufferedWriter bw, FlatSESEEnterNode fsen, int depth)
1580 throws java.io.IOException {
1581 for (int i = 0; i < depth; ++i) {
1584 bw.write("- " + fsen.getPrettyIdentifier() + "\n");
1586 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1587 while (childItr.hasNext()) {
1588 FlatSESEEnterNode fsenChild = childItr.next();
1589 printSESEHierarchyTree(bw, fsenChild, depth + 1);
1593 private void printSESEInfo(BufferedWriter bw) throws java.io.IOException {
1594 bw.write("\nSESE info\n-------------\n");
1595 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1596 while (rootItr.hasNext()) {
1597 FlatSESEEnterNode root = rootItr.next();
1598 if (root.getIsCallerSESEplaceholder()) {
1599 if (!root.getChildren().isEmpty()) {
1600 printSESEInfoTree(bw, root);
1603 printSESEInfoTree(bw, root);
1608 public DisjointAnalysis getDisjointAnalysis() {
1609 return disjointAnalysisTaints;
1612 private void printSESEInfoTree(BufferedWriter bw, FlatSESEEnterNode fsen)
1613 throws java.io.IOException {
1615 if (!fsen.getIsCallerSESEplaceholder()) {
1616 bw.write("SESE " + fsen.getPrettyIdentifier());
1617 if( fsen.getIsLeafSESE() ) {
1618 bw.write(" (leaf)");
1622 bw.write(" in-set: " + fsen.getInVarSet() + "\n");
1623 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1624 while (tItr.hasNext()) {
1625 TempDescriptor inVar = tItr.next();
1626 if (fsen.getReadyInVarSet().contains(inVar)) {
1627 bw.write(" (ready) " + inVar + "\n");
1629 if (fsen.getStaticInVarSet().contains(inVar)) {
1630 bw.write(" (static) " + inVar + " from " + fsen.getStaticInVarSrc(inVar) + "\n");
1632 if (fsen.getDynamicInVarSet().contains(inVar)) {
1633 bw.write(" (dynamic)" + inVar + "\n");
1637 bw.write(" Dynamic vars to manage: " + fsen.getDynamicVarSet() + "\n");
1639 bw.write(" out-set: " + fsen.getOutVarSet() + "\n");
1643 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1644 while (childItr.hasNext()) {
1645 FlatSESEEnterNode fsenChild = childItr.next();
1646 printSESEInfoTree(bw, fsenChild);