boolean isCanonical = (basicBlockMap.get(start) == basicBlock); if (DEBUG) System.out.println("  Block " + basicBlock.getId() + (isCanonical ? " is" : " is not") + " the canonical block for " + start);      if (!handledPEI) { CodeExceptionGen codeExceptionGen = exceptionHandlerMap.getHandlerForStartInstruction(start); if (codeExceptionGen != null) basicBlock.setExceptionGen(codeExceptionGen); }
	public void build() {		BasicBlock startBlock = getBlock(methodGen.getInstructionList().getStart(), new LinkedList<InstructionHandle>());		addEdge(cfg.getEntry(), startBlock, START_EDGE);	workListLoop:		while (!workList.isEmpty()) {			WorkListItem item = workList.removeFirst();			InstructionHandle start = item.start;			BasicBlock basicBlock = item.basicBlock;			LinkedList<InstructionHandle> jsrStack = item.jsrStack;			boolean handledPEI = item.handledPEI;			if (DEBUG) System.out.println("START BLOCK " + basicBlock.getId());			// If the start instruction is a PEI which we haven't handled yet, then			// this block is an Exception Thrower Block (ETB).			if (isPEI(start) && !handledPEI) {				// This block is an ETB.				basicBlock.setExceptionThrower(true);				// Add handled exception edges.				addExceptionEdges(start, basicBlock, jsrStack);				// Add fall through edge. Note that we add the work list item for the				// new block by hand, because getBlock()				//   (1) sets handledPEI to false, and				//   (2) maps the start instruction to the new block; the ETB is				//       the correct block for the start instruction, not the				//       fall through block				BasicBlock nextBasicBlock = cfg.allocate();				addEdge(basicBlock, nextBasicBlock, FALL_THROUGH_EDGE);				WorkListItem nextItem = new WorkListItem(start, nextBasicBlock, jsrStack, true);				workList.add(nextItem);				continue workListLoop;			}			InstructionHandle handle = start;			InstructionHandle next = null;			TargetEnumeratingVisitor visitor = null;			int endBlockMode;			// Add instructions to the basic block		scanInstructionsLoop:			while (true) {				// Add the instruction to the block				basicBlock.addInstruction(handle);				if (DEBUG) System.out.println("** Add " + handle + (isPEI(handle) ? " [PEI]" : ""));				// Except for instructions in JSR subroutines, no instruction should be				// in more than one basic block.				if (allHandlesToBasicBlockMap.get(handle) != null && jsrStack.isEmpty())					throw new IllegalStateException("Instruction in multiple blocks: " + handle);				allHandlesToBasicBlockMap.put(handle, basicBlock);				// PEIs should always be the first instruction in the basic block				if (isPEI(handle) && handle != basicBlock.getFirstInstruction())					throw new IllegalStateException("PEI is not first instruction in block!");				// This will be assigned if the potential next instruction in the				// basic block is something other than what would be returned				// by handle.getNext().  This only happens for JSR and RET instructions.				next = null;				Instruction ins = handle.getInstruction();				// Handle JSR, RET, and explicit branches.				if (ins instanceof JsrInstruction) {					// Remember where we came from					jsrStack.addLast(handle);					// Transfer control to the subroutine					JsrInstruction jsr = (JsrInstruction) ins;					next = jsr.getTarget();				} else if (ins instanceof RET) {					// Return control to instruction after JSR					next = jsrStack.removeLast().getNext();				} else if ((visitor = new TargetEnumeratingVisitor(handle, cpg)).isEndOfBasicBlock()) {					// Basic block ends with explicit branch.					endBlockMode = BRANCH;					break scanInstructionsLoop;				}				// If control gets here, then the current instruction was not cause				// for ending the basic block.  Check the next instruction, which may				// be cause for ending the block.				if (next == null)					next = handle.getNext();				if (next == null)					throw new IllegalStateException("Falling off end of method: " + handle);				// Control merge?				if (isMerge(next)) {					endBlockMode = MERGE;					break scanInstructionsLoop;				}				// Next instruction is a PEI?				if (isPEI(next)) {					endBlockMode = NEXT_IS_PEI;					break scanInstructionsLoop;				}				// The basic block definitely continues to the next instruction.				handle = next;			}			if (DEBUG) dumpBlock(basicBlock);			// Depending on how the basic block ended, add appropriate edges to the CFG.			if (next != null) {				// There is a successor instruction, meaning that this				// is a control merge, or the block was ended because of a PEI.				// In either case, just fall through to the successor.				if (endBlockMode != MERGE && endBlockMode != NEXT_IS_PEI)					throw new IllegalStateException("next != null, but not merge or PEI");				BasicBlock nextBlock = getBlock(next, jsrStack);				addEdge(basicBlock, nextBlock, FALL_THROUGH_EDGE);			} else {				// There is no successor instruction, meaning that the block ended				// in an explicit branch of some sort.				if (endBlockMode != BRANCH)					throw new IllegalStateException("next == null, but not branch");				if (visitor.instructionIsThrow()) {					// Explicit ATHROW instruction.  Add exception edges,					// and mark the block as an ETB.					addExceptionEdges(handle, basicBlock, jsrStack);					basicBlock.setExceptionThrower(true);				} else if (visitor.instructionIsReturn() || visitor.instructionIsExit()) {					// Return or call to System.exit().  In either case,					// add a return edge.					addEdge(basicBlock, cfg.getExit(), RETURN_EDGE);				} else {					// The TargetEnumeratingVisitor takes care of telling us what the targets are.					// (This includes the fall through edges for IF branches.)					Iterator<Target> i = visitor.targetIterator();					while (i.hasNext()) {						Target target = i.next();						BasicBlock targetBlock = getBlock(target.getTargetInstruction(), jsrStack);						addEdge(basicBlock, targetBlock, target.getEdgeType());					}				}				}		}	}