[LL FIR] KT-58257 Implement active session invalidation

- This commit replaces session modification trackers with event-based
  session invalidation. The removal of modification trackers should
  improve overall performance, because session invalidation events
  happen less frequently than sessions are accessed. Getting rid of
  modification trackers also allows sessions to refer to other sessions
  lazily, which is essential when cyclic dependencies occur.
- The new `LLFirSession` validity tracker has constant complexity and
  will not cause the same kind of performance issues as dependency
  modification trackers. It is a bridge to support modification trackers
  in certain parts of the code (e.g. for `CachedValue`s), while being
  backed by event-based invalidation.
- `LLFirSessionInvalidationService` is the bridge between modification
  events and `LLFirSessionCache`. It finds out which modules should be
  invalidated and instructs the session cache to remove the associated
  sessions.
- Session invalidation must always happen in a write action to preserve
  consistency between sessions. Otherwise, while a session A is already
  removed from the cache, it might still be referenced by a dependent
  session B which is in the process of being invalidated. Such a session
  must never be returned from `getSession`.

^KT-57515 fixed
This commit is contained in:
Marco Pennekamp
2023-05-24 14:09:51 +02:00
committed by Space Team
parent 1f556589a2
commit e76692ef8d
20 changed files with 225 additions and 212 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.JvmFirD
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidationService
import org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization.JvmStubBasedDeserializedSymbolProviderFactory
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
@@ -56,6 +57,9 @@ object FirStandaloneServiceRegistrar : AnalysisApiStandaloneServiceRegistrar {
registerService(JvmFirDeserializedSymbolProviderFactory::class.java, JvmStubBasedDeserializedSymbolProviderFactory::class.java)
registerService(KotlinReferenceProviderContributor::class.java, KotlinFirReferenceContributor::class.java)
registerService(ReadWriteAccessChecker::class.java, ReadWriteAccessCheckerFirImpl::class.java)
registerService(LLFirSessionInvalidationService::class.java)
LLFirSessionInvalidationService.getInstance(project).subscribeToModificationEvents()
}
}
@@ -114,12 +114,13 @@ public class StandaloneAnalysisAPISessionBuilder(
) {
val project = kotlinCoreProjectEnvironment.project
project.apply {
registerService(KotlinMessageBusProvider::class.java, KotlinProjectMessageBusProvider::class.java)
FirStandaloneServiceRegistrar.registerProjectServices(project)
FirStandaloneServiceRegistrar.registerProjectExtensionPoints(project)
FirStandaloneServiceRegistrar.registerProjectModelServices(project, kotlinCoreProjectEnvironment.parentDisposable)
registerService(KotlinModificationTrackerFactory::class.java, KotlinStaticModificationTrackerFactory::class.java)
registerService(KotlinMessageBusProvider::class.java, KotlinProjectMessageBusProvider::class.java)
registerService(KotlinGlobalModificationService::class.java, KotlinStaticGlobalModificationService::class.java)
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())