00001 package ca.mcgill.sable.soot.jimple;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 import ca.mcgill.sable.soot.*;
00096 import ca.mcgill.sable.util.*;
00097
00098 public class StmtGraph
00099 {
00100 List heads;
00101 List tails;
00102
00103 Map stmtToSuccs;
00104 Map stmtToPreds;
00105 SootMethod method;
00106 List stmts;
00107 int size;
00108 StmtList stmtList;
00109
00110 private boolean isPseudoTopologicalOrderReady;
00111 private List topOrder;
00112
00113 private boolean isReversePseudoTopologicalOrderReady;
00114 private List reverseTopOrder;
00115
00116 private Map stmtToColor;
00117 private final int WHITE = 0,
00118 GRAY = 1,
00119 BLACK = 2;
00120
00121 private LinkedList order;
00122 private boolean isReversed;
00123
00124 StmtGraph(StmtList stmtList, boolean addExceptionEdges)
00125 {
00126 this.stmtList = stmtList;
00127 this.method = getBody().getMethod();
00128
00129 if(Main.isVerbose)
00130 System.out.println("[" + method.getName() +
00131 "] Constructing StmtGraph...");
00132
00133 if(Main.isProfilingOptimization)
00134 Main.graphTimer.start();
00135
00136
00137 {
00138 stmts = new LinkedList();
00139
00140 stmts.addAll(stmtList);
00141 stmts = Collections.unmodifiableList(stmts);
00142 size = stmtList.size();
00143 }
00144
00145
00146 {
00147 Map classToHandler = new HashMap();
00148
00149 stmtToSuccs = new HashMap(size * 2 + 1, 0.7f);
00150 stmtToPreds = new HashMap(size * 2 + 1, 0.7f);
00151
00152
00153
00154 {
00155 ListIterator stmtIt = stmtList.listIterator();
00156
00157 while(stmtIt.hasNext())
00158 {
00159 Stmt s = (Stmt) stmtIt.next();
00160
00161 List successors = new ArrayList();
00162 boolean addNext = true;
00163
00164 if(s instanceof GotoStmt)
00165 {
00166 successors.add(((GotoStmt) s).getTarget());
00167 addNext = false;
00168 }
00169 else if(s instanceof IfStmt)
00170 {
00171 successors.add(((IfStmt) s).getTarget());
00172 }
00173 else if(s instanceof ReturnStmt || s instanceof ReturnVoidStmt)
00174 {
00175 addNext = false;
00176 }
00177 else if(s instanceof RetStmt)
00178 {
00179
00180
00181 ListIterator it = stmtList.listIterator();
00182
00183 while(it.hasNext())
00184 {
00185 Stmt stmt = (Stmt) it.next();
00186
00187 if(stmt instanceof AssignStmt)
00188 {
00189 AssignStmt as = (AssignStmt) stmt;
00190
00191 if(as.getRightOp() instanceof NextNextStmtRef)
00192 {
00193 Iterator succIt = stmtList.listIterator(it.nextIndex());
00194
00195 if(succIt.hasNext())
00196 {
00197 succIt.next();
00198
00199 if(succIt.hasNext())
00200 successors.add(succIt.next());
00201 }
00202 }
00203 }
00204 }
00205
00206 addNext = false;
00207 }
00208 else if(s instanceof ThrowStmt)
00209 {
00210 addNext = false;
00211 }
00212 else if(s instanceof LookupSwitchStmt)
00213 {
00214 LookupSwitchStmt l = (LookupSwitchStmt) s;
00215
00216 successors.add(l.getDefaultTarget());
00217
00218 Iterator targetIt = l.getTargets().iterator();
00219
00220 while(targetIt.hasNext())
00221 successors.add(targetIt.next());
00222
00223 addNext = false;
00224 }
00225 else if(s instanceof TableSwitchStmt)
00226 {
00227 TableSwitchStmt t = (TableSwitchStmt) s;
00228
00229 successors.add(t.getDefaultTarget());
00230
00231 Iterator targetIt = t.getTargets().iterator();
00232
00233 while(targetIt.hasNext())
00234 successors.add(targetIt.next());
00235
00236
00237 addNext = false;
00238 }
00239
00240
00241 if(addNext)
00242 {
00243 successors.add(stmtList.get(stmtIt.nextIndex()));
00244 }
00245
00246
00247
00248 stmtToSuccs.put(s, successors);
00249 }
00250 }
00251
00252
00253 if(addExceptionEdges)
00254 {
00255 Iterator trapIt = getBody().getTraps().
00256 iterator();
00257
00258 while(trapIt.hasNext())
00259 {
00260 Trap trap = (Trap) trapIt.next();
00261
00262 Stmt beginStmt = (Stmt) trap.getBeginUnit();
00263 Stmt handlerStmt = (Stmt) trap.getHandlerUnit();
00264 Stmt endStmt = (Stmt) trap.getEndUnit();
00265 Iterator stmtIt = stmtList.listIterator(stmtList.indexOf(beginStmt));
00266
00267 for(;;)
00268 {
00269 Stmt s = (Stmt) stmtIt.next();
00270
00271 ((List) stmtToSuccs.get(s)).add(handlerStmt);
00272
00273 if(s == endStmt)
00274 break;
00275 }
00276 }
00277 }
00278
00279
00280 {
00281 ListIterator stmtIt = stmtList.listIterator();
00282
00283 while(stmtIt.hasNext())
00284 {
00285 Stmt s = (Stmt) stmtIt.next();
00286 stmtToSuccs.put(s, Collections.unmodifiableList((List) stmtToSuccs.get(s)));
00287 }
00288 }
00289 }
00290
00291
00292
00293 {
00294 Map stmtToPredList = new HashMap(size * 2 + 1, 0.7f);
00295
00296
00297 {
00298 Iterator stmtIt = stmtList.iterator();
00299
00300 while(stmtIt.hasNext())
00301 {
00302 stmtToPredList.put(stmtIt.next(), new ArrayList());
00303 }
00304 }
00305
00306
00307 {
00308 Iterator stmtIt = stmtList.iterator();
00309
00310 while(stmtIt.hasNext())
00311 {
00312 Stmt s = (Stmt) stmtIt.next();
00313 Iterator succIt = ((List) stmtToSuccs.get(s)).iterator();
00314
00315 while(succIt.hasNext())
00316 {
00317 List predList = (List) stmtToPredList.get(succIt.next());
00318 predList.add(s);
00319 }
00320 }
00321 }
00322
00323
00324
00325 {
00326 Iterator stmtIt = stmtList.iterator();
00327
00328 while(stmtIt.hasNext())
00329 {
00330 Stmt s = (Stmt) stmtIt.next();
00331
00332 List predList = (List) stmtToPredList.get(s);
00333 stmtToPreds.put(s, Collections.unmodifiableList(predList));
00334 }
00335 }
00336
00337 }
00338
00339
00340 {
00341 List tailList = new ArrayList();
00342
00343
00344 {
00345 Iterator stmtIt = stmtList.iterator();
00346
00347 while(stmtIt.hasNext())
00348 {
00349 Stmt s = (Stmt) stmtIt.next();
00350
00351 List succs = (List) stmtToSuccs.get(s);
00352
00353 if(succs.size() == 0)
00354 tailList.add(s);
00355 }
00356 }
00357
00358 tails = Collections.unmodifiableList(tailList);
00359 }
00360
00361
00362 {
00363 List headList = new ArrayList();
00364
00365
00366 {
00367 Iterator stmtIt = stmtList.iterator();
00368
00369 while(stmtIt.hasNext())
00370 {
00371 Stmt s = (Stmt) stmtIt.next();
00372 List preds = (List) stmtToPreds.get(s);
00373
00374 if(preds.size() == 0)
00375 headList.add(s);
00376 }
00377 }
00378
00379 heads = Collections.unmodifiableList(headList);
00380 }
00381
00382 if(Main.isProfilingOptimization)
00383 Main.graphTimer.end();
00384 }
00385 private LinkedList computeOrder(boolean isReversed)
00386 {
00387 stmtToColor = new HashMap();
00388
00389 this.isReversed = isReversed;
00390 order = new LinkedList();
00391
00392
00393 {
00394 Iterator stmtIt = iterator();
00395
00396 while(stmtIt.hasNext())
00397 {
00398 Stmt s = (Stmt) stmtIt.next();
00399
00400 stmtToColor.put(s, new Integer(WHITE));
00401 }
00402 }
00403
00404
00405 {
00406 Iterator stmtIt = iterator();
00407
00408 while(stmtIt.hasNext())
00409 {
00410 Stmt s = (Stmt) stmtIt.next();
00411
00412 if(((Integer) stmtToColor.get(s)).intValue() == WHITE)
00413 visitStmt(s);
00414 }
00415 }
00416
00417 return order;
00418 }
00419 public StmtBody getBody()
00420 {
00421 return stmtList.getBody();
00422 }
00423
00424
00425
00426
00427
00428
00429 public List getExtendedBasicBlockPathBetween(Stmt from, Stmt to)
00430 {
00431 StmtGraph g = this;
00432
00433
00434 if (g.getPredsOf(to).size() > 1)
00435 return null;
00436
00437
00438
00439 LinkedList pathStack = new LinkedList();
00440 LinkedList pathStackIndex = new LinkedList();
00441
00442 pathStack.add(from);
00443 pathStackIndex.add(new Integer(0));
00444
00445 int psiMax = (g.getSuccsOf((Stmt)pathStack.get(0))).size();
00446 int level = 0;
00447 while (((Integer)pathStackIndex.get(0)).intValue() != psiMax)
00448 {
00449 int p = ((Integer)(pathStackIndex.get(level))).intValue();
00450
00451 List succs = g.getSuccsOf((Stmt)(pathStack.get(level)));
00452 if (p >= succs.size())
00453 {
00454
00455
00456 pathStack.remove(level);
00457 pathStackIndex.remove(level);
00458
00459 level--;
00460 int q = ((Integer)pathStackIndex.get(level)).intValue();
00461 pathStackIndex.set(level, new Integer(q+1));
00462 continue;
00463 }
00464
00465 Stmt betweenStmt = (Stmt)(succs.get(p));
00466
00467
00468 if (betweenStmt == to)
00469 {
00470 pathStack.add(to);
00471 return pathStack;
00472 }
00473
00474
00475 if (g.getPredsOf(betweenStmt).size() > 1)
00476 {
00477 pathStackIndex.set(level, new Integer(p+1));
00478 continue;
00479 }
00480
00481
00482 level++;
00483 pathStackIndex.add(new Integer(0));
00484 pathStack.add(betweenStmt);
00485 }
00486 return null;
00487 }
00488 public List getHeads()
00489 {
00490 return heads;
00491 }
00492 public List getPredsOf(Stmt s)
00493 {
00494 if(!stmtToPreds.containsKey(s))
00495 throw new RuntimeException("Invalid stmt" + s);
00496
00497 return (List) stmtToPreds.get(s);
00498 }
00499 public List getSuccsOf(Stmt s)
00500 {
00501 if(!stmtToSuccs.containsKey(s))
00502 throw new RuntimeException("Invalid stmt" + s);
00503
00504 return (List) stmtToSuccs.get(s);
00505 }
00506 public List getTails()
00507 {
00508 return tails;
00509 }
00510 public Iterator iterator()
00511 {
00512 return stmts.iterator();
00513 }
00514 public Iterator pseudoTopologicalOrderIterator()
00515 {
00516 if(!isPseudoTopologicalOrderReady)
00517 {
00518 topOrder = Collections.unmodifiableList(computeOrder(false));
00519 isPseudoTopologicalOrderReady = true;
00520 }
00521
00522 return topOrder.iterator();
00523 }
00524 public Iterator reversePseudoTopologicalOrderIterator()
00525 {
00526 if(!isReversePseudoTopologicalOrderReady)
00527 {
00528 reverseTopOrder = Collections.unmodifiableList(computeOrder(false));
00529 isReversePseudoTopologicalOrderReady = true;
00530 }
00531
00532 return reverseTopOrder.iterator();
00533 }
00534 public int size()
00535 {
00536 return size;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 private void visitStmt(Stmt startStmt)
00567 {
00568 LinkedList stmtStack = new LinkedList();
00569 LinkedList indexStack = new LinkedList();
00570
00571 stmtToColor.put(startStmt, new Integer(GRAY));
00572
00573 stmtStack.addLast(startStmt);
00574 indexStack.addLast(new Integer(-1));
00575
00576 while(!stmtStack.isEmpty())
00577 {
00578 int toVisitIndex = ((Integer) indexStack.removeLast()).intValue();
00579 Stmt toVisitStmt = (Stmt) stmtStack.getLast();
00580
00581 toVisitIndex++;
00582
00583 indexStack.addLast(new Integer(toVisitIndex));
00584
00585 if(toVisitIndex >= getSuccsOf(toVisitStmt).size())
00586 {
00587
00588 if(isReversed)
00589 order.addLast(toVisitStmt);
00590 else
00591 order.addFirst(toVisitStmt);
00592
00593 stmtToColor.put(toVisitStmt, new Integer(BLACK));
00594
00595
00596 stmtStack.removeLast();
00597 indexStack.removeLast();
00598 }
00599 else
00600 {
00601 Stmt childStmt = (Stmt) getSuccsOf(toVisitStmt).get(toVisitIndex);
00602
00603
00604 if(((Integer) stmtToColor.get(childStmt)).intValue() == WHITE)
00605 {
00606 stmtToColor.put(childStmt, new Integer(GRAY));
00607
00608 stmtStack.addLast(childStmt);
00609 indexStack.addLast(new Integer(-1));
00610 }
00611 }
00612 }
00613 }
00614 }