BitSet getBasicBlocks() { if (basicBlocks == null) { Instruction[] code = mi.getInstructions(); BitSet bb = new BitSet(code.length); bb.set(0); // first insn is always a bb start // first, look at the insn type for (int i = 0; i < code.length; i++) { Instruction insn = code[i]; if (insn instanceof IfInstruction) { IfInstruction ifInsn = (IfInstruction) insn; Instruction tgt = ifInsn.getTarget(); bb.set(tgt.getInstructionIndex()); tgt = ifInsn.getNext(); bb.set(tgt.getInstructionIndex()); } else if (insn instanceof GOTO) { Instruction tgt = ((GOTO) insn).getTarget(); bb.set(tgt.getInstructionIndex()); } else if (insn instanceof InvokeInstruction) { // hmm, this might be a bit too conservative, but who says we // don't jump out of a caller into a handler, or even that we // ever return from the call? Instruction tgt = insn.getNext(); bb.set(tgt.getInstructionIndex()); } } // and now look at the handlers (every first insn is a bb start) ExceptionHandler[] handlers = mi.getExceptions(); if (handlers != null) { for (int i = 0; i < handlers.length; i++) { Instruction tgt = mi.getInstructionAt(handlers[i].getHandler()); bb.set(tgt.getInstructionIndex()); } } basicBlocks = bb; /** dump * System.out.println(); * System.out.println(mi.getFullName()); * for (int i=0; i<code.length; i++) { * System.out.print(String.format("%1$2d %2$c ",i, bb.get(i) ? '>' : ' ')); * System.out.println(code[i]); * } **/ } return basicBlocks; }
BitSet getHandlerStarts() { BitSet b = new BitSet(mi.getInstructions().length); ExceptionHandler[] handler = mi.getExceptions(); if (handler != null) { for (int i = 0; i < handler.length; i++) { Instruction hs = mi.getInstructionAt(handler[i].getHandler()); b.set(hs.getInstructionIndex()); } } return b; }