From 51cd5fb5d82174cc3642e434bc1317bc57f59cb8 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 19 Jul 2022 18:45:10 +0200 Subject: [PATCH] [LL FIR] reuse source sessions --- .../api/fir/LLFirGlobalResolveComponents.kt | 2 -- .../level/api/fir/LLFirResolveStateService.kt | 27 ++++++++++++++----- .../LLFirNonUnderContentRootSessionFactory.kt | 2 +- .../sessions/LLFirSessionProviderStorage.kt | 26 +++++++++--------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirGlobalResolveComponents.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirGlobalResolveComponents.kt index c06c98037c4..811a5baf149 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirGlobalResolveComponents.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirGlobalResolveComponents.kt @@ -9,9 +9,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider import org.jetbrains.kotlin.analysis.project.structure.KtModule -@Suppress("unused") internal class LLFirGlobalResolveComponents( - val useSiteKtModule: KtModule, val project: Project, ) { val phaseRunner: LLFirPhaseRunner = LLFirPhaseRunner() diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt index 663f36e7862..4a873bb0e04 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/LLFirResolveStateService.kt @@ -10,16 +10,17 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ProjectRootModificationTracker import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession -import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.* +import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProviderStorage -import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolvableResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession +import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker import org.jetbrains.kotlin.analysis.utils.caches.strongCachedValue -import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.withLock internal class LLFirResolveSessionService(project: Project) { private val sessionProviderStorage = LLFirSessionProviderStorage(project) @@ -28,11 +29,22 @@ internal class LLFirResolveSessionService(project: Project) { project.createProjectWideOutOfBlockModificationTracker(), ProjectRootModificationTracker.getInstance(project), ) { - ConcurrentHashMap() + mutableMapOf() } - fun getFirResolveSession(module: KtModule): LLFirResolvableResolveSession = - stateCache.computeIfAbsent(module) { createFirResolveSessionFor(module, sessionProviderStorage) } + private val cacheLock = ReentrantReadWriteLock() + + fun getFirResolveSession(module: KtModule): LLFirResolvableResolveSession { + cacheLock.readLock().withLock { + stateCache[module]?.let { return it } + } + cacheLock.writeLock().withLock { + stateCache[module]?.let { return it } + val session = createFirResolveSessionFor(module, sessionProviderStorage) + stateCache[module] = session + return session + } + } companion object { fun getInstance(project: Project): LLFirResolveSessionService = @@ -54,6 +66,7 @@ internal class LLFirResolveSessionService(project: Project) { sessionProvider, ) } + is KtLibraryModule, is KtLibrarySourceModule -> { LLFirLibraryOrLibrarySourceResolvableResolveSession( useSiteSession.moduleComponents.globalResolveComponents, @@ -62,6 +75,7 @@ internal class LLFirResolveSessionService(project: Project) { sessionProvider, ) } + is KtNotUnderContentRootModule -> { LLFirNotUnderContentRootResolvableResolveSession( useSiteSession.moduleComponents.globalResolveComponents, @@ -70,6 +84,7 @@ internal class LLFirResolveSessionService(project: Project) { sessionProvider, ) } + else -> { error("Unexpected $useSiteKtModule") } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirNonUnderContentRootSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirNonUnderContentRootSessionFactory.kt index d4310aeda8f..030dbd95ea7 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirNonUnderContentRootSessionFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/LLFirNonUnderContentRootSessionFactory.kt @@ -54,7 +54,7 @@ internal class LLFirNonUnderContentRootSessionFactory(private val project: Proje val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(JvmPlatforms.unspecifiedJvmPlatform) val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) - val globalResolveComponents = LLFirGlobalResolveComponents(module, project) + val globalResolveComponents = LLFirGlobalResolveComponents(project) val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider) val contentScope = module.contentScope val session = LLFirNonUnderContentRootSession(module, project, components, builtinsSession.builtinTypes) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt index 2fa232fe7c3..6df3e916962 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionProviderStorage.kt @@ -11,30 +11,29 @@ import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toPersistentMap import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents +import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySessionFactory +import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirNonUnderContentRootSessionFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.firKtModuleBasedModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor import org.jetbrains.kotlin.analysis.low.level.api.fir.util.executeWithoutPCE import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker import java.util.concurrent.ConcurrentHashMap -import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory -import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirNonUnderContentRootSessionFactory class LLFirSessionProviderStorage(val project: Project) { - private val sessionsCache = ConcurrentHashMap() + private val sessionsCache = LLFirSessionsCache() private val librariesSessionFactory = LLFirLibrarySessionFactory.getInstance(project) - private val builtInsSessionFactopry = LLFirBuiltinsSessionFactory.getInstance(project) + private val builtInsSessionFactory = LLFirBuiltinsSessionFactory.getInstance(project) + + private val globalComponents = LLFirGlobalResolveComponents(project) fun getSessionProvider( useSiteKtModule: KtModule, configureSession: (LLFirSession.() -> Unit)? = null ): LLFirSessionProvider { - val globalComponents = LLFirGlobalResolveComponents(useSiteKtModule, project) - - val cache = sessionsCache.getOrPut(useSiteKtModule) { FromModuleViewSessionCache() } - val (sessions, session) = cache.withMappings(project) { mappings -> + val (sessions, session) = sessionsCache.withMappings(project) { mappings -> val sessions = mutableMapOf().apply { putAll(mappings) } val session = executeWithoutPCE { when (useSiteKtModule) { @@ -43,26 +42,29 @@ class LLFirSessionProviderStorage(val project: Project) { project, useSiteKtModule, globalComponents, - cache.sessionInvalidator, + sessionsCache.sessionInvalidator, sessions, librariesSessionFactory, configureSession = configureSession, ) } + is KtLibraryModule, is KtLibrarySourceModule -> { LLFirSessionFactory.createLibraryOrLibrarySourceResolvableSession( project, useSiteKtModule, globalComponents, - cache.sessionInvalidator, - builtInsSessionFactopry.getBuiltinsSession(useSiteKtModule.platform), + sessionsCache.sessionInvalidator, + builtInsSessionFactory.getBuiltinsSession(useSiteKtModule.platform), sessions, configureSession = configureSession, ) } + is KtNotUnderContentRootModule -> LLFirNonUnderContentRootSessionFactory.getInstance(project) .getNonUnderContentRootSession(useSiteKtModule, sessions) + else -> error("Unexpected ${useSiteKtModule::class.simpleName}") } @@ -74,7 +76,7 @@ class LLFirSessionProviderStorage(val project: Project) { } } -private class FromModuleViewSessionCache { +private class LLFirSessionsCache { @Volatile private var mappings: PersistentMap = persistentMapOf()