diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 8a1ed1c8fda..53b9af7a2ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -15,7 +15,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.PrimitiveType; -import org.jetbrains.kotlin.builtins.UnsignedTypes; import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.intrinsics.HashCode; @@ -148,6 +147,10 @@ public class AsmUtil { return primitiveTypeByBoxedType.get(boxedType); } + public static boolean isBoxedPrimitiveType(@NotNull Type boxedType) { + return primitiveTypeByBoxedType.get(boxedType) != null; + } + @NotNull public static Type unboxUnlessPrimitive(@NotNull Type boxedOrPrimitiveType) { if (isPrimitive(boxedOrPrimitiveType)) return boxedOrPrimitiveType; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxedBasicValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxedBasicValue.kt index a596a9546ca..032ed403438 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxedBasicValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/BoxedBasicValue.kt @@ -67,6 +67,7 @@ class BoxedValueDescriptor( var isSafeToRemove = true; private set val unboxedType: Type = getUnboxedType(boxedType, generationState) + val isInlineClassValue = isInlineClassValue(boxedType) fun getAssociatedInsns() = associatedInsns.toList() @@ -120,3 +121,7 @@ fun unboxedTypeOfInlineClass(boxedType: Type, state: GenerationState): Type? { val descriptor = state.jvmBackendClassResolver.resolveToClassDescriptors(boxedType).singleOrNull() ?: return null return state.typeMapper.mapType(descriptor.defaultType) } + +private fun isInlineClassValue(boxedType: Type): Boolean { + return !AsmUtil.isBoxedPrimitiveType(boxedType) && boxedType != AsmTypes.K_CLASS_TYPE +} 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 8fc4e84fc7e..baeae977fb7 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 @@ -276,14 +276,15 @@ fun isProgressionClass(type: Type) = isRangeOrProgression(buildFqNameByInternal(type.internalName)) fun AbstractInsnNode.isAreEqualIntrinsicForSameTypedBoxedValues(values: List) = - isAreEqualIntrinsic() && areSameTypedBoxedValues(values) + isAreEqualIntrinsic() && areSameTypedPrimitiveBoxedValues(values) -fun areSameTypedBoxedValues(values: List): Boolean { +fun areSameTypedPrimitiveBoxedValues(values: List): Boolean { if (values.size != 2) return false val (v1, v2) = values return v1 is BoxedBasicValue && v2 is BoxedBasicValue && - v1.descriptor.unboxedType == v2.descriptor.unboxedType + v1.descriptor.unboxedType == v2.descriptor.unboxedType && + !v1.descriptor.isInlineClassValue && !v2.descriptor.isInlineClassValue } fun AbstractInsnNode.isAreEqualIntrinsic() = @@ -299,7 +300,7 @@ fun canValuesBeUnboxedForAreEqual(values: List, generationState: Gen values.none { getUnboxedType(it.type, generationState) in shouldUseEqualsForWrappers } fun AbstractInsnNode.isJavaLangComparableCompareToForSameTypedBoxedValues(values: List) = - isJavaLangComparableCompareTo() && areSameTypedBoxedValues(values) + isJavaLangComparableCompareTo() && areSameTypedPrimitiveBoxedValues(values) fun AbstractInsnNode.isJavaLangComparableCompareTo() = isMethodInsnWith(Opcodes.INVOKEINTERFACE) { diff --git a/compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt b/compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt new file mode 100644 index 00000000000..94de3457bdc --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +InlineClasses +// IGNORE_BACKEND: JVM_IR + +inline class Foo(val x: Int) : Comparable { + override fun compareTo(other: Foo): Int { + return 10 + } +} + +fun box(): String { + val f1 = Foo(42) + val ff1: Comparable = f1 + + if (ff1.compareTo(f1) != 10) return "Fail" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/boxingOptimization/boxingAndEquals.kt b/compiler/testData/codegen/bytecodeText/boxingOptimization/boxingAndEquals.kt index 7b0f5e4208f..8056b38c3ef 100644 --- a/compiler/testData/codegen/bytecodeText/boxingOptimization/boxingAndEquals.kt +++ b/compiler/testData/codegen/bytecodeText/boxingOptimization/boxingAndEquals.kt @@ -20,8 +20,8 @@ fun getAndCheckInlinedInt(a: InlinedInt, b: InlinedInt) = // @TestInlinedKt.class: // 0 valueOf // 0 Value -// 0 areEqual -// 0 INVOKESTATIC InlinedInt\$Erased.box +// 1 areEqual +// 2 INVOKESTATIC InlinedInt\$Erased.box // 0 INVOKEVIRTUAL InlinedInt.unbox // FILE: Inline.kt 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 531c0a22776..99ded83e538 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 @@ -11196,6 +11196,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/computablePropertyInsideInlineClass.kt"); } + @TestMetadata("conformToComparableAndCallInterfaceMethod.kt") + public void testConformToComparableAndCallInterfaceMethod() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index cd1ea2ee654..f775fc94b1c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11196,6 +11196,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/computablePropertyInsideInlineClass.kt"); } + @TestMetadata("conformToComparableAndCallInterfaceMethod.kt") + public void testConformToComparableAndCallInterfaceMethod() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 042d1c6859a..edbfbbe566e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11196,6 +11196,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/computablePropertyInsideInlineClass.kt"); } + @TestMetadata("conformToComparableAndCallInterfaceMethod.kt") + public void testConformToComparableAndCallInterfaceMethod() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 08f741e21dd..0c65197a3c7 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -9826,6 +9826,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/computablePropertyInsideInlineClass.kt"); } + @TestMetadata("conformToComparableAndCallInterfaceMethod.kt") + public void testConformToComparableAndCallInterfaceMethod() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.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 a70eb8d63be..ce2043ab6b3 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 @@ -10831,6 +10831,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/computablePropertyInsideInlineClass.kt"); } + @TestMetadata("conformToComparableAndCallInterfaceMethod.kt") + public void testConformToComparableAndCallInterfaceMethod() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/conformToComparableAndCallInterfaceMethod.kt"); + } + @TestMetadata("correctBoxingForBranchExpressions.kt") public void testCorrectBoxingForBranchExpressions() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/correctBoxingForBranchExpressions.kt");