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.
This commit is contained in:
Alexander Udalov
2020-06-10 21:46:29 +02:00
parent d24e136ba8
commit 3154eca218
11 changed files with 102 additions and 113 deletions
@@ -10,12 +10,11 @@ import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatureComposer { class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatureComposer {
inner class SignatureBuilder : FirVisitorVoid() { inner class SignatureBuilder : FirVisitorVoid() {
@@ -70,15 +69,21 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu
return when { return when {
declaration is FirRegularClass && declaration.visibility != Visibilities.LOCAL -> { declaration is FirRegularClass && declaration.visibility != Visibilities.LOCAL -> {
val classId = declaration.classId 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 -> { declaration is FirTypeAlias -> {
val classId = declaration.symbol.classId 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<*> -> { declaration is FirCallableMemberDeclaration<*> -> {
val callableId = declaration.symbol.callableId 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()}") 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? { override fun composeAccessorSignature(property: FirProperty, isSetter: Boolean): IdSignature? {
val propertySignature = composeSignature(property) as? IdSignature.PublicSignature ?: return null val propertySignature = composeSignature(property) as? IdSignature.PublicSignature ?: return null
val accessorFqName = if (isSetter) { val accessorFqName = if (isSetter) {
propertySignature.declarationFqn.child(Name.special("<set-${property.name}>")) propertySignature.declarationFqName + ".<set-${property.name.asString()}>"
} else { } else {
propertySignature.declarationFqn.child(Name.special("<get-${property.name}>")) propertySignature.declarationFqName + ".<get-${property.name.asString()}>"
} }
return IdSignature.PublicSignature(propertySignature.packageFqn, accessorFqName, propertySignature.id, propertySignature.mask) return IdSignature.PublicSignature(propertySignature.packageFqName, accessorFqName, propertySignature.id, propertySignature.mask)
} }
} }
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal 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.DescriptorWithContainerSource
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -361,22 +362,19 @@ class DeclarationStubGenerator(
private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? { private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? {
val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor ?: return null val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor ?: return null
return propertyDescriptor.accessors.singleOrNull { val shortName = signature.accessorSignature.shortName
it.name == signature.accessorSignature.declarationFqn.shortName() return propertyDescriptor.accessors.singleOrNull { it.name.asString() == shortName }
}
} }
private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? { private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? {
val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName()) val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName())
val pathSegments = signature.declarationFqn.pathSegments() val nameSegments = signature.nameSegments
val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() } val toplevelDescriptors = packageDescriptor.memberScope.getDescriptorsFiltered { name -> name.asString() == nameSegments.first() }
.filter { it.name == pathSegments.first() } val candidates = nameSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
acc.flatMap { container -> acc.flatMap { container ->
val classDescriptor = container as? ClassDescriptor ?: return@flatMap emptyList() val classDescriptor = container as? ClassDescriptor ?: return@flatMap emptyList()
val nextStepCandidates = classDescriptor.constructors + classDescriptor.constructors.filter { it.name.asString() == current } +
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } classDescriptor.unsubstitutedMemberScope.getDescriptorsFiltered { name -> name.asString() == current }
nextStepCandidates.filter { it.name == current }
} }
} }
return candidates.firstOrNull { symbolTable.signaturer.composeSignature(it) == signature } return candidates.firstOrNull { symbolTable.signaturer.composeSignature(it) == signature }
@@ -46,10 +46,16 @@ sealed class IdSignature {
return "${if (isPublic) "public" else "private"} ${render()}" 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 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<String> get() = declarationFqName.split('.')
private fun adaptMask(old: Long): Long { private fun adaptMask(old: Long): Long {
return old xor Flags.values().fold(0L) { a, f -> return old xor Flags.values().fold(0L) { a, f ->
@@ -59,35 +65,34 @@ sealed class IdSignature {
} }
override fun topLevelSignature(): IdSignature { override fun topLevelSignature(): IdSignature {
if (declarationFqn.isRoot) { if (declarationFqName.isEmpty()) {
assert(id == null) assert(id == null)
// package signature // package signature
return this return this
} }
val pathSegments = declarationFqn.pathSegments() val nameSegments = nameSegments
if (nameSegments.size == 1) return this
if (pathSegments.size == 1) return this return PublicSignature(packageFqName, nameSegments.first(), null, adaptMask(mask))
return PublicSignature(packageFqn, FqName(pathSegments.first().asString()), 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 nearestPublicSig(): PublicSignature = this
override fun flags(): Long = mask 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 asPublic(): PublicSignature? = this
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is PublicSignature && other is PublicSignature && packageFqName == other.packageFqName && declarationFqName == other.declarationFqName &&
packageFqn == other.packageFqn && declarationFqn == other.declarationFqn && id == other.id && mask == other.mask id == other.id && mask == other.mask
override fun hashCode(): Int = 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() { class AccessorSignature(val propertySignature: IdSignature, val accessorSignature: PublicSignature) : IdSignature() {
@@ -121,7 +126,7 @@ sealed class IdSignature {
override fun topLevelSignature(): IdSignature { override fun topLevelSignature(): IdSignature {
val topLevelContainer = container.topLevelSignature() val topLevelContainer = container.topLevelSignature()
if (topLevelContainer === container) { if (topLevelContainer === container) {
if (topLevelContainer is PublicSignature && topLevelContainer.declarationFqn.isRoot) { if (topLevelContainer is PublicSignature && topLevelContainer.declarationFqName.isEmpty()) {
// private top level // private top level
return this return this
} }
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
class DescriptorByIdSignatureFinder( class DescriptorByIdSignatureFinder(
private val moduleDescriptor: ModuleDescriptor, private val moduleDescriptor: ModuleDescriptor,
@@ -43,26 +44,25 @@ class DescriptorByIdSignatureFinder(
private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? { private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? {
val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor
?: return null ?: return null
return propertyDescriptor.accessors.singleOrNull { val shortName = signature.accessorSignature.shortName
it.name == signature.accessorSignature.declarationFqn.shortName() return propertyDescriptor.accessors.singleOrNull { it.name.asString() == shortName }
}
} }
private fun performLookup(signature: IdSignature.PublicSignature): Collection<DeclarationDescriptor> { private fun performLookup(signature: IdSignature.PublicSignature): Collection<DeclarationDescriptor> {
val declarationName = signature.declarationFqn.pathSegments().first() val declarationName = signature.firstNameSegment
return when (lookupMode) { return when (lookupMode) {
LookupMode.MODULE_WITH_DEPENDENCIES -> { LookupMode.MODULE_WITH_DEPENDENCIES -> {
moduleDescriptor moduleDescriptor
.getPackage(signature.packageFqName()) .getPackage(signature.packageFqName())
.memberScope .memberScope
.getContributedDescriptors { name -> name == declarationName } .getContributedDescriptors { name -> name.asString() == declarationName }
} }
LookupMode.MODULE_ONLY -> { LookupMode.MODULE_ONLY -> {
(moduleDescriptor as ModuleDescriptorImpl) (moduleDescriptor as ModuleDescriptorImpl)
.packageFragmentProviderForModuleContentWithoutDependencies .packageFragmentProviderForModuleContentWithoutDependencies
.getPackageFragments(signature.packageFqName()) .getPackageFragments(signature.packageFqName())
.map { it.getMemberScope() } .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? { private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? {
val toplevelDescriptors = performLookup(signature) val toplevelDescriptors = performLookup(signature)
.ifEmpty { return null } .ifEmpty { return null }
val pathSegments = signature.declarationFqn.pathSegments() val candidates = signature.nameSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
acc.flatMap { container -> acc.flatMap { container ->
val classDescriptor = container as? ClassDescriptor val classDescriptor = container as? ClassDescriptor ?: return@flatMap emptyList<DeclarationDescriptor>()
?: return@flatMap emptyList<DeclarationDescriptor>() classDescriptor.constructors.filter { it.name.asString() == current } +
val nextStepCandidates = classDescriptor.constructors + classDescriptor.unsubstitutedMemberScope.getDescriptorsFiltered { name -> name.asString() == current } +
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } +
// Static scope is required only for Enum.values() and Enum.valueOf(). // Static scope is required only for Enum.values() and Enum.valueOf().
classDescriptor.staticScope.getContributedDescriptors { name -> name == current } classDescriptor.staticScope.getDescriptorsFiltered { name -> name.asString() == current }
nextStepCandidates.filter { it.name == current }
} }
} }
@@ -5,14 +5,8 @@
package org.jetbrains.kotlin.backend.common.serialization package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import java.util.regex.Pattern import java.util.regex.Pattern
internal val functionPattern = Pattern.compile("^K?(Suspend)?Function\\d+$") internal val functionPattern = Pattern.compile("^K?(Suspend)?Function\\d+$")
internal val kotlinFqn = FqName("kotlin") internal val functionalPackages = listOf("kotlin", "kotlin.coroutines", "kotlin.reflect")
internal val kotlinCoroutinesFqn = kotlinFqn.child(Name.identifier("coroutines"))
internal val kotlinReflectFqn = kotlinFqn.child(Name.identifier("reflect"))
internal val functionalPackages = listOf(kotlinFqn, kotlinCoroutinesFqn, kotlinReflectFqn)
@@ -12,12 +12,12 @@ import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.common.serialization.encodings.* 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.IrConst.ValueCase.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration.DeclaratorCase.* 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.IrOperation.OperationCase.*
import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement.StatementCase 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.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.backend.common.serialization.proto.IrVarargElement.VarargElementCase
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement 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.*
import org.jetbrains.kotlin.ir.types.impl.* import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance 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.IrAnonymousInit as ProtoAnonymousInit
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody 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.IrWhile as ProtoWhile
import org.jetbrains.kotlin.backend.common.serialization.proto.Loop as ProtoLoop 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.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.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) { 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 abstract val deserializeInlineFunctions: Boolean
fun deserializeFqName(fqn: List<Int>): FqName { fun deserializeFqName(fqn: List<Int>): String =
return fqn.run { fqn.joinToString(".", transform = ::deserializeString)
if (isEmpty()) FqName.ROOT else FqName.fromSegments(map { deserializeString(it) })
}
}
private fun deserializeIrSymbolAndRemap(code: Long): IrSymbol { private fun deserializeIrSymbolAndRemap(code: Long): IrSymbol {
// TODO: could be simplified // TODO: could be simplified
@@ -224,9 +220,8 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
val hash = proto.accessorHashId val hash = proto.accessorHashId
val mask = proto.flags val mask = proto.flags
val accessorSignature = with(propertySignature) { val accessorSignature =
IdSignature.PublicSignature(packageFqn, declarationFqn.child(Name.special(name)), hash, mask) IdSignature.PublicSignature(propertySignature.packageFqName, "${propertySignature.declarationFqName}.$name", hash, mask)
}
return IdSignature.AccessorSignature(propertySignature, accessorSignature) return IdSignature.AccessorSignature(propertySignature, accessorSignature)
} }
@@ -184,8 +184,8 @@ open class IrFileSerializer(
private fun serializePublicSignature(signature: IdSignature.PublicSignature): ProtoPublicIdSignature { private fun serializePublicSignature(signature: IdSignature.PublicSignature): ProtoPublicIdSignature {
val proto = ProtoPublicIdSignature.newBuilder() val proto = ProtoPublicIdSignature.newBuilder()
proto.addAllPackageFqName(serializeFqName(signature.packageFqn)) proto.addAllPackageFqName(serializeFqName(signature.packageFqName))
proto.addAllDeclarationFqName(serializeFqName(signature.declarationFqn)) proto.addAllDeclarationFqName(serializeFqName(signature.declarationFqName))
signature.id?.let { proto.memberUniqId = it } signature.id?.let { proto.memberUniqId = it }
if (signature.mask != 0L) { if (signature.mask != 0L) {
@@ -200,7 +200,7 @@ open class IrFileSerializer(
proto.propertySignature = protoIdSignature(signature.propertySignature) proto.propertySignature = protoIdSignature(signature.propertySignature)
with(signature.accessorSignature) { with(signature.accessorSignature) {
proto.name = serializeString(declarationFqn.shortName().asString()) proto.name = serializeString(shortName)
proto.accessorHashId = id ?: error("Expected hash Id") proto.accessorHashId = id ?: error("Expected hash Id")
if (mask != 0L) { if (mask != 0L) {
proto.flags = mask proto.flags = mask
@@ -297,7 +297,7 @@ open class IrFileSerializer(
private fun serializeAnnotations(annotations: List<IrConstructorCall>) = private fun serializeAnnotations(annotations: List<IrConstructorCall>) =
annotations.map { serializeConstructorCall(it) } annotations.map { serializeConstructorCall(it) }
private fun serializeFqName(fqName: FqName) = fqName.pathSegments().map { serializeString(it.asString()) } private fun serializeFqName(fqName: String): List<Int> = fqName.split(".").map(::serializeString)
private fun serializeIrStarProjection() = BinaryTypeProjection.STAR_CODE private fun serializeIrStarProjection() = BinaryTypeProjection.STAR_CODE
@@ -1228,7 +1228,7 @@ open class IrFileSerializer(
val proto = ProtoFile.newBuilder() val proto = ProtoFile.newBuilder()
.setFileEntry(serializeFileEntry(file.fileEntry)) .setFileEntry(serializeFileEntry(file.fileEntry))
.addAllFqName(serializeFqName(file.fqName)) .addAllFqName(serializeFqName(file.fqName.asString()))
.addAllAnnotation(serializeAnnotations(file.annotations)) .addAllAnnotation(serializeAnnotations(file.annotations))
file.declarations.forEach { file.declarations.forEach {
@@ -7,16 +7,17 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.declarations.* 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.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind { internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind {
return when (this) { return when (this) {
@@ -81,19 +82,11 @@ class IrModuleDeserializerWithBuiltIns(
}.toMap() }.toMap()
private fun checkIsFunctionInterface(idSig: IdSignature): Boolean { private fun checkIsFunctionInterface(idSig: IdSignature): Boolean {
val publicSig = idSig.asPublic() ?: return false val publicSig = idSig.asPublic()
return publicSig != null &&
if (publicSig.packageFqn !in functionalPackages) return false publicSig.packageFqName in functionalPackages &&
publicSig.declarationFqName.isNotEmpty() &&
val declarationFqn = publicSig.declarationFqn functionPattern.matcher(publicSig.firstNameSegment).find()
if (declarationFqn.isRoot) return false
val fqnParts = declarationFqn.pathSegments()
val className = fqnParts.first()
return functionPattern.matcher(className.asString()).find()
} }
override operator fun contains(idSig: IdSignature): Boolean { override operator fun contains(idSig: IdSignature): Boolean {
@@ -106,11 +99,10 @@ class IrModuleDeserializerWithBuiltIns(
delegate.deserializeReachableDeclarations() delegate.deserializeReachableDeclarations()
} }
private fun computeFunctionDescriptor(className: Name): FunctionClassDescriptor { private fun computeFunctionDescriptor(className: String): FunctionClassDescriptor {
val nameString = className.asString() val isK = className[0] == 'K'
val isK = nameString[0] == 'K' val isSuspend = (if (isK) className[1] else className[0]) == 'S'
val isSuspend = (if (isK) nameString[1] else nameString[0]) == 'S' val arity = className.run { substring(indexOfFirst { it.isDigit() }).toInt(10) }
val arity = nameString.run { substring(indexOfFirst { it.isDigit() }).toInt(10) }
return functionFactory.run { return functionFactory.run {
when { when {
isK && isSuspend -> kSuspendFunctionClassDescriptor(arity) isK && isSuspend -> kSuspendFunctionClassDescriptor(arity)
@@ -124,11 +116,11 @@ class IrModuleDeserializerWithBuiltIns(
private fun resolveFunctionalInterface(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { private fun resolveFunctionalInterface(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val publicSig = idSig.asPublic() ?: error("$idSig has to be public") 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 className = fqnParts.firstOrNull() ?: error("Expected class name for $idSig")
val functionDescriptor = computeFunctionDescriptor(className) 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) { val functionClass = when (functionDescriptor.functionKind) {
FunctionClassDescriptor.Kind.KSuspendFunction -> functionFactory.kSuspendFunctionN(functionDescriptor.arity) { callback -> FunctionClassDescriptor.Kind.KSuspendFunction -> functionFactory.kSuspendFunctionN(functionDescriptor.arity) { callback ->
@@ -148,19 +140,19 @@ class IrModuleDeserializerWithBuiltIns(
return when (fqnParts.size) { return when (fqnParts.size) {
1 -> functionClass.symbol.also { assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) } 1 -> functionClass.symbol.also { assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) }
2 -> { 2 -> {
val memberName = fqnParts[1]!! val memberName = fqnParts[1]
functionClass.declarations.single { it is IrDeclarationWithName && it.name == memberName }.let { functionClass.declarations.single { it is IrDeclarationWithName && it.name.asString() == memberName }.let {
(it as IrSymbolOwner).symbol (it as IrSymbolOwner).symbol
} }
} }
3 -> { 3 -> {
assert(idSig is IdSignature.AccessorSignature) assert(idSig is IdSignature.AccessorSignature)
assert(symbolKind == BinarySymbolData.SymbolKind.FUNCTION_SYMBOL) assert(symbolKind == BinarySymbolData.SymbolKind.FUNCTION_SYMBOL)
val propertyName = fqnParts[1]!! val propertyName = fqnParts[1]
val accessorName = fqnParts[2]!! val accessorName = fqnParts[2]
functionClass.declarations.filterIsInstance<IrProperty>().single { it.name == propertyName }.let { p -> functionClass.declarations.filterIsInstance<IrProperty>().single { it.name.asString() == propertyName }.let { p ->
p.getter?.let { g -> if (g.name == accessorName) return g.symbol } p.getter?.let { g -> if (g.name.asString() == accessorName) return g.symbol }
p.setter?.let { s -> if (s.name == accessorName) return s.symbol } p.setter?.let { s -> if (s.name.asString() == accessorName) return s.symbol }
error("No accessor found for signature $idSig") error("No accessor found for signature $idSig")
} }
} }
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.CodedInputStream
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance
import org.jetbrains.kotlin.resolve.descriptorUtil.module 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) val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName)
@@ -26,10 +26,12 @@ abstract class IdSignatureBuilder<D> {
} }
protected fun build(): IdSignature { protected fun build(): IdSignature {
val packageFqName = packageFqn.asString()
val classFqName = classFqnSegments.joinToString(".")
return if (hashIdAcc == null) { return if (hashIdAcc == null) {
IdSignature.PublicSignature(packageFqn, FqName.fromSegments(classFqnSegments), hashId, mask) IdSignature.PublicSignature(packageFqName, classFqName, hashId, mask)
} else { } else {
val accessorSignature = IdSignature.PublicSignature(packageFqn, FqName.fromSegments(classFqnSegments), hashIdAcc, mask) val accessorSignature = IdSignature.PublicSignature(packageFqName, classFqName, hashIdAcc, mask)
hashIdAcc = null hashIdAcc = null
classFqnSegments.run { removeAt(lastIndex) } classFqnSegments.run { removeAt(lastIndex) }
val propertySignature = build() val propertySignature = build()
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.FqName
open class IdSignatureSerializer(val mangler: KotlinMangler.IrMangler) : IdSignatureComputer { 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 val publicSignatureBuilder = PublicIdSigBuilder()
private fun composeContainerIdSignature(container: IrDeclarationParent): IdSignature { private fun composeContainerIdSignature(container: IrDeclarationParent): IdSignature =
if (container is IrPackageFragment) return IdSignature.PublicSignature(container.fqName, FqName.ROOT, null, 0) when (container) {
if (container is IrDeclaration) return table.signatureByDeclaration(container) is IrPackageFragment -> IdSignature.PublicSignature(container.fqName.asString(), "", null, 0)
error("Unexpected container ${container.render()}") is IrDeclaration -> table.signatureByDeclaration(container)
} else -> error("Unexpected container ${container.render()}")
}
fun composePublicIdSignature(declaration: IrDeclaration): IdSignature { fun composePublicIdSignature(declaration: IrDeclaration): IdSignature {
assert(mangler.run { declaration.isExported() }) { assert(mangler.run { declaration.isExported() }) {