diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 55b76b8aa6f..8046f0f0af3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1804,13 +1804,13 @@ public class ExpressionCodegen extends JetVisitor implem Label finallyStart = new Label(); v.mark(finallyStart); finallyBlockStackElement.addGapLabel(finallyStart); - if (context.isInlineFunction() || context.isInliningLambda()) { + if (InlineCodegenUtil.isFinallyMarkerRequired(context)) { InlineCodegenUtil.generateFinallyMarker(v, finallyDeep, true); } //noinspection ConstantConditions gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); - if (context.isInlineFunction() || context.isInliningLambda()) { + if (InlineCodegenUtil.isFinallyMarkerRequired(context)) { InlineCodegenUtil.generateFinallyMarker(v, finallyDeep, false); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 389ccedcc55..7ef0381395b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -52,6 +52,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.Method; import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; +import org.jetbrains.org.objectweb.asm.tree.InsnList; import org.jetbrains.org.objectweb.asm.tree.LabelNode; import org.jetbrains.org.objectweb.asm.tree.MethodNode; @@ -62,6 +63,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags; import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker; +import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isFunctionLiteral; import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert; @@ -290,6 +292,7 @@ public class InlineCodegen extends CallGenerator { List infos = MethodInliner.processReturns(adapter, labelOwner, true, null); generateAndInsertFinallyBlocks(adapter, infos, ((StackValue.Local)remapper.remap(parameters.totalSize() + 1).value).index); + removeFinallyMarkers(adapter); adapter.accept(new InliningInstructionAdapter(codegen.v)); @@ -647,8 +650,8 @@ public class InlineCodegen extends CallGenerator { public void generateAndInsertFinallyBlocks( - MethodNode intoNode, - List insertPoints, + @NotNull MethodNode intoNode, + @NotNull List insertPoints, int offsetForFinallyLocalVar ) { if (!codegen.hasFinallyBlocks()) return; @@ -667,7 +670,7 @@ public class InlineCodegen extends CallGenerator { processor.processInstruction(curInstr, true); if (InlineCodegenUtil.isFinallyStart(curInstr)) { //TODO deep index calc could be more precise - curFinallyDeep = InlineCodegenUtil.getConstant(curInstr.getPrevious()); + curFinallyDeep = getConstant(curInstr.getPrevious()); } MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr); @@ -709,6 +712,25 @@ public class InlineCodegen extends CallGenerator { //processor.substituteLocalVarTable(intoNode); } + 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)) { + //just to assert + AbstractInsnNode marker = curInstr; + getConstant(marker.getPrevious()); + curInstr = curInstr.getNext(); + instructions.remove(marker.getPrevious()); + instructions.remove(marker); + continue; + } + curInstr = curInstr.getNext(); + } + } + private SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap) { return new NestedSourceMapper(sourceMapper, nodeAndSmap.getRanges(), nodeAndSmap.getClassSMAP().getSourceInfo()); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 8b64ad1d317..77aa9788a53 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -427,12 +427,21 @@ public class InlineCodegenUtil { return INLINE_MARKER_CLASS_NAME.equals(method.owner) && name.equals(method.name); } + public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) { + return context.isInlineFunction() || context.isInliningLambda(); + } + public static int getConstant(AbstractInsnNode ins) { int opcode = ins.getOpcode(); Integer value; if (opcode >= Opcodes.ICONST_0 && opcode <= Opcodes.ICONST_5) { value = opcode - Opcodes.ICONST_0; - } else { + } + else if (opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH) { + IntInsnNode index = (IntInsnNode) ins; + value = index.operand; + } + else { LdcInsnNode index = (LdcInsnNode) ins; value = (Integer) index.cst; } diff --git a/compiler/testData/codegen/bytecodeText/inline/removedFinallyMarkers.kt b/compiler/testData/codegen/bytecodeText/inline/removedFinallyMarkers.kt new file mode 100644 index 00000000000..fa3c5cc46b0 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inline/removedFinallyMarkers.kt @@ -0,0 +1,33 @@ +inline fun test(s: ()->Int){ + var i = 0; + try { + i = s() + i = i + 10 + } finally { + //finallyStart + i + //finallyEnd + //and same markers in default catch handler + } +} + +fun box() : String { + var p: Int = 1 + test { + try { + p = 1 + return "OK" + } catch(e: Exception) { + p = -1; + p + } finally { + p++ + } + + } + return "fail" +} + +// 2 InlineMarker.finallyStart +// 2 InlineMarker.finallyEnd +// 4 InlineMarker \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index a9168eb9b64..ac3f1ea6b05 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -499,6 +499,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("removedFinallyMarkers.kt") + public void testRemovedFinallyMarkers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/removedFinallyMarkers.kt"); + doTest(fileName); + } + @TestMetadata("splitedExceptionTable.kt") public void testSplitedExceptionTable() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/splitedExceptionTable.kt");