From 61faa068d4e2ab29b7431e42d76a6aaddf9a8980 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 5 Sep 2017 15:57:51 +0300 Subject: [PATCH] Do not optimize == for KClasses in redundant boxing elimination For primitive wrappers such as java.lang.Integer, jlc = java.lang.Integer.class jlt = java.lang.Integer.TYPE !(ljc.equals(ljt)) However, in Kotlin corresponding KClass instances are equal. #KT-17748 Fixed Target versions 1.1.50 #KT-17879 Fixed Target versions 1.1.50 --- .../optimization/boxing/BoxingInterpreter.kt | 7 +++--- .../box/boxingOptimization/kClassEquals.kt | 20 ++++++++++++++++ .../codegen/box/boxingOptimization/kt17748.kt | 17 +++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 12 ++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 12 ++++++++++ .../LightAnalysisModeTestGenerated.java | 12 ++++++++++ .../semantics/JsCodegenBoxTestGenerated.java | 24 +++++++++++++++++++ 7 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt create mode 100644 compiler/testData/codegen/box/boxingOptimization/kt17748.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingInterpreter.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingInterpreter.kt index b264e25486d..ceb808266ae 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingInterpreter.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxingInterpreter.kt @@ -233,11 +233,10 @@ fun AbstractInsnNode.isAreEqualIntrinsic() = desc == "(Ljava/lang/Object;Ljava/lang/Object;)Z" } +private val shouldUseEqualsForWrappers = setOf(Type.DOUBLE_TYPE, Type.FLOAT_TYPE, AsmTypes.JAVA_CLASS_TYPE) + fun canValuesBeUnboxedForAreEqual(values: List): Boolean = - !values.any { - val unboxedType = getUnboxedType(it.type) - unboxedType == Type.DOUBLE_TYPE || unboxedType == Type.FLOAT_TYPE - } + values.none { getUnboxedType(it.type) in shouldUseEqualsForWrappers } fun AbstractInsnNode.isJavaLangComparableCompareToForSameTypedBoxedValues(values: List) = isJavaLangComparableCompareTo() && areSameTypedBoxedValues(values) diff --git a/compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt b/compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt new file mode 100644 index 00000000000..1e2ac20cd79 --- /dev/null +++ b/compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt @@ -0,0 +1,20 @@ +// IGNORE_BACKEND: JS, NATIVE + +fun test(a: Any) = when (a::class) { + String::class -> "String" + Int::class -> "Int" + Boolean::class -> "Boolean" + else -> "Else" +} + +fun box(): String { + val s = "" + val i = 0 + val b = false + + if (test(s) != "String") return "Fail 1" + if (test(i) != "Int") return "Fail 2" + if (test(b) != "Boolean") return "Fail 3" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/boxingOptimization/kt17748.kt b/compiler/testData/codegen/box/boxingOptimization/kt17748.kt new file mode 100644 index 00000000000..27e309527e5 --- /dev/null +++ b/compiler/testData/codegen/box/boxingOptimization/kt17748.kt @@ -0,0 +1,17 @@ +// IGNORE_BACKEND: JS, NATIVE + +fun box(): String { + 42.doSwitchInt() + "".doSwitchString() + return "OK" +} + +inline fun E.doSwitchInt(): String = when (E::class) { + Int::class -> "success!" + else -> throw AssertionError() +} + +inline fun E.doSwitchString(): String = when(E::class) { + String::class -> "success!" + else -> throw AssertionError() +} \ 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 4a14bf69b0b..c955669c302 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 @@ -950,12 +950,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("kClassEquals.kt") + public void testKClassEquals() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt"); + doTest(fileName); + } + @TestMetadata("kt15871.kt") public void testKt15871() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt"); doTest(fileName); } + @TestMetadata("kt17748.kt") + public void testKt17748() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt17748.kt"); + doTest(fileName); + } + @TestMetadata("kt19767.kt") public void testKt19767() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt19767.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 8732565fd80..c011aef776b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -950,12 +950,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kClassEquals.kt") + public void testKClassEquals() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt"); + doTest(fileName); + } + @TestMetadata("kt15871.kt") public void testKt15871() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt"); doTest(fileName); } + @TestMetadata("kt17748.kt") + public void testKt17748() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt17748.kt"); + doTest(fileName); + } + @TestMetadata("kt19767.kt") public void testKt19767() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt19767.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 6b8005810cb..c4618f6d2b0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -950,12 +950,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("kClassEquals.kt") + public void testKClassEquals() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt"); + doTest(fileName); + } + @TestMetadata("kt15871.kt") public void testKt15871() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt"); doTest(fileName); } + @TestMetadata("kt17748.kt") + public void testKt17748() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt17748.kt"); + doTest(fileName); + } + @TestMetadata("kt19767.kt") public void testKt19767() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt19767.kt"); 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 09235632fde..61188dac4bb 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 @@ -1148,12 +1148,36 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("kClassEquals.kt") + public void testKClassEquals() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kClassEquals.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("kt15871.kt") public void testKt15871() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt"); doTest(fileName); } + @TestMetadata("kt17748.kt") + public void testKt17748() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt17748.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + @TestMetadata("kt19767.kt") public void testKt19767() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt19767.kt");