private static void insertSemaphore(ControlFlowGraph graph,
                                      Set<BasicBlock> setTry,
                                      BasicBlock head,
                                      BasicBlock handler,
                                      int var,
                                      Record information,
                                      int bytecodeVersion) {
    Set<BasicBlock> setCopy = new HashSet<>(setTry);

    int finallyType = information.firstCode;
    Map<BasicBlock, Boolean> mapLast = information.mapLast;

    // first and last statements
    removeExceptionInstructionsEx(handler, 1, finallyType);
    for (Entry<BasicBlock, Boolean> entry : mapLast.entrySet()) {
      BasicBlock last = entry.getKey();

      if (entry.getValue()) {
        removeExceptionInstructionsEx(last, 2, finallyType);
        graph.getFinallyExits().add(last);
      }
    }

    // disable semaphore at statement exit points
    for (BasicBlock block : setTry) {
      for (BasicBlock dest : block.getSuccessors()) {
        // break out
        if (dest != graph.getLast() && !setCopy.contains(dest)) {
          // disable semaphore
          SimpleInstructionSequence seq = new SimpleInstructionSequence();
          seq.addInstruction(Instruction.create(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecodeVersion, new int[]{0}), -1);
          seq.addInstruction(Instruction.create(CodeConstants.opc_istore, false, CodeConstants.GROUP_GENERAL, bytecodeVersion, new int[]{var}), -1);

          // build a separate block
          BasicBlock newBlock = new BasicBlock(++graph.last_id, seq);

          // insert between block and dest
          block.replaceSuccessor(dest, newBlock);
          newBlock.addSuccessor(dest);
          setCopy.add(newBlock);
          graph.getBlocks().addWithKey(newBlock, newBlock.id);

          // exception ranges
          // FIXME: special case synchronized
          copyExceptionEdges(graph, block, newBlock);
        }
      }
    }

    // enable semaphore at the statement entrance
    BasicBlock newHead = createHeadBlock(graph, 1, var, bytecodeVersion);
    insertBlockBefore(graph, head, newHead);

    // initialize semaphore with false
    BasicBlock newHeadInit = createHeadBlock(graph, 0, var, bytecodeVersion);
    insertBlockBefore(graph, newHead, newHeadInit);

    setCopy.add(newHead);
    setCopy.add(newHeadInit);

    for (BasicBlock hd : new HashSet<>(newHeadInit.getSuccessorExceptions())) {
      ExceptionRangeCFG range = graph.getExceptionRange(hd, newHeadInit);

      if (setCopy.containsAll(range.getProtectedRange())) {
        newHeadInit.removeSuccessorException(hd);
        range.getProtectedRange().remove(newHeadInit);
      }
    }
  }
private static void insertSemaphore(ControlFlowGraph graph,
                                      Set<BasicBlock> setTry,
                                      BasicBlock head,
                                      BasicBlock handler,
                                      int var,
                                      Record information,
                                      int bytecodeVersion)