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;
11 import java.util.Stack;
12 import java.util.Map.Entry;
14 import Analysis.ArrayReferencees;
15 import Analysis.Liveness;
16 import Analysis.CallGraph.CallGraph;
17 import Analysis.Disjoint.DisjointAnalysis;
18 import Analysis.Disjoint.Effect;
19 import Analysis.Disjoint.EffectsAnalysis;
20 import Analysis.Disjoint.Taint;
22 import IR.MethodDescriptor;
27 import IR.Flat.FlatEdge;
28 import IR.Flat.FlatFieldNode;
29 import IR.Flat.FlatMethod;
30 import IR.Flat.FlatNode;
31 import IR.Flat.FlatOpNode;
32 import IR.Flat.FlatNew;
33 import IR.Flat.FlatSESEEnterNode;
34 import IR.Flat.FlatSESEExitNode;
35 import IR.Flat.FlatSetFieldNode;
36 import IR.Flat.FlatWriteDynamicVarNode;
37 import IR.Flat.TempDescriptor;
39 public class OoOJavaAnalysis {
41 // data from the compiler
43 private TypeUtil typeUtil;
44 private CallGraph callGraph;
45 private RBlockRelationAnalysis rblockRel;
46 private RBlockStatusAnalysis rblockStatus;
47 private DisjointAnalysis disjointAnalysisTaints;
48 private DisjointAnalysis disjointAnalysisReach;
50 private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
51 private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
52 private Hashtable<FlatNode, VarSrcTokTable> variableResults;
53 private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
54 private Hashtable<FlatNode, CodePlan> codePlans;
56 private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
58 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
60 // temporal data structures to track analysis progress.
61 static private int uniqueLockSetId = 0;
62 // mapping of a conflict graph to its compiled lock
63 private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
64 // mapping of a sese block to its conflict graph
65 private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
70 // private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
71 // private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
72 // private OwnershipAnalysis ownAnalysisForSESEConflicts;
74 // static private int uniqueLockSetId = 0;
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 // conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
120 // methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
121 // conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
123 // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
124 // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
125 // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
127 // 1st pass, find basic rblock relations
128 rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
130 rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
133 // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
134 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
135 while (rootItr.hasNext()) {
136 FlatSESEEnterNode root = rootItr.next();
137 livenessAnalysisBackward(root, true, null);
140 // 3rd pass, variable analysis
141 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
142 while (methItr.hasNext()) {
143 Descriptor d = methItr.next();
144 FlatMethod fm = state.getMethodFlat(d);
146 // starting from roots do a forward, fixed-point
147 // variable analysis for refinement and stalls
148 variableAnalysisForward(fm);
151 // 4th pass, compute liveness contribution from
152 // virtual reads discovered in variable pass
153 rootItr = rblockRel.getRootSESEs().iterator();
154 while (rootItr.hasNext()) {
155 FlatSESEEnterNode root = rootItr.next();
156 livenessAnalysisBackward(root, true, null);
159 // 5th pass, use disjointness with NO FLAGGED REGIONS
160 // to compute taints and effects
161 disjointAnalysisTaints =
162 new DisjointAnalysis(state,
167 null, // no FlatNew set to flag
172 // 6th pass, not available analysis FOR VARIABLES!
173 methItr = descriptorsToAnalyze.iterator();
174 while (methItr.hasNext()) {
175 Descriptor d = methItr.next();
176 FlatMethod fm = state.getMethodFlat(d);
178 // compute what is not available at every program
179 // point, in a forward fixed-point pass
180 notAvailableForward(fm);
183 // 7th pass, make conflict graph
184 // conflict graph is maintained by each parent sese,
185 Iterator descItr=disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
186 while (descItr.hasNext()) {
187 Descriptor d = (Descriptor)descItr.next();
188 FlatMethod fm = state.getMethodFlat(d);
190 makeConflictGraph(fm);
194 Iterator iter = sese2conflictGraph.entrySet().iterator();
195 while (iter.hasNext()) {
196 Entry e = (Entry) iter.next();
197 FlatNode fn = (FlatNode) e.getKey();
198 ConflictGraph conflictGraph = (ConflictGraph) e.getValue();
199 System.out.println("---------------------------------------");
200 System.out.println("CONFLICT GRAPH for " + fn);
201 Set<String> keySet = conflictGraph.id2cn.keySet();
202 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
203 String key = (String) iterator.next();
204 ConflictNode node = conflictGraph.id2cn.get(key);
205 System.out.println("key=" + key + " \n" + node.toStringAllEffects());
209 // 8th pass, calculate all possible conflicts without using reachability info
210 // and identify set of FlatNew that next disjoint reach. analysis should flag
211 Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
212 calculateConflicts(sitesToFlag,false);
214 // 9th pass, ask disjoint analysis to compute reachability
215 // for objects that may cause heap conflicts so the most
216 // efficient method to deal with conflict can be computed
218 disjointAnalysisReach =
219 new DisjointAnalysis(state,
225 null, // don't do effects analysis again!
226 null // don't do effects analysis again!
228 //writeConflictGraph();
229 // 10th pass, calculate conflicts with reachability info
230 calculateConflicts(null, true);
233 // 11th pass, compiling locks
236 // #th pass, writing conflict graph
237 writeConflictGraph();
240 if( state.OOODEBUG ) {
243 disjointAnalysisTaints.getEffectsAnalysis().writeEffects( "effects.txt" );
244 writeConflictGraph();
245 } catch( IOException e ) {}
250 private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
251 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
253 // start from an SESE exit, visit nodes in reverse up to
254 // SESE enter in a fixed-point scheme, where children SESEs
255 // should already be analyzed and therefore can be skipped
256 // because child SESE enter node has all necessary info
257 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
260 flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
262 flatNodesToVisit.add(fsen.getFlatExit());
265 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
268 liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
271 while (!flatNodesToVisit.isEmpty()) {
272 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
273 flatNodesToVisit.remove(fn);
275 Set<TempDescriptor> prev = livenessResults.get(fn);
277 // merge sets from control flow joins
278 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
279 for (int i = 0; i < fn.numNext(); i++) {
280 FlatNode nn = fn.getNext(i);
281 Set<TempDescriptor> s = livenessResults.get(nn);
287 Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
289 // if a new result, schedule backward nodes for analysis
290 if (!curr.equals(prev)) {
291 livenessResults.put(fn, curr);
293 // don't flow backwards past current SESE enter
294 if (!fn.equals(fsen)) {
295 for (int i = 0; i < fn.numPrev(); i++) {
296 FlatNode nn = fn.getPrev(i);
297 flatNodesToVisit.add(nn);
303 Set<TempDescriptor> s = livenessResults.get(fsen);
308 // remember liveness per node from the root view as the
309 // global liveness of variables for later passes to use
311 livenessRootView.putAll(livenessResults);
314 // post-order traversal, so do children first
315 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
316 while (childItr.hasNext()) {
317 FlatSESEEnterNode fsenChild = childItr.next();
318 livenessAnalysisBackward(fsenChild, false, liveout);
322 private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
323 FlatSESEEnterNode currentSESE, boolean toplevel,
324 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
327 case FKind.FlatSESEExitNode:
329 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
330 if (!liveout.containsKey(fsexn)) {
331 liveout.put(fsexn, new HashSet<TempDescriptor>());
333 liveout.get(fsexn).addAll(liveIn);
335 // no break, sese exits should also execute default actions
338 // handle effects of statement in reverse, writes then reads
339 TempDescriptor[] writeTemps = fn.writesTemps();
340 for (int i = 0; i < writeTemps.length; ++i) {
341 liveIn.remove(writeTemps[i]);
344 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
345 Set<TempDescriptor> livetemps = liveout.get(fsexn);
346 if (livetemps != null && livetemps.contains(writeTemps[i])) {
347 // write to a live out temp...
348 // need to put in SESE liveout set
349 currentSESE.addOutVar(writeTemps[i]);
354 TempDescriptor[] readTemps = fn.readsTemps();
355 for (int i = 0; i < readTemps.length; ++i) {
356 liveIn.add(readTemps[i]);
359 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
360 if (virtualReadTemps != null) {
361 liveIn.addAll(virtualReadTemps);
372 private void variableAnalysisForward(FlatMethod fm) {
374 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
375 flatNodesToVisit.add(fm);
377 while (!flatNodesToVisit.isEmpty()) {
378 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
379 flatNodesToVisit.remove(fn);
381 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
382 assert seseStack != null;
384 VarSrcTokTable prev = variableResults.get(fn);
386 // merge sets from control flow joins
387 VarSrcTokTable curr = new VarSrcTokTable();
388 for (int i = 0; i < fn.numPrev(); i++) {
389 FlatNode nn = fn.getPrev(i);
390 VarSrcTokTable incoming = variableResults.get(nn);
391 curr.merge(incoming);
394 if (!seseStack.empty()) {
395 variable_nodeActions(fn, curr, seseStack.peek());
398 // if a new result, schedule forward nodes for analysis
399 if (!curr.equals(prev)) {
400 variableResults.put(fn, curr);
402 for (int i = 0; i < fn.numNext(); i++) {
403 FlatNode nn = fn.getNext(i);
404 flatNodesToVisit.add(nn);
410 private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
411 FlatSESEEnterNode currentSESE) {
414 case FKind.FlatSESEEnterNode: {
415 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
416 assert fsen.equals(currentSESE);
418 vstTable.age(currentSESE);
419 vstTable.assertConsistency();
423 case FKind.FlatSESEExitNode: {
424 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
425 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
426 assert currentSESE.getChildren().contains(fsen);
428 // remap all of this child's children tokens to be
429 // from this child as the child exits
430 vstTable.remapChildTokens(fsen);
432 // liveness virtual reads are things that might be
433 // written by an SESE and should be added to the in-set
434 // anything virtually read by this SESE should be pruned
435 // of parent or sibling sources
436 Set<TempDescriptor> liveVars = livenessRootView.get(fn);
437 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
439 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
440 if (fsenVirtReadsOld != null) {
441 fsenVirtReads.addAll(fsenVirtReadsOld);
443 livenessVirtualReads.put(fn, fsenVirtReads);
445 // then all child out-set tokens are guaranteed
446 // to be filled in, so clobber those entries with
447 // the latest, clean sources
448 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
449 while (outVarItr.hasNext()) {
450 TempDescriptor outVar = outVarItr.next();
451 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
453 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
454 vstTable.remove(outVar);
457 vstTable.assertConsistency();
462 case FKind.FlatOpNode: {
463 FlatOpNode fon = (FlatOpNode) fn;
465 if (fon.getOp().getOp() == Operation.ASSIGN) {
466 TempDescriptor lhs = fon.getDest();
467 TempDescriptor rhs = fon.getLeft();
469 vstTable.remove(lhs);
471 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
473 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
474 while (itr.hasNext()) {
475 VariableSourceToken vst = itr.next();
477 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
480 if (currentSESE.getChildren().contains(vst.getSESE())) {
481 // if the source comes from a child, copy it over
482 forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
485 // otherwise, stamp it as us as the source
486 forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
490 vstTable.addAll(forAddition);
492 // only break if this is an ASSIGN op node,
493 // otherwise fall through to default case
494 vstTable.assertConsistency();
499 // note that FlatOpNode's that aren't ASSIGN
500 // fall through to this default case
502 TempDescriptor[] writeTemps = fn.writesTemps();
503 if (writeTemps.length > 0) {
505 // for now, when writeTemps > 1, make sure
506 // its a call node, programmer enforce only
507 // doing stuff like calling a print routine
508 // assert writeTemps.length == 1;
509 if (writeTemps.length > 1) {
510 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
514 vstTable.remove(writeTemps[0]);
516 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
517 ts.add(writeTemps[0]);
519 vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
522 vstTable.assertConsistency();
529 private void notAvailableForward(FlatMethod fm) {
531 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
532 flatNodesToVisit.add(fm);
534 while (!flatNodesToVisit.isEmpty()) {
535 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
536 flatNodesToVisit.remove(fn);
538 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
539 assert seseStack != null;
541 Set<TempDescriptor> prev = notAvailableResults.get(fn);
543 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
544 for (int i = 0; i < fn.numPrev(); i++) {
545 FlatNode nn = fn.getPrev(i);
546 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
547 if (notAvailIn != null) {
548 curr.addAll(notAvailIn);
552 if (!seseStack.empty()) {
553 notAvailable_nodeActions(fn, curr, seseStack.peek());
556 // if a new result, schedule forward nodes for analysis
557 if (!curr.equals(prev)) {
558 notAvailableResults.put(fn, curr);
560 for (int i = 0; i < fn.numNext(); i++) {
561 FlatNode nn = fn.getNext(i);
562 flatNodesToVisit.add(nn);
568 private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
569 FlatSESEEnterNode currentSESE) {
571 // any temps that are removed from the not available set
572 // at this node should be marked in this node's code plan
573 // as temps to be grabbed at runtime!
577 case FKind.FlatSESEEnterNode: {
578 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
579 assert fsen.equals(currentSESE);
581 // keep a copy of what's not available into the SESE
582 // and restore it at the matching exit node
583 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
584 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
585 while (tdItr.hasNext()) {
586 notAvailCopy.add(tdItr.next());
588 notAvailableIntoSESE.put(fsen, notAvailCopy);
594 case FKind.FlatSESEExitNode: {
595 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
596 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
597 assert currentSESE.getChildren().contains(fsen);
599 notAvailSet.addAll(fsen.getOutVarSet());
601 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
602 assert notAvailIn != null;
603 notAvailSet.addAll(notAvailIn);
608 case FKind.FlatMethod: {
612 case FKind.FlatOpNode: {
613 FlatOpNode fon = (FlatOpNode) fn;
615 if (fon.getOp().getOp() == Operation.ASSIGN) {
616 TempDescriptor lhs = fon.getDest();
617 TempDescriptor rhs = fon.getLeft();
619 // copy makes lhs same availability as rhs
620 if (notAvailSet.contains(rhs)) {
621 notAvailSet.add(lhs);
623 notAvailSet.remove(lhs);
626 // only break if this is an ASSIGN op node,
627 // otherwise fall through to default case
632 // note that FlatOpNode's that aren't ASSIGN
633 // fall through to this default case
635 TempDescriptor[] writeTemps = fn.writesTemps();
636 for (int i = 0; i < writeTemps.length; i++) {
637 TempDescriptor wTemp = writeTemps[i];
638 notAvailSet.remove(wTemp);
640 TempDescriptor[] readTemps = fn.readsTemps();
641 for (int i = 0; i < readTemps.length; i++) {
642 TempDescriptor rTemp = readTemps[i];
643 notAvailSet.remove(rTemp);
645 // if this variable has exactly one source, potentially
646 // get other things from this source as well
647 VarSrcTokTable vstTable = variableResults.get(fn);
649 VSTWrapper vstIfStatic = new VSTWrapper();
650 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
652 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
654 VariableSourceToken vst = vstIfStatic.vst;
656 Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
659 // look through things that are also available from same source
660 while (availItr.hasNext()) {
661 VariableSourceToken vstAlsoAvail = availItr.next();
663 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
664 while (refVarItr.hasNext()) {
665 TempDescriptor refVarAlso = refVarItr.next();
667 // if a variable is available from the same source, AND it ALSO
668 // only comes from one statically known source, mark it available
669 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
670 Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
672 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
673 notAvailSet.remove(refVarAlso);
685 private void makeConflictGraph(FlatMethod fm) {
687 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
688 flatNodesToVisit.add(fm);
690 Set<FlatNode> visited = new HashSet<FlatNode>();
692 while (!flatNodesToVisit.isEmpty()) {
693 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
694 flatNodesToVisit.remove(fn);
697 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
698 assert seseStack != null;
700 if (!seseStack.isEmpty()) {
702 ConflictGraph conflictGraph = sese2conflictGraph.get(seseStack.peek());
703 if (conflictGraph == null) {
704 conflictGraph = new ConflictGraph();
707 conflictGraph_nodeAction(fn, seseStack.peek());
710 // schedule forward nodes for analysis
711 for (int i = 0; i < fn.numNext(); i++) {
712 FlatNode nn = fn.getNext(i);
713 if (!visited.contains(nn)) {
714 flatNodesToVisit.add(nn);
723 private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
725 ConflictGraph conflictGraph;
726 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
730 case FKind.FlatSESEEnterNode: {
732 if (currentSESE.getParent() == null) {
735 conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
736 if (conflictGraph == null) {
737 conflictGraph = new ConflictGraph();
740 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
742 if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
743 // collects effects set of invar set and generates invar node
744 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(currentSESE);
745 conflictGraph.addLiveIn(taint2Effects);
748 if (conflictGraph.id2cn.size() > 0) {
749 sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
755 case FKind.FlatFieldNode:
756 case FKind.FlatElementNode: {
758 conflictGraph = sese2conflictGraph.get(currentSESE);
759 if (conflictGraph == null) {
760 conflictGraph = new ConflictGraph();
763 FlatFieldNode ffn = (FlatFieldNode) fn;
764 TempDescriptor rhs = ffn.getSrc();
767 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
768 conflictGraph.addStallSite(taint2Effects, rhs);
770 if (conflictGraph.id2cn.size() > 0) {
771 sese2conflictGraph.put(currentSESE, conflictGraph);
776 case FKind.FlatSetFieldNode:
777 case FKind.FlatSetElementNode: {
779 conflictGraph = sese2conflictGraph.get(currentSESE);
780 if (conflictGraph == null) {
781 conflictGraph = new ConflictGraph();
784 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
785 TempDescriptor lhs = fsfn.getDst();
786 TempDescriptor rhs = fsfn.getSrc();
788 // collects effects of stall site and generates stall site node
789 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
790 conflictGraph.addStallSite(taint2Effects, rhs);
791 conflictGraph.addStallSite(taint2Effects, lhs);
793 if (conflictGraph.id2cn.size() > 0) {
794 sese2conflictGraph.put(currentSESE, conflictGraph);
802 private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
803 // decide fine-grain edge or coarse-grain edge among all vertexes by
804 // pair-wise comparison
805 Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
806 while (seseIter.hasNext()) {
807 FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
808 ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
810 // clear current conflict before recalculating with reachability info
811 conflictGraph.clearAllConflictEdge();
812 conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
813 conflictGraph.setFMEnclosing(sese.getfmEnclosing());
815 conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
816 sese2conflictGraph.put(sese, conflictGraph);
820 private void writeConflictGraph() {
821 Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
822 while (keyEnum.hasMoreElements()) {
823 FlatNode key = (FlatNode) keyEnum.nextElement();
824 ConflictGraph cg = sese2conflictGraph.get(key);
826 if (cg.hasConflictEdge()) {
827 cg.writeGraph("ConflictGraphFor" + key, false);
829 } catch (IOException e) {
830 System.out.println("Error writing");
836 private void synthesizeLocks() {
837 Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
838 for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
839 Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
840 FlatNode sese = graphEntry.getKey();
841 ConflictGraph conflictGraph = graphEntry.getValue();
842 calculateCovering(conflictGraph);
846 private void calculateCovering(ConflictGraph conflictGraph) {
847 uniqueLockSetId = 0; // reset lock counter for every new conflict graph
848 HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
849 HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
850 HashSet<SESELock> lockSet = new HashSet<SESELock>();
852 Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
853 for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
854 ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
855 if (conflictEdge.isCoarseEdge()) {
856 coarseToCover.add(conflictEdge);
858 fineToCover.add(conflictEdge);
862 HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
863 toCover.addAll(fineToCover);
864 toCover.addAll(coarseToCover);
866 while (!toCover.isEmpty()) {
868 SESELock seseLock = new SESELock();
869 seseLock.setID(uniqueLockSetId++);
873 do { // fine-grained edge
877 for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
880 ConflictEdge edge = (ConflictEdge) iterator.next();
881 if (seseLock.getConflictNodeSet().size() == 0) {
883 if (seseLock.isWriteNode(edge.getVertexU())) {
884 // mark as fine_write
885 if (edge.getVertexU().isStallSiteNode()) {
886 type = ConflictNode.PARENT_WRITE;
888 type = ConflictNode.FINE_WRITE;
890 seseLock.addConflictNode(edge.getVertexU(), type);
893 if (edge.getVertexU().isStallSiteNode()) {
894 type = ConflictNode.PARENT_READ;
896 type = ConflictNode.FINE_READ;
898 seseLock.addConflictNode(edge.getVertexU(), type);
900 if (edge.getVertexV() != edge.getVertexU()) {
901 if (seseLock.isWriteNode(edge.getVertexV())) {
902 // mark as fine_write
903 if (edge.getVertexV().isStallSiteNode()) {
904 type = ConflictNode.PARENT_WRITE;
906 type = ConflictNode.FINE_WRITE;
908 seseLock.addConflictNode(edge.getVertexV(), type);
911 if (edge.getVertexV().isStallSiteNode()) {
912 type = ConflictNode.PARENT_READ;
914 type = ConflictNode.FINE_READ;
916 seseLock.addConflictNode(edge.getVertexV(), type);
920 seseLock.addConflictEdge(edge);
921 fineToCover.remove(edge);
922 break;// exit iterator loop
923 }// end of initial setup
925 ConflictNode newNode;
926 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
927 // new node has a fine-grained edge to all current node
928 // If there is a coarse grained edge where need a fine edge, it's
929 // okay to add the node
930 // but the edge must remain uncovered.
934 if (seseLock.isWriteNode(newNode)) {
935 if (newNode.isStallSiteNode()) {
936 type = ConflictNode.PARENT_WRITE;
938 type = ConflictNode.FINE_WRITE;
940 seseLock.setNodeType(newNode, type);
942 if (newNode.isStallSiteNode()) {
943 type = ConflictNode.PARENT_READ;
945 type = ConflictNode.FINE_READ;
947 seseLock.setNodeType(newNode, type);
950 seseLock.addEdge(edge);
951 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
952 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
953 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
955 // mark all fine edges between new node and nodes in the group as
957 if (!conflictEdge.getVertexU().equals(newNode)) {
958 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
960 seseLock.addConflictEdge(conflictEdge);
961 fineToCover.remove(conflictEdge);
963 } else if (!conflictEdge.getVertexV().equals(newNode)) {
964 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
966 seseLock.addConflictEdge(conflictEdge);
967 fineToCover.remove(conflictEdge);
973 break;// exit iterator loop
981 for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
983 ConflictEdge edge = (ConflictEdge) iterator.next();
985 if (seseLock.getConflictNodeSet().size() == 0) {
987 if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
988 // node has a coarse-grained edge with itself
989 if (!(edge.getVertexU().isStallSiteNode())) {
990 // and it is not parent
991 type = ConflictNode.SCC;
993 type = ConflictNode.PARENT_COARSE;
995 seseLock.addConflictNode(edge.getVertexU(), type);
997 if (edge.getVertexU().isStallSiteNode()) {
998 type = ConflictNode.PARENT_COARSE;
1000 type = ConflictNode.COARSE;
1002 seseLock.addConflictNode(edge.getVertexU(), type);
1004 if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
1005 // node has a coarse-grained edge with itself
1006 if (!(edge.getVertexV().isStallSiteNode())) {
1007 // and it is not parent
1008 type = ConflictNode.SCC;
1010 type = ConflictNode.PARENT_COARSE;
1012 seseLock.addConflictNode(edge.getVertexV(), type);
1014 if (edge.getVertexV().isStallSiteNode()) {
1015 type = ConflictNode.PARENT_COARSE;
1017 type = ConflictNode.COARSE;
1019 seseLock.addConflictNode(edge.getVertexV(), type);
1022 coarseToCover.remove(edge);
1023 seseLock.addConflictEdge(edge);
1024 break;// exit iterator loop
1025 }// end of initial setup
1027 ConflictNode newNode;
1028 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1029 // new node has a coarse-grained edge to all fine-read, fine-write,
1033 if (seseLock.hasSelfCoarseEdge(newNode)) {
1035 if (newNode.isStallSiteNode()) {
1036 type = ConflictNode.PARENT_COARSE;
1038 type = ConflictNode.SCC;
1040 seseLock.setNodeType(newNode, type);
1042 if (newNode.isStallSiteNode()) {
1043 type = ConflictNode.PARENT_COARSE;
1045 type = ConflictNode.COARSE;
1047 seseLock.setNodeType(newNode, type);
1050 seseLock.addEdge(edge);
1051 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1052 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1053 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1054 // mark all coarse edges between new node and nodes in the group
1056 if (!conflictEdge.getVertexU().equals(newNode)) {
1057 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1059 seseLock.addConflictEdge(conflictEdge);
1060 coarseToCover.remove(conflictEdge);
1062 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1063 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1065 seseLock.addConflictEdge(conflictEdge);
1066 coarseToCover.remove(conflictEdge);
1071 break;// exit iterator loop
1077 lockSet.add(seseLock);
1080 toCover.addAll(fineToCover);
1081 toCover.addAll(coarseToCover);
1085 conflictGraph2SESELock.put(conflictGraph, lockSet);
1088 public void writeReports( String timeReport ) throws java.io.IOException {
1090 BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
1091 bw.write( "MLP Analysis Results\n\n" );
1092 bw.write( timeReport+"\n\n" );
1093 printSESEHierarchy( bw );
1095 printSESEInfo( bw );
1098 Iterator<Descriptor> methItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
1099 while( methItr.hasNext() ) {
1100 MethodDescriptor md = (MethodDescriptor) methItr.next();
1101 FlatMethod fm = state.getMethodFlat( md );
1104 new BufferedWriter(new FileWriter("mlpReport_" + md.getClassMethodName()
1105 + md.getSafeMethodDescriptor() + ".txt"));
1106 bw.write("MLP Results for " + md + "\n-------------------\n");
1108 FlatSESEEnterNode implicitSESE = (FlatSESEEnterNode) fm.getNext(0);
1109 if (!implicitSESE.getIsCallerSESEplaceholder() && implicitSESE != rblockRel.getMainSESE()) {
1110 System.out.println(implicitSESE + " is not implicit?!");
1113 bw.write("Dynamic vars to manage:\n " + implicitSESE.getDynamicVarSet());
1115 bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessRootView));
1116 bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
1117 bw.write("\n\nNot Available Results-Out\n---------------------\n"
1118 + fm.printMethod(notAvailableResults));
1119 bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
1125 private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
1126 bw.write( "SESE Hierarchy\n--------------\n" );
1127 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1128 while( rootItr.hasNext() ) {
1129 FlatSESEEnterNode root = rootItr.next();
1130 if( root.getIsCallerSESEplaceholder() ) {
1131 if( !root.getChildren().isEmpty() ) {
1132 printSESEHierarchyTree( bw, root, 0 );
1135 printSESEHierarchyTree( bw, root, 0 );
1140 private void printSESEHierarchyTree( BufferedWriter bw,
1141 FlatSESEEnterNode fsen,
1143 ) throws java.io.IOException {
1144 for( int i = 0; i < depth; ++i ) {
1147 bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
1149 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1150 while( childItr.hasNext() ) {
1151 FlatSESEEnterNode fsenChild = childItr.next();
1152 printSESEHierarchyTree( bw, fsenChild, depth + 1 );
1157 private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
1158 bw.write("\nSESE info\n-------------\n" );
1159 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1160 while( rootItr.hasNext() ) {
1161 FlatSESEEnterNode root = rootItr.next();
1162 if( root.getIsCallerSESEplaceholder() ) {
1163 if( !root.getChildren().isEmpty() ) {
1164 printSESEInfoTree( bw, root );
1167 printSESEInfoTree( bw, root );
1172 private void printSESEInfoTree( BufferedWriter bw,
1173 FlatSESEEnterNode fsen
1174 ) throws java.io.IOException {
1176 if( !fsen.getIsCallerSESEplaceholder() ) {
1177 bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
1179 bw.write( " in-set: "+fsen.getInVarSet()+"\n" );
1180 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1181 while( tItr.hasNext() ) {
1182 TempDescriptor inVar = tItr.next();
1183 if( fsen.getReadyInVarSet().contains( inVar ) ) {
1184 bw.write( " (ready) "+inVar+"\n" );
1186 if( fsen.getStaticInVarSet().contains( inVar ) ) {
1187 bw.write( " (static) "+inVar+" from "+
1188 fsen.getStaticInVarSrc( inVar )+"\n" );
1190 if( fsen.getDynamicInVarSet().contains( inVar ) ) {
1191 bw.write( " (dynamic)"+inVar+"\n" );
1195 bw.write( " Dynamic vars to manage: "+fsen.getDynamicVarSet()+"\n");
1197 bw.write( " out-set: "+fsen.getOutVarSet()+"\n" );
1201 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1202 while( childItr.hasNext() ) {
1203 FlatSESEEnterNode fsenChild = childItr.next();
1204 printSESEInfoTree( bw, fsenChild );