/** * Create the edges in the control flow graph with the basic blocks. * * @param insts the instructions * @param numBlocks an array containing the number of basic block for each instruction. * @param bbs the basic blocks */ private void findCFGEdges(Instruction[] insts, short[] numBlocks, BasicBlock[] bbs) { for (int i = 0; i < bbs.length; ++i) { BasicBlock bb = bbs[i]; Instruction lastInst = insts[bb.getEnd()]; if (lastInst.canComplete() && i != bbs.length - 1) { // the next block is accessible bb.addDefaultNextBlock(bbs[i + 1]); } if (lastInst instanceof JumpInstruction) { // goto, jsr are distincts than other jump instructions. Edge edge; JumpInstruction jumpInst = (JumpInstruction) lastInst; if (lastInst.getOpcode() == ClassfileConstants2.opc_goto) { edge = bb.addDefaultNextBlock( bbs[numBlocks[getInstructionLine(insts, jumpInst.getTarget())]]); jumpInst.setTarget(new EdgeLabel(edge)); } else if (lastInst.getOpcode() == ClassfileConstants2.opc_jsr) { // do nothing here // see method findSubRoutines } else { edge = bb.addConditionNextBlock( bbs[numBlocks[getInstructionLine(insts, jumpInst.getTarget())]]); jumpInst.setTarget(new EdgeLabel(edge)); } } if (lastInst instanceof SwitchInstruction) { SwitchInstruction si = (SwitchInstruction) lastInst; for (int k = -1; k < si.getSwitchCount(); k++) { Edge edge = bb.addSwitchNextBlock(bbs[numBlocks[getInstructionLine(insts, si.getTarget(k))]]); si.setTarget(k, new EdgeLabel(edge)); } } } }
/** * Remove critical edges. A critical edge is an edge from a block with more than one successor to * a block with more than one predecessor. Critical edges can hinder code motion and should be * removed. */ private void removeCriticalEdges() { LinkedList list = new LinkedList(); for (BasicBlock bb = firstBB; bb != null; bb = bb.getNext()) { if (bb.getOutEdgesNumber() > 1) { Iterator outEdges = bb.getOutEdges(); while (outEdges.hasNext()) { Edge outEdge = (Edge) outEdges.next(); BasicBlock succ = (BasicBlock) outEdge.getTarget(); if (succ.getInEdgesNumber() > 1 && !succ.isFirstBlockSubroutine() && !succ.isCatchBlock()) { list.addLast(outEdge); } } } } while (!list.isEmpty()) { Edge edge = (Edge) list.removeFirst(); BasicBlock source = (BasicBlock) edge.getSource(); BasicBlock target = (BasicBlock) edge.getTarget(); if (source.getOutEdgesNumber() > 1 && target.getInEdgesNumber() > 1) { // insert a new block in the CFG between source and target BasicBlock insert = new BasicBlock(graph); edge.getSource().changeEdgeTarget(edge, insert); insert.addDefaultNextBlock(target); // insert the new block before target in the trace target.insertBefore(insert); for (int i = 0; i < exceptionHandlers.length; ++i) { if (exceptionHandlers[i].contains(target)) { exceptionHandlers[i].addProtectedBlock(insert); insert.addExceptionNextBlock(target); } } } } }
/** * Find the blocks protected by each ExceptionHandler. Add "exception edges" in the control flow * graph. Add a basic block before the block which catch the exception. This last block store the * exception in a variable. * * <p>Modification 02/04/2002 : add an exception edge between the blocks before the first block * protected and the catch block. * * @param numBlocks an array containing the number of basic block for each instruction. * @param insts the instructions * @param bbs the basic blocks */ private void findExceptionBlocks(short[] numBlocks, Instruction[] insts, BasicBlock[] bbs) { // shows if we had ever add a block for the catch block boolean[] marqued = new boolean[bbs.length]; for (int i = 0; i < exceptionHandlers.length; ++i) { ExceptionHandler handle = exceptionHandlers[i]; int numBlock = numBlocks[handle.getHandle()]; BasicBlock catchBlock = bbs[numBlock]; if (!marqued[numBlock]) { // add a new block // if the first instruction is the saving of the // exception put this instruction in the // new block else this saving will be added during // the 3-adress code generation BasicBlock newBlock; Instruction first = insts[catchBlock.getStart()]; if (first instanceof LocalVarInstruction && ((LocalVarInstruction) first).isStore()) { int instructionLine = catchBlock.getStart(); newBlock = new BasicBlock(instructionLine, instructionLine, graph); // remove this instruction from the next block catchBlock.setStart(instructionLine + 1); } else { newBlock = new BasicBlock(graph); } newBlock.setCatchBlock(true); catchBlock.insertBefore(newBlock); newBlock.addDefaultNextBlock(catchBlock); bbs[numBlock] = newBlock; catchBlock = newBlock; marqued[numBlock] = true; } handle.setHandlerBlock(catchBlock); } for (int i = 0; i < exceptionHandlers.length; ++i) { ExceptionHandler handle = exceptionHandlers[i]; BasicBlock catchBlock = handle.getHandlerBlock(); int numInst = handle.getStart(); int instEnd = handle.getEnd(); int numBlock = -1; // MODIFICATION 02/04/2002 if (numInst <= instEnd) { BasicBlock first = bbs[numBlocks[numInst]]; if (catchBlock != first) { // this is possible ! Iterator preds = first.getPredecessors(); while (preds.hasNext()) { BasicBlock pred = (BasicBlock) preds.next(); pred.addExceptionNextBlock(catchBlock); } } } // END MODIFICATION 02/04/2002 numBlock = -1; for (; numInst <= instEnd; ++numInst) { if (numBlocks[numInst] != numBlock) { numBlock = numBlocks[numInst]; // add blocks in exception handler. BasicBlock bb = bbs[numBlock]; handle.addProtectedBlock(bb); // add exception edges bb.addExceptionNextBlock(catchBlock); // if it's a catch block add also the next block if (marqued[numBlock]) { BasicBlock next = bb.getNext(); handle.addProtectedBlock(next); next.addExceptionNextBlock(catchBlock); } } } } }