[Analysis API] remove caches from KtFirScopeProvider

The hit-rate for this cache seems to be very law and it causes additional memory consumption

^KTIJ-22749
This commit is contained in:
Ilya Kirillov
2023-02-03 21:18:38 +01:00
committed by teamcity
parent b04b3d389f
commit 489ffc5acb
@@ -45,7 +45,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.addToStdlib.applyIf import org.jetbrains.kotlin.utils.addToStdlib.applyIf
import java.util.*
internal class KtFirScopeProvider( internal class KtFirScopeProvider(
override val analysisSession: KtFirAnalysisSession, override val analysisSession: KtFirAnalysisSession,
@@ -56,12 +55,6 @@ internal class KtFirScopeProvider(
// KtFirScopeProvider is thread local, so it's okay to use the same session here // KtFirScopeProvider is thread local, so it's okay to use the same session here
private val scopeSession = analysisSession.getScopeSessionFor(analysisSession.useSiteSession) private val scopeSession = analysisSession.getScopeSessionFor(analysisSession.useSiteSession)
private val memberScopeCache = IdentityHashMap<KtSymbolWithMembers, KtScope>()
private val declaredMemberScopeCache = IdentityHashMap<KtSymbolWithMembers, KtScope>()
private val delegatedMemberScopeCache = IdentityHashMap<KtSymbolWithMembers, KtScope>()
private val fileScopeCache = IdentityHashMap<KtFileSymbol, KtScope>()
private val packageMemberScopeCache = IdentityHashMap<KtPackageSymbol, KtScope>()
private inline fun <T> KtSymbolWithMembers.withFirForScope(crossinline body: (FirClass) -> T): T? { private inline fun <T> KtSymbolWithMembers.withFirForScope(crossinline body: (FirClass) -> T): T? {
return when (this) { return when (this) {
is KtFirNamedClassOrObjectSymbol -> body(firSymbol.fir) is KtFirNamedClassOrObjectSymbol -> body(firSymbol.fir)
@@ -78,19 +71,17 @@ internal class KtFirScopeProvider(
} }
override fun getMemberScope(classSymbol: KtSymbolWithMembers): KtScope { override fun getMemberScope(classSymbol: KtSymbolWithMembers): KtScope {
return memberScopeCache.getOrPut(classSymbol) { val firScope = classSymbol.withFirForScope { fir ->
val firScope = classSymbol.withFirForScope { fir -> fir.lazyResolveToPhase(FirResolvePhase.STATUS)
fir.lazyResolveToPhase(FirResolvePhase.STATUS) val firSession = analysisSession.useSiteSession
val firSession = analysisSession.useSiteSession fir.unsubstitutedScope(
fir.unsubstitutedScope( firSession,
firSession, scopeSession,
scopeSession, withForcedTypeCalculator = false
withForcedTypeCalculator = false )
) }?.applyIf(classSymbol is KtEnumEntrySymbol, ::EnumEntryContainingNamesAwareScope)
}?.applyIf(classSymbol is KtEnumEntrySymbol, ::EnumEntryContainingNamesAwareScope) ?: return getEmptyScope()
?: return@getOrPut getEmptyScope() return KtFirDelegatingScope(firScope, builder)
KtFirDelegatingScope(firScope, builder)
}
} }
override fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope { override fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope {
@@ -106,43 +97,37 @@ internal class KtFirScopeProvider(
} }
override fun getDeclaredMemberScope(classSymbol: KtSymbolWithMembers): KtScope { override fun getDeclaredMemberScope(classSymbol: KtSymbolWithMembers): KtScope {
return declaredMemberScopeCache.getOrPut(classSymbol) { val firScope = classSymbol.withFirForScope {
val firScope = classSymbol.withFirForScope { analysisSession.useSiteSession.declaredMemberScope(it)
analysisSession.useSiteSession.declaredMemberScope(it) } ?: return getEmptyScope()
} ?: return@getOrPut getEmptyScope()
KtFirDelegatingScope(firScope, builder) return KtFirDelegatingScope(firScope, builder)
}
} }
override fun getDelegatedMemberScope(classSymbol: KtSymbolWithMembers): KtScope { override fun getDelegatedMemberScope(classSymbol: KtSymbolWithMembers): KtScope {
val declaredScope = (getDeclaredMemberScope(classSymbol) as? KtFirDelegatingScope)?.firScope val declaredScope = (getDeclaredMemberScope(classSymbol) as? KtFirDelegatingScope)?.firScope
?: return delegatedMemberScopeCache.getOrPut(classSymbol) { getEmptyScope() } ?: return getEmptyScope()
return delegatedMemberScopeCache.getOrPut(classSymbol) { val firScope = classSymbol.withFirForScope { fir ->
val firScope = classSymbol.withFirForScope { fir -> fir.lazyResolveToPhase(FirResolvePhase.STATUS)
fir.lazyResolveToPhase(FirResolvePhase.STATUS) val delegateFields = fir.delegateFields
val delegateFields = fir.delegateFields if (delegateFields.isNotEmpty()) {
if (delegateFields.isNotEmpty()) { val firSession = analysisSession.useSiteSession
val firSession = analysisSession.useSiteSession FirDelegatedMemberScope(
FirDelegatedMemberScope( firSession,
firSession, scopeSession,
scopeSession, fir,
fir, declaredScope,
declaredScope, delegateFields
delegateFields )
) } else null
} else null } ?: return getEmptyScope()
} ?: return@getOrPut getEmptyScope()
KtFirDelegatedMemberScope(firScope, builder) return KtFirDelegatedMemberScope(firScope, builder)
}
} }
override fun getFileScope(fileSymbol: KtFileSymbol): KtScope { override fun getFileScope(fileSymbol: KtFileSymbol): KtScope {
return fileScopeCache.getOrPut(fileSymbol) {
check(fileSymbol is KtFirFileSymbol) { "KtFirScopeProvider can only work with KtFirFileSymbol, but ${fileSymbol::class} was provided" } check(fileSymbol is KtFirFileSymbol) { "KtFirScopeProvider can only work with KtFirFileSymbol, but ${fileSymbol::class} was provided" }
KtFirFileScope(fileSymbol, builder) return KtFirFileScope(fileSymbol, builder)
}
} }
override fun getEmptyScope(): KtScope { override fun getEmptyScope(): KtScope {
@@ -150,9 +135,7 @@ internal class KtFirScopeProvider(
} }
override fun getPackageScope(packageSymbol: KtPackageSymbol): KtScope { override fun getPackageScope(packageSymbol: KtPackageSymbol): KtScope {
return packageMemberScopeCache.getOrPut(packageSymbol) { return createPackageScope(packageSymbol.fqName)
createPackageScope(packageSymbol.fqName)
}
} }