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 cd98ea4daa1..cd07a3d9cde 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmFlags import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable +import org.jetbrains.kotlin.metadata.serialization.StringTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.protobuf.GeneratedMessageLite import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -39,7 +40,6 @@ import org.jetbrains.kotlin.serialization.SerializerExtension import org.jetbrains.kotlin.types.FlexibleType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.commons.Method class JvmSerializerExtension @JvmOverloads constructor( private val bindings: JvmSerializationBindings, @@ -60,6 +60,7 @@ class JvmSerializerExtension @JvmOverloads constructor( private val jvmDefaultMode = state.jvmDefaultMode private val approximator = state.typeApproximator private val useOldManglingScheme = state.useOldManglingSchemeForFunctionsWithInlineClassesInSignatures + private val signatureSerializer = JvmSignatureSerializerImpl(stringTable) override fun shouldUseTypeTable(): Boolean = useTypeTable @@ -163,7 +164,7 @@ class JvmSerializerExtension @JvmOverloads constructor( ) { val method = getBinding(METHOD_FOR_FUNCTION, descriptor) if (method != null) { - val signature = SignatureSerializer().methodSignature(descriptor, method) + val signature = signatureSerializer.methodSignature(descriptor, descriptor.name, method) if (signature != null) { proto.setExtension(JvmProtoBuf.constructorSignature, signature) } @@ -178,7 +179,7 @@ class JvmSerializerExtension @JvmOverloads constructor( ) { val method = getBinding(METHOD_FOR_FUNCTION, descriptor) if (method != null) { - val signature = SignatureSerializer().methodSignature(descriptor, method) + val signature = signatureSerializer.methodSignature(descriptor, descriptor.name, method) if (signature != null) { proto.setExtension(JvmProtoBuf.methodSignature, signature) } @@ -232,8 +233,6 @@ class JvmSerializerExtension @JvmOverloads constructor( versionRequirementTable: MutableVersionRequirementTable?, childSerializer: DescriptorSerializer ) { - val signatureSerializer = SignatureSerializer() - val getter = descriptor.getter val setter = descriptor.setter val getterMethod = if (getter == null) null else getBinding(METHOD_FOR_FUNCTION, getter) @@ -245,13 +244,14 @@ class JvmSerializerExtension @JvmOverloads constructor( assert(descriptor.isDelegated || delegateMethod == null) { "non-delegated property $descriptor has delegate method" } val signature = signatureSerializer.propertySignature( - descriptor, + descriptor.name, 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 + if (syntheticMethod != null) signatureSerializer.methodSignature(null, null, syntheticMethod) else null, + if (delegateMethod != null) signatureSerializer.methodSignature(null, null, delegateMethod) else null, + if (getterMethod != null) signatureSerializer.methodSignature(null, null, getterMethod) else null, + if (setterMethod != null) signatureSerializer.methodSignature(null, null, setterMethod) else null, + field?.first?.descriptor?.let { signatureSerializer.requiresPropertySignature(descriptor, it) } ?: false, ) if (signature != null) { @@ -295,101 +295,42 @@ class JvmSerializerExtension @JvmOverloads constructor( private fun getBinding(slice: SerializationMappingSlice, key: K): V? = bindings.get(slice, key) ?: globalBindings.get(slice, key) +} - private inner class SignatureSerializer { - fun methodSignature(descriptor: FunctionDescriptor?, method: Method): JvmProtoBuf.JvmMethodSignature? { - val builder = JvmProtoBuf.JvmMethodSignature.newBuilder() - if (descriptor == null || descriptor.name.asString() != method.name) { - builder.name = stringTable.getStringIndex(method.name) - } - if (descriptor == null || requiresSignature(descriptor, method.descriptor)) { - builder.desc = stringTable.getStringIndex(method.descriptor) - } - return if (builder.hasName() || builder.hasDesc()) builder.build() else null +class JvmSignatureSerializerImpl(stringTable: StringTable) : JvmSignatureSerializer(stringTable) { + // We don't write those signatures which can be trivially reconstructed from already serialized data + // TODO: make JvmStringTable implement NameResolver and use JvmProtoBufUtil#getJvmMethodSignature instead + override fun requiresFunctionSignature(descriptor: FunctionDescriptor, desc: String): Boolean { + val sb = StringBuilder() + sb.append("(") + val receiverParameter = descriptor.extensionReceiverParameter + if (receiverParameter != null) { + val receiverDesc = mapTypeDefault(receiverParameter.value.type) ?: return true + sb.append(receiverDesc) } - // We don't write those signatures which can be trivially reconstructed from already serialized data - // TODO: make JvmStringTable implement NameResolver and use JvmProtoBufUtil#getJvmMethodSignature instead - private fun requiresSignature(descriptor: FunctionDescriptor, desc: String): Boolean { - val sb = StringBuilder() - sb.append("(") - val receiverParameter = descriptor.extensionReceiverParameter - if (receiverParameter != null) { - val receiverDesc = mapTypeDefault(receiverParameter.value.type) ?: return true - sb.append(receiverDesc) - } - - for (valueParameter in descriptor.valueParameters) { - val paramDesc = mapTypeDefault(valueParameter.type) ?: return true - sb.append(paramDesc) - } - - sb.append(")") - - val returnType = descriptor.returnType - val returnTypeDesc = (if (returnType == null) "V" else mapTypeDefault(returnType)) ?: return true - sb.append(returnTypeDesc) - - return sb.toString() != desc + for (valueParameter in descriptor.valueParameters) { + val paramDesc = mapTypeDefault(valueParameter.type) ?: return true + sb.append(paramDesc) } - private fun requiresSignature(descriptor: PropertyDescriptor, desc: String): Boolean { - return desc != mapTypeDefault(descriptor.type) - } + sb.append(")") - private fun mapTypeDefault(type: KotlinType): String? { - val classifier = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null - val classId = classifier.classId - return if (classId == null) null else ClassMapperLite.mapClass(classId.asString()) - } + val returnType = descriptor.returnType + val returnTypeDesc = (if (returnType == null) "V" else mapTypeDefault(returnType)) ?: return true + sb.append(returnTypeDesc) - fun propertySignature( - descriptor: PropertyDescriptor, - fieldName: String?, - fieldDesc: String?, - syntheticMethod: JvmProtoBuf.JvmMethodSignature?, - delegateMethod: JvmProtoBuf.JvmMethodSignature?, - getter: JvmProtoBuf.JvmMethodSignature?, - setter: JvmProtoBuf.JvmMethodSignature? - ): JvmProtoBuf.JvmPropertySignature? { - val signature = JvmProtoBuf.JvmPropertySignature.newBuilder() + return sb.toString() != desc + } - if (fieldDesc != null) { - assert(fieldName != null) { "Field name shouldn't be null when there's a field type: $fieldDesc" } - signature.field = fieldSignature(descriptor, fieldName!!, fieldDesc) - } + override fun requiresPropertySignature(descriptor: PropertyDescriptor, desc: String): Boolean { + return desc != mapTypeDefault(descriptor.type) + } - if (syntheticMethod != null) { - signature.syntheticMethod = syntheticMethod - } - - if (delegateMethod != null) { - signature.delegateMethod = delegateMethod - } - - if (getter != null) { - signature.getter = getter - } - if (setter != null) { - signature.setter = setter - } - - return signature.build().takeIf { it.serializedSize > 0 } - } - - fun fieldSignature( - descriptor: PropertyDescriptor, - name: String, - desc: String - ): JvmProtoBuf.JvmFieldSignature { - val builder = JvmProtoBuf.JvmFieldSignature.newBuilder() - if (descriptor.name.asString() != name) { - builder.name = stringTable.getStringIndex(name) - } - if (requiresSignature(descriptor, desc)) { - builder.desc = stringTable.getStringIndex(desc) - } - return builder.build() - } + private fun mapTypeDefault(type: KotlinType): String? { + val classifier = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null + val classId = classifier.classId + return if (classId == null) null else ClassMapperLite.mapClass(classId.asString()) } } + diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSignatureSerializer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSignatureSerializer.kt new file mode 100644 index 00000000000..f6fced80c83 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSignatureSerializer.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.codegen.serialization + +import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf +import org.jetbrains.kotlin.metadata.serialization.StringTable +import org.jetbrains.kotlin.name.Name +import org.jetbrains.org.objectweb.asm.commons.Method + +abstract class JvmSignatureSerializer(val stringTable: StringTable) { + fun methodSignature(descriptor: F?, descriptorName: Name?, method: Method): JvmProtoBuf.JvmMethodSignature? { + val builder = JvmProtoBuf.JvmMethodSignature.newBuilder() + if (descriptor == null || descriptorName?.asString() != method.name) { + builder.name = stringTable.getStringIndex(method.name) + } + if (descriptor == null || requiresFunctionSignature(descriptor, method.descriptor)) { + builder.desc = stringTable.getStringIndex(method.descriptor) + } + return if (builder.hasName() || builder.hasDesc()) builder.build() else null + } + + protected abstract fun requiresFunctionSignature(descriptor: F, desc: String): Boolean + + abstract fun requiresPropertySignature(descriptor: P, desc: String): Boolean + + fun propertySignature( + descriptorName: Name, + fieldName: String?, + fieldDesc: String?, + syntheticMethod: JvmProtoBuf.JvmMethodSignature?, + delegateMethod: JvmProtoBuf.JvmMethodSignature?, + getter: JvmProtoBuf.JvmMethodSignature?, + setter: JvmProtoBuf.JvmMethodSignature?, + requiresFieldSignature: Boolean + ): JvmProtoBuf.JvmPropertySignature? { + val signature = JvmProtoBuf.JvmPropertySignature.newBuilder() + + if (fieldDesc != null) { + assert(fieldName != null) { "Field name shouldn't be null when there's a field type: $fieldDesc" } + signature.field = fieldSignature(descriptorName, fieldName!!, fieldDesc, requiresFieldSignature, stringTable) + } + + if (syntheticMethod != null) { + signature.syntheticMethod = syntheticMethod + } + + if (delegateMethod != null) { + signature.delegateMethod = delegateMethod + } + + if (getter != null) { + signature.getter = getter + } + if (setter != null) { + signature.setter = setter + } + + return signature.build().takeIf { it.serializedSize > 0 } + } + + private fun fieldSignature( + propertyName: Name, + fieldName: String, + fieldDesc: String, + requiresFieldSignature: Boolean, + stringTable: StringTable + ): JvmProtoBuf.JvmFieldSignature { + val builder = JvmProtoBuf.JvmFieldSignature.newBuilder() + if (propertyName.asString() != fieldName) { + builder.name = stringTable.getStringIndex(fieldName) + } + if (requiresFieldSignature) { + builder.desc = stringTable.getStringIndex(fieldDesc) + } + return builder.build() + } +} \ No newline at end of file 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 47708c95387..47bb3884565 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 @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend.jvm import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings +import org.jetbrains.kotlin.codegen.serialization.JvmSignatureSerializer import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.ClassKind @@ -63,6 +64,7 @@ class FirJvmSerializerExtension( override val constValueProvider: ConstValueProvider?, override val additionalAnnotationsProvider: FirAdditionalMetadataAnnotationsProvider?, ) : FirSerializerExtension() { + private val signatureSerializer = FirJvmSignatureSerializer(stringTable) constructor( session: FirSession, @@ -187,7 +189,7 @@ class FirJvmSerializerExtension( ) { val method = getBinding(METHOD_FOR_FIR_FUNCTION, constructor) if (method != null) { - val signature = SignatureSerializer().methodSignature(constructor, method) + val signature = signatureSerializer.methodSignature(constructor, null, method) if (signature != null) { proto.setExtension(JvmProtoBuf.constructorSignature, signature) } @@ -202,7 +204,7 @@ class FirJvmSerializerExtension( ) { val method = getBinding(METHOD_FOR_FIR_FUNCTION, function) if (method != null) { - val signature = SignatureSerializer().methodSignature(function, method) + val signature = signatureSerializer.methodSignature(function, (function as? FirSimpleFunction)?.name, method) if (signature != null) { proto.setExtension(JvmProtoBuf.methodSignature, signature) } @@ -233,8 +235,6 @@ class FirJvmSerializerExtension( versionRequirementTable: MutableVersionRequirementTable?, childSerializer: FirElementSerializer ) { - val signatureSerializer = SignatureSerializer() - val getter = property.getter val setter = property.setter val getterMethod = if (getter == null) null else getBinding(METHOD_FOR_FIR_FUNCTION, getter) @@ -246,13 +246,14 @@ class FirJvmSerializerExtension( assert(property.delegate != null || delegateMethod == null) { "non-delegated property ${property.render()} has delegate method" } val signature = signatureSerializer.propertySignature( - property, + property.name, 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 + if (syntheticMethod != null) signatureSerializer.methodSignature(null, null, syntheticMethod) else null, + if (delegateMethod != null) signatureSerializer.methodSignature(null, null, delegateMethod) else null, + if (getterMethod != null) signatureSerializer.methodSignature(null, null, getterMethod) else null, + if (setterMethod != null) signatureSerializer.methodSignature(null, null, setterMethod) else null, + requiresFieldSignature = field?.first?.descriptor?.let { signatureSerializer.requiresPropertySignature(property, it) } ?: false ) if (signature != null) { @@ -297,102 +298,6 @@ class FirJvmSerializerExtension( private fun getBinding(slice: JvmSerializationBindings.SerializationMappingSlice, key: K): V? = bindings.get(slice, key) ?: globalBindings.get(slice, key) - private inner class SignatureSerializer { - fun methodSignature(function: FirFunction?, method: Method): JvmProtoBuf.JvmMethodSignature? { - val builder = JvmProtoBuf.JvmMethodSignature.newBuilder() - if (function == null || (function as? FirSimpleFunction)?.name?.asString() != method.name) { - builder.name = stringTable.getStringIndex(method.name) - } - if (function == null || requiresSignature(function, method.descriptor)) { - builder.desc = stringTable.getStringIndex(method.descriptor) - } - return if (builder.hasName() || builder.hasDesc()) builder.build() else null - } - - // We don't write those signatures which can be trivially reconstructed from already serialized data - // TODO: make JvmStringTable implement NameResolver and use JvmProtoBufUtil#getJvmMethodSignature instead - private fun requiresSignature(function: FirFunction, desc: String): Boolean { - val sb = StringBuilder() - sb.append("(") - val receiverTypeRef = function.receiverParameter?.typeRef - if (receiverTypeRef != null) { - val receiverDesc = mapTypeDefault(receiverTypeRef) ?: return true - sb.append(receiverDesc) - } - - for (valueParameter in function.valueParameters) { - val paramDesc = mapTypeDefault(valueParameter.returnTypeRef) ?: return true - sb.append(paramDesc) - } - - sb.append(")") - - val returnTypeRef = function.returnTypeRef - val returnTypeDesc = (mapTypeDefault(returnTypeRef)) ?: return true - sb.append(returnTypeDesc) - - return sb.toString() != desc - } - - private fun requiresSignature(property: FirProperty, desc: String): Boolean { - return desc != mapTypeDefault(property.returnTypeRef) - } - - private fun mapTypeDefault(typeRef: FirTypeRef): String? { - val classId = typeRef.coneTypeSafe()?.classId - return if (classId == null) null else ClassMapperLite.mapClass(classId.asString()) - } - - fun propertySignature( - property: FirProperty, - fieldName: String?, - fieldDesc: String?, - syntheticMethod: JvmProtoBuf.JvmMethodSignature?, - delegateMethod: JvmProtoBuf.JvmMethodSignature?, - getter: JvmProtoBuf.JvmMethodSignature?, - setter: JvmProtoBuf.JvmMethodSignature? - ): JvmProtoBuf.JvmPropertySignature? { - val signature = JvmProtoBuf.JvmPropertySignature.newBuilder() - - if (fieldDesc != null) { - assert(fieldName != null) { "Field name shouldn't be null when there's a field type: $fieldDesc" } - signature.field = fieldSignature(property, fieldName!!, fieldDesc) - } - - if (syntheticMethod != null) { - signature.syntheticMethod = syntheticMethod - } - - if (delegateMethod != null) { - signature.delegateMethod = delegateMethod - } - - if (getter != null) { - signature.getter = getter - } - if (setter != null) { - signature.setter = setter - } - - return signature.build().takeIf { it.serializedSize > 0 } - } - - fun fieldSignature( - property: FirProperty, - name: String, - desc: String - ): JvmProtoBuf.JvmFieldSignature { - val builder = JvmProtoBuf.JvmFieldSignature.newBuilder() - if (property.name.asString() != name) { - builder.name = stringTable.getStringIndex(name) - } - if (requiresSignature(property, desc)) { - builder.desc = stringTable.getStringIndex(desc) - } - return builder.build() - } - } - companion object { val METHOD_FOR_FIR_FUNCTION = JvmSerializationBindings.SerializationMappingSlice.create() val FIELD_FOR_PROPERTY = JvmSerializationBindings.SerializationMappingSlice.create>() @@ -404,3 +309,39 @@ class FirJvmSerializerExtension( private val JVM_DEFAULT_WITH_COMPATIBILITY_CLASS_ID = ClassId.topLevel(JVM_DEFAULT_WITH_COMPATIBILITY_FQ_NAME) } } + +class FirJvmSignatureSerializer(stringTable: FirElementAwareStringTable) : JvmSignatureSerializer(stringTable) { + // We don't write those signatures which can be trivially reconstructed from already serialized data + // TODO: make JvmStringTable implement NameResolver and use JvmProtoBufUtil#getJvmMethodSignature instead + override fun requiresFunctionSignature(descriptor: FirFunction, desc: String): Boolean { + val sb = StringBuilder() + sb.append("(") + val receiverTypeRef = descriptor.receiverParameter?.typeRef + if (receiverTypeRef != null) { + val receiverDesc = mapTypeDefault(receiverTypeRef) ?: return true + sb.append(receiverDesc) + } + + for (valueParameter in descriptor.valueParameters) { + val paramDesc = mapTypeDefault(valueParameter.returnTypeRef) ?: return true + sb.append(paramDesc) + } + + sb.append(")") + + val returnTypeRef = descriptor.returnTypeRef + val returnTypeDesc = (mapTypeDefault(returnTypeRef)) ?: return true + sb.append(returnTypeDesc) + + return sb.toString() != desc + } + + override fun requiresPropertySignature(descriptor: FirProperty, desc: String): Boolean { + return desc != mapTypeDefault(descriptor.returnTypeRef) + } + + private fun mapTypeDefault(typeRef: FirTypeRef): String? { + val classId = typeRef.coneTypeSafe()?.classId + return if (classId == null) null else ClassMapperLite.mapClass(classId.asString()) + } +}