diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java index 79f730f1054..9e70170d5fa 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/MethodInliner.java @@ -356,7 +356,6 @@ public class MethodInliner { AbstractInsnNode cur = node.instructions.getFirst(); int index = 0; - Set possibleDeadLabels = new HashSet(); while (cur != null) { Frame frame = sources[index]; @@ -416,15 +415,12 @@ public class MethodInliner { if (frame == null) { //clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems if (prevNode.getType() == AbstractInsnNode.LABEL) { - possibleDeadLabels.add((LabelNode) prevNode); + //NB: Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression) + //it may occurs that interval for default handler starts before catch start label, so this label seems as dead, + //but as result all this labels will be merged into one (see KT-5863) } else { node.instructions.remove(prevNode); } - } else { - //Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression) - //it may occurs that interval for default handler starts before catch start label, so this label seems as dead, - //but as result all this labels will be merged into one (see KT-5863) - possibleDeadLabels.remove(prevNode.getPrevious()); } } @@ -432,7 +428,7 @@ public class MethodInliner { List blocks = node.tryCatchBlocks; for (Iterator iterator = blocks.iterator(); iterator.hasNext(); ) { TryCatchBlockNode block = iterator.next(); - if (possibleDeadLabels.contains(block.start) && possibleDeadLabels.contains(block.end)) { + if (isEmptyTryInterval(block)) { iterator.remove(); } } @@ -440,6 +436,15 @@ public class MethodInliner { return node; } + private static boolean isEmptyTryInterval(@NotNull TryCatchBlockNode tryCatchBlockNode) { + LabelNode start = tryCatchBlockNode.start; + AbstractInsnNode end = tryCatchBlockNode.end; + while (end != start && end instanceof LabelNode) { + end = end.getPrevious(); + } + return start == end; + } + public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) { if (insnNode.getOpcode() == Opcodes.ALOAD) { int varIndex = ((VarInsnNode) insnNode).var; diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt new file mode 100644 index 00000000000..20c72b783fa --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt @@ -0,0 +1,18 @@ +import test.* + +fun call(): String { + return nonLocal() +} + +inline fun nonLocal(): String { + mysynchronized(Object()) { + return "nonLocal" + } + return "local" +} + +fun box(): String { + val call = call() + if (call != "nonLocal") return "fail $call" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.2.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.2.kt new file mode 100644 index 00000000000..dcf18fa5923 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.2.kt @@ -0,0 +1,11 @@ +package test + +public inline fun mysynchronized(lock: Any, block: () -> R): R { + try { + return block() + } + finally { + //do nothing + 1 + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java index d27fb28dcd3..aafb85af3d7 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -567,6 +567,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT doTestMultiFileWithInlineCheck(fileName); } + @TestMetadata("synchonized.1.kt") + public void testSynchonized() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + @TestMetadata("throwInFinally.1.kt") public void testThrowInFinally() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/throwInFinally.1.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index df3ce0dcf8b..cb64bfa128a 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -567,6 +567,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doBoxTestWithInlineCheck(fileName); } + @TestMetadata("synchonized.1.kt") + public void testSynchonized() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + @TestMetadata("throwInFinally.1.kt") public void testThrowInFinally() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/throwInFinally.1.kt");