From cbf78c729847763b747e8f5f39815349ffba351b Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 27 Jun 2016 18:56:38 +0300 Subject: [PATCH] KotlinCacheServiceImpl: create new locks when creating caches that delegate to other caches Remove single globalContext that was passed around to every configurations Correctly create exception trackers when delegating caches Delegate builtIns instance when delegating caches Create specialized JvmBuiltIns only if Sdk is specified --- .../caches/resolve/KotlinCacheServiceImpl.kt | 183 ++++++++++-------- .../caches/resolve/ModuleDependencyMapper.kt | 5 +- .../caches/resolve/ProjectResolutionFacade.kt | 12 +- .../idea/caches/resolve/globalContextUtils.kt | 30 +-- 4 files changed, 117 insertions(+), 113 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index fa4f7d8740d..34705e1bf31 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.context.GlobalContext import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider @@ -65,55 +66,69 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } } - private val globalContext = GlobalContext(logProcessCanceled = true) - // TODO: soft reference? // TODO: cache by script definition? private val facadeForScriptDependencies by lazy { - ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - "dependencies of scripts", - project, - JvmPlatform, // TODO: Js scripts? - null, // TODO: provide sdk via dependencies - commonGlobalContext = globalContext, - allModules = listOf(ScriptDependenciesModuleInfo(project)), - dependencies = listOf( - LibraryModificationTracker.getInstance(project), //TODO: provide correct trackers - ProjectRootModificationTracker.getInstance(project) - ), - moduleFilter = { true } - ) - } + val globalContext = GlobalContext() + ProjectResolutionFacade( + project, globalContext, + globalResolveSessionProvider( + "dependencies of scripts", + JvmPlatform, // TODO: Js scripts? + null, // TODO: provide sdk via dependencies + allModules = listOf(ScriptDependenciesModuleInfo(project)), + dependencies = listOf( + LibraryModificationTracker.getInstance(project), //TODO: provide correct trackers + ProjectRootModificationTracker.getInstance(project) + ), + moduleFilter = { true } + ) + ) } private inner class GlobalFacade(platform: TargetPlatform, sdk: Sdk?) { - val facadeForLibraries = ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - "project libraries for platform $platform", - project, - platform, - sdk, - commonGlobalContext = globalContext, - moduleFilter = { it.isLibraryClasses() }, - dependencies = listOf( - LibraryModificationTracker.getInstance(project), - ProjectRootModificationTracker.getInstance(project) - ) - ) - } + private val sdkContext = GlobalContext() + val facadeForSdk = ProjectResolutionFacade( + project, sdkContext, + globalResolveSessionProvider( + "sdk $sdk", + platform, + sdk, + moduleFilter = { it is SdkInfo }, + dependencies = listOf( + LibraryModificationTracker.getInstance(project), + ProjectRootModificationTracker.getInstance(project) + ) + )) - val facadeForModules = ProjectResolutionFacade(project, globalContext.storageManager) { - globalResolveSessionProvider( - "project source roots and libraries for platform $platform", - project, - platform, - sdk, - commonGlobalContext = globalContext, - reuseDataFrom = facadeForLibraries, - moduleFilter = { !it.isLibraryClasses() }, - dependencies = listOf(PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)) - } + private val librariesContext = sdkContext.contextWithNewLockAndCompositeExceptionTracker() + val facadeForLibraries = ProjectResolutionFacade( + project, librariesContext, + globalResolveSessionProvider( + "project libraries for platform $platform", + platform, + sdk, + reuseDataFrom = facadeForSdk, + moduleFilter = { it is LibraryInfo }, + dependencies = listOf( + LibraryModificationTracker.getInstance(project), + ProjectRootModificationTracker.getInstance(project) + ) + ) + ) + + + private val modulesContext = librariesContext.contextWithNewLockAndCompositeExceptionTracker() + val facadeForModules = ProjectResolutionFacade( + project, modulesContext, + globalResolveSessionProvider( + "project source roots and libraries for platform $platform", + platform, + sdk, + reuseDataFrom = facadeForLibraries, + moduleFilter = { !it.isLibraryClasses() }, + dependencies = listOf(PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)) + ) } @Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages") @@ -146,13 +161,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { fun makeGlobalResolveSessionProvider(reuseDataFrom: ProjectResolutionFacade? = null, moduleFilter: (IdeaModuleInfo) -> Boolean = { true }, allModules: Collection? = null - ): CachedValueProvider.Result { + ): (GlobalContextImpl, Project) -> CachedValueProvider.Result { return globalResolveSessionProvider( debugName, - project, targetPlatform, sdk, - commonGlobalContext = globalContext, syntheticFiles = files, reuseDataFrom = reuseDataFrom, moduleFilter = moduleFilter, @@ -164,30 +177,38 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { return when { syntheticFileModule is ModuleSourceInfo -> { val dependentModules = syntheticFileModule.getDependentModules() - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider( - reuseDataFrom = globalFacade(targetPlatform, sdk), - moduleFilter = { it in dependentModules }) - } + val modulesFacade = globalFacade(targetPlatform, sdk) + val globalContext = modulesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider( + reuseDataFrom = modulesFacade, + moduleFilter = { it in dependentModules }) + ) } syntheticFileModule is ScriptModuleInfo || syntheticFileModule is ScriptDependenciesModuleInfo -> { - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider( - reuseDataFrom = facadeForScriptDependencies, - allModules = listOf(syntheticFileModule) + syntheticFileModule.dependencies(), - moduleFilter = { it == syntheticFileModule } - ) - } + val globalContext = facadeForScriptDependencies.globalContext.contextWithNewLockAndCompositeExceptionTracker() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider( + reuseDataFrom = facadeForScriptDependencies, + moduleFilter = { it == syntheticFileModule }, + allModules = syntheticFileModule.dependencies() + ) + ) } syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> { - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider( - reuseDataFrom = librariesFacade(targetPlatform, sdk), - moduleFilter = { it == syntheticFileModule } - ) - } + val librariesFacade = librariesFacade(targetPlatform, sdk) + val globalContext = librariesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider( + reuseDataFrom = librariesFacade, + moduleFilter = { it == syntheticFileModule } + ) + ) } syntheticFileModule.isLibraryClasses() -> { @@ -195,9 +216,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { // currently the only known scenario is when we cannot determine that file is a library source // (file under both classes and sources root) LOG.warn("Creating cache with synthetic files ($files) in classes of library $syntheticFileModule") - ProjectResolutionFacade(project, globalContext.storageManager) { - makeGlobalResolveSessionProvider() - } + val globalContext = GlobalContext() + ProjectResolutionFacade( + project, globalContext, + makeGlobalResolveSessionProvider() + ) } else -> throw IllegalStateException("Unknown IdeaModuleInfo ${syntheticFileModule.javaClass}") @@ -278,40 +301,40 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private fun globalResolveSessionProvider( debugName: String, - project: Project, platform: TargetPlatform, sdk: Sdk?, dependencies: Collection, moduleFilter: (IdeaModuleInfo) -> Boolean, - commonGlobalContext: GlobalContextImpl, reuseDataFrom: ProjectResolutionFacade? = null, syntheticFiles: Collection = listOf(), allModules: Collection? = null // null means create resolvers for modules from idea model -): CachedValueProvider.Result { +): (GlobalContextImpl, Project) -> CachedValueProvider.Result = { globalContext, project -> val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject() - val globalContext = commonGlobalContext.withCompositeExceptionTrackerUnderSameLock() - val builtIns: KotlinBuiltIns = when (platform) { - is JsPlatform -> JsPlatform.builtIns - is JvmPlatform -> JvmBuiltIns(globalContext.storageManager) + val reusedBuiltIns = delegateResolverProvider?.builtIns + val newBuiltIns: KotlinBuiltIns? = when { + reusedBuiltIns != null -> null + platform is JsPlatform -> JsPlatform.builtIns + platform is JvmPlatform && sdk != null -> JvmBuiltIns(globalContext.storageManager) else -> DefaultBuiltIns.Instance } + val builtIns = reusedBuiltIns ?: newBuiltIns!! val moduleResolverProvider = createModuleResolverProvider( debugName, project, globalContext, sdk, AnalyzerFacadeProvider.getAnalyzerFacade(platform), syntheticFiles, delegateResolverForProject, moduleFilter, - allModules, builtIns + allModules, + builtIns ) - if (builtIns is JvmBuiltIns) { - val moduleInfoToUse = sdk?.let { SdkInfo(project, it) } ?: moduleResolverProvider.resolverForProject.allModules.firstOrNull() - if (moduleInfoToUse != null) { - builtIns.setOwnerModuleDescriptor(moduleResolverProvider.resolverForProject.descriptorForModule(moduleInfoToUse)) - } + if (newBuiltIns is JvmBuiltIns) { + val sdkInfo = SdkInfo(project, sdk!!) + newBuiltIns.setOwnerModuleDescriptor(moduleResolverProvider.resolverForProject.descriptorForModule(sdkInfo)) } val allDependencies = dependencies + listOf(moduleResolverProvider.exceptionTracker) - return CachedValueProvider.Result.create(moduleResolverProvider, allDependencies) + CachedValueProvider.Result.create(moduleResolverProvider, allDependencies) } + diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt index 55d724e36d0..d56a354a85f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt @@ -80,6 +80,7 @@ fun createModuleResolverProvider( return ModuleResolverProviderImpl( resolverForProject, + builtIns, globalContext ) } @@ -112,11 +113,13 @@ private fun collectAllModuleInfosFromIdeaModel(project: Project): List + val builtIns: KotlinBuiltIns } class ModuleResolverProviderImpl( override val resolverForProject: ResolverForProject, - val globalContext: GlobalContextImpl + override val builtIns: KotlinBuiltIns, + globalContext: GlobalContextImpl ) : ModuleResolverProvider { override val exceptionTracker: ExceptionTracker = globalContext.exceptionTracker } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt index a0b636ca955..f370a8e92cc 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import com.intellij.util.containers.SLRUCache import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.project.ResolveElementCache @@ -36,20 +37,19 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.storage.StorageManager internal class ProjectResolutionFacade( val project: Project, - private val storageManager: StorageManager, - computeModuleResolverProvider: () -> CachedValueProvider.Result + val globalContext: GlobalContextImpl, + computeModuleResolverProvider: (GlobalContextImpl, Project) -> CachedValueProvider.Result ) { private val cachedValue = CachedValuesManager.getManager(project).createCachedValue( - computeModuleResolverProvider, + { computeModuleResolverProvider(globalContext, project) }, /* trackValue = */ false ) val moduleResolverProvider: ModuleResolverProvider - get() = storageManager.compute { cachedValue.value } + get() = globalContext.storageManager.compute { cachedValue.value } fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = moduleResolverProvider.resolverForProject.resolverForModule(moduleInfo) fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt index 8b485da4671..b1d104ba1e2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/globalContextUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,15 +17,12 @@ package org.jetbrains.kotlin.idea.caches.resolve import org.jetbrains.kotlin.context.GlobalContextImpl -import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.ExceptionTracker -import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.diagnostic.Logger +import org.jetbrains.kotlin.storage.LockBasedStorageManager -fun GlobalContextImpl.withCompositeExceptionTrackerUnderSameLock(): GlobalContextImpl { +internal fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(): GlobalContextImpl { val newExceptionTracker = CompositeExceptionTracker(this.exceptionTracker) - val newStorageManager = LockBasedStorageManager.createDelegatingWithSameLock(this.storageManager, newExceptionTracker) - return GlobalContextImpl(newStorageManager, newExceptionTracker) + return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(newExceptionTracker), newExceptionTracker) } private class CompositeExceptionTracker(val delegate: ExceptionTracker) : ExceptionTracker() { @@ -33,22 +30,3 @@ private class CompositeExceptionTracker(val delegate: ExceptionTracker) : Except return super.getModificationCount() + delegate.modificationCount } } - -private class ExceptionTrackerWithProcessCanceledReport() : ExceptionTracker() { - override fun handleException(throwable: Throwable): RuntimeException { - if (throwable is ProcessCanceledException) { - LOG.info("ProcessCancelException was thrown while analyzing libraries. Cache has to be rebuilt.") - } - throw super.handleException(throwable) - } - - - companion object { - val LOG = Logger.getInstance(ExceptionTrackerWithProcessCanceledReport::class.java) - } -} - -fun GlobalContext(logProcessCanceled: Boolean): GlobalContextImpl { - val tracker = if (logProcessCanceled) ExceptionTrackerWithProcessCanceledReport() else ExceptionTracker() - return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(tracker), tracker) -}