1 19 20 25 26 package soot.jimple.toolkits.graph; 27 import soot.options.*; 28 29 30 import soot.*; 31 import soot.util.*; 32 import java.util.*; 33 import soot.jimple.*; 34 import soot.toolkits.graph.*; 35 import soot.jimple.internal.*; 36 37 50 public class LoopConditionUnroller extends BodyTransformer { 51 56 private Set visitingSuccs; 57 58 private Set visitedBlocks; 59 private int maxSize; 60 private Body body; 61 62 private Map unitsToTraps; 63 64 67 69 protected void internalTransform(Body body, String phaseName, Map options) { 70 if(Options.v().verbose()) 71 G.v().out.println("[" + body.getMethod().getName() + 72 "] Unrolling Loop Conditions..."); 73 74 visitingSuccs = new HashSet(); 75 visitedBlocks = new HashSet(); 76 this.body = body; 77 this.maxSize = PhaseOptions.getInt(options, "maxSize"); 78 79 BlockGraph bg = new BriefBlockGraph(body); 80 Iterator headIter = bg.getHeads().iterator(); 81 while (headIter.hasNext()) 82 unrollConditions((Block)headIter.next()); 83 84 if(Options.v().verbose()) 85 G.v().out.println("[" + body.getMethod().getName() + 86 "] Unrolling Loop Conditions done."); 87 } 88 89 98 private Unit insertGotoAfter(Unit node, Unit target) { 99 Unit newGoto = Jimple.v().newGotoStmt(target); 100 body.getUnits().insertAfter(newGoto, node); 101 return newGoto; 102 } 103 104 112 private Unit insertCloneAfter(Chain unitChain, Unit node, Unit toClone) 113 { 114 Unit clone = (Unit)toClone.clone(); 115 body.getUnits().insertAfter(clone, node); 116 return clone; 117 } 118 119 127 128 private Unit insertGotoBefore(Chain unitChain, Unit node, Unit target) 129 { 130 Unit newGoto = Jimple.v().newGotoStmt(target); 131 body.getUnits().insertBefore(newGoto, node); 132 newGoto.redirectJumpsToThisTo(node); 133 return newGoto; 134 } 135 136 144 private void redirectBranch(Unit node, Unit oldTarget, Unit newTarget) { 145 Iterator targetIt = node.getUnitBoxes().iterator(); 146 while (targetIt.hasNext()) { 147 UnitBox targetBox = (UnitBox)targetIt.next(); 148 Unit target = (Unit)targetBox.getUnit(); 149 if (target == oldTarget) 150 targetBox.setUnit(newTarget); 151 } 152 } 153 154 160 private int getSize(Block block) { 161 int size = 0; 162 Chain unitChain = body.getUnits(); 163 for (Unit unit = block.getHead(); unit != block.getTail(); 164 unit = (Unit)unitChain.getSuccOf(unit)) 165 size++; 166 size++; return size; 168 } 169 170 179 private Map getTraps() { 180 181 if (unitsToTraps != null) 182 return unitsToTraps; 183 unitsToTraps = new HashMap(); 184 Iterator trapsIt = body.getTraps().iterator(); 185 while (trapsIt.hasNext()) { 186 Trap trap = (Trap)trapsIt.next(); 187 Unit beginUnit = trap.getBeginUnit(); 188 List unitTraps = (List)unitsToTraps.get(beginUnit); 189 if (unitTraps == null) { 190 unitTraps = new ArrayList(); 191 unitsToTraps.put(beginUnit, unitTraps); 192 } 193 unitTraps.add(trap); 194 Unit endUnit = trap.getEndUnit(); 195 if (endUnit != beginUnit) { 196 unitTraps = (List)unitsToTraps.get(endUnit); 197 if (unitTraps == null) { 198 unitTraps = new ArrayList(); 199 unitsToTraps.put(endUnit, unitTraps); 200 } 201 unitTraps.add(trap); 202 } 203 } 204 return unitsToTraps; 205 } 206 207 218 private Unit copyBlock(Block block) { 219 Map traps = getTraps(); 220 Set openedTraps = new HashSet(); 221 Map copiedTraps = new HashMap(); 222 Chain unitChain = body.getUnits(); 223 224 Unit tail = block.getTail(); 225 Unit immediateSucc = (Unit)unitChain.getSuccOf(tail); 226 Unit newGoto = insertGotoAfter(tail, immediateSucc); 227 Unit last = newGoto; boolean first = true; 229 Unit copiedHead = null; 230 for (Unit currentUnit = block.getHead(); currentUnit != newGoto; 231 currentUnit = (Unit)unitChain.getSuccOf(currentUnit)) { 232 last = insertCloneAfter(unitChain, last, currentUnit); 233 if (first) { 234 first = false; 235 copiedHead = last; 236 } 237 242 List currentTraps = (List)traps.get(currentUnit); 243 if (currentTraps != null) { 244 Iterator trapIt = currentTraps.iterator(); 245 while(trapIt.hasNext()) { 246 Trap trap = (Trap)trapIt.next(); 247 if (trap.getBeginUnit() == currentUnit) { 248 Trap copiedTrap = (Trap)trap.clone(); 249 copiedTrap.setBeginUnit(last); 250 copiedTraps.put(trap, copiedTrap); 251 252 openedTraps.add(copiedTrap); 253 body.getTraps().insertAfter(copiedTrap, trap); 255 256 } 257 if (trap.getEndUnit() == currentUnit) { 258 Trap copiedTrap = (Trap)copiedTraps.get(trap); 259 if (copiedTrap == null) { 260 261 copiedTrap = (Trap)trap.clone(); 262 copiedTrap.setBeginUnit(copiedHead); 263 264 body.getTraps().insertAfter(copiedTrap, trap); 265 } else { 266 openedTraps.remove(copiedTrap); 267 } 268 269 copiedTrap.setEndUnit(last); 270 } 271 } 272 } 273 } 274 275 Iterator openedIterator = openedTraps.iterator(); 276 while(openedIterator.hasNext()) { 277 ((Trap)openedIterator.next()).setEndUnit(last); 278 } 279 return copiedHead; 280 } 281 282 288 private void unrollConditions(Block block) { 289 290 if (visitedBlocks.contains(block)) return; visitedBlocks.add(block); 292 visitingSuccs.add(block); Iterator succsIt = block.getSuccs().iterator(); 294 while (succsIt.hasNext()) { 295 Block succ = (Block)succsIt.next(); 296 297 if (visitedBlocks.contains(succ)) { 298 if (succ != block && visitingSuccs.contains(succ)) { 299 302 if (succ.getPreds().size() >= 2 && succ.getSuccs().size() == 2) { 303 Block condition = succ; Block loopTailBlock = block; 306 if (getSize(condition) <= maxSize) { 307 Unit copiedHead = copyBlock(condition); 308 309 Unit loopTail = loopTailBlock.getTail(); 310 if (loopTail instanceof GotoStmt) 311 ((GotoStmt)loopTail).setTarget(copiedHead); 312 else if (loopTail instanceof IfStmt) { 313 if (((IfStmt)loopTail).getTarget() == condition.getHead()) 314 ((IfStmt)loopTail).setTarget(copiedHead); 315 else 316 insertGotoAfter(loopTail, copiedHead); 317 } else 318 insertGotoAfter(loopTail, copiedHead); 319 } 320 } 321 } 322 } else { 323 324 unrollConditions(succ); 325 } 326 } 327 visitingSuccs.remove(block); 328 } 329 } 330 | Popular Tags |