From 1716720604397d49d9e3c897fdc0b85782b98032 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 17 Jan 2018 14:31:48 +0300 Subject: [PATCH] Optimize declaration providers for case of non-existing packages Avoid creating memoized function nodes when the value is obviously null Otherwise, it may lead to about 25M retained by empty concurrent hashmap nodes --- .../kotlin/resolve/lazy/ResolveSession.java | 23 +++++++++---------- .../AbstractDeclarationProviderFactory.java | 3 +++ .../FileBasedDeclarationProviderFactory.java | 5 ++-- .../lazy/LazyJavaPackageFragmentProvider.kt | 21 ++++++++--------- .../PluginDeclarationProviderFactory.kt | 7 ++++-- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java index 6b1e74b0cac..51748dcf81e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java @@ -63,7 +63,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { private final BindingTrace trace; private final DeclarationProviderFactory declarationProviderFactory; - private final MemoizedFunctionToNullable packages; + private final CacheWithNotNullValues packages; private final PackageFragmentProvider packageFragmentProvider; private final MemoizedFunctionToNotNull fileAnnotations; @@ -169,7 +169,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace); this.module = rootDescriptor; - this.packages = storageManager.createMemoizedFunctionWithNullableValues(this::createPackage); + this.packages = storageManager.createCacheWithNotNullValues(); this.declarationProviderFactory = declarationProviderFactory; @@ -216,7 +216,15 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { @Override @Nullable public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) { - return packages.invoke(fqName); + PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName); + if (provider == null) { + return null; + } + + return packages.computeIfAbsent( + fqName, + () -> new LazyPackageDescriptor(module, fqName, this, provider) + ); } @@ -231,15 +239,6 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { return packageDescriptor; } - @Nullable - private LazyPackageDescriptor createPackage(FqName fqName) { - PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName); - if (provider == null) { - return null; - } - return new LazyPackageDescriptor(module, fqName, this, provider); - } - @NotNull @Override public ModuleDescriptor getModuleDescriptor() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java index 18308e87ce9..5182ce55d6b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java @@ -34,8 +34,11 @@ public abstract class AbstractDeclarationProviderFactory implements DeclarationP @Nullable protected abstract PackageMemberDeclarationProvider createPackageMemberDeclarationProvider(@NotNull FqName name); + public abstract boolean packageExists(@NotNull FqName fqName); + @Override public PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName) { + if (!packageExists(packageFqName)) return null; return packageDeclarationProviders.invoke(packageFqName); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/FileBasedDeclarationProviderFactory.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/FileBasedDeclarationProviderFactory.java index 8a5e2f97570..a22b529d621 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/FileBasedDeclarationProviderFactory.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/FileBasedDeclarationProviderFactory.java @@ -65,7 +65,8 @@ public class FileBasedDeclarationProviderFactory extends AbstractDeclarationProv } } - private boolean isPackageDeclaredExplicitly(@NotNull FqName packageFqName) { + @Override + public boolean packageExists(@NotNull FqName packageFqName) { return index.invoke().declaredPackages.contains(packageFqName); } @@ -76,7 +77,7 @@ public class FileBasedDeclarationProviderFactory extends AbstractDeclarationProv @Nullable @Override protected PackageMemberDeclarationProvider createPackageMemberDeclarationProvider(@NotNull FqName packageFqName) { - if (isPackageDeclaredExplicitly(packageFqName)) { + if (packageExists(packageFqName)) { return new FileBasedPackageMemberDeclarationProvider( storageManager, packageFqName, this, index.invoke().filesByPackage.get(packageFqName)); } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt index 255a921eafe..c73c7bcb3e7 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaPackageFragmentProvider.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.storage.MemoizedFunctionToNullable +import org.jetbrains.kotlin.storage.CacheWithNotNullValues class LazyJavaPackageFragmentProvider( components: JavaResolverComponents @@ -28,17 +28,16 @@ class LazyJavaPackageFragmentProvider( private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY, lazyOf(null)) - private val packageFragments: MemoizedFunctionToNullable = - c.storageManager.createMemoizedFunctionWithNullableValues { - fqName -> - val jPackage = c.components.finder.findPackage(fqName) - if (jPackage != null) { - LazyJavaPackageFragment(c, jPackage) - } - else null - } + private val packageFragments: CacheWithNotNullValues = + c.storageManager.createCacheWithNotNullValues() - private fun getPackageFragment(fqName: FqName) = packageFragments(fqName) + private fun getPackageFragment(fqName: FqName): LazyJavaPackageFragment? { + val jPackage = c.components.finder.findPackage(fqName) ?: return null + + return packageFragments.computeIfAbsent(fqName) { + LazyJavaPackageFragment(c, jPackage) + } + } override fun getPackageFragments(fqName: FqName) = listOfNotNull(getPackageFragment(fqName)) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt index fb0b5f89ccf..4f03ede358a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt @@ -57,7 +57,10 @@ class PluginDeclarationProviderFactory( } } - private fun packageExists(name: FqName): Boolean { + override fun packageExists(fqName: FqName) = + fileBasedDeclarationProviderFactory.packageExists(fqName) || stubBasedPackageExists(fqName) + + private fun stubBasedPackageExists(name: FqName): Boolean { return if (moduleInfo is ModuleSourceInfo) project.service().packageExists(name, moduleInfo) else @@ -65,7 +68,7 @@ class PluginDeclarationProviderFactory( } private fun getStubBasedPackageMemberDeclarationProvider(name: FqName): PackageMemberDeclarationProvider? { - if (!packageExists(name)) return null + if (!stubBasedPackageExists(name)) return null return StubBasedPackageMemberDeclarationProvider(name, project, indexedFilesScope) }