1 package Analysis.OoOJava;
3 import java.io.IOException;
4 import java.util.Enumeration;
5 import java.util.HashSet;
6 import java.util.Hashtable;
7 import java.util.Iterator;
9 import java.util.Stack;
10 import java.util.Map.Entry;
12 import Analysis.ArrayReferencees;
13 import Analysis.Liveness;
14 import Analysis.CallGraph.CallGraph;
15 import Analysis.Disjoint.DisjointAnalysis;
16 import Analysis.Disjoint.Effect;
17 import Analysis.Disjoint.EffectsAnalysis;
18 import Analysis.Disjoint.Taint;
20 import IR.MethodDescriptor;
25 import IR.Flat.FlatEdge;
26 import IR.Flat.FlatFieldNode;
27 import IR.Flat.FlatMethod;
28 import IR.Flat.FlatNode;
29 import IR.Flat.FlatOpNode;
30 import IR.Flat.FlatNew;
31 import IR.Flat.FlatSESEEnterNode;
32 import IR.Flat.FlatSESEExitNode;
33 import IR.Flat.FlatSetFieldNode;
34 import IR.Flat.FlatWriteDynamicVarNode;
35 import IR.Flat.TempDescriptor;
37 public class OoOJavaAnalysis {
39 // data from the compiler
41 private TypeUtil typeUtil;
42 private CallGraph callGraph;
43 private RBlockRelationAnalysis rblockRel;
44 private RBlockStatusAnalysis rblockStatus;
45 private DisjointAnalysis disjointAnalysisTaints;
46 private DisjointAnalysis disjointAnalysisReach;
48 private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
49 private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
50 private Hashtable<FlatNode, VarSrcTokTable> variableResults;
51 private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
52 private Hashtable<FlatNode, CodePlan> codePlans;
54 private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
56 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
58 // temporal data structures to track analysis progress.
59 static private int uniqueLockSetId = 0;
60 // mapping of a conflict graph to its compiled lock
61 private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
62 // mapping of a sese block to its conflict graph
63 private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
68 // private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
69 // private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
70 // private OwnershipAnalysis ownAnalysisForSESEConflicts;
72 // static private int uniqueLockSetId = 0;
74 public static int maxSESEage = -1;
76 public int getMaxSESEage() {
81 public CodePlan getCodePlan(FlatNode fn) {
82 CodePlan cp = codePlans.get(fn);
86 public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
87 ArrayReferencees arrayReferencees) {
89 double timeStartAnalysis = (double) System.nanoTime();
92 this.typeUtil = typeUtil;
93 this.callGraph = callGraph;
94 this.maxSESEage = state.MLP_MAXSESEAGE;
96 livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
97 livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
98 variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
99 notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
100 codePlans = new Hashtable<FlatNode, CodePlan>();
101 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
103 notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
105 sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
106 conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
108 // add all methods transitively reachable from the
109 // source's main to set for analysis
110 MethodDescriptor mdSourceEntry = typeUtil.getMain();
111 FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
113 Set<MethodDescriptor> descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
115 descriptorsToAnalyze.add(mdSourceEntry);
117 // conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
118 // methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
119 // conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
121 // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
122 // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
123 // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
125 // 1st pass, find basic rblock relations
126 rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
128 rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
131 // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
132 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
133 while (rootItr.hasNext()) {
134 FlatSESEEnterNode root = rootItr.next();
135 livenessAnalysisBackward(root, true, null);
138 // 3rd pass, variable analysis
139 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
140 while (methItr.hasNext()) {
141 Descriptor d = methItr.next();
142 FlatMethod fm = state.getMethodFlat(d);
144 // starting from roots do a forward, fixed-point
145 // variable analysis for refinement and stalls
146 variableAnalysisForward(fm);
149 // 4th pass, compute liveness contribution from
150 // virtual reads discovered in variable pass
151 rootItr = rblockRel.getRootSESEs().iterator();
152 while (rootItr.hasNext()) {
153 FlatSESEEnterNode root = rootItr.next();
154 livenessAnalysisBackward(root, true, null);
157 // 5th pass, use disjointness with NO FLAGGED REGIONS
158 // to compute taints and effects
159 disjointAnalysisTaints =
160 new DisjointAnalysis(state,
165 null, // no FlatNew set to flag
170 // 6th pass, not available analysis FOR VARIABLES!
171 methItr = descriptorsToAnalyze.iterator();
172 while (methItr.hasNext()) {
173 Descriptor d = methItr.next();
174 FlatMethod fm = state.getMethodFlat(d);
176 // compute what is not available at every program
177 // point, in a forward fixed-point pass
178 notAvailableForward(fm);
181 // 7th pass, make conflict graph
182 // conflict graph is maintained by each parent sese,
183 Iterator descItr=disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
184 while (descItr.hasNext()) {
185 Descriptor d = (Descriptor)descItr.next();
186 FlatMethod fm = state.getMethodFlat(d);
188 makeConflictGraph(fm);
192 Iterator iter = sese2conflictGraph.entrySet().iterator();
193 while (iter.hasNext()) {
194 Entry e = (Entry) iter.next();
195 FlatNode fn = (FlatNode) e.getKey();
196 ConflictGraph conflictGraph = (ConflictGraph) e.getValue();
197 System.out.println("---------------------------------------");
198 System.out.println("CONFLICT GRAPH for " + fn);
199 Set<String> keySet = conflictGraph.id2cn.keySet();
200 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
201 String key = (String) iterator.next();
202 ConflictNode node = conflictGraph.id2cn.get(key);
203 System.out.println("key=" + key + " \n" + node.toStringAllEffects());
207 // 8th pass, calculate all possible conflicts without using reachability info
208 // and identify set of FlatNew that next disjoint reach. analysis should flag
209 Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
210 calculateConflicts(sitesToFlag,false);
212 // 9th pass, ask disjoint analysis to compute reachability
213 // for objects that may cause heap conflicts so the most
214 // efficient method to deal with conflict can be computed
216 disjointAnalysisReach =
217 new DisjointAnalysis(state,
223 null, // don't do effects analysis again!
224 null // don't do effects analysis again!
227 // 10th pass, calculate conflicts with reachability info
228 calculateConflicts(null, true);
231 // 11th pass, compiling locks
234 // #th pass, writing conflict graph
235 writeConflictGraph();
240 private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
241 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
243 // start from an SESE exit, visit nodes in reverse up to
244 // SESE enter in a fixed-point scheme, where children SESEs
245 // should already be analyzed and therefore can be skipped
246 // because child SESE enter node has all necessary info
247 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
250 flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
252 flatNodesToVisit.add(fsen.getFlatExit());
255 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
258 liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
261 while (!flatNodesToVisit.isEmpty()) {
262 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
263 flatNodesToVisit.remove(fn);
265 Set<TempDescriptor> prev = livenessResults.get(fn);
267 // merge sets from control flow joins
268 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
269 for (int i = 0; i < fn.numNext(); i++) {
270 FlatNode nn = fn.getNext(i);
271 Set<TempDescriptor> s = livenessResults.get(nn);
277 Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
279 // if a new result, schedule backward nodes for analysis
280 if (!curr.equals(prev)) {
281 livenessResults.put(fn, curr);
283 // don't flow backwards past current SESE enter
284 if (!fn.equals(fsen)) {
285 for (int i = 0; i < fn.numPrev(); i++) {
286 FlatNode nn = fn.getPrev(i);
287 flatNodesToVisit.add(nn);
293 Set<TempDescriptor> s = livenessResults.get(fsen);
298 // remember liveness per node from the root view as the
299 // global liveness of variables for later passes to use
301 livenessRootView.putAll(livenessResults);
304 // post-order traversal, so do children first
305 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
306 while (childItr.hasNext()) {
307 FlatSESEEnterNode fsenChild = childItr.next();
308 livenessAnalysisBackward(fsenChild, false, liveout);
312 private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
313 FlatSESEEnterNode currentSESE, boolean toplevel,
314 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
317 case FKind.FlatSESEExitNode:
319 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
320 if (!liveout.containsKey(fsexn)) {
321 liveout.put(fsexn, new HashSet<TempDescriptor>());
323 liveout.get(fsexn).addAll(liveIn);
325 // no break, sese exits should also execute default actions
328 // handle effects of statement in reverse, writes then reads
329 TempDescriptor[] writeTemps = fn.writesTemps();
330 for (int i = 0; i < writeTemps.length; ++i) {
331 liveIn.remove(writeTemps[i]);
334 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
335 Set<TempDescriptor> livetemps = liveout.get(fsexn);
336 if (livetemps != null && livetemps.contains(writeTemps[i])) {
337 // write to a live out temp...
338 // need to put in SESE liveout set
339 currentSESE.addOutVar(writeTemps[i]);
344 TempDescriptor[] readTemps = fn.readsTemps();
345 for (int i = 0; i < readTemps.length; ++i) {
346 liveIn.add(readTemps[i]);
349 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
350 if (virtualReadTemps != null) {
351 liveIn.addAll(virtualReadTemps);
362 private void variableAnalysisForward(FlatMethod fm) {
364 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
365 flatNodesToVisit.add(fm);
367 while (!flatNodesToVisit.isEmpty()) {
368 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
369 flatNodesToVisit.remove(fn);
371 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
372 assert seseStack != null;
374 VarSrcTokTable prev = variableResults.get(fn);
376 // merge sets from control flow joins
377 VarSrcTokTable curr = new VarSrcTokTable();
378 for (int i = 0; i < fn.numPrev(); i++) {
379 FlatNode nn = fn.getPrev(i);
380 VarSrcTokTable incoming = variableResults.get(nn);
381 curr.merge(incoming);
384 if (!seseStack.empty()) {
385 variable_nodeActions(fn, curr, seseStack.peek());
388 // if a new result, schedule forward nodes for analysis
389 if (!curr.equals(prev)) {
390 variableResults.put(fn, curr);
392 for (int i = 0; i < fn.numNext(); i++) {
393 FlatNode nn = fn.getNext(i);
394 flatNodesToVisit.add(nn);
400 private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
401 FlatSESEEnterNode currentSESE) {
404 case FKind.FlatSESEEnterNode: {
405 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
406 assert fsen.equals(currentSESE);
408 vstTable.age(currentSESE);
409 vstTable.assertConsistency();
413 case FKind.FlatSESEExitNode: {
414 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
415 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
416 assert currentSESE.getChildren().contains(fsen);
418 // remap all of this child's children tokens to be
419 // from this child as the child exits
420 vstTable.remapChildTokens(fsen);
422 // liveness virtual reads are things that might be
423 // written by an SESE and should be added to the in-set
424 // anything virtually read by this SESE should be pruned
425 // of parent or sibling sources
426 Set<TempDescriptor> liveVars = livenessRootView.get(fn);
427 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
429 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
430 if (fsenVirtReadsOld != null) {
431 fsenVirtReads.addAll(fsenVirtReadsOld);
433 livenessVirtualReads.put(fn, fsenVirtReads);
435 // then all child out-set tokens are guaranteed
436 // to be filled in, so clobber those entries with
437 // the latest, clean sources
438 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
439 while (outVarItr.hasNext()) {
440 TempDescriptor outVar = outVarItr.next();
441 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
443 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
444 vstTable.remove(outVar);
447 vstTable.assertConsistency();
452 case FKind.FlatOpNode: {
453 FlatOpNode fon = (FlatOpNode) fn;
455 if (fon.getOp().getOp() == Operation.ASSIGN) {
456 TempDescriptor lhs = fon.getDest();
457 TempDescriptor rhs = fon.getLeft();
459 vstTable.remove(lhs);
461 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
463 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
464 while (itr.hasNext()) {
465 VariableSourceToken vst = itr.next();
467 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
470 if (currentSESE.getChildren().contains(vst.getSESE())) {
471 // if the source comes from a child, copy it over
472 forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
475 // otherwise, stamp it as us as the source
476 forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
480 vstTable.addAll(forAddition);
482 // only break if this is an ASSIGN op node,
483 // otherwise fall through to default case
484 vstTable.assertConsistency();
489 // note that FlatOpNode's that aren't ASSIGN
490 // fall through to this default case
492 TempDescriptor[] writeTemps = fn.writesTemps();
493 if (writeTemps.length > 0) {
495 // for now, when writeTemps > 1, make sure
496 // its a call node, programmer enforce only
497 // doing stuff like calling a print routine
498 // assert writeTemps.length == 1;
499 if (writeTemps.length > 1) {
500 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
504 vstTable.remove(writeTemps[0]);
506 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
507 ts.add(writeTemps[0]);
509 vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
512 vstTable.assertConsistency();
519 private void notAvailableForward(FlatMethod fm) {
521 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
522 flatNodesToVisit.add(fm);
524 while (!flatNodesToVisit.isEmpty()) {
525 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
526 flatNodesToVisit.remove(fn);
528 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
529 assert seseStack != null;
531 Set<TempDescriptor> prev = notAvailableResults.get(fn);
533 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
534 for (int i = 0; i < fn.numPrev(); i++) {
535 FlatNode nn = fn.getPrev(i);
536 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
537 if (notAvailIn != null) {
538 curr.addAll(notAvailIn);
542 if (!seseStack.empty()) {
543 notAvailable_nodeActions(fn, curr, seseStack.peek());
546 // if a new result, schedule forward nodes for analysis
547 if (!curr.equals(prev)) {
548 notAvailableResults.put(fn, curr);
550 for (int i = 0; i < fn.numNext(); i++) {
551 FlatNode nn = fn.getNext(i);
552 flatNodesToVisit.add(nn);
558 private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
559 FlatSESEEnterNode currentSESE) {
561 // any temps that are removed from the not available set
562 // at this node should be marked in this node's code plan
563 // as temps to be grabbed at runtime!
567 case FKind.FlatSESEEnterNode: {
568 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
569 assert fsen.equals(currentSESE);
571 // keep a copy of what's not available into the SESE
572 // and restore it at the matching exit node
573 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
574 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
575 while (tdItr.hasNext()) {
576 notAvailCopy.add(tdItr.next());
578 notAvailableIntoSESE.put(fsen, notAvailCopy);
584 case FKind.FlatSESEExitNode: {
585 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
586 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
587 assert currentSESE.getChildren().contains(fsen);
589 notAvailSet.addAll(fsen.getOutVarSet());
591 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
592 assert notAvailIn != null;
593 notAvailSet.addAll(notAvailIn);
598 case FKind.FlatMethod: {
602 case FKind.FlatOpNode: {
603 FlatOpNode fon = (FlatOpNode) fn;
605 if (fon.getOp().getOp() == Operation.ASSIGN) {
606 TempDescriptor lhs = fon.getDest();
607 TempDescriptor rhs = fon.getLeft();
609 // copy makes lhs same availability as rhs
610 if (notAvailSet.contains(rhs)) {
611 notAvailSet.add(lhs);
613 notAvailSet.remove(lhs);
616 // only break if this is an ASSIGN op node,
617 // otherwise fall through to default case
622 // note that FlatOpNode's that aren't ASSIGN
623 // fall through to this default case
625 TempDescriptor[] writeTemps = fn.writesTemps();
626 for (int i = 0; i < writeTemps.length; i++) {
627 TempDescriptor wTemp = writeTemps[i];
628 notAvailSet.remove(wTemp);
630 TempDescriptor[] readTemps = fn.readsTemps();
631 for (int i = 0; i < readTemps.length; i++) {
632 TempDescriptor rTemp = readTemps[i];
633 notAvailSet.remove(rTemp);
635 // if this variable has exactly one source, potentially
636 // get other things from this source as well
637 VarSrcTokTable vstTable = variableResults.get(fn);
639 VSTWrapper vstIfStatic = new VSTWrapper();
640 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
642 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
644 VariableSourceToken vst = vstIfStatic.vst;
646 Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
649 // look through things that are also available from same source
650 while (availItr.hasNext()) {
651 VariableSourceToken vstAlsoAvail = availItr.next();
653 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
654 while (refVarItr.hasNext()) {
655 TempDescriptor refVarAlso = refVarItr.next();
657 // if a variable is available from the same source, AND it ALSO
658 // only comes from one statically known source, mark it available
659 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
660 Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
662 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
663 notAvailSet.remove(refVarAlso);
675 private void makeConflictGraph(FlatMethod fm) {
677 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
678 flatNodesToVisit.add(fm);
680 Set<FlatNode> visited = new HashSet<FlatNode>();
682 while (!flatNodesToVisit.isEmpty()) {
683 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
684 flatNodesToVisit.remove(fn);
687 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
688 assert seseStack != null;
690 if (!seseStack.isEmpty()) {
692 ConflictGraph conflictGraph = sese2conflictGraph.get(seseStack.peek());
693 if (conflictGraph == null) {
694 conflictGraph = new ConflictGraph();
697 conflictGraph_nodeAction(fn, seseStack.peek());
700 // schedule forward nodes for analysis
701 for (int i = 0; i < fn.numNext(); i++) {
702 FlatNode nn = fn.getNext(i);
703 if (!visited.contains(nn)) {
704 flatNodesToVisit.add(nn);
713 private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
715 ConflictGraph conflictGraph;
716 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
720 case FKind.FlatSESEEnterNode: {
722 if (currentSESE.getParent() == null) {
725 conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
726 if (conflictGraph == null) {
727 conflictGraph = new ConflictGraph();
730 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
732 if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
733 // collects effects set of invar set and generates invar node
734 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(currentSESE);
735 conflictGraph.addLiveIn(taint2Effects);
738 if (conflictGraph.id2cn.size() > 0) {
739 sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
745 case FKind.FlatFieldNode:
746 case FKind.FlatElementNode: {
748 conflictGraph = sese2conflictGraph.get(currentSESE);
749 if (conflictGraph == null) {
750 conflictGraph = new ConflictGraph();
753 FlatFieldNode ffn = (FlatFieldNode) fn;
754 TempDescriptor rhs = ffn.getSrc();
757 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
758 conflictGraph.addStallSite(taint2Effects, rhs);
760 if (conflictGraph.id2cn.size() > 0) {
761 sese2conflictGraph.put(currentSESE, conflictGraph);
766 case FKind.FlatSetFieldNode:
767 case FKind.FlatSetElementNode: {
769 conflictGraph = sese2conflictGraph.get(currentSESE);
770 if (conflictGraph == null) {
771 conflictGraph = new ConflictGraph();
774 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
775 TempDescriptor lhs = fsfn.getDst();
776 TempDescriptor rhs = fsfn.getSrc();
778 // collects effects of stall site and generates stall site node
779 Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
780 conflictGraph.addStallSite(taint2Effects, rhs);
781 conflictGraph.addStallSite(taint2Effects, lhs);
783 if (conflictGraph.id2cn.size() > 0) {
784 sese2conflictGraph.put(currentSESE, conflictGraph);
792 private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
793 // decide fine-grain edge or coarse-grain edge among all vertexes by
794 // pair-wise comparison
795 Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
796 while (seseIter.hasNext()) {
797 FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
798 ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
800 // clear current conflict before recalculating with reachability info
801 conflictGraph.clearAllConflictEdge();
802 conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
803 conflictGraph.setFMEnclosing(sese.getfmEnclosing());
805 conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
806 sese2conflictGraph.put(sese, conflictGraph);
810 private void writeConflictGraph() {
811 Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
812 while (keyEnum.hasMoreElements()) {
813 FlatNode key = (FlatNode) keyEnum.nextElement();
814 ConflictGraph cg = sese2conflictGraph.get(key);
816 if (cg.hasConflictEdge()) {
817 cg.writeGraph("ConflictGraphFor" + key, false);
819 } catch (IOException e) {
820 System.out.println("Error writing");
826 private void synthesizeLocks() {
827 Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
828 for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
829 Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
830 FlatNode sese = graphEntry.getKey();
831 ConflictGraph conflictGraph = graphEntry.getValue();
832 calculateCovering(conflictGraph);
836 private void calculateCovering(ConflictGraph conflictGraph) {
837 uniqueLockSetId = 0; // reset lock counter for every new conflict graph
838 HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
839 HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
840 HashSet<SESELock> lockSet = new HashSet<SESELock>();
842 Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
843 for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
844 ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
845 if (conflictEdge.isCoarseEdge()) {
846 coarseToCover.add(conflictEdge);
848 fineToCover.add(conflictEdge);
852 HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
853 toCover.addAll(fineToCover);
854 toCover.addAll(coarseToCover);
856 while (!toCover.isEmpty()) {
858 SESELock seseLock = new SESELock();
859 seseLock.setID(uniqueLockSetId++);
863 do { // fine-grained edge
867 for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
870 ConflictEdge edge = (ConflictEdge) iterator.next();
871 if (seseLock.getConflictNodeSet().size() == 0) {
873 if (seseLock.isWriteNode(edge.getVertexU())) {
874 // mark as fine_write
875 if (edge.getVertexU().isStallSiteNode()) {
876 type = ConflictNode.PARENT_WRITE;
878 type = ConflictNode.FINE_WRITE;
880 seseLock.addConflictNode(edge.getVertexU(), type);
883 if (edge.getVertexU().isStallSiteNode()) {
884 type = ConflictNode.PARENT_READ;
886 type = ConflictNode.FINE_READ;
888 seseLock.addConflictNode(edge.getVertexU(), type);
890 if (edge.getVertexV() != edge.getVertexU()) {
891 if (seseLock.isWriteNode(edge.getVertexV())) {
892 // mark as fine_write
893 if (edge.getVertexV().isStallSiteNode()) {
894 type = ConflictNode.PARENT_WRITE;
896 type = ConflictNode.FINE_WRITE;
898 seseLock.addConflictNode(edge.getVertexV(), type);
901 if (edge.getVertexV().isStallSiteNode()) {
902 type = ConflictNode.PARENT_READ;
904 type = ConflictNode.FINE_READ;
906 seseLock.addConflictNode(edge.getVertexV(), type);
910 seseLock.addConflictEdge(edge);
911 fineToCover.remove(edge);
912 break;// exit iterator loop
913 }// end of initial setup
915 ConflictNode newNode;
916 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
917 // new node has a fine-grained edge to all current node
918 // If there is a coarse grained edge where need a fine edge, it's
919 // okay to add the node
920 // but the edge must remain uncovered.
924 if (seseLock.isWriteNode(newNode)) {
925 if (newNode.isStallSiteNode()) {
926 type = ConflictNode.PARENT_WRITE;
928 type = ConflictNode.FINE_WRITE;
930 seseLock.setNodeType(newNode, type);
932 if (newNode.isStallSiteNode()) {
933 type = ConflictNode.PARENT_READ;
935 type = ConflictNode.FINE_READ;
937 seseLock.setNodeType(newNode, type);
940 seseLock.addEdge(edge);
941 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
942 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
943 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
945 // mark all fine edges between new node and nodes in the group as
947 if (!conflictEdge.getVertexU().equals(newNode)) {
948 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
950 seseLock.addConflictEdge(conflictEdge);
951 fineToCover.remove(conflictEdge);
953 } else if (!conflictEdge.getVertexV().equals(newNode)) {
954 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
956 seseLock.addConflictEdge(conflictEdge);
957 fineToCover.remove(conflictEdge);
963 break;// exit iterator loop
971 for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
973 ConflictEdge edge = (ConflictEdge) iterator.next();
975 if (seseLock.getConflictNodeSet().size() == 0) {
977 if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
978 // node has a coarse-grained edge with itself
979 if (!(edge.getVertexU().isStallSiteNode())) {
980 // and it is not parent
981 type = ConflictNode.SCC;
983 type = ConflictNode.PARENT_COARSE;
985 seseLock.addConflictNode(edge.getVertexU(), type);
987 if (edge.getVertexU().isStallSiteNode()) {
988 type = ConflictNode.PARENT_COARSE;
990 type = ConflictNode.COARSE;
992 seseLock.addConflictNode(edge.getVertexU(), type);
994 if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
995 // node has a coarse-grained edge with itself
996 if (!(edge.getVertexV().isStallSiteNode())) {
997 // and it is not parent
998 type = ConflictNode.SCC;
1000 type = ConflictNode.PARENT_COARSE;
1002 seseLock.addConflictNode(edge.getVertexV(), type);
1004 if (edge.getVertexV().isStallSiteNode()) {
1005 type = ConflictNode.PARENT_COARSE;
1007 type = ConflictNode.COARSE;
1009 seseLock.addConflictNode(edge.getVertexV(), type);
1012 coarseToCover.remove(edge);
1013 seseLock.addConflictEdge(edge);
1014 break;// exit iterator loop
1015 }// end of initial setup
1017 ConflictNode newNode;
1018 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1019 // new node has a coarse-grained edge to all fine-read, fine-write,
1023 if (seseLock.hasSelfCoarseEdge(newNode)) {
1025 if (newNode.isStallSiteNode()) {
1026 type = ConflictNode.PARENT_COARSE;
1028 type = ConflictNode.SCC;
1030 seseLock.setNodeType(newNode, type);
1032 if (newNode.isStallSiteNode()) {
1033 type = ConflictNode.PARENT_COARSE;
1035 type = ConflictNode.COARSE;
1037 seseLock.setNodeType(newNode, type);
1040 seseLock.addEdge(edge);
1041 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1042 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1043 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1044 // mark all coarse edges between new node and nodes in the group
1046 if (!conflictEdge.getVertexU().equals(newNode)) {
1047 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1049 seseLock.addConflictEdge(conflictEdge);
1050 coarseToCover.remove(conflictEdge);
1052 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1053 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1055 seseLock.addConflictEdge(conflictEdge);
1056 coarseToCover.remove(conflictEdge);
1061 break;// exit iterator loop
1067 lockSet.add(seseLock);
1070 toCover.addAll(fineToCover);
1071 toCover.addAll(coarseToCover);
1075 conflictGraph2SESELock.put(conflictGraph, lockSet);