diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/DeadCodeEliminationMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/DeadCodeEliminationMethodTransformer.kt index 3fd369385d5..57b0ea2feb4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/DeadCodeEliminationMethodTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/DeadCodeEliminationMethodTransformer.kt @@ -20,6 +20,7 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful +import org.jetbrains.kotlin.codegen.optimization.common.removeEmptyCatchBlocks class DeadCodeEliminationMethodTransformer : MethodTransformer() { override fun transform(internalClassName: String, methodNode: MethodNode) { @@ -28,10 +29,12 @@ class DeadCodeEliminationMethodTransformer : MethodTransformer() { val insnsArray = insnList.toArray() // Do not remove not meaningful nodes (labels/linenumbers) because they can be referred - // by try/catch blocks or local variables table - // We remove unneeded ones further after all optimizations by calling CommonPackage.prepareForEmitting(methodNode) + // by try/catch blocks or local variables table. insnsArray.zip(frames).filter { it.second == null && it.first.isMeaningful }.forEach { insnList.remove(it.first) } + + // Remove empty try-catch blocks to make sure we don't break data flow analysis invariants by dead code elimination. + methodNode.removeEmptyCatchBlocks() } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java index fa2d7acc539..f055261691f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java @@ -35,9 +35,9 @@ public class OptimizationMethodVisitor extends TransformationMethodVisitor { private static final MethodTransformer[] OPTIMIZATION_TRANSFORMERS = new MethodTransformer[] { new RedundantNullCheckMethodTransformer(), new RedundantBoxingMethodTransformer(), + new RedundantCoercionToUnitTransformer(), new DeadCodeEliminationMethodTransformer(), - new RedundantGotoMethodTransformer(), - new RedundantCoercionToUnitTransformer() + new RedundantGotoMethodTransformer() }; private final boolean disableOptimization; diff --git a/compiler/testData/codegen/box/deadCodeElimination/kt14357.kt b/compiler/testData/codegen/box/deadCodeElimination/kt14357.kt new file mode 100644 index 00000000000..377a6facdac --- /dev/null +++ b/compiler/testData/codegen/box/deadCodeElimination/kt14357.kt @@ -0,0 +1,10 @@ +fun box(): String { + if (false) { + try { + null!! + } catch (e: Exception) { + throw e + } + } + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/deadCodeElimination/kt14357.kt b/compiler/testData/codegen/bytecodeText/deadCodeElimination/kt14357.kt new file mode 100644 index 00000000000..f81e9f51f5f --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/deadCodeElimination/kt14357.kt @@ -0,0 +1,11 @@ +fun test() { + if (false) { + try { + println("Hello Kotlin") + } catch (e: Exception) { + e.printStackTrace() + } + } +} + +// 0 INVOKE \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 93c011069a9..1a082403cfb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -5079,6 +5079,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/deadCodeElimination/intersectingVariableRangeInFinally.kt"); doTest(fileName); } + + @TestMetadata("kt14357.kt") + public void testKt14357() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/deadCodeElimination/kt14357.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/defaultArguments") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index fcc2c7c238c..9ca0102576e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -889,6 +889,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("kt14357.kt") + public void testKt14357() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/deadCodeElimination/kt14357.kt"); + doTest(fileName); + } + @TestMetadata("lastReturn.kt") public void testLastReturn() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/deadCodeElimination/lastReturn.kt");