synchronized :: (Instr, Instr, Instr, Instr, Instr) -> Instr -> Instr
synchronized (storeCode, loadCode, throwCode, monEnter, monExit) syncCode = Instr $ do
  let tryCode     = syncCode
      finallyCode = monExit
  [startLabel, endLabel, finallyLabel, finallyEndLabel, defaultLabel]
    <- mkSystemLabels 5
  lb <- saveLastBranch
  unInstr $ monEnter
  InstrState { isCtrlFlow   = cf
             , isLabelTable = lt } <- get
  (tryCF, tryLT, mtryLB) <- withCFState cf lt $ unInstr $
       putLabel' startLabel
    <> tryCode
    <> finallyCode
    <> putLabel' endLabel
    <> condGoto Special defaultLabel
  (finallyCF, finallyLT, mfinallyLB) <- withCFState cf lt $ unInstr $
       ctrlFlow (CF.mapStack (CF.push jthrowable))
    <> putLabel finallyLabel
    <> storeCode
    <> finallyCode
    <> putLabel' finallyEndLabel
    <> loadCode
    <> throwCode
  addExceptionHandler startLabel endLabel finallyLabel Nothing
  addExceptionHandler finallyLabel finallyEndLabel finallyLabel Nothing
  putCtrlFlow' $ CF.merge cf [tryCF, finallyCF]
  mergeLabels [tryLT, finallyLT]
  unInstr $ putLabel defaultLabel
  resetLastBranch $ fromMaybe lb (selectLatestLB mtryLB mfinallyLB)
synchronized :: (Instr, Instr, Instr, Instr, Instr) -> Instr -> Instr
synchronized (storeCode, loadCode, throwCode, monEnter, monExit) syncCode = Instr $ do
  let tryCode     = syncCode
      finallyCode = monExit
  [startLabel, endLabel, finallyLabel, finallyEndLabel, defaultLabel]
    <- mkSystemLabels 5
  lb <- saveLastBranch
  unInstr $ monEnter
  InstrState { isCtrlFlow   = cf
             , isLabelTable = lt } <- get
  (tryCF, tryLT, mtryLB) <- withCFState cf lt $ unInstr $
       putLabel' startLabel
    <> tryCode
    <> finallyCode
    <> putLabel' endLabel
    <> condGoto Special defaultLabel
  (finallyCF, finallyLT, mfinallyLB) <- withCFState cf lt $ unInstr $
       ctrlFlow (CF.mapStack (CF.push jthrowable))
    <> putLabel finallyLabel
    <> storeCode
    <> finallyCode
    <> putLabel' finallyEndLabel
    <> loadCode
    <> throwCode
  addExceptionHandler startLabel endLabel finallyLabel Nothing
  addExceptionHandler finallyLabel finallyEndLabel finallyLabel Nothing
  putCtrlFlow' $ CF.merge cf [tryCF, finallyCF]
  mergeLabels [tryLT, finallyLT]
  unInstr $ putLabel defaultLabel
  resetLastBranch $ fromMaybe lb (selectLatestLB mtryLB mfinallyLB)
synchronized (storeCode, loadCode, throwCode, monEnter, monExit) syncCode = Instr $ do
  let tryCode     = syncCode
      finallyCode = monExit
  [startLabel, endLabel, finallyLabel, finallyEndLabel, defaultLabel]
    <- mkSystemLabels 5
  lb <- saveLastBranch
  unInstr $ monEnter
  InstrState { isCtrlFlow   = cf
             , isLabelTable = lt } <- get
  (tryCF, tryLT, mtryLB) <- withCFState cf lt $ unInstr $
       putLabel' startLabel
    <> tryCode
    <> finallyCode
    <> putLabel' endLabel
    <> condGoto Special defaultLabel
  (finallyCF, finallyLT, mfinallyLB) <- withCFState cf lt $ unInstr $
       ctrlFlow (CF.mapStack (CF.push jthrowable))
    <> putLabel finallyLabel
    <> storeCode
    <> finallyCode
    <> putLabel' finallyEndLabel
    <> loadCode
    <> throwCode
  addExceptionHandler startLabel endLabel finallyLabel Nothing
  addExceptionHandler finallyLabel finallyEndLabel finallyLabel Nothing
  putCtrlFlow' $ CF.merge cf [tryCF, finallyCF]
  mergeLabels [tryLT, finallyLT]
  unInstr $ putLabel defaultLabel
  resetLastBranch $ fromMaybe lb (selectLatestLB mtryLB mfinallyLB)