diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt index 19a54548d98..1f611d99620 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt @@ -34,23 +34,20 @@ class FirJavaModuleBasedSession( init { sessionProvider.sessionCache[moduleInfo] = this - _firSymbolProvider = FirCompositeSymbolProvider( - listOf( - service(), - JavaSymbolProvider(this, sessionProvider.project, scope), - dependenciesProvider ?: FirDependenciesSymbolProviderImpl(this) - ) - ) - registerComponent( FirSymbolProvider::class, - _firSymbolProvider as FirSymbolProvider + FirCompositeSymbolProvider( + listOf( + service(), + JavaSymbolProvider(this, sessionProvider.project, scope), + dependenciesProvider ?: FirDependenciesSymbolProviderImpl(this) + ) + ) as FirSymbolProvider ) - _correspondingSupertypesCache = FirCorrespondingSupertypesCache(this) registerComponent( FirCorrespondingSupertypesCache::class, - _correspondingSupertypesCache as FirCorrespondingSupertypesCache + FirCorrespondingSupertypesCache(this) ) } } @@ -68,7 +65,9 @@ class FirLibrarySession private constructor( init { sessionProvider.sessionCache[moduleInfo] = this val javaSymbolProvider = JavaSymbolProvider(this, sessionProvider.project, scope) - _firSymbolProvider = + + registerComponent( + FirSymbolProvider::class, FirCompositeSymbolProvider( listOf( FirLibrarySymbolProviderImpl(this), @@ -82,18 +81,13 @@ class FirLibrarySession private constructor( javaSymbolProvider, FirDependenciesSymbolProviderImpl(this) ) - ) - - registerComponent( - FirSymbolProvider::class, - _firSymbolProvider as FirSymbolProvider + ) as FirSymbolProvider ) registerComponent(FirClassDeclaredMemberScopeProvider::class, FirClassDeclaredMemberScopeProvider()) - _correspondingSupertypesCache = FirCorrespondingSupertypesCache(this) registerComponent( FirCorrespondingSupertypesCache::class, - _correspondingSupertypesCache as FirCorrespondingSupertypesCache + FirCorrespondingSupertypesCache(this) ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt index bb9fb0e18cd..a95e55be747 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.resolve import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.declarations.toFirClassLike import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction @@ -17,7 +18,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -abstract class FirSymbolProvider { +abstract class FirSymbolProvider : FirSessionComponent { abstract fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 5c593bc756d..3b03a26df28 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.resolve import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.componentArrayAccessor import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier @@ -36,9 +38,8 @@ inline fun MutableMap.getOrPut(key: K, defaultValue: (K) -> } } -val FirSession.firSymbolProvider: FirSymbolProvider get() = _firSymbolProvider as FirSymbolProvider? ?: service() -val FirSession.correspondingSupertypesCache: FirCorrespondingSupertypesCache - get() = _correspondingSupertypesCache as FirCorrespondingSupertypesCache? ?: service() +val FirSession.firSymbolProvider: FirSymbolProvider by componentArrayAccessor() +val FirSession.correspondingSupertypesCache: FirCorrespondingSupertypesCache by componentArrayAccessor() fun ConeClassLikeLookupTag.toSymbol(useSiteSession: FirSession): ConeClassifierSymbol? { val firSymbolProvider = useSiteSession.firSymbolProvider diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/FirCorrespondingSupertypesCache.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/FirCorrespondingSupertypesCache.kt index ca8c08b428d..8948c82f02d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/FirCorrespondingSupertypesCache.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/FirCorrespondingSupertypesCache.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.declarations.toFirClassLike import org.jetbrains.kotlin.fir.resolve.constructClassType import org.jetbrains.kotlin.fir.resolve.constructType @@ -16,7 +17,7 @@ import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.types.model.SimpleTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker -class FirCorrespondingSupertypesCache(private val session: FirSession) { +class FirCorrespondingSupertypesCache(private val session: FirSession) : FirSessionComponent { private val context = ConeTypeCheckerContext(false, session) private val cache = HashMap>?>(1000, 0.5f) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt index d40e9697eec..eb54ec2c753 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt @@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.utils.Jsr305State +import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KClass +import kotlin.reflect.KProperty abstract class FirSession(val sessionProvider: FirSessionProvider?) { open val moduleInfo: ModuleInfo? get() = null @@ -17,16 +19,21 @@ abstract class FirSession(val sessionProvider: FirSessionProvider?) { val components: MutableMap, Any> = mutableMapOf() - var _firSymbolProvider: Any? = null - - var _correspondingSupertypesCache: Any? = null + internal val componentArray = ComponentArray() + @Suppress("UNCHECKED_CAST") fun getService(kclass: KClass): T = components[kclass] as T - protected fun registerComponent(tClass: KClass, t: T) { + protected fun registerComponent(tClass: KClass, t: T) { assert(tClass !in components) { "Already registered component" } components[tClass] = t + + // TODO: Make t of FirSessionComponent + if (t is FirSessionComponent) { + @Suppress("UNCHECKED_CAST") + componentArray[(tClass as KClass).componentId()] = t + } } } @@ -36,3 +43,51 @@ interface FirSessionProvider { inline fun FirSession.service(): T = getService(T::class) + +internal object ComponentTypeRegistry { + private val idPerType = mutableMapOf, Int>() + + fun id(kClass: KClass): Int { + return idPerType.getOrPut(kClass) { idPerType.size } + } +} + + +private fun KClass.componentId(): Int { + return ComponentTypeRegistry.id(this) +} + + +class ComponentArrayAccessor(val type: KClass) : ReadOnlyProperty { + val id: Int = type.componentId() + override fun getValue(thisRef: FirSession, property: KProperty<*>): T { + @Suppress("UNCHECKED_CAST") + return thisRef.componentArray.getOrNull(id) as? T ?: error("No '$type'($id) component in session: $thisRef") + } +} + +inline fun componentArrayAccessor(): ComponentArrayAccessor { + return ComponentArrayAccessor(T::class) +} + +interface FirSessionComponent + +internal class ComponentArray : AbstractList() { + override val size: Int + get() = data.size + private var data = arrayOfNulls(20) + private fun ensureCapacity(index: Int) { + if (data.size < index) { + data = data.copyOf(data.size * 2) + } + } + + operator fun set(index: Int, value: FirSessionComponent) { + ensureCapacity(index) + data[index] = value + } + + override operator fun get(index: Int): FirSessionComponent? { + return data[index] + } +} \ No newline at end of file