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`.
This commit is contained in:
pyos
2021-06-30 16:10:30 +02:00
committed by Alexander Udalov
parent 6a3c79bb9e
commit 664bb055c8
6 changed files with 44 additions and 11 deletions
@@ -35,6 +35,8 @@ public final class JvmSerializationBindings {
SerializationMappingSlice.create();
public static final SerializationMappingSlice<PropertyDescriptor, Method> SYNTHETIC_METHOD_FOR_PROPERTY =
SerializationMappingSlice.create();
public static final SerializationMappingSlice<PropertyDescriptor, Method> DELEGATE_METHOD_FOR_PROPERTY =
SerializationMappingSlice.create();
public static final class SerializationMappingSlice<K, V> extends BasicWritableSlice<K, V> {
public SerializationMappingSlice() {
@@ -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
}
@@ -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<FirFunction, Method>()
val FIELD_FOR_PROPERTY = JvmSerializationBindings.SerializationMappingSlice.create<FirProperty, Pair<Type, String>>()
val SYNTHETIC_METHOD_FOR_FIR_VARIABLE = JvmSerializationBindings.SerializationMappingSlice.create<FirVariable, Method>()
val DELEGATE_METHOD_FOR_FIR_VARIABLE = JvmSerializationBindings.SerializationMappingSlice.create<FirVariable, Method>()
}
}
@@ -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) {
@@ -57,7 +57,7 @@ import java.util.concurrent.ConcurrentHashMap
interface MetadataSerializer {
fun serialize(metadata: MetadataSource): Pair<MessageLite, JvmStringTable>?
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<Type, String>)
}
@@ -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()}")
@@ -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) {