[FIR2IR] Extract logic of IR declarations generation into separate component. Part 13

Move almost all caching of created classifiers from Fir2IrClassifiersGenerator
  back to Fir2IrClassifierStorage
This commit is contained in:
Dmitriy Novozhilov
2023-08-29 14:52:22 +03:00
committed by Space Team
parent 26211a0277
commit 41fa276022
2 changed files with 65 additions and 83 deletions
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
@@ -80,15 +79,31 @@ class Fir2IrClassifierStorage(
for ((index, typeParameter) in owner.typeParameters.withIndex()) {
val original = typeParameter.symbol.fir
getCachedIrTypeParameter(original)
?: classifiersGenerator.createIrTypeParameterWithoutBounds(original, index, irOwnerSymbol)
?: createAndCacheIrTypeParameter(original, index, irOwnerSymbol)
if (owner is FirProperty && owner.isVar) {
val context = ConversionTypeOrigin.SETTER
getCachedIrTypeParameter(original, context)
?: classifiersGenerator.createIrTypeParameterWithoutBounds(original, index, irOwnerSymbol, context)
?: createAndCacheIrTypeParameter(original, index, irOwnerSymbol, context)
}
}
}
private fun createAndCacheIrTypeParameter(
typeParameter: FirTypeParameter,
index: Int,
ownerSymbol: IrSymbol,
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
): IrTypeParameter {
val irTypeParameter = classifiersGenerator.createIrTypeParameterWithoutBounds(typeParameter, index, ownerSymbol)
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
if (typeOrigin.forSetter) {
typeParameterCacheForSetter[typeParameter] = irTypeParameter
} else {
typeParameterCache[typeParameter] = irTypeParameter
}
return irTypeParameter
}
internal fun setTypeParameters(
irOwner: IrTypeParametersContainer,
owner: FirTypeParameterRefsOwner,
@@ -140,7 +155,9 @@ class Fir2IrClassifierStorage(
typeAlias: FirTypeAlias,
parent: IrDeclarationParent
): IrTypeAlias {
return classifiersGenerator.createIrTypeAlias(typeAlias, parent)
return classifiersGenerator.createIrTypeAlias(typeAlias, parent).also {
typeAliasCache[typeAlias] = it
}
}
internal fun getCachedTypeAlias(firTypeAlias: FirTypeAlias): IrTypeAlias? = typeAliasCache[firTypeAlias]
@@ -150,7 +167,13 @@ class Fir2IrClassifierStorage(
parent: IrDeclarationParent,
predefinedOrigin: IrDeclarationOrigin? = null
): IrClass {
return classifiersGenerator.createIrClass(regularClass, parent, predefinedOrigin)
return classifiersGenerator.createIrClass(regularClass, parent, predefinedOrigin).also {
if (regularClass.visibility == Visibilities.Local) {
localStorage[regularClass] = it
} else {
classCache[regularClass] = it
}
}
}
fun createAndCacheAnonymousObject(
@@ -159,11 +182,22 @@ class Fir2IrClassifierStorage(
name: Name = SpecialNames.NO_NAME_PROVIDED,
irParent: IrDeclarationParent? = null
): IrClass {
return classifiersGenerator.createAnonymousObject(anonymousObject, visibility, name, irParent)
return classifiersGenerator.createAnonymousObject(anonymousObject, visibility, name, irParent).also {
localStorage[anonymousObject] = it
}
}
fun createAndCacheCodeFragmentClass(codeFragment: FirCodeFragment, containingFile: IrFile): IrClass {
return classifiersGenerator.createCodeFragmentClass(codeFragment, containingFile)
return classifiersGenerator.createCodeFragmentClass(codeFragment, containingFile).also {
codeFragmentCache[codeFragment] = it
}
}
fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
localStorage[anonymousObject]?.let { return it }
val irAnonymousObject = classifierStorage.createAndCacheAnonymousObject(anonymousObject, Visibilities.Private, name, irParent)
classifiersGenerator.processClassHeader(anonymousObject, irAnonymousObject)
return irAnonymousObject
}
internal fun getCachedIrTypeParameter(
@@ -183,7 +217,9 @@ class Fir2IrClassifierStorage(
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT
): IrTypeParameter {
getCachedIrTypeParameter(typeParameter, typeOrigin)?.let { return it }
return classifiersGenerator.createIrTypeParameterWithBounds(typeParameter, index, ownerSymbol, typeOrigin)
val irTypeParameter = createAndCacheIrTypeParameter(typeParameter, index, ownerSymbol, typeOrigin)
classifiersGenerator.initializeTypeParameterBounds(typeParameter, irTypeParameter)
return irTypeParameter
}
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
@@ -212,7 +248,9 @@ class Fir2IrClassifierStorage(
enumEntry,
irParent = irParent,
predefinedOrigin = predefinedOrigin
)
).also {
enumEntryCache[enumEntry] = it
}
}
@OptIn(IrSymbolInternals::class)
@@ -247,9 +285,23 @@ class Fir2IrClassifierStorage(
}
if (components.configuration.allowNonCachedDeclarations) {
return classifiersGenerator.createIrTypeParameterForNonCachedDeclaration(firTypeParameter)
return createIrTypeParameterForNonCachedDeclaration(firTypeParameter)
}
error("Cannot find cached type parameter by FIR symbol: ${firTypeParameterSymbol.name} of the owner: ${firTypeParameter.containingDeclarationSymbol}")
}
private fun createIrTypeParameterForNonCachedDeclaration(firTypeParameter: FirTypeParameter): IrTypeParameterSymbol {
val firTypeParameterOwnerSymbol = firTypeParameter.containingDeclarationSymbol
val firTypeParameterOwner = firTypeParameterOwnerSymbol.fir as FirTypeParameterRefsOwner
val index = firTypeParameterOwner.typeParameters.indexOf(firTypeParameter).also { check(it >= 0) }
val isSetter = firTypeParameterOwner is FirPropertyAccessor && firTypeParameterOwner.isSetter
val conversionTypeOrigin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
return createAndCacheIrTypeParameter(firTypeParameter, index, IrTypeParameterSymbolImpl(), conversionTypeOrigin).also {
classifiersGenerator.initializeTypeParameterBounds(firTypeParameter, it)
}.symbol
}
}
@@ -215,7 +215,6 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
parent.declarations += this
}
}
typeAliasCache[typeAlias] = irTypeAlias
irTypeAlias
}
}
@@ -265,11 +264,6 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
}
}
irClass.parent = parent
if (regularClass.visibility == Visibilities.Local) {
localStorage[regularClass] = irClass
} else {
classCache[regularClass] = irClass
}
return irClass
}
@@ -298,7 +292,6 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
if (irParent != null) {
irAnonymousObject.parent = irParent
}
localStorage[anonymousObject] = irAnonymousObject
return irAnonymousObject
}
@@ -336,33 +329,17 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
}
}
}
codeFragmentCache[codeFragment] = irClass
return irClass
}
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
localStorage[anonymousObject]?.let { return it }
val irAnonymousObject = classifierStorage.createAndCacheAnonymousObject(anonymousObject, Visibilities.Private, name, irParent)
processClassHeader(anonymousObject, irAnonymousObject)
return irAnonymousObject
}
fun createIrTypeParameterWithBounds(
typeParameter: FirTypeParameter,
index: Int,
ownerSymbol: IrSymbol,
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
): IrTypeParameter {
val irTypeParameter = createIrTypeParameterWithoutBounds(typeParameter, index, ownerSymbol, typeOrigin)
fun initializeTypeParameterBounds(typeParameter: FirTypeParameter, irTypeParameter: IrTypeParameter) {
irTypeParameter.superTypes = typeParameter.bounds.map { it.toIrType() }
return irTypeParameter
}
fun createIrTypeParameterWithoutBounds(
typeParameter: FirTypeParameter,
index: Int,
ownerSymbol: IrSymbol,
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
): IrTypeParameter {
require(index >= 0)
val origin = typeParameter.computeIrOrigin()
@@ -417,13 +394,6 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
)
}
}
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
if (typeOrigin.forSetter) {
typeParameterCacheForSetter[typeParameter] = irTypeParameter
} else {
typeParameterCache[typeParameter] = irTypeParameter
}
annotationGenerator.generate(irTypeParameter, typeParameter)
return irTypeParameter
}
@@ -442,7 +412,7 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
): IrEnumEntry {
return enumEntry.convertWithOffsets { startOffset, endOffset ->
val signature = signatureComposer.composeSignature(enumEntry)
val result = declareIrEnumEntry(signature) { symbol ->
declareIrEnumEntry(signature) { symbol ->
val origin = enumEntry.computeIrOrigin(predefinedOrigin)
irFactory.createEnumEntry(
startOffset = startOffset,
@@ -459,7 +429,7 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
// An enum entry with its own members requires an anonymous object generated.
// Otherwise, this is a default-ish enum entry whose initializer would be a delegating constructor call,
// which will be translated via visitor later.
val klass = getIrAnonymousObjectForEnumEntry(
val klass = classifierStorage.getIrAnonymousObjectForEnumEntry(
(enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject, enumEntry.name, irParent
)
this.correspondingClass = klass
@@ -467,8 +437,6 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
declarationStorage.leaveScope(this.symbol)
}
}
enumEntryCache[enumEntry] = result
result
}
}
@@ -508,44 +476,6 @@ class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrCompo
}
}
// TODO: should be decomposed
fun createIrClassSymbolByFirSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
val firClass = firClassSymbol.fir
classifierStorage.getCachedIrClass(firClass)?.let { return it.symbol }
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.Local) {
return createLocalIrClassOnTheFly(firClass).symbol
}
firClass as FirRegularClass
val classId = firClassSymbol.classId
val parentId = classId.outerClassId
val parentClass = parentId?.let { session.symbolProvider.getClassLikeSymbolByClassId(it) }
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentClass?.toLookupTag(), firClassSymbol, firClass.origin)!!
// firClass may be referenced by some parent's type parameters as a bound. In that case, getIrClassSymbol will be called recursively.
classifierStorage.getCachedIrClass(firClass)?.let { return it.symbol }
val irClass = lazyDeclarationsGenerator.createIrLazyClass(firClass, irParent)
classCache[firClass] = irClass
// NB: this is needed to prevent recursions in case of self bounds
(irClass as Fir2IrLazyClass).prepareTypeParameters()
return irClass.symbol
}
fun createIrTypeParameterForNonCachedDeclaration(firTypeParameter: FirTypeParameter): IrTypeParameterSymbol {
val firTypeParameterOwnerSymbol = firTypeParameter.containingDeclarationSymbol
val firTypeParameterOwner = firTypeParameterOwnerSymbol.fir as FirTypeParameterRefsOwner
val index = firTypeParameterOwner.typeParameters.indexOf(firTypeParameter).also { check(it >= 0) }
val isSetter = firTypeParameterOwner is FirPropertyAccessor && firTypeParameterOwner.isSetter
val conversionTypeOrigin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
return createIrTypeParameterWithoutBounds(firTypeParameter, index, IrTypeParameterSymbolImpl(), conversionTypeOrigin).apply {
superTypes = firTypeParameter.bounds.map { it.toIrType(typeConverter) }
}.symbol
}
private val temporaryParent by lazy {
irFactory.createSimpleFunction(
startOffset = UNDEFINED_OFFSET,