From 84a464449056891281418ee20adbf98ca7628143 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Wed, 10 Jun 2020 16:01:47 +0700 Subject: [PATCH] [Commonizer] Speed-up serialization of commonized member scopes --- .../builder/CommonizedMemberScope.kt | 89 +++++++++++++------ 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedMemberScope.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedMemberScope.kt index a23ae39a1e7..cd33c75ec9b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedMemberScope.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedMemberScope.kt @@ -5,42 +5,74 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.utils.Printer -class CommonizedMemberScope : MemberScopeImpl() { - private val members = ArrayList() +class CommonizedMemberScope : MemberScope { + private val functions = HashMap>() + private val variables = HashMap>() + private val classifiers = HashMap() - operator fun plusAssign(member: DeclarationDescriptor) { - this.members += member + private fun addMember(member: DeclarationDescriptor) { + when (member) { + is SimpleFunctionDescriptor -> functions.computeIfAbsent(member.name) { ArrayList(INITIAL_CAPACITY_FOR_CALLABLES) } += member + is PropertyDescriptor -> variables.computeIfAbsent(member.name) { ArrayList(INITIAL_CAPACITY_FOR_CALLABLES) } += member + is ClassifierDescriptorWithTypeParameters -> classifiers[member.name] = member + else -> error("Unsupported member type: ${member::class.java}, $member") + } } - override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = - members.filteredBy(name).firstOrNull() - - override fun getContributedVariables(name: Name, location: LookupLocation): Collection = - members.filteredBy(name).toList() + override fun getFunctionNames(): Set = functions.keys + override fun getVariableNames(): Set = variables.keys + override fun getClassifierNames(): Set = classifiers.keys override fun getContributedFunctions(name: Name, location: LookupLocation): Collection = - members.filteredBy(name).toList() + functions[name].orEmpty() + + override fun getContributedVariables(name: Name, location: LookupLocation): Collection = + variables[name].orEmpty() + + override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = + classifiers[name] override fun getContributedDescriptors( kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean - ): Collection = members.filter { kindFilter.accepts(it) && nameFilter(it.name) } + ): Collection { + val result = ArrayList(INITIAL_CAPACITY_FOR_CONTRIBUTED_DESCRIPTORS) + + if (kindFilter.acceptsKinds(DescriptorKindFilter.CLASSIFIERS_MASK)) { + classifiers.values.filterTo(result) { nameFilter(it.name) } + } + + if (kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) { + functions.forEach { (name, callables) -> + if (nameFilter(name)) + result.addAll(callables) + } + } + + if (kindFilter.acceptsKinds(DescriptorKindFilter.VARIABLES_MASK)) { + variables.forEach { (name, callables) -> + if (nameFilter(name)) + result.addAll(callables) + } + } + + return result + } override fun printScopeStructure(p: Printer) { p.println(this::class.java.simpleName, " {") p.pushIndent() - p.println("declarations = $members") + p.println("functions = $functions") + p.println("variables = $variables") + p.println("classifiers = $classifiers") p.popIndent() p.println("}") @@ -51,21 +83,26 @@ class CommonizedMemberScope : MemberScopeImpl() { operator fun Array.plusAssign(members: List) { members.forEachIndexed { index, member -> - if (member != null) { - this[index] += member - } + if (member != null) + this[index].addMember(member) } } operator fun List.plusAssign(members: List) { members.forEachIndexed { index, member -> - if (member != null) { - this[index]?.run { this += member } - } + if (member != null) + this[index]?.addMember(member) } } + + // Heuristic memory usage optimization. During commonization of ios_x64 and ios_arm64 only about 3% of functions are overloaded + // (and therefore have the same name in the same scope). For the remaining 97% the capacity of 1 is enough. + private const val INITIAL_CAPACITY_FOR_CALLABLES = 1 + + // Heuristic memory usage optimization. During commonization of ios_x64 and ios_arm64 the getContributedDescriptors() call + // returns empty list in 27% times and list of size 1 in 63% times. The default capacity of 0 looks reasonable. + private const val INITIAL_CAPACITY_FOR_CONTRIBUTED_DESCRIPTORS = 0 + + internal val STATS = HashMap() } } - -private inline fun List<*>.filteredBy(name: Name): Sequence = - this.asSequence().filterIsInstance().filter { it.name == name }