From cd3a797f2aba5222c45ece9eea8b734ea0d0c9bf Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Thu, 1 Feb 2018 21:26:28 +0300 Subject: [PATCH] JS: fix corner case in when translation (fix crash in KT-22544) --- .../switchOptimizationSingleStatementCase.kt | 27 +++++++++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ .../LightAnalysisModeTestGenerated.java | 6 +++++ .../inline/clean/EmptyStatementElimination.kt | 3 ++- .../js/inline/clean/FunctionPostProcessor.kt | 5 +++- .../semantics/JsCodegenBoxTestGenerated.java | 6 +++++ 7 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt diff --git a/compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt b/compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt new file mode 100644 index 00000000000..50447ed814d --- /dev/null +++ b/compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt @@ -0,0 +1,27 @@ +// CHECK_CASES_COUNT: function=test1 count=2 +// CHECK_IF_COUNT: function=test1 count=0 +// CHECK_BREAKS_COUNT: function=test1 count=1 + +// CHECK_CASES_COUNT: function=test2 count=2 +// CHECK_IF_COUNT: function=test2 count=0 +// CHECK_BREAKS_COUNT: function=test2 count=1 + +fun test1(v: Int) { + when (v) { + 1, 2 -> Unit + } +} + +fun test2(v: Int) { + loop@ while(true) { + when (v) { + 1, 2 -> break@loop + } + } +} + +fun box(): String { + test1(1) + test2(1) + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 88b08438fd0..9ea0dde8ceb 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -21489,6 +21489,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("switchOptimizationSingleStatementCase.kt") + public void testSwitchOptimizationSingleStatementCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt"); + doTest(fileName); + } + @TestMetadata("switchOptimizationSparse.kt") public void testSwitchOptimizationSparse() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSparse.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 8480a02e763..9a8ddfa67c8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -21489,6 +21489,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("switchOptimizationSingleStatementCase.kt") + public void testSwitchOptimizationSingleStatementCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt"); + doTest(fileName); + } + @TestMetadata("switchOptimizationSparse.kt") public void testSwitchOptimizationSparse() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSparse.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index bc8ea2d3576..dd9879cf479 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -21489,6 +21489,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("switchOptimizationSingleStatementCase.kt") + public void testSwitchOptimizationSingleStatementCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt"); + doTest(fileName); + } + @TestMetadata("switchOptimizationSparse.kt") public void testSwitchOptimizationSparse() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSparse.kt"); diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/EmptyStatementElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/EmptyStatementElimination.kt index c35f4be646d..0718844ab76 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/EmptyStatementElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/EmptyStatementElimination.kt @@ -75,7 +75,8 @@ internal class EmptyStatementElimination(private val root: JsStatement) { for (case in x.cases) { processStatements(case.statements) } - if (x.cases.dropLast(1).none { it is JsDefault } && x.cases.dropLast(1).all { it.statements.isEmpty() }) { + if (x.cases.lastOrNull() is JsDefault && + x.cases.dropLast(1).all { it.statements.isEmpty() }) { hasChanges = true val conditionStatement = JsAstUtils.asSyntheticStatement(x.expression) ctx.replaceMe(JsBlock(listOf(conditionStatement) + x.cases.last().statements)) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt index e768286db00..28e5d05e95e 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt @@ -37,7 +37,10 @@ class FunctionPostProcessor(val root: JsFunction) { fun apply() { do { - val hasChanges = optimizations.fold(false) { existing, f -> existing or f() } + var hasChanges = false + for (opt in optimizations) { + hasChanges = hasChanges or opt() + } } while (hasChanges) } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 070e0bf9f31..2203f466016 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -25251,6 +25251,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("switchOptimizationSingleStatementCase.kt") + public void testSwitchOptimizationSingleStatementCase() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSingleStatementCase.kt"); + doTest(fileName); + } + @TestMetadata("switchOptimizationSparse.kt") public void testSwitchOptimizationSparse() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/when/switchOptimizationSparse.kt");