Optimization: introduce FirIdeResolveStateService to cache FirResolveState

This commit is contained in:
Mikhail Glukhikh
2019-08-01 12:25:25 +03:00
parent b4760bcbd3
commit d35a26a75b
4 changed files with 87 additions and 9 deletions
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.ModificationTracker
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.analyzer.TrackableModuleInfo
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
interface FirIdeResolveStateService {
companion object {
fun getInstance(project: Project): FirIdeResolveStateService =
ServiceManager.getService(project, FirIdeResolveStateService::class.java)!!
}
val fallbackModificationTracker: ModificationTracker?
fun getResolveState(moduleInfo: IdeaModuleInfo): FirResolveState
}
private class FirModuleData(val state: FirResolveState, val modificationTracker: ModificationTracker?) {
val modificationCount: Long = modificationTracker?.modificationCount ?: Long.MIN_VALUE
fun isOutOfDate(): Boolean {
val currentModCount = modificationTracker?.modificationCount
return currentModCount != null && currentModCount > modificationCount
}
}
class FirIdeResolveStateServiceImpl(val project: Project) : FirIdeResolveStateService {
private val stateCache = mutableMapOf<IdeaModuleInfo, FirModuleData>()
private fun createResolveState(): FirResolveState {
val provider = FirProjectSessionProvider(project)
return FirResolveStateImpl(provider)
}
private fun createModuleData(moduleInfo: IdeaModuleInfo): FirModuleData {
val state = createResolveState()
val modificationTracker = (moduleInfo as? TrackableModuleInfo)?.createModificationTracker() ?: fallbackModificationTracker
return FirModuleData(state, modificationTracker)
}
// TODO: multi thread protection
override fun getResolveState(moduleInfo: IdeaModuleInfo): FirResolveState {
var moduleData = stateCache.getOrPut(moduleInfo) {
createModuleData(moduleInfo)
}
if (moduleData.isOutOfDate()) {
moduleData = createModuleData(moduleInfo)
stateCache[moduleInfo] = moduleData
}
return moduleData.state
}
override val fallbackModificationTracker: ModificationTracker? =
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
}
@@ -58,12 +58,5 @@ class FirResolveStateImpl(override val sessionProvider: FirSessionProvider) : Fi
}
}
// TODO: caching
object FirIdeResolveFactory {
fun initiate(psi: KtElement): FirResolveState {
val provider = FirProjectSessionProvider(psi.project)
return FirResolveStateImpl(provider)
}
}
fun KtElement.firResolveState(): FirResolveState = FirIdeResolveFactory.initiate(this)
fun KtElement.firResolveState(): FirResolveState =
FirIdeResolveStateService.getInstance(project).getResolveState(getModuleInfo())
@@ -274,6 +274,9 @@
<projectService serviceInterface="org.jetbrains.kotlin.caches.resolve.KotlinCacheService"
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheServiceImpl"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.fir.FirIdeResolveStateService"
serviceImplementation="org.jetbrains.kotlin.idea.fir.FirIdeResolveStateServiceImpl"/>
<projectService serviceInterface="org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory"
serviceImplementation="org.jetbrains.kotlin.idea.vfilefinder.IDEVirtualFileFinderFactory"/>
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.fir
import org.jetbrains.kotlin.idea.AbstractResolveElementCacheTest
class FirResolveStateTest : AbstractResolveElementCacheTest() {
fun testSimpleStateCaching() {
doTest {
val firstStatement = statements[0]
val secondStatement = statements[1]
assertSame(firstStatement.firResolveState(), secondStatement.firResolveState())
}
}
}