Fix explicit 'equals' for primitive types

This commit is contained in:
Dmitry Petrov
2019-12-25 11:27:42 +03:00
parent 1d5370a56a
commit babe6eb581
4 changed files with 24 additions and 8 deletions
@@ -30,9 +30,29 @@ import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberOrNullableType import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberOrNullableType
import org.jetbrains.kotlin.types.typeUtil.upperBoundedByPrimitiveNumberOrNullableType import org.jetbrains.kotlin.types.typeUtil.upperBoundedByPrimitiveNumberOrNullableType
import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class ExplicitEquals : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
val (a, b) = expression.receiverAndArgs()
// TODO use specialized boxed type - this might require types like 'java.lang.Integer' in IR
a.accept(codegen, data).coerce(AsmTypes.OBJECT_TYPE, codegen.context.irBuiltIns.anyNType).materialize()
b.accept(codegen, data).coerce(AsmTypes.OBJECT_TYPE, codegen.context.irBuiltIns.anyNType).materialize()
codegen.mv.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
AsmTypes.OBJECT_TYPE.internalName,
"equals",
Type.getMethodDescriptor(Type.BOOLEAN_TYPE, AsmTypes.OBJECT_TYPE),
false
)
return MaterialValue(codegen, Type.BOOLEAN_TYPE, codegen.context.irBuiltIns.booleanType)
}
}
class Equals(val operator: IElementType) : IntrinsicMethod() { class Equals(val operator: IElementType) : IntrinsicMethod() {
private class BooleanConstantFalseCheck(val value: PromisedValue) : BooleanValue(value.codegen) { private class BooleanConstantFalseCheck(val value: PromisedValue) : BooleanValue(value.codegen) {
override fun materialize() = value.discard().let { mv.iconst(0) } override fun materialize() = value.discard().let { mv.iconst(0) }
@@ -103,7 +103,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
unaryFunForPrimitives("inc", INC) + unaryFunForPrimitives("inc", INC) +
unaryFunForPrimitives("dec", DEC) + unaryFunForPrimitives("dec", DEC) +
unaryFunForPrimitives("hashCode", HashCode) + unaryFunForPrimitives("hashCode", HashCode) +
binaryFunForPrimitives("equals", EQUALS, irBuiltIns.anyClass) + binaryFunForPrimitives("equals", EXPLICIT_EQUALS, irBuiltIns.anyClass) +
binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) + binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) +
binaryOp("plus", IADD) + binaryOp("plus", IADD) +
binaryOp("minus", ISUB) + binaryOp("minus", ISUB) +
@@ -193,7 +193,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
private val INC = Increment(1) private val INC = Increment(1)
private val DEC = Increment(-1) private val DEC = Increment(-1)
private val EQUALS = Equals(KtTokens.EQEQ) private val EXPLICIT_EQUALS = ExplicitEquals()
private fun IrFunctionSymbol.toKey(): Key? { private fun IrFunctionSymbol.toKey(): Key? {
val parent = owner.parent val parent = owner.parent
@@ -1,10 +1,7 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
// FILE: equalsNull_lv12.kt // FILE: equalsNull.kt
// IGNORE_BACKEND: JVM_IR
// ^ TODO: fix intrinsic for 'equals' for boxed primitives
import kotlin.test.* import kotlin.test.*
@@ -4,8 +4,7 @@
// WITH_RUNTIME // WITH_RUNTIME
// FILE: equalsNull_withExplicitFlag.kt // FILE: equalsNull_withExplicitFlag.kt
// Should be ignored on JVM IR. // IGNORE_BACKEND: JVM_IR
// ^ TODO: fix intrinsic for 'equals' for boxed primitives
// JVM_IR supports behavior since Kotlin 1.3, // JVM_IR supports behavior since Kotlin 1.3,
// and '-Xno-exception-on-explicit-equals-for-boxed-null' is a fallback flag introduced in 1.2. // and '-Xno-exception-on-explicit-equals-for-boxed-null' is a fallback flag introduced in 1.2.