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
|
||||
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")
|
||||
private val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2")
|
||||
val SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME = Name.identifier("p1")
|
||||
val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2")
|
||||
|
||||
@JvmStatic
|
||||
fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? =
|
||||
|
||||
+19
@@ -79,6 +79,7 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F
|
||||
buildPrimaryInlineClassConstructor(declaration, irConstructor)
|
||||
buildBoxFunction(declaration)
|
||||
buildUnboxFunction(declaration)
|
||||
buildSpecializedEqualsMethod(declaration)
|
||||
}
|
||||
|
||||
return declaration
|
||||
@@ -371,4 +372,22 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F
|
||||
|
||||
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.jvm.JvmLoweredDeclarationOrigin
|
||||
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.buildFun
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFunWithDescriptorForInlining
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
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.IrValueParameterSymbol
|
||||
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.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
class IrReplacementFunction(
|
||||
@@ -73,14 +78,14 @@ class MemoizedInlineClassReplacements {
|
||||
storageManager.createMemoizedFunction { irClass ->
|
||||
require(irClass.isInline)
|
||||
buildFun {
|
||||
name = Name.identifier("box-impl")
|
||||
name = Name.identifier(KotlinTypeMapper.BOX_JVM_METHOD_NAME)
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER
|
||||
returnType = irClass.defaultType
|
||||
}.apply {
|
||||
parent = irClass
|
||||
copyTypeParametersFrom(irClass)
|
||||
addValueParameter {
|
||||
name = Name.identifier("v")
|
||||
name = InlineClassDescriptorResolver.BOXING_VALUE_PARAMETER_NAME
|
||||
type = InlineClassAbi.getUnderlyingType(irClass)
|
||||
}
|
||||
}
|
||||
@@ -94,7 +99,7 @@ class MemoizedInlineClassReplacements {
|
||||
storageManager.createMemoizedFunction { irClass ->
|
||||
require(irClass.isInline)
|
||||
buildFun {
|
||||
name = Name.identifier("unbox-impl")
|
||||
name = Name.identifier(KotlinTypeMapper.UNBOX_JVM_METHOD_NAME)
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER
|
||||
returnType = InlineClassAbi.getUnderlyingType(irClass)
|
||||
}.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? {
|
||||
require(function.dispatchReceiverParameter != null && function is IrSimpleFunction)
|
||||
val overrides = function.overriddenSymbols.mapNotNull {
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
// WITH_REFLECT
|
||||
// FULL_JDK
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
@@ -16,11 +15,11 @@ fun box(): String {
|
||||
Simple::class.java.getDeclaredMethod(name, String::class.java, String::class.java)
|
||||
?: return "$name not found"
|
||||
|
||||
try {
|
||||
val result = try {
|
||||
specializedEquals.invoke(null, "a", "b")
|
||||
} catch (e: InvocationTargetException) {
|
||||
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