@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; }
public void removeFinallyMarkers(@NotNull MethodNode intoNode) { if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return; InsnList instructions = intoNode.instructions; AbstractInsnNode curInstr = instructions.getFirst(); while (curInstr != null) { if (InlineCodegenUtil.isFinallyMarker(curInstr)) { AbstractInsnNode marker = curInstr; // just to assert getConstant(marker.getPrevious()); curInstr = curInstr.getNext(); instructions.remove(marker.getPrevious()); instructions.remove(marker); continue; } curInstr = curInstr.getNext(); } }