1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.util.Iterator ; 23 24 import org.apache.bcel.generic.InstructionHandle; 25 import org.apache.bcel.generic.MethodGen; 26 27 import edu.umd.cs.findbugs.SystemProperties; 28 29 46 public class Dataflow <Fact, AnalysisType extends DataflowAnalysis<Fact>> { 47 private CFG cfg; 48 private AnalysisType analysis; 49 private BlockOrder blockOrder; 50 private boolean isForwards; 51 private int numIterations; 52 53 static final boolean DEBUG = SystemProperties.getBoolean("dataflow.debug"); 54 55 61 public Dataflow(CFG cfg, AnalysisType analysis) { 62 this.cfg = cfg; 63 this.analysis = analysis; 64 blockOrder = analysis.getBlockOrder(cfg); 65 isForwards = analysis.isForwards(); 66 numIterations = 0; 67 68 Iterator <BasicBlock> i = cfg.blockIterator(); 70 while (i.hasNext()) { 71 BasicBlock block = i.next(); 72 73 74 Fact result = analysis.getResultFact(block); 76 if (block == logicalEntryBlock()) 77 try { 78 analysis.initEntryFact(result); 79 } catch (DataflowAnalysisException e) { 80 analysis.initResultFact(result); 81 } 82 else analysis.initResultFact(result); 83 } 84 } 85 86 private static final int MAX_ITERS = SystemProperties.getInteger("dataflow.maxiters", 100).intValue(); 88 89 private String getFullyQualifiedMethodName() { 90 String methodName; 91 MethodGen methodGen = cfg.getMethodGen(); 92 if (methodGen == null) 93 methodName = cfg.getMethodName(); 94 else methodName = SignatureConverter.convertMethodSignature(methodGen); 95 return methodName; 96 } 97 102 public void execute() throws DataflowAnalysisException { 103 boolean change; 104 105 if (DEBUG) { 106 String shortAnalysisName = analysis.getClass().getName(); 107 int pkgEnd = shortAnalysisName.lastIndexOf('.'); 108 if (pkgEnd >= 0) { 109 shortAnalysisName = shortAnalysisName.substring(pkgEnd + 1); 110 } 111 System.out.println("Executing " + shortAnalysisName + " on " + getFullyQualifiedMethodName()); 112 } 113 114 int timestamp = 0; 115 do { 116 change = false; 117 ++numIterations; 118 119 if (DEBUG) { 120 System.out.println("----------------------------------------------------------------------"); 121 System.out.println(this.getClass().getName() + " iteration: " + numIterations + ", timestamp: " + timestamp); 122 System.out.println("----------------------------------------------------------------------"); 123 } 124 125 if (numIterations >= MAX_ITERS) { 126 assert false : "Too many iterations (" + numIterations + ") in dataflow when analyzing " + getFullyQualifiedMethodName(); 127 break; 128 } 129 130 analysis.startIteration(); 131 132 if (DEBUG) { 133 if (blockOrder instanceof ReverseDFSOrder) { 134 ReverseDFSOrder rBlockOrder = (ReverseDFSOrder) blockOrder; 135 System.out.println("Entry point is: " + logicalEntryBlock()); 136 System.out.println("Basic block order: "); 137 Iterator <BasicBlock> i = blockOrder.blockIterator(); 138 while (i.hasNext()) { 139 140 BasicBlock block = i.next(); 141 if (DEBUG) debug(block, "rBlockOrder " + rBlockOrder.rdfs.getDiscoveryTime(block) + "\n"); 142 } 143 } 144 } 145 146 Iterator <BasicBlock> i = blockOrder.blockIterator(); 148 while (i.hasNext()) { 149 150 BasicBlock block = i.next(); 151 if (DEBUG) debug(block, "start\n"); 152 153 Fact start = analysis.getStartFact(block); 155 boolean needToRecompute = false; 156 Fact result = analysis.getResultFact(block); 158 int originalResultTimestamp = analysis.getLastUpdateTimestamp(result); 159 160 if (block == logicalEntryBlock()) { 164 analysis.makeFactTop(start); 165 analysis.initEntryFact(start); 166 if (DEBUG) debug(block, "Init entry fact ==> " + start + "\n"); 167 needToRecompute = true; 168 } else { 169 int lastCalculated = analysis.getLastUpdateTimestamp(start); 170 Iterator <Edge> predEdgeIter = logicalPredecessorEdgeIterator(block); 171 172 int predCount = 0; 173 while (predEdgeIter.hasNext()) { 174 Edge edge = predEdgeIter.next(); 175 BasicBlock logicalPred = isForwards ? edge.getSource() : edge.getTarget(); 176 177 Fact predFact = analysis.getResultFact(logicalPred); 179 int predLastUpdated = analysis.getLastUpdateTimestamp(predFact); 180 if (!analysis.isTop(predFact)) { 181 predCount++; 182 if (predLastUpdated >= lastCalculated) { 183 184 needToRecompute = true; 185 if (DEBUG) { 186 System.out.println("Need to recompute. My timestamp = " + lastCalculated + ", pred timestamp = " + predLastUpdated + ", pred fact = " + predFact); 187 } 188 break; 189 } 190 } 191 } 192 if (predCount == 0) needToRecompute = true; 193 194 if (!needToRecompute) { 195 if (DEBUG) { 196 debug(block, "Skipping: predecessors haven't changed"); 197 System.out.println(" curr timestamp: " + timestamp); 198 System.out.println(" last timestamp: " + lastCalculated); 199 predEdgeIter = logicalPredecessorEdgeIterator(block); 200 201 while (predEdgeIter.hasNext()) { 202 Edge edge = predEdgeIter.next(); 203 BasicBlock logicalPred = isForwards ? edge.getSource() : edge.getTarget(); 204 205 Fact predFact = analysis.getResultFact(logicalPred); 207 int predLastUpdated = analysis.getLastUpdateTimestamp(predFact); 208 System.out.println(" pred timestamp: " + predLastUpdated); 209 } 210 System.out.println("Fact: " + start); 211 } 212 continue; 213 } 214 215 if (needToRecompute) { 216 217 analysis.makeFactTop(start); 218 predEdgeIter = logicalPredecessorEdgeIterator(block); 219 while (predEdgeIter.hasNext()) { 220 Edge edge = predEdgeIter.next(); 221 BasicBlock logicalPred = isForwards ? edge.getSource() : edge.getTarget(); 222 223 Fact predFact = analysis.getResultFact(logicalPred); 225 226 Fact edgeFact = analysis.createFact(); 228 analysis.copy(predFact, edgeFact); 229 analysis.edgeTransfer(edge, edgeFact); 230 231 if (DEBUG && !analysis.same(edgeFact, predFact)) { 232 debug(block, logicalPred, edge, 233 "Edge transfer " + predFact + " ==> " + edgeFact); 234 } 235 236 if (DEBUG) debug(block, logicalPred, edge, "\n Meet " + start + "\n with " + edgeFact 239 + "\n pred last updated at " + analysis.getLastUpdateTimestamp(predFact) +"\n"); 240 241 242 analysis.meetInto(edgeFact, edge, start); 243 analysis.setLastUpdateTimestamp(start, timestamp); 244 245 int pos = -1; 246 if (block.getFirstInstruction() != null) 247 pos = block.getFirstInstruction().getPosition(); 248 if (DEBUG) System.out.println(" [" + pos +"]==> " + start +" @ " + timestamp + " \n"); 249 } 250 } 251 } 252 if (DEBUG) debug(block, "start fact is " + start + "\n"); 253 254 boolean resultWasTop = analysis.isTop(result); 256 Fact origResult = null; 257 if (!resultWasTop) { 258 origResult = analysis.createFact(); 259 analysis.copy(result, origResult); 260 } 261 262 if (true || analysis.isTop(start)) { 263 265 analysis.transfer(block, null, start, result); 266 } else { 267 analysis.copy(start, result); 268 } 269 270 if (DEBUG && SystemProperties.getBoolean("dataflow.blockdebug")) { 271 debug(block, "Dumping flow values for block:\n"); 272 Iterator <org.apache.bcel.generic.InstructionHandle> ii = block.instructionIterator(); 273 while (ii.hasNext()) { 274 org.apache.bcel.generic.InstructionHandle handle = ii.next(); 275 Fact tmpResult = analysis.createFact(); 276 analysis.transfer(block, handle, start, tmpResult); 277 System.out.println("\t" + handle + " " + tmpResult); 278 } 279 } 280 281 if (DEBUG) debug(block, "orig result is " + origResult + "\n"); 283 boolean thisResultChanged = false; 284 if (resultWasTop) 285 thisResultChanged = !analysis.isTop(result); 286 else thisResultChanged = !analysis.same(result, origResult); 287 if (thisResultChanged) { 288 timestamp++; 289 if (DEBUG) debug(block, "result changed at timestamp " + timestamp + "\n"); 290 if (DEBUG && !needToRecompute) { 291 System.out.println("I thought I didn't need to recompute"); 292 } 293 change = true; 294 analysis.setLastUpdateTimestamp(result, timestamp); 295 } else 296 analysis.setLastUpdateTimestamp(result, originalResultTimestamp); 297 298 if (DEBUG) debug(block, "result is " + result + " @ timestamp " 299 + analysis.getLastUpdateTimestamp(result) + "\n"); 300 } 301 302 analysis.finishIteration(); 303 } while (change); 304 } 305 306 private static String blockId(BasicBlock bb) { 307 InstructionHandle handle = bb.getFirstInstruction(); 308 if (handle == null) return ""+ bb.getId(); 309 return bb.getId()+":"+ handle.getPosition() + " " + handle.getInstruction(); 310 } 311 private static void debug(BasicBlock bb, String msg) { 312 313 314 System.out.print("Dataflow (block " + blockId(bb) + "): " + msg); 315 } 316 317 private static void debug(BasicBlock bb, BasicBlock pred, Edge edge, String msg) { 318 System.out.print("Dataflow (block " + blockId(bb) + ", predecessor " + blockId(pred) + 319 " [" + Edge.edgeTypeToString(edge.getType()) + "]): " + msg); 320 } 321 322 325 public int getNumIterations() { 326 return numIterations; 327 } 328 329 332 public Fact getStartFact(BasicBlock block) { 333 return analysis.getStartFact(block); 334 } 335 336 339 public Fact getResultFact(BasicBlock block) { 340 return analysis.getResultFact(block); 341 } 342 343 346 public AnalysisType getAnalysis() { 347 return analysis; 348 } 349 350 353 public CFG getCFG() { 354 return cfg; 355 } 356 357 362 private Iterator <Edge> logicalPredecessorEdgeIterator(BasicBlock block) { 363 return isForwards ? cfg.incomingEdgeIterator(block) : cfg.outgoingEdgeIterator(block); 364 } 365 366 371 private BasicBlock logicalEntryBlock() { 372 return isForwards ? cfg.getEntry() : cfg.getExit(); 373 } 374 } 375 376 | Popular Tags |