private final static void duplicateCode (OPT_IR ir, HashMap origToDupMap, HashSet exceptionHandlerBlocks){
private final void duplicateCode (OPT_IR ir, HashMap origToDupMap, HashSet exceptionHandlerBlocks){
  private final static void duplicateCode (OPT_IR ir, HashMap origToDupMap, HashSet exceptionHandlerBlocks){    if (DEBUG) VM.sysWrite("In duplicate code\n");    // Iterate through all blocks and duplicate them.  While    // iterating, loop until you see the block that was the *original*    // last block.  (Need to do it this way because we're adding    // blocks to the end as we loop.)    OPT_BasicBlock origLastBlock = ir.cfg.lastInCodeOrder();    boolean done = false;    OPT_BasicBlock curBlock = ir.cfg.firstInCodeOrder();    while (!done && curBlock != null) {      if (curBlock == origLastBlock)  // Stop after this iteration        done = true;      // Don't duplicate the exit node      if (curBlock == ir.cfg.exit()) {        // Next block        curBlock = curBlock.nextBasicBlockInCodeOrder();        continue;      }      // Check if the block needs to be split for later insertion of      // a check.  We split the entry basic block (first basic block      // in the method) to insert the method-entry check, and also      // exception handler blocks to simplify handling      if (curBlock == ir.cfg.entry() ||          curBlock.isExceptionHandlerBasicBlock()) {                OPT_Instruction splitInstr = null;                if (curBlock == ir.cfg.entry())           splitInstr = getFirstInstWithOperator(IR_PROLOGUE,curBlock);        else           splitInstr = getFirstInstWithOperator(LABEL,curBlock);                // Split entry node so the split instr isn't duplicated, but rest        // of block is.           OPT_BasicBlock blockTail =           curBlock.splitNodeWithLinksAt(splitInstr,ir);         curBlock.recomputeNormalOut(ir);                if (curBlock.isExceptionHandlerBasicBlock()) {          // Remember that the tail of the block we just split is an          // exception handler and we want to add a check here          exceptionHandlerBlocks.add(blockTail);        }                // proceed with the duplication using the second half of the split block.        curBlock = blockTail;                  // Is this necessary?   TODO:  see if it can be removed.        OPT_DefUse.recomputeSpansBasicBlock(ir);      }                  // Copy the basic block      OPT_BasicBlock dup = myCopyWithoutLinks(curBlock,ir);       dup.setInfrequent();  // duplicated code is known to be infrequent.            if (DEBUG2) VM.sysWrite("Copying bb: " + curBlock +                               " to be " + dup + "\n");            ir.cfg.addLastInCodeOrder(dup);            // Attach a goto to the duplicated code block, so that it      // doesn't fall through within the duplicated code, and jumps      // back to the checking code.  This is a bit of a convoluted way      // of doing things and could be cleaned up.  It was done      // originally done to make the remaining passes simpler.      OPT_BasicBlock fallthrough = curBlock.getFallThroughBlock();      if (fallthrough != null) {                OPT_Instruction g =           Goto.create(GOTO,                       fallthrough.makeJumpTarget());         dup.appendInstruction(g);      }      dup.recomputeNormalOut(ir);      origToDupMap.put(curBlock,dup); // Remember that basic block "dup"          // Next block      curBlock = curBlock.nextBasicBlockInCodeOrder();    }  }