From cae800b24e2044007a9dd1da90d5c70cc1afbe51 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Mon, 25 Feb 2019 16:17:54 +0300 Subject: [PATCH] [JS IR BE] Fix deserialization performance --- .../ir/DeserializeDescriptorReference.kt | 97 +++++++++++++++---- 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/DeserializeDescriptorReference.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/DeserializeDescriptorReference.kt index c6d955ad845..ebcbf83ca74 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/DeserializeDescriptorReference.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/DeserializeDescriptorReference.kt @@ -20,6 +20,49 @@ class DescriptorReferenceDeserializer( val descriptorResolver: (FqName) -> DeclarationDescriptor ) { + private val cache = mutableMapOf>() + + private fun getContributedDescriptors(packageFqNameString: String): Collection = + cache.getOrPut(packageFqNameString) { + val packageFqName = packageFqNameString.let { + if (it == "") FqName.ROOT else FqName(it) + }// TODO: whould we store an empty string in the protobuf? + + currentModule.getPackage(packageFqName).memberScope.getContributedDescriptors() + } + + private data class ClassName(val packageFqName: String, val classFqName: String) + + private class ClassMembers(val defaultConstructor: ClassConstructorDescriptor?, + val members: Map, + val realMembers: Map) + + private val membersCache = mutableMapOf() + + + private fun computeUniqIdIndex(descriptor: DeclarationDescriptor) = descriptor.getUniqId()?.index ?: checkerDesc(descriptor) + + private fun getMembers(packageFqNameString: String, classFqNameString: String, + members: Collection): ClassMembers = + membersCache.getOrPut(ClassName(packageFqNameString, classFqNameString)) { + val allMembersMap = mutableMapOf() + val realMembersMap = mutableMapOf() + var classConstructorDescriptor: ClassConstructorDescriptor? = null + members.forEach { member -> + if (member is ClassConstructorDescriptor) + classConstructorDescriptor = member + val realMembers = + if (member is CallableMemberDescriptor && member.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) + member.resolveFakeOverrideMaybeAbstract().map { it.original } + else + setOf(member) + + computeUniqIdIndex(member)?.let { allMembersMap[it] = member } + realMembers.map { computeUniqIdIndex(it) }.filterNotNull().forEach { realMembersMap[it] = member } + } + ClassMembers(classConstructorDescriptor, allMembersMap, realMembersMap) + } + fun deserializeDescriptorReference( packageFqNameString: String, classFqNameString: String, @@ -40,7 +83,7 @@ class DescriptorReferenceDeserializer( val protoIndex = index val (clazz, members) = if (classFqNameString == "") { - Pair(null, currentModule.getPackage(packageFqName).memberScope.getContributedDescriptors()) + Pair(null, getContributedDescriptors(packageFqNameString)) } else { val clazz = currentModule.findClassAcrossModuleDependencies(ClassId(packageFqName, classFqName, false))!! Pair(clazz, clazz.unsubstitutedMemberScope.getContributedDescriptors() + clazz.getConstructors()) @@ -80,26 +123,44 @@ class DescriptorReferenceDeserializer( return descriptorResolver(packageFqName.child(Name.identifier(name))) } - members.forEach { member -> - if (isDefaultConstructor && member is ClassConstructorDescriptor) return member + val membersWithIndices = getMembers(packageFqNameString, classFqNameString, members) - val realMembers = - if (isFakeOverride && member is CallableMemberDescriptor && member.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) - member.resolveFakeOverrideMaybeAbstract().map { it.original } - else - setOf(member) + return when { + isDefaultConstructor -> membersWithIndices.defaultConstructor - val memberIndices = realMembers.map { it.getUniqId()?.index ?: checkerDesc(it) }.filterNotNull() - - if (memberIndices.contains(protoIndex)) { - return when { - member is PropertyDescriptor && isSetter -> member.setter!! - member is PropertyDescriptor && isGetter -> member.getter!! - else -> member + else -> { + val map = if (isFakeOverride) membersWithIndices.realMembers else membersWithIndices.members + map[protoIndex]?.let { member -> + when { + member is PropertyDescriptor && isSetter -> member.setter!! + member is PropertyDescriptor && isGetter -> member.getter!! + else -> member + } } } - } - - error("Could not find serialized descriptor for index: $index $packageFqName,$classFqName,$name") + } ?: + error("Could not find serialized descriptor for index: ${index} ${packageFqName},${classFqName},${name}") +// +// members.forEach { member -> +// if (isDefaultConstructor && member is ClassConstructorDescriptor) return member +// +// val realMembers = +// if (isFakeOverride && member is CallableMemberDescriptor && member.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) +// member.resolveFakeOverrideMaybeAbstract().map { it.original } +// else +// setOf(member) +// +// val memberIndices = realMembers.map { it.getUniqId()?.index ?: checkerDesc(it) }.filterNotNull() +// +// if (memberIndices.contains(protoIndex)) { +// return when { +// member is PropertyDescriptor && isSetter -> member.setter!! +// member is PropertyDescriptor && isGetter -> member.getter!! +// else -> member +// } +// } +// } +// +// error("Could not find serialized descriptor for index: $index $packageFqName,$classFqName,$name") } } \ No newline at end of file