Perform tryLock-and-checkCanceled on waiting lock in LockBasedStorageManager

Relates to #KT-38012
This commit is contained in:
Vladimir Dolzhenko
2020-04-09 16:23:24 +02:00
parent 6fae29bcc0
commit b0483a67c2
7 changed files with 117 additions and 27 deletions
@@ -38,6 +38,8 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticsElementsCache
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.storage.CancellableSimpleLock
import org.jetbrains.kotlin.storage.guarded
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
@@ -54,6 +56,9 @@ internal class PerFileAnalysisCache(val file: KtFile, componentProvider: Compone
private val cache = HashMap<PsiElement, AnalysisResult>()
private var fileResult: AnalysisResult? = null
private val lock = ReentrantLock()
private val guardLock = CancellableSimpleLock(lock) {
ProgressIndicatorProvider.checkCanceled()
}
internal fun fetchAnalysisResults(element: KtElement): AnalysisResult? {
assert(element.containingKtFile == file) { "Wrong file. Expected $file, but was ${element.containingKtFile}" }
@@ -75,28 +80,23 @@ internal class PerFileAnalysisCache(val file: KtFile, componentProvider: Compone
val analyzableParent = KotlinResolveDataProvider.findAnalyzableParent(element)
lock.lock()
try {
ProgressIndicatorProvider.checkCanceled()
return guardLock.guarded {
// step 1: perform incremental analysis IF it is applicable
getIncrementalAnalysisResult()?.let { return it }
getIncrementalAnalysisResult()?.let { return@guarded it }
// cache does not contain AnalysisResult per each kt/psi element
// instead it looks up analysis for its parents - see lookUp(analyzableElement)
// step 2: return result if it is cached
lookUp(analyzableParent)?.let {
return it
return@guarded it
}
// step 3: perform analyze of analyzableParent as nothing has been cached yet
val result = analyze(analyzableParent)
cache[analyzableParent] = result
return result
} finally {
lock.unlock()
return@guarded result
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider
@@ -20,6 +21,8 @@ import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationList
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompositeBindingContext
import org.jetbrains.kotlin.storage.CancellableSimpleLock
import org.jetbrains.kotlin.storage.guarded
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import java.util.concurrent.locks.ReentrantLock
@@ -48,6 +51,10 @@ internal class ProjectResolutionFacade(
get() = globalContext.storageManager.compute { cachedValue.value }
private val analysisResultsLock = ReentrantLock()
private val analysisResultsSimpleLock = CancellableSimpleLock(analysisResultsLock) {
ProgressManager.checkCanceled()
}
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
{
val resolverForProject = cachedResolverForProject
@@ -142,13 +149,8 @@ internal class ProjectResolutionFacade(
internal fun getAnalysisResultsForElements(elements: Collection<KtElement>): AnalysisResult {
assert(elements.isNotEmpty()) { "elements collection should not be empty" }
val slruCache = run {
analysisResultsLock.lock()
try {
analysisResults.value!!
} finally {
analysisResultsLock.unlock()
}
val slruCache = analysisResultsSimpleLock.guarded {
analysisResults.value!!
}
val results = elements.map {
val perFileCache = slruCache[it.containingKtFile]
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.storage.ExceptionTracker
import org.jetbrains.kotlin.storage.LockBasedStorageManager
@@ -23,7 +24,9 @@ private fun GlobalContextImpl.contextWithCompositeExceptionTracker(debugName: St
private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(debugName: String): GlobalContextImpl {
val newExceptionTracker = CompositeExceptionTracker(this.exceptionTracker)
return GlobalContextImpl(
LockBasedStorageManager.createWithExceptionHandling(debugName, newExceptionTracker),
LockBasedStorageManager.createWithExceptionHandling(debugName, newExceptionTracker) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
},
newExceptionTracker
)
}