diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt index f6b2b686364..a90c8abe416 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/EnumWhenLowering.kt @@ -18,10 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.isNullable -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.ir.util.getPropertyGetter -import org.jetbrains.kotlin.ir.util.isNullConst -import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid /** Look for when-constructs where subject is enum entry. @@ -53,9 +50,14 @@ open class EnumWhenLowering(protected val context: CommonBackendContext) : IrEle return super.visitBlock(expression) } val subject = expression.statements[0] - if (subject !is IrVariable || subject.type.getClass()?.kind != ClassKind.ENUM_CLASS) { + if (subject !is IrVariable) { return super.visitBlock(expression) } + val subjectClass = subject.type.getClass() + if (subjectClass == null || subjectClass.kind != ClassKind.ENUM_CLASS || subjectClass.isEffectivelyExternal()) { + return super.visitBlock(expression) + } + // Will be initialized only when we found a branch that compares // subject with compile-time known enum entry. val subjectOrdinalProvider = lazy { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index a63fa462564..3802c0d414a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -385,6 +385,12 @@ private val forLoopsLoweringPhase = makeBodyLoweringPhase( description = "[Optimization] For loops lowering" ) +private val enumWhenPhase = makeJsModulePhase( + ::EnumWhenLowering, + name = "EnumWhenLowering", + description = "Replace `when` subjects of enum types with their ordinals" +).toModuleLowering() + private val propertyLazyInitLoweringPhase = makeBodyLoweringPhase( ::PropertyLazyInitLowering, name = "PropertyLazyInitLowering", @@ -832,6 +838,7 @@ private val loweringList = listOf( initializersCleanupLoweringPhase, kotlinNothingValueExceptionPhase, // Common prefix ends + enumWhenPhase, enumEntryInstancesLoweringPhase, enumEntryInstancesBodyLoweringPhase, enumClassCreateInitializerLoweringPhase, diff --git a/compiler/testData/codegen/box/when/enumOptimization/bigEnum.kt b/compiler/testData/codegen/box/when/enumOptimization/bigEnum.kt index 7f9a6e600ae..629b6d1a32a 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/bigEnum.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/bigEnum.kt @@ -1,12 +1,8 @@ // WITH_RUNTIME -// CHECK_CASES_COUNT: function=bar1 count=6 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar1 count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=bar1 count=0 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=bar1 count=2 IGNORED_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar2 count=6 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar2 count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=bar2 count=0 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=bar2 count=3 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=bar1 count=6 +// CHECK_IF_COUNT: function=bar1 count=0 +// CHECK_CASES_COUNT: function=bar2 count=6 +// CHECK_IF_COUNT: function=bar2 count=0 import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/when/enumOptimization/duplicatingItems.kt b/compiler/testData/codegen/box/when/enumOptimization/duplicatingItems.kt index 73e20014331..f6936f90650 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/duplicatingItems.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/duplicatingItems.kt @@ -1,8 +1,7 @@ // WITH_RUNTIME // CHECK_CASES_COUNT: function=bar count=3 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=bar count=0 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=bar count=2 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=bar count=4 IGNORED_BACKENDS=JS +// CHECK_IF_COUNT: function=bar count=0 import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/when/enumOptimization/enumInsideClassObject.kt b/compiler/testData/codegen/box/when/enumOptimization/enumInsideClassObject.kt index c04fea4afab..1ce3c8075a0 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/enumInsideClassObject.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/enumInsideClassObject.kt @@ -1,6 +1,5 @@ // WITH_RUNTIME -// CHECK_CASES_COUNT: function=foo count=3 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=foo count=0 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=foo count=3 // CHECK_IF_COUNT: function=foo count=0 import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/when/enumOptimization/expression.kt b/compiler/testData/codegen/box/when/enumOptimization/expression.kt index c1aa6c0100c..418f1860d09 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/expression.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/expression.kt @@ -1,11 +1,8 @@ // WITH_RUNTIME -// CHECK_CASES_COUNT: function=bar1 count=3 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar1 count=0 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=bar1 count=3 // CHECK_IF_COUNT: function=bar1 count=0 -// CHECK_CASES_COUNT: function=bar2 count=4 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar2 count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=bar2 count=0 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=bar2 count=3 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=bar2 count=4 +// CHECK_IF_COUNT: function=bar2 count=0 import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/when/enumOptimization/kt14597.kt b/compiler/testData/codegen/box/when/enumOptimization/kt14597.kt index 1a8906cd280..7af0d40883e 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/kt14597.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/kt14597.kt @@ -1,7 +1,5 @@ -// CHECK_CASES_COUNT: function=box count=6 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=box count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=box count=1 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=box count=7 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=box count=6 +// CHECK_IF_COUNT: function=box count=1 enum class En { A, B, C } diff --git a/compiler/testData/codegen/box/when/enumOptimization/kt14597_full.kt b/compiler/testData/codegen/box/when/enumOptimization/kt14597_full.kt index 54a38bb67f6..2926f787c9e 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/kt14597_full.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/kt14597_full.kt @@ -1,7 +1,5 @@ -// CHECK_CASES_COUNT: function=box count=18 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=box count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=box count=3 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=box count=21 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=box count=18 +// CHECK_IF_COUNT: function=box count=3 enum class En { A, B, C } diff --git a/compiler/testData/codegen/box/when/enumOptimization/nullability.kt b/compiler/testData/codegen/box/when/enumOptimization/nullability.kt index 35beca78fac..9240d29b8e5 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/nullability.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/nullability.kt @@ -1,8 +1,12 @@ // WITH_RUNTIME -// CHECK_CASES_COUNT: function=foo1 count=0 -// CHECK_IF_COUNT: function=foo1 count=2 -// CHECK_CASES_COUNT: function=foo2 count=0 -// CHECK_IF_COUNT: function=foo2 count=2 +// CHECK_CASES_COUNT: function=foo1 count=0 TARGET_BACKENDS=JS +// CHECK_CASES_COUNT: function=foo1 count=4 IGNORED_BACKENDS=JS +// CHECK_IF_COUNT: function=foo1 count=2 TARGET_BACKENDS=JS +// CHECK_IF_COUNT: function=foo1 count=0 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=foo2 count=0 TARGET_BACKENDS=JS +// CHECK_CASES_COUNT: function=foo2 count=3 IGNORED_BACKENDS=JS +// CHECK_IF_COUNT: function=foo2 count=2 TARGET_BACKENDS=JS +// CHECK_IF_COUNT: function=foo2 count=0 IGNORED_BACKENDS=JS import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt b/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt index 20d5f740782..bfce330f0bc 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/nullableEnum.kt @@ -1,5 +1,7 @@ -// CHECK_CASES_COUNT: function=test count=0 -// CHECK_IF_COUNT: function=test count=3 +// CHECK_CASES_COUNT: function=test count=0 TARGET_BACKENDS=JS +// CHECK_CASES_COUNT: function=test count=3 IGNORED_BACKENDS=JS +// CHECK_IF_COUNT: function=test count=3 TARGET_BACKENDS=JS +// CHECK_IF_COUNT: function=test count=0 IGNORED_BACKENDS=JS enum class E { A, diff --git a/compiler/testData/codegen/box/when/enumOptimization/withoutElse.kt b/compiler/testData/codegen/box/when/enumOptimization/withoutElse.kt index 5e761bd1ba7..d61ebab36af 100644 --- a/compiler/testData/codegen/box/when/enumOptimization/withoutElse.kt +++ b/compiler/testData/codegen/box/when/enumOptimization/withoutElse.kt @@ -1,12 +1,10 @@ // WITH_RUNTIME // CHECK_CASES_COUNT: function=bar1 count=3 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar1 count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=bar1 count=0 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=bar1 count=3 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=bar1 count=4 IGNORED_BACKENDS=JS +// CHECK_IF_COUNT: function=bar1 count=0 // CHECK_CASES_COUNT: function=bar2 count=4 TARGET_BACKENDS=JS -// CHECK_CASES_COUNT: function=bar2 count=0 IGNORED_BACKENDS=JS -// CHECK_IF_COUNT: function=bar2 count=0 TARGET_BACKENDS=JS -// CHECK_IF_COUNT: function=bar2 count=4 IGNORED_BACKENDS=JS +// CHECK_CASES_COUNT: function=bar2 count=5 IGNORED_BACKENDS=JS +// CHECK_IF_COUNT: function=bar2 count=0 import kotlin.test.assertEquals diff --git a/js/js.translator/testData/box/expression/when/externalEnumSubject.kt b/js/js.translator/testData/box/expression/when/externalEnumSubject.kt index 984e463bc93..f62392604eb 100644 --- a/js/js.translator/testData/box/expression/when/externalEnumSubject.kt +++ b/js/js.translator/testData/box/expression/when/externalEnumSubject.kt @@ -1,4 +1,5 @@ // EXPECTED_REACHABLE_NODES: 1291 +// CHECK_IF_COUNT: function=foo count=2 external enum class X { A, B }