1 19 20 package soot.shimple.internal; 21 22 import soot.*; 23 import soot.util.*; 24 import java.util.*; 25 import soot.shimple.*; 26 import soot.shimple.toolkits.scalar.*; 27 import soot.shimple.toolkits.graph.*; 28 import soot.options.*; 29 import soot.jimple.*; 30 import soot.jimple.internal.*; 31 import soot.jimple.toolkits.base.*; 32 import soot.jimple.toolkits.callgraph.*; 33 import soot.jimple.toolkits.pointer.*; 34 import soot.jimple.toolkits.scalar.*; 35 import soot.toolkits.graph.*; 36 import soot.toolkits.scalar.*; 37 38 46 public class PhiNodeManager 47 { 48 protected ShimpleBody body; 49 protected ShimpleFactory sf; 50 protected DominatorTree dt; 51 protected DominanceFrontier df; 52 protected BlockGraph cfg; 53 protected GuaranteedDefs gd; 54 55 public PhiNodeManager(ShimpleBody body) 56 { 57 this.body = body; 58 sf = G.v().shimpleFactory; 59 } 60 61 public void update() 62 { 63 gd = new GuaranteedDefs(sf.getUnitGraph()); 64 cfg = sf.getBlockGraph(); 65 dt = sf.getDominatorTree(); 66 df = sf.getDominanceFrontier(); 67 } 68 69 protected MultiMap varToBlocks; 70 71 77 public boolean insertTrivialPhiNodes() 78 { 79 update(); 80 boolean change = false; 81 MultiMap localsToDefPoints = new SHashMultiMap(); 82 varToBlocks = new HashMultiMap(); 83 84 for(Iterator blocksIt = cfg.iterator(); blocksIt.hasNext();){ 86 Block block = (Block)blocksIt.next(); 87 88 for(Iterator unitsIt = block.iterator(); unitsIt.hasNext();){ 89 Unit unit = (Unit) unitsIt.next(); 90 91 List defBoxes = unit.getDefBoxes(); 92 for(Iterator defBoxesIt = defBoxes.iterator(); defBoxesIt.hasNext();){ 93 Value def = ((ValueBox)defBoxesIt.next()).getValue(); 94 if(def instanceof Local) 95 localsToDefPoints.put(def, block); 96 } 97 98 if(Shimple.isPhiNode(unit)) 99 varToBlocks.put(Shimple.getLhsLocal(unit), block); 100 } 101 } 102 103 104 105 int[] workFlags = new int[cfg.size()]; 106 int iterCount = 0; 107 Stack workList = new Stack(); 108 109 110 111 { 112 Iterator localsIt = localsToDefPoints.keySet().iterator(); 113 114 while(localsIt.hasNext()){ 115 Local local = (Local) localsIt.next(); 116 117 iterCount++; 118 119 { 121 Iterator defNodesIt = localsToDefPoints.get(local).iterator(); 122 while(defNodesIt.hasNext()){ 123 Block block = (Block) defNodesIt.next(); 124 workFlags[block.getIndexInMethod()] = iterCount; 125 workList.push(block); 126 } 127 } 128 129 while(!workList.empty()){ 130 Block block = (Block) workList.pop(); 131 DominatorNode node = dt.getDode(block); 132 Iterator frontierNodes = df.getDominanceFrontierOf(node).iterator(); 133 134 while(frontierNodes.hasNext()){ 135 Block frontierBlock = (Block) ((DominatorNode) frontierNodes.next()).getGode(); 136 int fBIndex = frontierBlock.getIndexInMethod(); 137 138 if(needsPhiNode(local, frontierBlock)){ 139 prependTrivialPhiNode(local, frontierBlock); 140 change = true; 141 142 if(workFlags[fBIndex] < iterCount){ 143 workFlags[fBIndex] = iterCount; 144 workList.push(frontierBlock); 145 } 146 } 147 } 148 } 149 } 150 } 151 152 return change; 153 } 154 155 159 public void prependTrivialPhiNode(Local local, Block frontierBlock) 160 { 161 List preds = frontierBlock.getPreds(); 162 PhiExpr pe = Shimple.v().newPhiExpr(local, preds); 163 pe.setBlockId(frontierBlock.getIndexInMethod()); 164 Unit trivialPhi = Jimple.v().newAssignStmt(local, pe); 165 Unit blockHead = frontierBlock.getHead(); 166 167 if(blockHead instanceof IdentityUnit) 169 frontierBlock.insertAfter(trivialPhi, frontierBlock.getHead()); 170 else 171 frontierBlock.insertBefore(trivialPhi, frontierBlock.getHead()); 172 173 varToBlocks.put(local, frontierBlock); 174 } 175 176 182 protected boolean needsPhiNode(Local local, Block block) 183 { 184 if(varToBlocks.get(local).contains(block)) 185 return false; 186 187 Iterator unitsIt = block.iterator(); 188 189 if(!unitsIt.hasNext()){ 190 if(!block.getSuccs().isEmpty()) 191 throw new RuntimeException ("Empty block in CFG?"); 192 193 return false; 195 } 196 197 Unit unit = (Unit) unitsIt.next(); 198 199 List definedLocals = gd.getGuaranteedDefs(unit); 201 202 while(definedLocals == null){ 204 if(!unitsIt.hasNext()) 205 throw new RuntimeException ("Almost empty block in CFG?"); 206 unit = (Unit) unitsIt.next(); 207 definedLocals = gd.getGuaranteedDefs(unit); 208 } 209 210 return definedLocals.contains(local); 211 } 212 213 221 public void trimExceptionalPhiNodes() 222 { 223 Set handlerUnits = new HashSet(); 224 Iterator trapsIt = body.getTraps().iterator(); 225 226 while(trapsIt.hasNext()) { 227 Trap trap = (Trap) trapsIt.next(); 228 handlerUnits.add(trap.getHandlerUnit()); 229 } 230 231 Iterator blocksIt = cfg.iterator(); 232 while(blocksIt.hasNext()){ 233 Block block = (Block) blocksIt.next(); 234 235 if(handlerUnits.contains(block.getHead())){ 237 Iterator unitsIt = block.iterator(); 238 while(unitsIt.hasNext()){ 239 Unit unit = (Unit) unitsIt.next(); 240 241 PhiExpr phi = Shimple.getPhiExpr(unit); 243 244 if(phi == null) 245 continue; 246 247 trimPhiNode(phi); 248 } 249 } 250 } 251 } 252 253 256 public void trimPhiNode(PhiExpr phiExpr) 257 { 258 261 262 MultiMap valueToPairs = new HashMultiMap(); 263 264 Iterator argsIt = phiExpr.getArgs().iterator(); 265 while(argsIt.hasNext()){ 266 ValueUnitPair argPair = (ValueUnitPair) argsIt.next(); 267 Value value = argPair.getValue(); 268 valueToPairs.put(value, argPair); 269 } 270 271 275 276 Iterator valuesIt = valueToPairs.keySet().iterator(); 277 while(valuesIt.hasNext()){ 278 Value value = (Value) valuesIt.next(); 279 280 Set pairsSet = valueToPairs.get(value); 284 List champs = new ArrayList(pairsSet); 285 List challengers = new ArrayList(pairsSet); 286 287 ValueUnitPair champ = (ValueUnitPair) champs.remove(0); 289 Unit champU = champ.getUnit(); 290 291 boolean retry = true; 295 while(retry){ 296 retry = false; 297 298 for(int i = 0; i < challengers.size(); i++){ 301 ValueUnitPair challenger = (ValueUnitPair)challengers.get(i); 302 303 if(challenger.equals(champ)) 304 continue; 305 Unit challengerU = challenger.getUnit(); 306 307 if(dominates(champU, challengerU)) 309 phiExpr.removeArg(challenger); 310 311 else if(dominates(challengerU, champU)){ 313 phiExpr.removeArg(champ); 314 champ = challenger; 315 champU = champ.getUnit(); 316 champs.remove(champ); 317 } 318 319 else 325 retry = true; 326 } 327 328 if(retry) { 329 if(champs.size() == 0) 330 break; 331 champ = (ValueUnitPair)champs.remove(0); 332 champU = champ.getUnit(); 333 } 334 } 335 } 336 337 368 } 369 370 protected Map unitToBlock; 371 372 376 public boolean dominates(Unit champ, Unit challenger) 377 { 378 if(champ == null || challenger == null) 379 throw new RuntimeException ("Assertion failed."); 380 381 if(champ.equals(challenger)) 383 return true; 384 385 if(unitToBlock == null) 386 unitToBlock = getUnitToBlockMap(cfg); 387 388 Block champBlock = (Block) unitToBlock.get(champ); 389 Block challengerBlock = (Block) unitToBlock.get(challenger); 390 391 if(champBlock.equals(challengerBlock)){ 392 Iterator unitsIt = champBlock.iterator(); 393 394 while(unitsIt.hasNext()){ 395 Unit unit = (Unit) unitsIt.next(); 396 if(unit.equals(champ)) 397 return true; 398 if(unit.equals(challenger)) 399 return false; 400 } 401 402 throw new RuntimeException ("Assertion failed."); 403 } 404 405 DominatorNode champNode = dt.getDode(champBlock); 406 DominatorNode challengerNode = dt.getDode(challengerBlock); 407 408 411 return(dt.isDominatorOf(champNode, challengerNode)); 412 } 413 414 420 public boolean doEliminatePhiNodes() 421 { 422 boolean addedNewLocals = false; 425 426 List phiNodes = new ArrayList(); 428 429 List equivStmts = new ArrayList(); 436 437 List predBoxes = new ArrayList(); 441 442 Chain units = body.getUnits(); 443 Iterator unitsIt = units.iterator(); 444 445 while(unitsIt.hasNext()){ 446 Unit unit = (Unit) unitsIt.next(); 447 PhiExpr phi = Shimple.getPhiExpr(unit); 448 449 if(phi == null) 450 continue; 451 452 Local lhsLocal = Shimple.getLhsLocal(unit); 453 454 for(int i = 0; i < phi.getArgCount(); i++){ 455 Value phiValue = phi.getValue(i); 456 AssignStmt convertedPhi = 457 Jimple.v().newAssignStmt(lhsLocal, phiValue); 458 459 equivStmts.add(convertedPhi); 460 predBoxes.add(phi.getArgBox(i)); 461 } 462 463 phiNodes.add(unit); 464 } 465 466 if(equivStmts.size() != predBoxes.size()) 467 throw new RuntimeException ("Assertion failed."); 468 469 470 471 for(int i = 0; i < equivStmts.size(); i++){ 472 AssignStmt stmt = (AssignStmt) equivStmts.get(i); 473 Unit pred = ((UnitBox) predBoxes.get(i)).getUnit(); 474 475 if(pred == null) 476 throw new RuntimeException ("Assertion failed."); 477 478 if(pred.branches()){ 483 boolean needPriming = false; 484 Local lhsLocal = (Local) stmt.getLeftOp(); 485 Local savedLocal = Jimple.v().newLocal(lhsLocal.getName()+"_", 486 lhsLocal.getType()); 487 Iterator useBoxesIt = pred.getUseBoxes().iterator(); 488 489 while(useBoxesIt.hasNext()){ 490 ValueBox useBox = (ValueBox) useBoxesIt.next(); 491 if(lhsLocal.equals(useBox.getValue())){ 492 needPriming = true; 493 addedNewLocals = true; 494 useBox.setValue(savedLocal); 495 } 496 } 497 498 if(needPriming){ 499 body.getLocals().add(savedLocal); 500 AssignStmt copyStmt = Jimple.v().newAssignStmt(savedLocal, lhsLocal); 501 units.insertBefore(copyStmt, pred); 502 } 503 504 units.insertBefore(stmt, pred); 506 } 507 else 508 units.insertAfter(stmt, pred); 509 } 510 511 Iterator phiNodesIt = phiNodes.iterator(); 512 513 while(phiNodesIt.hasNext()){ 514 Unit removeMe = (Unit) phiNodesIt.next(); 515 units.remove(removeMe); 516 removeMe.clearUnitBoxes(); 517 } 518 519 return addedNewLocals; 520 } 521 522 526 public Map getUnitToBlockMap(BlockGraph blocks) 527 { 528 Map unitToBlock = new HashMap(); 529 530 Iterator blocksIt = blocks.iterator(); 531 while(blocksIt.hasNext()){ 532 Block block = (Block) blocksIt.next(); 533 Iterator unitsIt = block.iterator(); 534 535 while(unitsIt.hasNext()){ 536 Unit unit = (Unit) unitsIt.next(); 537 unitToBlock.put(unit, block); 538 } 539 } 540 541 return unitToBlock; 542 } 543 } 544 | Popular Tags |