JVM IR: Generate equals-impl0 method for inline classes
This commit is contained in:
committed by
Alexander Udalov
parent
e4456127e4
commit
b85a475358
@@ -19,12 +19,12 @@ object InlineClassDescriptorResolver {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val UNBOX_METHOD_NAME = Name.identifier("unbox")
|
val UNBOX_METHOD_NAME = Name.identifier("unbox")
|
||||||
|
|
||||||
private val SPECIALIZED_EQUALS_NAME = Name.identifier("equals-impl0")
|
val SPECIALIZED_EQUALS_NAME = Name.identifier("equals-impl0")
|
||||||
|
|
||||||
private val BOXING_VALUE_PARAMETER_NAME = Name.identifier("v")
|
val BOXING_VALUE_PARAMETER_NAME = Name.identifier("v")
|
||||||
|
|
||||||
private val SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME = Name.identifier("p1")
|
val SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME = Name.identifier("p1")
|
||||||
private val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2")
|
val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2")
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? =
|
fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? =
|
||||||
|
|||||||
+19
@@ -79,6 +79,7 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F
|
|||||||
buildPrimaryInlineClassConstructor(declaration, irConstructor)
|
buildPrimaryInlineClassConstructor(declaration, irConstructor)
|
||||||
buildBoxFunction(declaration)
|
buildBoxFunction(declaration)
|
||||||
buildUnboxFunction(declaration)
|
buildUnboxFunction(declaration)
|
||||||
|
buildSpecializedEqualsMethod(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
return declaration
|
return declaration
|
||||||
@@ -371,4 +372,22 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F
|
|||||||
|
|
||||||
irClass.declarations += function
|
irClass.declarations += function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildSpecializedEqualsMethod(irClass: IrClass) {
|
||||||
|
val function = manager.getSpecializedEqualsMethod(irClass, context.irBuiltIns)
|
||||||
|
val left = function.valueParameters[0]
|
||||||
|
val right = function.valueParameters[1]
|
||||||
|
val type = left.type.unboxInlineClass()
|
||||||
|
|
||||||
|
function.body = context.createIrBuilder(irClass.symbol).run {
|
||||||
|
irExprBody(
|
||||||
|
irEquals(
|
||||||
|
coerceInlineClasses(irGet(left), left.type, type),
|
||||||
|
coerceInlineClasses(irGet(right), right.type, type)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
irClass.declarations += function
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-3
@@ -11,18 +11,23 @@ import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
|
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFunWithDescriptorForInlining
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFunWithDescriptorForInlining
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.getClass
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
class IrReplacementFunction(
|
class IrReplacementFunction(
|
||||||
@@ -73,14 +78,14 @@ class MemoizedInlineClassReplacements {
|
|||||||
storageManager.createMemoizedFunction { irClass ->
|
storageManager.createMemoizedFunction { irClass ->
|
||||||
require(irClass.isInline)
|
require(irClass.isInline)
|
||||||
buildFun {
|
buildFun {
|
||||||
name = Name.identifier("box-impl")
|
name = Name.identifier(KotlinTypeMapper.BOX_JVM_METHOD_NAME)
|
||||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER
|
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER
|
||||||
returnType = irClass.defaultType
|
returnType = irClass.defaultType
|
||||||
}.apply {
|
}.apply {
|
||||||
parent = irClass
|
parent = irClass
|
||||||
copyTypeParametersFrom(irClass)
|
copyTypeParametersFrom(irClass)
|
||||||
addValueParameter {
|
addValueParameter {
|
||||||
name = Name.identifier("v")
|
name = InlineClassDescriptorResolver.BOXING_VALUE_PARAMETER_NAME
|
||||||
type = InlineClassAbi.getUnderlyingType(irClass)
|
type = InlineClassAbi.getUnderlyingType(irClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +99,7 @@ class MemoizedInlineClassReplacements {
|
|||||||
storageManager.createMemoizedFunction { irClass ->
|
storageManager.createMemoizedFunction { irClass ->
|
||||||
require(irClass.isInline)
|
require(irClass.isInline)
|
||||||
buildFun {
|
buildFun {
|
||||||
name = Name.identifier("unbox-impl")
|
name = Name.identifier(KotlinTypeMapper.UNBOX_JVM_METHOD_NAME)
|
||||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER
|
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER
|
||||||
returnType = InlineClassAbi.getUnderlyingType(irClass)
|
returnType = InlineClassAbi.getUnderlyingType(irClass)
|
||||||
}.apply {
|
}.apply {
|
||||||
@@ -103,6 +108,32 @@ class MemoizedInlineClassReplacements {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val specializedEqualsCache = storageManager.createCacheWithNotNullValues<IrClass, IrSimpleFunction>()
|
||||||
|
fun getSpecializedEqualsMethod(irClass: IrClass, irBuiltIns: IrBuiltIns): IrSimpleFunction {
|
||||||
|
require(irClass.isInline)
|
||||||
|
return specializedEqualsCache.computeIfAbsent(irClass) {
|
||||||
|
buildFun {
|
||||||
|
name = InlineClassDescriptorResolver.SPECIALIZED_EQUALS_NAME
|
||||||
|
// TODO: Revisit this once we allow user defined equals methods in inline classes.
|
||||||
|
origin = JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD
|
||||||
|
returnType = irBuiltIns.booleanType
|
||||||
|
}.apply {
|
||||||
|
parent = irClass
|
||||||
|
// We ignore type arguments here, since there is no good way to go from type arguments to types in the IR anyway.
|
||||||
|
val typeArgument =
|
||||||
|
IrSimpleTypeImpl(null, irClass.symbol, false, List(irClass.typeParameters.size) { IrStarProjectionImpl }, listOf())
|
||||||
|
addValueParameter {
|
||||||
|
name = InlineClassDescriptorResolver.SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME
|
||||||
|
type = typeArgument
|
||||||
|
}
|
||||||
|
addValueParameter {
|
||||||
|
name = InlineClassDescriptorResolver.SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME
|
||||||
|
type = typeArgument
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createMethodReplacement(function: IrFunction): IrReplacementFunction? {
|
private fun createMethodReplacement(function: IrFunction): IrReplacementFunction? {
|
||||||
require(function.dispatchReceiverParameter != null && function is IrSimpleFunction)
|
require(function.dispatchReceiverParameter != null && function is IrSimpleFunction)
|
||||||
val overrides = function.overriddenSymbols.mapNotNull {
|
val overrides = function.overriddenSymbols.mapNotNull {
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,5 @@
|
|||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
@@ -16,11 +15,11 @@ fun box(): String {
|
|||||||
Simple::class.java.getDeclaredMethod(name, String::class.java, String::class.java)
|
Simple::class.java.getDeclaredMethod(name, String::class.java, String::class.java)
|
||||||
?: return "$name not found"
|
?: return "$name not found"
|
||||||
|
|
||||||
try {
|
val result = try {
|
||||||
specializedEquals.invoke(null, "a", "b")
|
specializedEquals.invoke(null, "a", "b")
|
||||||
} catch (e: InvocationTargetException) {
|
} catch (e: InvocationTargetException) {
|
||||||
return if (e.targetException is NullPointerException) "OK" else "${e.targetException}"
|
return if (e.targetException is NullPointerException) "OK" else "${e.targetException}"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Reserved method invoked successfully"
|
return if (result == false) "OK" else "Fail"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user