Exemple #1
0
  @NotNull
  // process local and global returns (local substituted with goto end-label global kept unchanged)
  public static List<PointForExternalFinallyBlocks> processReturns(
      @NotNull MethodNode node,
      @NotNull LabelOwner labelOwner,
      boolean remapReturn,
      Label endLabel) {
    if (!remapReturn) {
      return Collections.emptyList();
    }
    List<PointForExternalFinallyBlocks> result = new ArrayList<PointForExternalFinallyBlocks>();
    InsnList instructions = node.instructions;
    AbstractInsnNode insnNode = instructions.getFirst();
    while (insnNode != null) {
      if (InlineCodegenUtil.isReturnOpcode(insnNode.getOpcode())) {
        AbstractInsnNode previous = insnNode.getPrevious();
        MethodInsnNode flagNode;
        boolean isLocalReturn = true;
        String labelName = null;
        if (previous != null
            && previous instanceof MethodInsnNode
            && InlineCodegenUtil.NON_LOCAL_RETURN.equals(((MethodInsnNode) previous).owner)) {
          flagNode = (MethodInsnNode) previous;
          labelName = flagNode.name;
        }

        if (labelName != null) {
          isLocalReturn = labelOwner.isMyLabel(labelName);
          // remove global return flag
          if (isLocalReturn) {
            instructions.remove(previous);
          }
        }

        if (isLocalReturn && endLabel != null) {
          LabelNode labelNode = (LabelNode) endLabel.info;
          JumpInsnNode jumpInsnNode = new JumpInsnNode(Opcodes.GOTO, labelNode);
          instructions.insert(insnNode, jumpInsnNode);
          instructions.remove(insnNode);
          insnNode = jumpInsnNode;
        }

        // genetate finally block before nonLocalReturn flag/return/goto
        result.add(
            new PointForExternalFinallyBlocks(
                isLocalReturn ? insnNode : insnNode.getPrevious(),
                getReturnType(insnNode.getOpcode())));
      }
      insnNode = insnNode.getNext();
    }
    return result;
  }