| 1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.util.BitSet ; 23 import java.util.Iterator ; 24 import java.util.NoSuchElementException ; 25 26 import org.apache.bcel.Constants; 27 import org.apache.bcel.generic.CodeExceptionGen; 28 import org.apache.bcel.generic.InstructionHandle; 29 30 import edu.umd.cs.findbugs.graph.AbstractVertex; 31 32 38 public class BasicBlock extends AbstractVertex<Edge, BasicBlock> implements Debug { 39 40 43 44 47 private static final BitSet nullCheckInstructionSet = new BitSet (); 48 49 static { 50 nullCheckInstructionSet.set(Constants.GETFIELD); 51 nullCheckInstructionSet.set(Constants.PUTFIELD); 52 nullCheckInstructionSet.set(Constants.INVOKESPECIAL); 53 nullCheckInstructionSet.set(Constants.INVOKEVIRTUAL); 54 nullCheckInstructionSet.set(Constants.INVOKEINTERFACE); 55 nullCheckInstructionSet.set(Constants.AALOAD); 56 nullCheckInstructionSet.set(Constants.AASTORE); 57 nullCheckInstructionSet.set(Constants.BALOAD); 58 nullCheckInstructionSet.set(Constants.BASTORE); 59 nullCheckInstructionSet.set(Constants.CALOAD); 60 nullCheckInstructionSet.set(Constants.CASTORE); 61 nullCheckInstructionSet.set(Constants.DALOAD); 62 nullCheckInstructionSet.set(Constants.DASTORE); 63 nullCheckInstructionSet.set(Constants.FALOAD); 64 nullCheckInstructionSet.set(Constants.FASTORE); 65 nullCheckInstructionSet.set(Constants.IALOAD); 66 nullCheckInstructionSet.set(Constants.IASTORE); 67 nullCheckInstructionSet.set(Constants.LALOAD); 68 nullCheckInstructionSet.set(Constants.LASTORE); 69 nullCheckInstructionSet.set(Constants.SALOAD); 70 nullCheckInstructionSet.set(Constants.SASTORE); 71 nullCheckInstructionSet.set(Constants.MONITORENTER); 72 nullCheckInstructionSet.set(Constants.ARRAYLENGTH); 73 } 77 78 81 82 private InstructionHandle firstInstruction; 83 private InstructionHandle lastInstruction; 84 private InstructionHandle exceptionThrower; private CodeExceptionGen exceptionGen; private boolean inJSRSubroutine; 87 88 91 92 95 public BasicBlock() { 96 this.firstInstruction = null; 97 this.lastInstruction = null; 98 this.exceptionThrower = null; 99 this.exceptionGen = null; 100 this.inJSRSubroutine = false; 101 } 102 103 public boolean isInJSRSubroutine() { 104 return inJSRSubroutine; 105 } 106 107 void setInJSRSubroutine(boolean inJSRSubroutine) { 108 this.inJSRSubroutine = inJSRSubroutine; 109 } 110 111 public int getId() { 112 return getLabel(); 113 } 114 115 @Override  116 public String toString() { 117 return "block " + String.valueOf(getLabel()); 118 } 119 120 125 public void setExceptionThrower(InstructionHandle exceptionThrower) { 126 this.exceptionThrower = exceptionThrower; 127 } 128 129 132 public boolean isExceptionThrower() { 133 return exceptionThrower != null; 134 } 135 136 141 public InstructionHandle getExceptionThrower() { 142 return exceptionThrower; 143 } 144 145 148 public boolean isNullCheck() { 149 if (!isExceptionThrower() || getFirstInstruction() != null) 153 return false; 154 short opcode = exceptionThrower.getInstruction().getOpcode(); 155 return nullCheckInstructionSet.get(opcode); 156 } 157 158 161 public InstructionHandle getFirstInstruction() { 162 return firstInstruction; 163 } 164 165 168 public InstructionHandle getLastInstruction() { 169 return lastInstruction; 170 } 171 172 178 public InstructionHandle getSuccessorOf(InstructionHandle handle) { 179 if (VERIFY_INTEGRITY) { 180 if (!containsInstruction(handle)) 181 throw new IllegalStateException (); 182 } 183 return handle == lastInstruction 184 ? null 185 : handle.getNext(); 186 } 187 188 194 public InstructionHandle getPredecessorOf(InstructionHandle handle) { 195 if (VERIFY_INTEGRITY) { 196 if (!containsInstruction(handle)) 197 throw new IllegalStateException (); 198 } 199 return handle == firstInstruction 200 ? null 201 : handle.getPrev(); 202 } 203 204 209 public void addInstruction(InstructionHandle handle) { 210 if (firstInstruction == null) { 211 firstInstruction = lastInstruction = handle; 212 } else { 213 if (VERIFY_INTEGRITY && handle != lastInstruction.getNext()) 214 throw new IllegalStateException ("Adding non-consecutive instruction"); 215 lastInstruction = handle; 216 } 217 } 218 219 225 public class InstructionIterator implements Iterator <InstructionHandle> { 226 private InstructionHandle next, last; 227 228 public InstructionIterator(InstructionHandle first, InstructionHandle last) { 229 this.next = first; 230 this.last = last; 231 } 232 233 public boolean hasNext() { 234 return next != null; 235 } 236 237 public InstructionHandle next() { 238 if (!hasNext()) 239 throw new NoSuchElementException (); 240 InstructionHandle result = next; 241 next = (result == last) ? null : next.getNext(); 242 return result; 243 } 244 245 public void remove() { 246 throw new UnsupportedOperationException (); 247 } 248 249 public InstructionIterator duplicate() { 250 return new InstructionIterator(next, last); 251 } 252 253 @Override  254 public boolean equals(Object o) { 255 if (!(o instanceof InstructionIterator)) 256 return false; 257 InstructionIterator other = (InstructionIterator) o; 258 return this.next == other.next && this.last == other.last; 259 } 260 261 @Override  262 public int hashCode() { 263 int code = getBasicBlock().hashCode() * 227; 264 if (next != null) 265 code += next.getPosition() + 1; 266 return code; 267 } 268 269 private BasicBlock getBasicBlock() { 270 return BasicBlock.this; 271 } 272 273 @Override  274 public String toString() { 275 StringBuffer buf = new StringBuffer (); 276 buf.append("[basicBlock="); 277 buf.append(getBasicBlock().getId()); 278 buf.append(", index="); 279 buf.append(next == null ? "end" : String.valueOf(next.getPosition())); 280 buf.append(']'); 281 return buf.toString(); 282 } 283 } 284 285 288 public InstructionIterator instructionIterator() { 289 return new InstructionIterator(firstInstruction, lastInstruction); 290 } 291 292 295 private static class InstructionReverseIterator implements Iterator <InstructionHandle> { 296 private InstructionHandle next, first; 297 298 public InstructionReverseIterator(InstructionHandle last, InstructionHandle first) { 299 this.next = last; 300 this.first = first; 301 } 302 303 public boolean hasNext() { 304 return next != null; 305 } 306 307 public InstructionHandle next() throws NoSuchElementException { 308 if (!hasNext()) 309 throw new NoSuchElementException (); 310 InstructionHandle result = next; 311 next = (result == first) ? null : next.getPrev(); 312 return result; 313 } 314 315 public void remove() { 316 throw new UnsupportedOperationException (); 317 } 318 } 319 320 324 public Iterator <InstructionHandle> instructionReverseIterator() { 325 return new InstructionReverseIterator(lastInstruction, firstInstruction); 326 } 327 328 331 public boolean isEmpty() { 332 return firstInstruction == null; 333 } 334 335 338 public boolean isExceptionHandler() { 339 return exceptionGen != null; 340 } 341 342 348 public CodeExceptionGen getExceptionGen() { 349 return exceptionGen; 350 } 351 352 358 public void setExceptionGen(CodeExceptionGen exceptionGen) { 359 this.exceptionGen = exceptionGen; 360 } 361 362 368 public boolean containsInstruction(InstructionHandle handle) { 369 Iterator <InstructionHandle> i = instructionIterator(); 370 while (i.hasNext()) { 371 if (i.next() == handle) 372 return true; 373 } 374 return false; 375 } 376 377 385 public boolean containsInstructionWithOffset(int offset) { 386 Iterator <InstructionHandle> i = instructionIterator(); 387 while (i.hasNext()) { 388 if (i.next().getPosition() == offset) 389 return true; 390 } 391 return false; 392 } 393 } 394 395 | Popular Tags |