From b270d66f6826426edfef063c3bdd2b02bd0f7071 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 19 Jan 2021 17:15:43 +0100 Subject: [PATCH] FIR: use FirCachesFactory for class cache in KotlinDeserializedJvmSymbolsProvider --- .../KotlinDeserializedJvmSymbolsProvider.kt | 72 +++++++++++-------- .../api/sessions/FirIdeSessionFactory.kt | 1 - 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index 31e2d300ca9..eed93a2ec38 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -10,7 +10,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.ThreadSafeMutableState -import org.jetbrains.kotlin.fir.caches.firCachesFactory +import org.jetbrains.kotlin.fir.caches.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext @@ -50,14 +50,22 @@ class KotlinDeserializedJvmSymbolsProvider( private val kotlinScopeProvider: KotlinScopeProvider, ) : FirSymbolProvider(session) { private val annotationsLoader = AnnotationsLoader(session) - private val classCache = SymbolProviderCache() private val typeAliasCache = SymbolProviderCache() private val packagePartsCache = SymbolProviderCache>() + private val classCache = + session.firCachesFactory.createCacheWithPostCompute( + createValue = { classId, context -> findAndDeserializeClass(classId, context) }, + postCompute = { _, symbol, result -> + if (result != null && symbol != null) { + postCompute(result.kotlinJvmBinaryClass, result.byteContent, symbol) + } + } + ) + + private val knownNameInPackageCache = KnownNameInPackageCache(session, javaClassFinder) - // TODO: implement thread safety for this property - private val handledByJava = HashSet() private class PackagePartsCacheData( val proto: ProtoBuf.Package, @@ -123,7 +131,7 @@ class KotlinDeserializedJvmSymbolsProvider( get() = classHeader.isPreRelease override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? { - return findAndDeserializeClass(classId) ?: findAndDeserializeTypeAlias(classId) + return getClass(classId) ?: findAndDeserializeTypeAlias(classId) } private fun findAndDeserializeTypeAlias( @@ -149,53 +157,58 @@ class KotlinDeserializedJvmSymbolsProvider( private fun findAndDeserializeClassViaParent(classId: ClassId): FirRegularClassSymbol? { val outerClassId = classId.outerClassId ?: return null - findAndDeserializeClass(outerClassId) ?: return null - return classCache[classId] + getClass(outerClassId) ?: return null + return classCache.getValueIfComputed(classId) + } + + private fun getClass( + classId: ClassId, + parentContext: FirDeserializationContext? = null + ): FirRegularClassSymbol? { + return classCache.getValue(classId, parentContext) } private fun findAndDeserializeClass( classId: ClassId, parentContext: FirDeserializationContext? = null - ): FirRegularClassSymbol? { - if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null - if (classId in classCache) return classCache[classId] - - if (classId in handledByJava) return null - + ): Pair { + if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null to null val result = try { kotlinClassFinder.findKotlinClassOrContent(classId) } catch (e: ProcessCanceledException) { - return null + return null to null } - val (kotlinJvmBinaryClass, byteContent) = when (result) { + val kotlinClass = when (result) { is KotlinClassFinder.Result.KotlinClass -> result is KotlinClassFinder.Result.ClassFileContent -> { - handledByJava.add(classId) - return try { - javaSymbolProvider.getFirJavaClass(classId, result) - } catch (e: ProcessCanceledException) { - null - } + return javaSymbolProvider.getFirJavaClass(classId, result) to null } - null -> return findAndDeserializeClassViaParent(classId) + null -> return findAndDeserializeClassViaParent(classId) to null } - if (kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null - val (nameResolver, classProto) = kotlinJvmBinaryClass.readClassDataFrom() ?: return null + if (kotlinClass.kotlinJvmBinaryClass.classHeader.kind != KotlinClassHeader.Kind.CLASS) return null to null + val (nameResolver, classProto) = kotlinClass.kotlinJvmBinaryClass.readClassDataFrom() ?: return null to null if (parentContext == null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.COMPANION_OBJECT) { - return findAndDeserializeClassViaParent(classId) + return findAndDeserializeClassViaParent(classId) to null } val symbol = FirRegularClassSymbol(classId) deserializeClassToSymbol( classId, classProto, symbol, nameResolver, session, - JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent), + JvmBinaryAnnotationDeserializer(session, kotlinClass.kotlinJvmBinaryClass, kotlinClass.byteContent), kotlinScopeProvider, - parentContext, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass), - this::findAndDeserializeClass + parentContext, KotlinJvmBinarySourceElement(kotlinClass.kotlinJvmBinaryClass), + this::getClass ) - classCache[classId] = symbol + return symbol to kotlinClass + } + + fun postCompute( + kotlinJvmBinaryClass: KotlinJvmBinaryClass, + byteContent: ByteArray?, + symbol: FirRegularClassSymbol + ) { val annotations = mutableListOf() kotlinJvmBinaryClass.loadClassAnnotations( object : KotlinJvmBinaryClass.AnnotationVisitor { @@ -209,7 +222,6 @@ class KotlinDeserializedJvmSymbolsProvider( byteContent, ) (symbol.fir.annotations as MutableList) += annotations - return symbol } private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index c7ee4898822..c4dcfb42c2f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -38,7 +38,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.fir.caches.FirThreadSafeCache import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirModuleWithDependenciesSymbolProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider -import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionFactory.registerIdeComponents import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirThreadSafeSymbolProviderWrapper import org.jetbrains.kotlin.idea.fir.low.level.api.util.ModuleLibrariesSearchScope import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled