1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.util.BitSet ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.NoSuchElementException ; 27 28 import org.apache.bcel.generic.ATHROW; 29 import org.apache.bcel.generic.InstructionHandle; 30 import org.apache.bcel.generic.MethodGen; 31 32 import edu.umd.cs.findbugs.graph.AbstractGraph; 33 34 40 public class CFG extends AbstractGraph<Edge, BasicBlock> implements Debug { 41 42 45 46 53 private class LocationIterator implements Iterator <Location> { 54 private Iterator <BasicBlock> blockIter; 55 private BasicBlock curBlock; 56 private Iterator <InstructionHandle> instructionIter; 57 private Location next; 58 59 private LocationIterator() { 60 this.blockIter = blockIterator(); 61 findNext(); 62 } 63 64 public boolean hasNext() { 65 findNext(); 66 return next != null; 67 } 68 69 public Location next() { 70 findNext(); 71 if (next == null) throw new NoSuchElementException (); 72 Location result = next; 73 next = null; 74 return result; 75 } 76 77 public void remove() { 78 throw new UnsupportedOperationException (); 79 } 80 81 private void findNext() { 82 while (next == null) { 83 if (instructionIter == null) { 85 if (!blockIter.hasNext()) 86 return; curBlock = blockIter.next(); 88 instructionIter = curBlock.instructionIterator(); 89 } 90 91 if (instructionIter.hasNext()) 92 next = new Location(instructionIter.next(), curBlock); 93 else 94 instructionIter = null; } 96 } 97 } 98 99 102 103 private BasicBlock entry, exit; 104 private int flags; 105 private String methodName; private MethodGen methodGen; 107 110 111 115 public CFG() { 116 } 117 118 121 public void setMethodName(String methodName) { 122 this.methodName = methodName; 123 } 124 125 public void setMethodGen(MethodGen methodGen) { 126 this.methodGen = methodGen; 127 } 128 public MethodGen getMethodGen() { 129 return methodGen; 130 } 131 134 public String getMethodName() { 135 return methodName; 136 } 137 138 void setFlags(int flags) { 139 this.flags = flags; 140 } 141 142 int getFlags() { 143 return flags; 144 } 145 146 boolean isFlagSet(int flag) { 147 return (flags & flag) != 0; 148 } 149 150 153 public BasicBlock getEntry() { 154 if (entry == null) { 155 entry = allocate(); 156 } 157 return entry; 158 } 159 160 163 public BasicBlock getExit() { 164 if (exit == null) { 165 exit = allocate(); 166 } 167 return exit; 168 } 169 170 182 public Edge createEdge(BasicBlock source, BasicBlock dest, int type) { 183 Edge edge = createEdge(source, dest); 184 edge.setType(type); 185 return edge; 186 } 187 188 194 public Edge lookupEdgeById(int id) { 195 Iterator <Edge> i = edgeIterator(); 196 while (i.hasNext()) { 197 Edge edge = i.next(); 198 if (edge.getId() == id) 199 return edge; 200 } 201 return null; 202 } 203 204 207 public Iterator <BasicBlock> blockIterator() { 208 return vertexIterator(); 209 } 210 211 214 public Iterator <Location> locationIterator() { 215 return new LocationIterator(); 216 } 217 218 225 public Collection <BasicBlock> getBlocks(BitSet idSet) { 226 LinkedList <BasicBlock> result = new LinkedList <BasicBlock>(); 227 for (Iterator <BasicBlock> i = blockIterator(); i.hasNext();) { 228 BasicBlock block = i.next(); 229 if (idSet.get(block.getId())) 230 result.add(block); 231 } 232 return result; 233 } 234 235 243 public Collection <BasicBlock> getBlocksContainingInstructionWithOffset(int offset) { 244 LinkedList <BasicBlock> result = new LinkedList <BasicBlock>(); 245 for (Iterator <BasicBlock> i = blockIterator(); i.hasNext(); ) { 246 BasicBlock block = i.next(); 247 if (block.containsInstructionWithOffset(offset)) 248 result.add(block); 249 } 250 return result; 251 } 252 253 260 public Collection <Location> getLocationsContainingInstructionWithOffset(int offset) { 261 LinkedList <Location> result = new LinkedList <Location>(); 262 for (Iterator <Location> i = locationIterator(); i.hasNext(); ) { 263 Location location = i.next(); 264 if (location.getHandle().getPosition() == offset) { 265 result.add(location); 266 } 267 } 268 return result; 269 } 270 271 279 public BasicBlock getPredecessorWithEdgeType(BasicBlock target, int edgeType) { 280 Edge edge = getIncomingEdgeWithType(target, edgeType); 281 return edge != null ? edge.getSource() : null; 282 } 283 284 292 public BasicBlock getSuccessorWithEdgeType(BasicBlock source, int edgeType) { 293 Edge edge = getOutgoingEdgeWithType(source, edgeType); 294 return edge != null ? edge.getTarget() : null; 295 } 296 297 304 public Location getExceptionThrowerLocation(Edge exceptionEdge) { 305 if (!exceptionEdge.isExceptionEdge()) 306 throw new IllegalArgumentException (); 307 308 InstructionHandle handle = exceptionEdge.getSource().getExceptionThrower(); 309 if (handle == null) 310 throw new IllegalStateException (); 311 312 BasicBlock basicBlock = (handle.getInstruction() instanceof ATHROW) 313 ? exceptionEdge.getSource() 314 : getSuccessorWithEdgeType(exceptionEdge.getSource(), EdgeTypes.FALL_THROUGH_EDGE); 315 if (basicBlock == null) 316 throw new IllegalStateException ("No basic block for thrower " + handle); 317 318 return new Location(handle, basicBlock); 319 } 320 321 328 public Edge getIncomingEdgeWithType(BasicBlock basicBlock, int edgeType) { 329 return getEdgeWithType(incomingEdgeIterator(basicBlock), edgeType); 330 } 331 332 339 public Edge getOutgoingEdgeWithType(BasicBlock basicBlock, int edgeType) { 340 return getEdgeWithType(outgoingEdgeIterator(basicBlock), edgeType); 341 } 342 343 private Edge getEdgeWithType(Iterator <Edge> iter, int edgeType) { 344 while (iter.hasNext()) { 345 Edge edge = iter.next(); 346 if (edge.getType() == edgeType) 347 return edge; 348 } 349 return null; 350 } 351 352 356 public BasicBlock allocate() { 357 BasicBlock b = new BasicBlock(); 358 addVertex(b); 359 return b; 360 } 361 362 367 public int getNumBasicBlocks() { 368 return getNumVertices(); 369 } 370 371 376 public int getMaxEdgeId() { 377 return getNumEdgeLabels(); 378 } 379 380 public void checkIntegrity() { 381 for (Iterator <BasicBlock> i = blockIterator(); i.hasNext();) { 383 BasicBlock basicBlock = i.next(); 384 InstructionHandle prev = null; 385 for (Iterator <InstructionHandle> j = basicBlock.instructionIterator(); j.hasNext();) { 386 InstructionHandle handle = j.next(); 387 if (prev != null && prev.getNext() != handle) 388 throw new IllegalStateException ("Non-consecutive instructions in block " + basicBlock.getId() + 389 ": prev=" + prev + ", handle=" + handle); 390 prev = handle; 391 } 392 } 393 } 394 395 @Override 396 protected Edge allocateEdge(BasicBlock source, BasicBlock target) { 397 return new Edge(source, target); 398 } 399 } 400 401 | Popular Tags |