diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index ef0c30360dc..e938d41b4aa 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -861,6 +861,33 @@ public class AsmUtil { }); } + @NotNull + public static BranchedValue genTotalOrderEqualsForExpressionOnStack( + @NotNull StackValue left, + @NotNull StackValue right, + @NotNull Type asmType + ) { + return new BranchedValue(left, right, asmType, Opcodes.IFEQ) { + @Override + public void condJump(@NotNull Label jumpLabel, @NotNull InstructionAdapter iv, boolean jumpIfFalse) { + if (asmType.getSort() == Type.FLOAT) { + left.put(asmType, kotlinType, iv); + right.put(asmType, kotlinType, iv); + iv.invokestatic("java/lang/Float", "compare", "(FF)I", false); + iv.visitJumpInsn(patchOpcode(jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ, iv), jumpLabel); + } else if (asmType.getSort() == Type.DOUBLE) { + left.put(asmType, kotlinType, iv); + right.put(asmType, kotlinType, iv); + iv.invokestatic("java/lang/Double", "compare", "(DD)I", false); + iv.visitJumpInsn(patchOpcode(jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ, iv), jumpLabel); + } else { + StackValue value = genEqualsForExpressionsOnStack(KtTokens.EQEQ, left, right); + BranchedValue.Companion.condJump(value, jumpLabel, jumpIfFalse, iv); + } + } + }; + } + @NotNull public static StackValue genEqualsBoxedOnStack(@NotNull IElementType opToken) { return StackValue.operation(Type.BOOLEAN_TYPE, v -> genAreEqualCall(v, opToken)); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ErasedInlineClassBodyCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ErasedInlineClassBodyCodegen.kt index 83132081bbc..4117592df98 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ErasedInlineClassBodyCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ErasedInlineClassBodyCodegen.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.codegen +import org.jetbrains.kotlin.codegen.AsmUtil.genTotalOrderEqualsForExpressionOnStack import org.jetbrains.kotlin.codegen.context.ClassContext import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper @@ -17,6 +18,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type class ErasedInlineClassBodyCodegen( aClass: KtClass, @@ -109,11 +111,17 @@ class ErasedInlineClassBodyCodegen( override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) { - val iv = codegen.v - iv.aconst(null) - iv.athrow() + val firstIndex = codegen.frameMap.getIndex(specializedEqualsDescriptor.valueParameters[0]) + val secondIndex = codegen.frameMap.getIndex(specializedEqualsDescriptor.valueParameters[1]) + val asmType = signature.valueParameters[0].asmType + val left = StackValue.local(firstIndex, asmType) + val right = StackValue.local(secondIndex, asmType) + genTotalOrderEqualsForExpressionOnStack(left, right, asmType).put(Type.BOOLEAN_TYPE, codegen.v) + codegen.v.areturn(Type.BOOLEAN_TYPE) } + + override fun skipNotNullAssertionsForParameters(): Boolean = true } ) } -} \ No newline at end of file +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java index e07c11a2971..588ebea55c4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionsFromAnyGeneratorImpl.java @@ -251,25 +251,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator { return Unit.INSTANCE; }); - if (asmType.getSort() == Type.FLOAT) { - thisPropertyValue.put(asmType, kotlinType, iv); - otherPropertyValue.put(asmType, kotlinType, iv); - iv.invokestatic("java/lang/Float", "compare", "(FF)I", false); - iv.ifne(ne); - } - else if (asmType.getSort() == Type.DOUBLE) { - thisPropertyValue.put(asmType, kotlinType, iv); - otherPropertyValue.put(asmType, kotlinType, iv); - iv.invokestatic("java/lang/Double", "compare", "(DD)I", false); - iv.ifne(ne); - } - else { - StackValue value = genEqualsForExpressionsOnStack( - KtTokens.EQEQ, thisPropertyValue, otherPropertyValue - ); - value.put(Type.BOOLEAN_TYPE, iv); - iv.ifeq(ne); - } + genTotalOrderEqualsForExpressionOnStack(thisPropertyValue, otherPropertyValue, asmType).condJump(ne, iv, true); } iv.mark(eq); diff --git a/compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt b/compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt index c4b87c0bc68..74874963c9e 100644 --- a/compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt +++ b/compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt @@ -15,11 +15,7 @@ fun box(): String { Simple::class.java.getDeclaredMethod(name, String::class.java, String::class.java) ?: return "$name not found" - val result = try { - specializedEquals.invoke(null, "a", "b") - } catch (e: InvocationTargetException) { - return if (e.targetException is NullPointerException) "OK" else "${e.targetException}" - } - - return if (result == false) "OK" else "Fail" + if (specializedEquals.invoke(null, "a", "b") as Boolean) + return "Fail" + return "OK" } diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/assertionsForParametersOfInlineClassTypes.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/assertionsForParametersOfInlineClassTypes.kt index dd4c42e6188..f47bcef05d0 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/assertionsForParametersOfInlineClassTypes.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/assertionsForParametersOfInlineClassTypes.kt @@ -2,7 +2,7 @@ inline class AsNonNullPrimitive(val i: Int) inline class AsNonNullReference(val s: String) -// ^ JVM: 5 assertions (constructor, box method, erased constructor, 2 assertions in equals--impl) +// ^ JVM: 3 assertions (constructor, box method, erased constructor) // JVM IR: 1 assertion (erased constructor) fun nonNullPrimitive(a: AsNonNullPrimitive) {} @@ -14,7 +14,7 @@ fun asNullablePrimitive(c: AsNonNullPrimitive?) {} fun asNullableReference(c: AsNonNullReference?) {} // JVM_TEMPLATES -// 8 checkParameterIsNotNull +// 6 checkParameterIsNotNull // 0 checkNotNullParameter // JVM_IR_TEMPLATES