JVM: Optimize inline class equality with nullable arguments

This commit is contained in:
Steven Schäfer
2019-09-17 17:05:59 +02:00
committed by Alexander Udalov
parent eda4953cb3
commit 1833a69c87
@@ -3409,7 +3409,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (!leftIsUnboxed || !rightIsUnboxed || !leftHasPrimitiveEquality || !rightHasPrimitiveEquality) { if (!leftIsUnboxed || !rightIsUnboxed || !leftHasPrimitiveEquality || !rightHasPrimitiveEquality) {
return genEqualsForInlineClasses( return genEqualsForInlineClasses(
left, right, opToken, pregeneratedSubject, leftKotlinType, rightKotlinType, left, right, opToken, pregeneratedSubject, leftKotlinType, rightKotlinType,
leftType, rightType, leftIsUnboxed, rightIsUnboxed leftType, rightType, leftIsInlineClass, leftIsUnboxed, rightIsUnboxed
); );
} }
} }
@@ -3502,6 +3502,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull KotlinType rightKotlinType, @NotNull KotlinType rightKotlinType,
@NotNull Type leftType, @NotNull Type leftType,
@NotNull Type rightType, @NotNull Type rightType,
boolean leftIsInlineClass,
boolean leftIsUnboxed, boolean leftIsUnboxed,
boolean rightIsUnboxed boolean rightIsUnboxed
) { ) {
@@ -3514,7 +3515,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
boolean flipComparison = opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ; boolean flipComparison = opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ;
// Don't call equals-impl0 if the class file version is too low to support it. // Don't call equals-impl0 if the class file version is too low to support it.
boolean useUnboxedEquals = leftIsUnboxed && JvmCodegenUtil.typeHasSpecializedInlineClassEquality(leftKotlinType, state); boolean useUnboxedEquals =
(leftIsUnboxed || (leftIsInlineClass && rightIsUnboxed)) &&
JvmCodegenUtil.typeHasSpecializedInlineClassEquality(leftKotlinType, state);
leftValue.put(leftType, leftKotlinType, v); leftValue.put(leftType, leftKotlinType, v);
//noinspection SuspiciousNameCombination //noinspection SuspiciousNameCombination
@@ -3571,12 +3574,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.goTo(endLabel); v.goTo(endLabel);
v.visitLabel(nonNullLabel); v.visitLabel(nonNullLabel);
} }
String descriptor = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, leftType, leftType); if (!leftIsUnboxed) {
AsmUtil.swap(v, topType, afterTopType);
KotlinType nonNullableLeftKotlinType = TypeUtils.makeNotNullable(leftKotlinType);
Type nonNullableLeftType = typeMapper.mapType(nonNullableLeftKotlinType);
StackValue.coerce(leftType, leftKotlinType, nonNullableLeftType, nonNullableLeftKotlinType, v);
afterTopType = nonNullableLeftType;
AsmUtil.swap(v, afterTopType, topType);
}
String descriptor = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, afterTopType, afterTopType);
v.invokestatic(className, InlineClassDescriptorResolver.SPECIALIZED_EQUALS_NAME.asString(), descriptor, false); v.invokestatic(className, InlineClassDescriptorResolver.SPECIALIZED_EQUALS_NAME.asString(), descriptor, false);
} else { } else {
// equals-impl expects a non-nullable first argument, yet `left` may be unboxed even if String descriptor = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, afterTopType, OBJECT_TYPE);
// it is nullable when it is a wrapper around a non-nullable reference type.
String descriptor = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, leftType, OBJECT_TYPE);
v.invokestatic(className, "equals-impl", descriptor, false); v.invokestatic(className, "equals-impl", descriptor, false);
} }
} else { } else {