Perform tryLock-and-checkCanceled on waiting lock in LockBasedStorageManager
Relates to #KT-38012
This commit is contained in:
+9
-9
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-7
@@ -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]
|
||||
|
||||
+4
-1
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user