From 3154eca218dc6a8adbed4a75852aa9fd77326631 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 10 Jun 2020 21:46:29 +0200 Subject: [PATCH] IR: use String instead of FqName in IdSignature.PublicSignature FqName/FqNameUnsafe tend to eagerly compute things like safe/parent/shortName which take a lot of space. This change helps to lower strongly reachable memory just before codegen in JVM IR by about 5% on a relatively big project. --- .../signaturer/FirBasedSignatureComposer.kt | 23 ++++---- .../ir/util/DeclarationStubGenerator.kt | 18 +++---- .../jetbrains/kotlin/ir/util/IdSignature.kt | 31 ++++++----- .../DescriptorByIdSignatureFinder.kt | 27 +++++----- .../FunctionalInterfacesUtils.kt | 8 +-- .../serialization/IrFileDeserializer.kt | 21 +++----- .../common/serialization/IrFileSerializer.kt | 10 ++-- .../serialization/IrModuleDeserializer.kt | 54 ++++++++----------- .../common/serialization/KotlinIrLinker.kt | 3 +- .../signature/IdSignatureBuilder.kt | 6 ++- .../signature/IdSignatureSerializer.kt | 14 ++--- 11 files changed, 102 insertions(+), 113 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt index d34ff8cc0d0..d6587849c48 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt @@ -10,12 +10,11 @@ import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatureComposer { inner class SignatureBuilder : FirVisitorVoid() { @@ -70,15 +69,21 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu return when { declaration is FirRegularClass && declaration.visibility != Visibilities.LOCAL -> { val classId = declaration.classId - IdSignature.PublicSignature(classId.packageFqName, classId.relativeClassName, builder.hashId, builder.mask) + IdSignature.PublicSignature( + classId.packageFqName.asString(), classId.relativeClassName.asString(), builder.hashId, builder.mask + ) } declaration is FirTypeAlias -> { val classId = declaration.symbol.classId - IdSignature.PublicSignature(classId.packageFqName, classId.relativeClassName, builder.hashId, builder.mask) + IdSignature.PublicSignature( + classId.packageFqName.asString(), classId.relativeClassName.asString(), builder.hashId, builder.mask + ) } declaration is FirCallableMemberDeclaration<*> -> { val callableId = declaration.symbol.callableId - IdSignature.PublicSignature(callableId.packageName, callableId.relativeCallableName, builder.hashId, builder.mask) + IdSignature.PublicSignature( + callableId.packageName.asString(), callableId.relativeCallableName.asString(), builder.hashId, builder.mask + ) } else -> throw AssertionError("Unsupported FIR declaration in signature composer: ${declaration.render()}") } @@ -87,10 +92,10 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu override fun composeAccessorSignature(property: FirProperty, isSetter: Boolean): IdSignature? { val propertySignature = composeSignature(property) as? IdSignature.PublicSignature ?: return null val accessorFqName = if (isSetter) { - propertySignature.declarationFqn.child(Name.special("")) + propertySignature.declarationFqName + "." } else { - propertySignature.declarationFqn.child(Name.special("")) + propertySignature.declarationFqName + "." } - return IdSignature.PublicSignature(propertySignature.packageFqn, accessorFqName, propertySignature.id, propertySignature.mask) + return IdSignature.PublicSignature(propertySignature.packageFqName, accessorFqName, propertySignature.id, propertySignature.mask) } -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index bd01aff6edf..4cadd12160b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.types.KotlinType @@ -361,22 +362,19 @@ class DeclarationStubGenerator( private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? { val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor ?: return null - return propertyDescriptor.accessors.singleOrNull { - it.name == signature.accessorSignature.declarationFqn.shortName() - } + val shortName = signature.accessorSignature.shortName + return propertyDescriptor.accessors.singleOrNull { it.name.asString() == shortName } } private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? { val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName()) - val pathSegments = signature.declarationFqn.pathSegments() - val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() } - .filter { it.name == pathSegments.first() } - val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current -> + val nameSegments = signature.nameSegments + val toplevelDescriptors = packageDescriptor.memberScope.getDescriptorsFiltered { name -> name.asString() == nameSegments.first() } + val candidates = nameSegments.drop(1).fold(toplevelDescriptors) { acc, current -> acc.flatMap { container -> val classDescriptor = container as? ClassDescriptor ?: return@flatMap emptyList() - val nextStepCandidates = classDescriptor.constructors + - classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } - nextStepCandidates.filter { it.name == current } + classDescriptor.constructors.filter { it.name.asString() == current } + + classDescriptor.unsubstitutedMemberScope.getDescriptorsFiltered { name -> name.asString() == current } } } return candidates.firstOrNull { symbolTable.signaturer.composeSignature(it) == signature } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt index 8df53c7f79f..ec78ccb717e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt @@ -46,10 +46,16 @@ sealed class IdSignature { return "${if (isPublic) "public" else "private"} ${render()}" } - class PublicSignature(val packageFqn: FqName, val declarationFqn: FqName, val id: Long?, val mask: Long) : IdSignature() { + class PublicSignature(val packageFqName: String, val declarationFqName: String, val id: Long?, val mask: Long) : IdSignature() { override val isPublic = true - override fun packageFqName() = packageFqn + override fun packageFqName(): FqName = FqName(packageFqName) + + val shortName: String get() = declarationFqName.substringAfterLast('.') + + val firstNameSegment: String get() = declarationFqName.substringBefore('.') + + val nameSegments: List get() = declarationFqName.split('.') private fun adaptMask(old: Long): Long { return old xor Flags.values().fold(0L) { a, f -> @@ -59,35 +65,34 @@ sealed class IdSignature { } override fun topLevelSignature(): IdSignature { - if (declarationFqn.isRoot) { + if (declarationFqName.isEmpty()) { assert(id == null) // package signature return this } - val pathSegments = declarationFqn.pathSegments() + val nameSegments = nameSegments + if (nameSegments.size == 1) return this - if (pathSegments.size == 1) return this - - return PublicSignature(packageFqn, FqName(pathSegments.first().asString()), null, adaptMask(mask)) + return PublicSignature(packageFqName, nameSegments.first(), null, adaptMask(mask)) } - override fun isPackageSignature(): Boolean = id == null && declarationFqn.isRoot + override fun isPackageSignature(): Boolean = id == null && declarationFqName.isEmpty() override fun nearestPublicSig(): PublicSignature = this override fun flags(): Long = mask - override fun render(): String = "${packageFqn.asString()}/${declarationFqn.asString()}|$id[${mask.toString(2)}]" + override fun render(): String = "$packageFqName/$declarationFqName|$id[${mask.toString(2)}]" override fun asPublic(): PublicSignature? = this override fun equals(other: Any?): Boolean = - other is PublicSignature && - packageFqn == other.packageFqn && declarationFqn == other.declarationFqn && id == other.id && mask == other.mask + other is PublicSignature && packageFqName == other.packageFqName && declarationFqName == other.declarationFqName && + id == other.id && mask == other.mask override fun hashCode(): Int = - ((packageFqn.hashCode() * 31 + declarationFqn.hashCode()) * 31 + id.hashCode()) * 31 + mask.hashCode() + ((packageFqName.hashCode() * 31 + declarationFqName.hashCode()) * 31 + id.hashCode()) * 31 + mask.hashCode() } class AccessorSignature(val propertySignature: IdSignature, val accessorSignature: PublicSignature) : IdSignature() { @@ -121,7 +126,7 @@ sealed class IdSignature { override fun topLevelSignature(): IdSignature { val topLevelContainer = container.topLevelSignature() if (topLevelContainer === container) { - if (topLevelContainer is PublicSignature && topLevelContainer.declarationFqn.isRoot) { + if (topLevelContainer is PublicSignature && topLevelContainer.declarationFqName.isEmpty()) { // private top level return this } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt index 8bbf6747544..6459e47d8dc 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.KotlinMangler +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered class DescriptorByIdSignatureFinder( private val moduleDescriptor: ModuleDescriptor, @@ -43,26 +44,25 @@ class DescriptorByIdSignatureFinder( private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? { val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor ?: return null - return propertyDescriptor.accessors.singleOrNull { - it.name == signature.accessorSignature.declarationFqn.shortName() - } + val shortName = signature.accessorSignature.shortName + return propertyDescriptor.accessors.singleOrNull { it.name.asString() == shortName } } private fun performLookup(signature: IdSignature.PublicSignature): Collection { - val declarationName = signature.declarationFqn.pathSegments().first() + val declarationName = signature.firstNameSegment return when (lookupMode) { LookupMode.MODULE_WITH_DEPENDENCIES -> { moduleDescriptor .getPackage(signature.packageFqName()) .memberScope - .getContributedDescriptors { name -> name == declarationName } + .getContributedDescriptors { name -> name.asString() == declarationName } } LookupMode.MODULE_ONLY -> { (moduleDescriptor as ModuleDescriptorImpl) .packageFragmentProviderForModuleContentWithoutDependencies .getPackageFragments(signature.packageFqName()) .map { it.getMemberScope() } - .flatMap { it.getContributedDescriptors { name -> name == declarationName } } + .flatMap { it.getContributedDescriptors { name -> name.asString() == declarationName } } } } } @@ -70,16 +70,13 @@ class DescriptorByIdSignatureFinder( private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? { val toplevelDescriptors = performLookup(signature) .ifEmpty { return null } - val pathSegments = signature.declarationFqn.pathSegments() - val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current -> + val candidates = signature.nameSegments.drop(1).fold(toplevelDescriptors) { acc, current -> acc.flatMap { container -> - val classDescriptor = container as? ClassDescriptor - ?: return@flatMap emptyList() - val nextStepCandidates = classDescriptor.constructors + - classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } + + val classDescriptor = container as? ClassDescriptor ?: return@flatMap emptyList() + classDescriptor.constructors.filter { it.name.asString() == current } + + classDescriptor.unsubstitutedMemberScope.getDescriptorsFiltered { name -> name.asString() == current } + // Static scope is required only for Enum.values() and Enum.valueOf(). - classDescriptor.staticScope.getContributedDescriptors { name -> name == current } - nextStepCandidates.filter { it.name == current } + classDescriptor.staticScope.getDescriptorsFiltered { name -> name.asString() == current } } } @@ -102,4 +99,4 @@ class DescriptorByIdSignatureFinder( candidateHash == id } } -} \ No newline at end of file +} diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FunctionalInterfacesUtils.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FunctionalInterfacesUtils.kt index f341e2b958f..fa5a3a0d874 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FunctionalInterfacesUtils.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/FunctionalInterfacesUtils.kt @@ -5,14 +5,8 @@ package org.jetbrains.kotlin.backend.common.serialization -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name import java.util.regex.Pattern internal val functionPattern = Pattern.compile("^K?(Suspend)?Function\\d+$") -internal val kotlinFqn = FqName("kotlin") -internal val kotlinCoroutinesFqn = kotlinFqn.child(Name.identifier("coroutines")) -internal val kotlinReflectFqn = kotlinFqn.child(Name.identifier("reflect")) - -internal val functionalPackages = listOf(kotlinFqn, kotlinCoroutinesFqn, kotlinReflectFqn) \ No newline at end of file +internal val functionalPackages = listOf("kotlin", "kotlin.coroutines", "kotlin.reflect") diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt index da6df2c86f8..9e00b016a6e 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt @@ -12,12 +12,12 @@ import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.serialization.encodings.* +import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature.IdsigCase.* import org.jetbrains.kotlin.backend.common.serialization.proto.IrConst.ValueCase.* import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration.DeclaratorCase.* import org.jetbrains.kotlin.backend.common.serialization.proto.IrOperation.OperationCase.* import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement.StatementCase import org.jetbrains.kotlin.backend.common.serialization.proto.IrType.KindCase.* -import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature.IdsigCase.* import org.jetbrains.kotlin.backend.common.serialization.proto.IrVarargElement.VarargElementCase import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement @@ -30,9 +30,11 @@ import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.* import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature +import org.jetbrains.kotlin.backend.common.serialization.proto.FileLocalIdSignature as ProtoFileLocalIdSignature +import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature import org.jetbrains.kotlin.backend.common.serialization.proto.IrAnonymousInit as ProtoAnonymousInit import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody @@ -99,10 +101,7 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.IrWhen as ProtoWh import org.jetbrains.kotlin.backend.common.serialization.proto.IrWhile as ProtoWhile import org.jetbrains.kotlin.backend.common.serialization.proto.Loop as ProtoLoop import org.jetbrains.kotlin.backend.common.serialization.proto.MemberAccessCommon as ProtoMemberAccessCommon -import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature import org.jetbrains.kotlin.backend.common.serialization.proto.PublicIdSignature as ProtoPublicIdSignature -import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature -import org.jetbrains.kotlin.backend.common.serialization.proto.FileLocalIdSignature as ProtoFileLocalIdSignature abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBuiltIns, val symbolTable: SymbolTable, var constructFakeOverrides: Boolean, protected var deserializeBodies: Boolean) { @@ -122,11 +121,8 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu abstract val deserializeInlineFunctions: Boolean - fun deserializeFqName(fqn: List): FqName { - return fqn.run { - if (isEmpty()) FqName.ROOT else FqName.fromSegments(map { deserializeString(it) }) - } - } + fun deserializeFqName(fqn: List): String = + fqn.joinToString(".", transform = ::deserializeString) private fun deserializeIrSymbolAndRemap(code: Long): IrSymbol { // TODO: could be simplified @@ -224,9 +220,8 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu val hash = proto.accessorHashId val mask = proto.flags - val accessorSignature = with(propertySignature) { - IdSignature.PublicSignature(packageFqn, declarationFqn.child(Name.special(name)), hash, mask) - } + val accessorSignature = + IdSignature.PublicSignature(propertySignature.packageFqName, "${propertySignature.declarationFqName}.$name", hash, mask) return IdSignature.AccessorSignature(propertySignature, accessorSignature) } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt index bf33e24c437..fe38e14d758 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt @@ -184,8 +184,8 @@ open class IrFileSerializer( private fun serializePublicSignature(signature: IdSignature.PublicSignature): ProtoPublicIdSignature { val proto = ProtoPublicIdSignature.newBuilder() - proto.addAllPackageFqName(serializeFqName(signature.packageFqn)) - proto.addAllDeclarationFqName(serializeFqName(signature.declarationFqn)) + proto.addAllPackageFqName(serializeFqName(signature.packageFqName)) + proto.addAllDeclarationFqName(serializeFqName(signature.declarationFqName)) signature.id?.let { proto.memberUniqId = it } if (signature.mask != 0L) { @@ -200,7 +200,7 @@ open class IrFileSerializer( proto.propertySignature = protoIdSignature(signature.propertySignature) with(signature.accessorSignature) { - proto.name = serializeString(declarationFqn.shortName().asString()) + proto.name = serializeString(shortName) proto.accessorHashId = id ?: error("Expected hash Id") if (mask != 0L) { proto.flags = mask @@ -297,7 +297,7 @@ open class IrFileSerializer( private fun serializeAnnotations(annotations: List) = annotations.map { serializeConstructorCall(it) } - private fun serializeFqName(fqName: FqName) = fqName.pathSegments().map { serializeString(it.asString()) } + private fun serializeFqName(fqName: String): List = fqName.split(".").map(::serializeString) private fun serializeIrStarProjection() = BinaryTypeProjection.STAR_CODE @@ -1228,7 +1228,7 @@ open class IrFileSerializer( val proto = ProtoFile.newBuilder() .setFileEntry(serializeFileEntry(file.fileEntry)) - .addAllFqName(serializeFqName(file.fqName)) + .addAllFqName(serializeFqName(file.fqName.asString())) .addAllAnnotation(serializeAnnotations(file.annotations)) file.declarations.forEach { diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt index c0810af731e..ac0c57bfdbb 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt @@ -7,16 +7,17 @@ package org.jetbrains.kotlin.backend.common.serialization import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.library.IrLibrary -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind { return when (this) { @@ -81,19 +82,11 @@ class IrModuleDeserializerWithBuiltIns( }.toMap() private fun checkIsFunctionInterface(idSig: IdSignature): Boolean { - val publicSig = idSig.asPublic() ?: return false - - if (publicSig.packageFqn !in functionalPackages) return false - - val declarationFqn = publicSig.declarationFqn - - if (declarationFqn.isRoot) return false - - val fqnParts = declarationFqn.pathSegments() - - val className = fqnParts.first() - - return functionPattern.matcher(className.asString()).find() + val publicSig = idSig.asPublic() + return publicSig != null && + publicSig.packageFqName in functionalPackages && + publicSig.declarationFqName.isNotEmpty() && + functionPattern.matcher(publicSig.firstNameSegment).find() } override operator fun contains(idSig: IdSignature): Boolean { @@ -106,11 +99,10 @@ class IrModuleDeserializerWithBuiltIns( delegate.deserializeReachableDeclarations() } - private fun computeFunctionDescriptor(className: Name): FunctionClassDescriptor { - val nameString = className.asString() - val isK = nameString[0] == 'K' - val isSuspend = (if (isK) nameString[1] else nameString[0]) == 'S' - val arity = nameString.run { substring(indexOfFirst { it.isDigit() }).toInt(10) } + private fun computeFunctionDescriptor(className: String): FunctionClassDescriptor { + val isK = className[0] == 'K' + val isSuspend = (if (isK) className[1] else className[0]) == 'S' + val arity = className.run { substring(indexOfFirst { it.isDigit() }).toInt(10) } return functionFactory.run { when { isK && isSuspend -> kSuspendFunctionClassDescriptor(arity) @@ -124,11 +116,11 @@ class IrModuleDeserializerWithBuiltIns( private fun resolveFunctionalInterface(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { val publicSig = idSig.asPublic() ?: error("$idSig has to be public") - val fqnParts = publicSig.declarationFqn.pathSegments() + val fqnParts = publicSig.nameSegments val className = fqnParts.firstOrNull() ?: error("Expected class name for $idSig") val functionDescriptor = computeFunctionDescriptor(className) - val topLevelSignature = IdSignature.PublicSignature(publicSig.packageFqn, FqName(className.asString()), null, publicSig.mask) + val topLevelSignature = IdSignature.PublicSignature(publicSig.packageFqName, className, null, publicSig.mask) val functionClass = when (functionDescriptor.functionKind) { FunctionClassDescriptor.Kind.KSuspendFunction -> functionFactory.kSuspendFunctionN(functionDescriptor.arity) { callback -> @@ -148,19 +140,19 @@ class IrModuleDeserializerWithBuiltIns( return when (fqnParts.size) { 1 -> functionClass.symbol.also { assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) } 2 -> { - val memberName = fqnParts[1]!! - functionClass.declarations.single { it is IrDeclarationWithName && it.name == memberName }.let { + val memberName = fqnParts[1] + functionClass.declarations.single { it is IrDeclarationWithName && it.name.asString() == memberName }.let { (it as IrSymbolOwner).symbol } } 3 -> { assert(idSig is IdSignature.AccessorSignature) assert(symbolKind == BinarySymbolData.SymbolKind.FUNCTION_SYMBOL) - val propertyName = fqnParts[1]!! - val accessorName = fqnParts[2]!! - functionClass.declarations.filterIsInstance().single { it.name == propertyName }.let { p -> - p.getter?.let { g -> if (g.name == accessorName) return g.symbol } - p.setter?.let { s -> if (s.name == accessorName) return s.symbol } + val propertyName = fqnParts[1] + val accessorName = fqnParts[2] + functionClass.declarations.filterIsInstance().single { it.name.asString() == propertyName }.let { p -> + p.getter?.let { g -> if (g.name.asString() == accessorName) return g.symbol } + p.setter?.let { s -> if (s.name.asString() == accessorName) return s.symbol } error("No accessor found for signature $idSig") } } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt index 8be35b4199a..2ee85b34706 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -173,7 +174,7 @@ abstract class KotlinIrLinker( } } - val fqName = fileDeserializer.deserializeFqName(fileProto.fqNameList) + val fqName = FqName(fileDeserializer.deserializeFqName(fileProto.fqNameList)) val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName) diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureBuilder.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureBuilder.kt index eb7d27d6b05..787f6e27202 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureBuilder.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureBuilder.kt @@ -26,10 +26,12 @@ abstract class IdSignatureBuilder { } protected fun build(): IdSignature { + val packageFqName = packageFqn.asString() + val classFqName = classFqnSegments.joinToString(".") return if (hashIdAcc == null) { - IdSignature.PublicSignature(packageFqn, FqName.fromSegments(classFqnSegments), hashId, mask) + IdSignature.PublicSignature(packageFqName, classFqName, hashId, mask) } else { - val accessorSignature = IdSignature.PublicSignature(packageFqn, FqName.fromSegments(classFqnSegments), hashIdAcc, mask) + val accessorSignature = IdSignature.PublicSignature(packageFqName, classFqName, hashIdAcc, mask) hashIdAcc = null classFqnSegments.run { removeAt(lastIndex) } val propertySignature = build() diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureSerializer.kt index dfcaf42de66..2e3f744deb3 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureSerializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/signature/IdSignatureSerializer.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.name.FqName open class IdSignatureSerializer(val mangler: KotlinMangler.IrMangler) : IdSignatureComputer { @@ -96,11 +95,12 @@ open class IdSignatureSerializer(val mangler: KotlinMangler.IrMangler) : IdSigna private val publicSignatureBuilder = PublicIdSigBuilder() - private fun composeContainerIdSignature(container: IrDeclarationParent): IdSignature { - if (container is IrPackageFragment) return IdSignature.PublicSignature(container.fqName, FqName.ROOT, null, 0) - if (container is IrDeclaration) return table.signatureByDeclaration(container) - error("Unexpected container ${container.render()}") - } + private fun composeContainerIdSignature(container: IrDeclarationParent): IdSignature = + when (container) { + is IrPackageFragment -> IdSignature.PublicSignature(container.fqName.asString(), "", null, 0) + is IrDeclaration -> table.signatureByDeclaration(container) + else -> error("Unexpected container ${container.render()}") + } fun composePublicIdSignature(declaration: IrDeclaration): IdSignature { assert(mangler.run { declaration.isExported() }) { @@ -130,4 +130,4 @@ open class IdSignatureSerializer(val mangler: KotlinMangler.IrMangler) : IdSigna } } } -} \ No newline at end of file +}