From 664bb055c81068abcf2d0c95eb54e1b7023c0b35 Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 30 Jun 2021 16:10:30 +0200 Subject: [PATCH] JVM_IR: support codegen of property delegate methods The purpose of a property-related method is now determined by its origin; codegen no longer assumes all methods with Property metadata source are `getX$annotations`. --- .../serialization/JvmSerializationBindings.java | 2 ++ .../codegen/serialization/JvmSerializerExtension.kt | 8 ++++++++ .../fir/backend/jvm/FirJvmSerializerExtension.kt | 10 ++++++++++ .../kotlin/fir/backend/jvm/FirMetadataSerializer.kt | 13 +++++++++++-- .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 9 ++------- .../jvm/codegen/DescriptorMetadataSerializer.kt | 13 +++++++++++-- 6 files changed, 44 insertions(+), 11 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java index 3eb4c9ba1be..5d7854a0251 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializationBindings.java @@ -35,6 +35,8 @@ public final class JvmSerializationBindings { SerializationMappingSlice.create(); public static final SerializationMappingSlice SYNTHETIC_METHOD_FOR_PROPERTY = SerializationMappingSlice.create(); + public static final SerializationMappingSlice DELEGATE_METHOD_FOR_PROPERTY = + SerializationMappingSlice.create(); public static final class SerializationMappingSlice extends BasicWritableSlice { public SerializationMappingSlice() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt index d8afafe5362..eb737357223 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt @@ -255,12 +255,15 @@ class JvmSerializerExtension @JvmOverloads constructor( val field = getBinding(FIELD_FOR_PROPERTY, descriptor) val syntheticMethod = getBinding(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor) + val delegateMethod = getBinding(DELEGATE_METHOD_FOR_PROPERTY, descriptor) + assert(descriptor.isDelegated || delegateMethod == null) { "non-delegated property $descriptor has delegate method" } val signature = signatureSerializer.propertySignature( descriptor, field?.second, field?.first?.descriptor, if (syntheticMethod != null) signatureSerializer.methodSignature(null, syntheticMethod) else null, + if (delegateMethod != null) signatureSerializer.methodSignature(null, delegateMethod) else null, if (getterMethod != null) signatureSerializer.methodSignature(null, getterMethod) else null, if (setterMethod != null) signatureSerializer.methodSignature(null, setterMethod) else null ) @@ -359,6 +362,7 @@ class JvmSerializerExtension @JvmOverloads constructor( fieldName: String?, fieldDesc: String?, syntheticMethod: JvmProtoBuf.JvmMethodSignature?, + delegateMethod: JvmProtoBuf.JvmMethodSignature?, getter: JvmProtoBuf.JvmMethodSignature?, setter: JvmProtoBuf.JvmMethodSignature? ): JvmProtoBuf.JvmPropertySignature? { @@ -373,6 +377,10 @@ class JvmSerializerExtension @JvmOverloads constructor( signature.syntheticMethod = syntheticMethod } + if (delegateMethod != null) { + signature.delegateMethod = delegateMethod + } + if (getter != null) { signature.getter = getter } diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt index 26e364acbb8..885494fb066 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall +import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.serialization.FirElementSerializer @@ -229,12 +230,15 @@ class FirJvmSerializerExtension( val field = getBinding(FIELD_FOR_PROPERTY, property) val syntheticMethod = getBinding(SYNTHETIC_METHOD_FOR_FIR_VARIABLE, property) + val delegateMethod = getBinding(DELEGATE_METHOD_FOR_FIR_VARIABLE, property) + assert(property.delegate != null || delegateMethod == null) { "non-delegated property ${property.render()} has delegate method" } val signature = signatureSerializer.propertySignature( property, field?.second, field?.first?.descriptor, if (syntheticMethod != null) signatureSerializer.methodSignature(null, syntheticMethod) else null, + if (delegateMethod != null) signatureSerializer.methodSignature(null, delegateMethod) else null, if (getterMethod != null) signatureSerializer.methodSignature(null, getterMethod) else null, if (setterMethod != null) signatureSerializer.methodSignature(null, setterMethod) else null ) @@ -334,6 +338,7 @@ class FirJvmSerializerExtension( fieldName: String?, fieldDesc: String?, syntheticMethod: JvmProtoBuf.JvmMethodSignature?, + delegateMethod: JvmProtoBuf.JvmMethodSignature?, getter: JvmProtoBuf.JvmMethodSignature?, setter: JvmProtoBuf.JvmMethodSignature? ): JvmProtoBuf.JvmPropertySignature? { @@ -348,6 +353,10 @@ class FirJvmSerializerExtension( signature.syntheticMethod = syntheticMethod } + if (delegateMethod != null) { + signature.delegateMethod = delegateMethod + } + if (getter != null) { signature.getter = getter } @@ -378,6 +387,7 @@ class FirJvmSerializerExtension( val METHOD_FOR_FIR_FUNCTION = JvmSerializationBindings.SerializationMappingSlice.create() val FIELD_FOR_PROPERTY = JvmSerializationBindings.SerializationMappingSlice.create>() val SYNTHETIC_METHOD_FOR_FIR_VARIABLE = JvmSerializationBindings.SerializationMappingSlice.create() + val DELEGATE_METHOD_FOR_FIR_VARIABLE = JvmSerializationBindings.SerializationMappingSlice.create() } } diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt index 0ab6346027d..082e22dfafc 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.backend.jvm import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.fir.FirSession @@ -26,6 +27,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.MetadataSource import org.jetbrains.kotlin.ir.util.getPackageFragment import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable @@ -188,9 +190,16 @@ class FirMetadataSerializer( return message to serializer!!.stringTable as JvmStringTable } - override fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method) { + override fun bindPropertyMetadata(metadata: MetadataSource.Property, signature: Method, origin: IrDeclarationOrigin) { val fir = (metadata as FirMetadataSource.Property).fir - context.state.globalSerializationBindings.put(FirJvmSerializerExtension.SYNTHETIC_METHOD_FOR_FIR_VARIABLE, fir, signature) + val slice = when (origin) { + JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS -> + FirJvmSerializerExtension.SYNTHETIC_METHOD_FOR_FIR_VARIABLE + IrDeclarationOrigin.PROPERTY_DELEGATE -> + FirJvmSerializerExtension.DELEGATE_METHOD_FOR_FIR_VARIABLE + else -> throw IllegalStateException("invalid origin $origin for property-related method $signature") + } + context.state.globalSerializationBindings.put(slice, fir, signature) } override fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index c191f1aeaa0..8b1f1754fca 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -57,7 +57,7 @@ import java.util.concurrent.ConcurrentHashMap interface MetadataSerializer { fun serialize(metadata: MetadataSource): Pair? - fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method) + fun bindPropertyMetadata(metadata: MetadataSource.Property, signature: Method, origin: IrDeclarationOrigin) fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method) fun bindFieldMetadata(metadata: MetadataSource.Property, signature: Pair) } @@ -391,12 +391,7 @@ class ClassCodegen private constructor( jvmSignatureClashDetector.trackMethod(method, RawSignature(node.name, node.desc, MemberKind.METHOD)) when (val metadata = method.metadata) { - is MetadataSource.Property -> { - assert(method.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS) { - "MetadataSource.Property on IrFunction should only be used for synthetic \$annotations methods: ${method.render()}" - } - metadataSerializer.bindMethodMetadata(metadata, Method(node.name, node.desc)) - } + is MetadataSource.Property -> metadataSerializer.bindPropertyMetadata(metadata, Method(node.name, node.desc), method.origin) is MetadataSource.Function -> metadataSerializer.bindMethodMetadata(metadata, Method(node.name, node.desc)) null -> Unit else -> error("Incorrect metadata source $metadata for:\n${method.dump()}") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt index 2491b086839..fe0f58cae25 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/DescriptorMetadataSerializer.kt @@ -6,12 +6,14 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.createFreeFakeLambdaDescriptor import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.MetadataSource import org.jetbrains.kotlin.ir.util.getPackageFragment import org.jetbrains.kotlin.ir.util.isInterface @@ -70,9 +72,16 @@ class DescriptorMetadataSerializer( return message to serializer!!.stringTable as JvmStringTable } - override fun bindMethodMetadata(metadata: MetadataSource.Property, signature: Method) { + override fun bindPropertyMetadata(metadata: MetadataSource.Property, signature: Method, origin: IrDeclarationOrigin) { val descriptor = (metadata as DescriptorMetadataSource.Property).descriptor - context.state.globalSerializationBindings.put(JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, signature) + val slice = when (origin) { + JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS -> + JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY + IrDeclarationOrigin.PROPERTY_DELEGATE -> + JvmSerializationBindings.DELEGATE_METHOD_FOR_PROPERTY + else -> throw IllegalStateException("invalid origin $origin for property-related method $signature") + } + context.state.globalSerializationBindings.put(slice, descriptor, signature) } override fun bindMethodMetadata(metadata: MetadataSource.Function, signature: Method) {