1 5 package de.uka.ipd.coverage.recording; 6 7 import java.util.ArrayList ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 11 import org.apache.bcel.generic.*; 12 13 17 44 public class BasicBlockIdentifyer { 45 46 public static BasicBlock[] getBasicBlocks(RegisteredMethod registeredMethod) { 47 ClassGen classGen = new ClassGen(registeredMethod.getJavaClass()); 48 MethodGen method = new MethodGen(registeredMethod.getMethod(), 49 classGen.getClassName(), classGen.getConstantPool()); 50 51 InstructionList il = insertBlockDelimiters(method); 52 53 BasicBlock[] blocks = createBlocksFromInstructionList(registeredMethod, il); 54 55 setBlockBranches(il, blocks); 56 57 return blocks; 58 } 59 60 66 private static BasicBlock[] createBlocksFromInstructionList( 67 RegisteredMethod registeredMethod, 68 InstructionList il) { 69 List blockList = new ArrayList (il.size()); 70 BasicBlockBuilder builder = new BasicBlockBuilder(); 71 for (Iterator iter = il.iterator(); iter.hasNext();) { 72 Instruction element = 73 ((InstructionHandle) iter.next()).getInstruction(); 74 if (element instanceof BlockDelimiter) { 75 BlockDelimiter delim = (BlockDelimiter) element; 76 if (delim.isStartBlock()) { 77 builder.createBasicBlock(); 78 builder.setRegisteredMethod(registeredMethod); 79 builder.setStartLine(delim.getPosition()); 80 } else if (delim.isEndBlock()) { 81 builder.setEndLine(delim.getPosition()); 82 blockList.add(builder.getBasicBlock()); 83 } 84 } 85 } 86 BasicBlock[] blocks = (BasicBlock[]) blockList.toArray( 87 new BasicBlock[blockList.size()]); 88 return blocks; 89 } 90 91 97 private static void setBlockBranches(InstructionList il, BasicBlock[] blocks) { 98 for (Iterator iter = il.iterator(); iter.hasNext();) { 99 Instruction element = ((InstructionHandle) iter.next()).getInstruction(); 100 if (element instanceof BlockDelimiter) { 101 BlockDelimiter delim = (BlockDelimiter) element; 102 if (delim.isEndBlock()) { 103 BasicBlock currentBlock = 104 searchBlockWithEnd(blocks, delim.getPosition()); 105 int[] targets = delim.getTargets(); 106 for (int i = 0; i < targets.length; i++) { 107 BasicBlock targetBlock = 108 searchBlockWithStart(blocks, targets[i]); 109 currentBlock.addSuccessor(targetBlock); 110 } 111 } 112 } 113 } 114 } 115 116 119 private static BasicBlock searchBlockWithStart(BasicBlock[] blocks, int startPC) { 120 for (int i = 0; i < blocks.length; i++) { 121 if (blocks[i].getStartLine() == startPC) { 122 return blocks[i]; 123 } 124 } 125 throw new AssertionError ("Block with startline " + startPC + " not found"); } 127 128 131 private static BasicBlock searchBlockWithEnd(BasicBlock[] blocks, int endPC) { 132 for (int i = 0; i < blocks.length; i++) { 133 if (blocks[i].getEndLine() == endPC) { 134 return blocks[i]; 135 } 136 } 137 throw new AssertionError ("Block with endline " + endPC + " not found"); } 139 140 153 protected static InstructionList insertBlockDelimiters(MethodGen method) { 154 InstructionList il = method.getInstructionList(); 155 InstructionHandle runningHandle = il.getStart(); 158 159 assert !(runningHandle.getInstruction() instanceof BlockDelimiter) : 160 "InstructionList was already instrumented with block delimiters!"; 162 insertStartDelimiter(il, runningHandle, runningHandle.getPosition()); 164 165 while (true) { 166 assert runningHandle.getPrev().getInstruction() 168 instanceof BlockDelimiter && 169 ((BlockDelimiter) runningHandle.getPrev().getInstruction()).isStartBlock() 170 : "No start block at begin of iteration!"; 172 while (!isBlockDelimiter(runningHandle.getInstruction())) { 176 runningHandle = runningHandle.getNext(); 177 } 178 if (runningHandle.getInstruction() instanceof BlockDelimiter) { 179 runningHandle = skipExistingBlockDelimiters(method, 180 il, runningHandle); 181 continue; 183 } 184 185 188 if (runningHandle.getInstruction() instanceof BranchInstruction) { 189 BranchHandle branchHandle = (BranchHandle) runningHandle; 190 if (runningHandle.getInstruction() instanceof Select) { 191 insertSelectTargetDelimiters(il, branchHandle); 192 } 193 insertBranchTargetDelimiters(il, branchHandle); 194 } 195 196 if (!isEndDelimiter(runningHandle.getPrev().getInstruction())) { 200 insertEndDelimiter(il, runningHandle, runningHandle.getPosition()); 201 } 202 203 if (runningHandle.getNext() == null) { 204 break; 205 } 206 207 runningHandle = runningHandle.getNext(); 209 210 if (!isStartDelimiter(runningHandle.getInstruction())) { 211 int nextPosition = getNextPosition(runningHandle); 215 insertStartDelimiter(il, runningHandle, nextPosition); 216 } else { 217 runningHandle = runningHandle.getNext(); 218 } 219 } 220 221 redirectExceptionHandlers(method); 222 223 assert checkConsistency(il); 225 assert checkBranchTargets(il); 226 assert checkExceptionHandlers(method); 227 228 229 return il; 230 } 231 232 236 private static boolean checkExceptionHandlers(MethodGen method) { 237 CodeExceptionGen[] eHandlers = method.getExceptionHandlers(); 238 for (int i = 0; i < eHandlers.length; i++) { 239 assert isStartDelimiter(eHandlers[i].getHandlerPC().getInstruction()); 240 } 241 return true; 242 } 243 244 247 private static void redirectExceptionHandlers(MethodGen method) { 248 CodeExceptionGen[] exceptionHandlers = method.getExceptionHandlers(); 251 for (int i = 0; i < exceptionHandlers.length; i++) { 252 InstructionHandle excHandler = exceptionHandlers[i].getHandlerPC(); 253 254 assert isStartDelimiter(excHandler.getPrev().getInstruction()) 255 : "Expected a start delimiter at the begin of the catch block," + " but there is none at method " + method.getName() + " for catch block with exception " + exceptionHandlers[i].getCatchType().getClassName(); 259 260 exceptionHandlers[i].setHandlerPC(excHandler.getPrev()); 261 } 262 } 263 264 269 private static boolean isStartDelimiter(Instruction instruction) { 270 if (instruction instanceof BlockDelimiter) { 271 BlockDelimiter delim = (BlockDelimiter) instruction; 272 if (delim.isStartBlock()) { 273 return true; 274 } 275 } 276 return false; 277 } 278 279 284 private static boolean isEndDelimiter(Instruction instruction) { 285 if (instruction instanceof BlockDelimiter) { 286 BlockDelimiter delim = (BlockDelimiter) instruction; 287 if (delim.isEndBlock()) { 288 return true; 289 } 290 } 291 return false; 292 } 293 294 298 private static void insertSelectTargetDelimiters( 299 InstructionList il, 300 BranchHandle selectHandle) { 301 Select selectInstruction = (Select) selectHandle.getInstruction(); 302 InstructionHandle[] targets = selectInstruction.getTargets(); 303 304 for (int i = 0; i < targets.length; i++) { 305 306 insertStartAndEndDelimiterForBranchTargets(il, targets[i]); 308 309 if (targets[i].getPrev().getInstruction() instanceof BlockDelimiter) { 311 BlockDelimiter delim = 314 (BlockDelimiter) targets[i].getPrev().getInstruction(); 315 if (delim.isStartBlock()) { 316 selectInstruction.setTarget(i, targets[i].getPrev()); 317 } 318 assert delim.isStartBlock() : "Branch target cannot be redirected. Missing start block"; assert (!delim.isEndBlock()) : 320 "Block end right before a branch target _after_ weaving in the branch delimiters"; } 322 323 } 324 } 325 326 330 private static boolean checkConsistency(InstructionList il) { 331 InstructionHandle runnerHandle = il.getStart(); 332 int pc = runnerHandle.getPosition(); 333 while (runnerHandle.getNext() != null) { 334 while (!(runnerHandle.getInstruction() instanceof BlockDelimiter)) { 335 assert runnerHandle.getNext() != null : "Instructionlist ends in block"; 337 assert runnerHandle.getPosition() > pc : "Positions not monotone! " + "Expected PC > " + pc + " but was " + runnerHandle.getPosition(); pc = runnerHandle.getPosition(); 340 341 runnerHandle = runnerHandle.getNext(); 342 343 } 344 345 assert ((BlockDelimiter) runnerHandle.getInstruction()).isStartBlock() : 346 "Expected start block, but is not!"; 348 runnerHandle = runnerHandle.getNext(); 349 while (!(runnerHandle.getInstruction() instanceof BlockDelimiter)) { 350 assert runnerHandle.getNext() != null : 351 "InstructionList ends with an end delimiter, " + "but there should be a return or throw."; 354 assert runnerHandle.getPosition() > pc : "Positions not monoton! " + "Expected PC > " + pc + " but was " + runnerHandle.getPosition(); pc = runnerHandle.getPosition(); 357 358 runnerHandle = runnerHandle.getNext(); 359 } 360 361 assert ((BlockDelimiter) runnerHandle.getInstruction()).isEndBlock() : 362 "Expected end block, but is not!"; 364 runnerHandle = runnerHandle.getNext(); 365 } 366 return true; 367 } 368 369 372 private static boolean checkBranchTargets(InstructionList il) { 373 InstructionHandle runnerHandle = il.getStart(); 374 while (runnerHandle != null) { 375 if (runnerHandle instanceof BranchHandle) { 376 if (runnerHandle.getInstruction() instanceof Select) { 377 InstructionHandle[] targets = 378 ((Select) runnerHandle.getInstruction()).getTargets(); 379 for (int i = 0; i < targets.length; i++) { 380 assert targets[i].getInstruction() instanceof 381 BlockDelimiter : " Select target is no block start at " + "position " + targets[i].getPosition(); } 384 } 385 BranchHandle branchHandle = (BranchHandle) runnerHandle; 386 assert branchHandle.getTarget().getInstruction() instanceof 387 BlockDelimiter : "Branch target is no block start at position " + branchHandle.getPosition() ; 389 } 390 runnerHandle = runnerHandle.getNext(); 391 } 392 return true; 393 } 394 395 398 private static int getNextPosition(InstructionHandle runningHandle) { 399 while (runningHandle.getInstruction() instanceof BlockDelimiter) { 400 runningHandle = runningHandle.getNext(); 401 } 402 return runningHandle.getPosition(); 403 } 404 405 409 private static InstructionHandle skipExistingBlockDelimiters( 410 MethodGen method, 411 InstructionList il, 412 InstructionHandle runningHandle) { 413 assert ((BlockDelimiter) runningHandle.getInstruction()).isEndBlock() : 414 "BasicBlockIdentifyer, Class: " + method.getClassName() + ", Method " + method.getName() + " Start block found where an end block was expected!" + " Blocks won't be right, there is no point in continuing"; do { 425 runningHandle = runningHandle.getNext(); 426 if (runningHandle instanceof BranchHandle) { 427 BranchHandle branchHandle = (BranchHandle) runningHandle; 428 insertBranchTargetDelimiters(il, branchHandle); 429 } 430 } while (!(runningHandle.getInstruction() 431 instanceof BlockDelimiter)); 432 runningHandle = runningHandle.getNext(); 434 return runningHandle; 435 } 436 437 443 private static void insertBranchTargetDelimiters( 444 InstructionList il, 445 BranchHandle branchHandle) { 446 447 InstructionHandle branchTarget = branchHandle.getTarget(); 448 449 if (branchTarget.getInstruction() instanceof BlockDelimiter) { 450 return; 451 } 452 453 insertStartAndEndDelimiterForBranchTargets(il, branchTarget); 454 455 redirectBranchTargets(branchHandle); 456 } 457 458 462 private static void insertStartAndEndDelimiterForBranchTargets( 463 InstructionList il, 464 InstructionHandle branchTarget) { 465 if (!(branchTarget.getPrev().getInstruction() instanceof BlockDelimiter)) { 467 468 if (branchTarget.getPrev() != null 471 && requiresExcludingEnd(branchTarget.getPrev().getInstruction()) 472 && !(branchTarget.getPrev().getPrev().getInstruction() 475 instanceof BlockDelimiter) ) { 476 477 insertEndDelimiter(il, branchTarget.getPrev(), 479 branchTarget.getPrev().getPosition()); 480 } else { 481 insertEndDelimiter(il, branchTarget, 483 branchTarget.getPrev().getPosition()); 484 } 485 insertStartDelimiter(il, branchTarget, branchTarget.getPosition()); 486 } 487 } 488 489 private static void redirectBranchTargets(BranchHandle branchHandle) { 490 InstructionHandle branchTarget = branchHandle.getTarget(); 491 492 if (branchTarget.getInstruction() instanceof BlockDelimiter) { 493 return; 494 } 495 496 if (branchTarget.getPrev().getInstruction() instanceof BlockDelimiter) { 498 BlockDelimiter delim = 501 (BlockDelimiter) branchTarget.getPrev().getInstruction(); 502 503 assert delim.isStartBlock() : "Branch target cannot be " + "redirected. Missing start block"; assert (!delim.isEndBlock()) : 506 "Block end right before a branch target _after_ weaving " + "in the branch delimiters"; 509 branchHandle.setTarget(branchTarget.getPrev()); 510 } 511 } 512 513 private static void insertStartDelimiter(InstructionList il, 514 InstructionHandle target, int position) { 515 516 assert position >= 0 : "Start position is " + position + " but must be >= 0"; 519 il.insert(target, new BlockDelimiter( 520 BlockDelimiter.BLOCK_START, 521 position)); 522 } 523 524 private static void insertEndDelimiter(InstructionList il, 525 InstructionHandle target, int position) { 526 BlockDelimiter blockDelimiter = new BlockDelimiter( 527 BlockDelimiter.BLOCK_END, 528 position); 529 if (target instanceof BranchHandle) { BranchHandle branchHandle = (BranchHandle) target; 531 blockDelimiter.addTarget(getNextPosition(branchHandle.getTarget())); 532 if (target.getInstruction() instanceof Select) { 533 Select select = (Select) target.getInstruction(); 534 InstructionHandle[] targets = select.getTargets(); 535 for (int i = 0; i < targets.length; i++) { 536 blockDelimiter.addTarget(getNextPosition(targets[i])); 537 } 538 } 539 if (!(target.getInstruction() instanceof UnconditionalBranch)) { 540 blockDelimiter.addTarget(getNextPosition(target.getNext())); 541 } 542 } else if (!requiresExcludingEnd(target.getInstruction())) { 543 blockDelimiter.addTarget(getNextPosition(target)); 544 } 545 il.insert(target, blockDelimiter); 546 } 547 548 551 private static boolean requiresExcludingEnd(Instruction instruction) { 552 boolean result = false; 553 if (instruction instanceof BranchInstruction 554 || instruction instanceof ReturnInstruction 555 || instruction instanceof ATHROW) { 556 result = true; 557 } 558 return result; 559 } 560 561 566 private static boolean isBlockDelimiter(Instruction instruction) { 567 boolean result = false; 568 if (instruction instanceof BlockDelimiter || requiresExcludingEnd(instruction)) { 571 result = true; 572 } 573 return result; 574 } 575 } 576 | Popular Tags |