[FIR2IR] Cache delegatable members properly

This commit is contained in:
Mikhail Glukhikh
2020-08-25 09:57:33 +03:00
parent 1e712f8398
commit 3f5beb77e8
9 changed files with 52 additions and 20 deletions
@@ -217,7 +217,7 @@ class Fir2IrConverter(
} }
is FirField -> { is FirField -> {
if (declaration.isSynthetic) { if (declaration.isSynthetic) {
declarationStorage.createIrFieldAndDelegatedMembers(declaration, parent as IrClass) declarationStorage.createIrFieldAndDelegatedMembers(declaration, containingClass!!, parent as IrClass)
} else { } else {
throw AssertionError("Unexpected non-synthetic field: ${declaration::class}") throw AssertionError("Unexpected non-synthetic field: ${declaration::class}")
} }
@@ -370,6 +370,10 @@ class Fir2IrDeclarationStorage(
} }
} }
internal fun cacheIrSimpleFunction(function: FirSimpleFunction, irFunction: IrSimpleFunction) {
functionCache[function] = irFunction
}
internal fun declareIrSimpleFunction( internal fun declareIrSimpleFunction(
signature: IdSignature?, signature: IdSignature?,
containerSource: DeserializedContainerSource?, containerSource: DeserializedContainerSource?,
@@ -737,12 +741,16 @@ class Fir2IrDeclarationStorage(
fun getCachedIrProperty(property: FirProperty): IrProperty? = propertyCache[property] fun getCachedIrProperty(property: FirProperty): IrProperty? = propertyCache[property]
internal fun cacheIrProperty(property: FirProperty, irProperty: IrProperty) {
propertyCache[property] = irProperty
}
fun getCachedIrField(field: FirField): IrField? = fieldCache[field] fun getCachedIrField(field: FirField): IrField? = fieldCache[field]
fun createIrFieldAndDelegatedMembers(field: FirField, parent: IrClass): IrField { fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass<*>, irClass: IrClass): IrField {
val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE) val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE)
irField.setAndModifyParent(parent) irField.setAndModifyParent(irClass)
delegatedMemberGenerator.generate(irField, parent) delegatedMemberGenerator.generate(irField, owner, irClass)
return irField return irField
} }
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameterCopy import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameterCopy
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -54,7 +55,7 @@ internal class DelegatedMemberGenerator(
) : Fir2IrComponents by components { ) : Fir2IrComponents by components {
// Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type. // Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type.
fun generate(irField: IrField, subClass: IrClass) { fun generate(irField: IrField, firSubClass: FirClass<*>, subClass: IrClass) {
val delegateClass = (irField.type as IrSimpleTypeImpl).classOrNull?.owner ?: return val delegateClass = (irField.type as IrSimpleTypeImpl).classOrNull?.owner ?: return
val subClasses = mutableMapOf(delegateClass to mutableListOf(subClass)) val subClasses = mutableMapOf(delegateClass to mutableListOf(subClass))
DFS.dfs( DFS.dfs(
@@ -73,21 +74,50 @@ internal class DelegatedMemberGenerator(
) )
for ((superClass, mayOverride) in subClasses) { for ((superClass, mayOverride) in subClasses) {
val classId = superClass.classId ?: continue val superClassId = superClass.classId ?: continue
if (classId == irBuiltIns.anyClass.owner.classId) continue if (superClassId == irBuiltIns.anyClass.owner.classId) continue
for (member in superClass.declarations) { for (member in superClass.declarations) {
val delegatable = member.isDelegatable() && !DFS.ifAny(mayOverride, { subClasses[it] ?: emptyList() }) { val delegatable = member.isDelegatable() && !DFS.ifAny(mayOverride, { subClasses[it] ?: emptyList() }) {
// Delegate to the most specific version of each member. // Delegate to the most specific version of each member.
it.declarations.any { !it.isFakeOverride && it.overrides(member) } it.declarations.any { !it.isFakeOverride && it.overrides(member) }
} }
if (!delegatable) continue if (!delegatable) continue
val scope = firSubClass.unsubstitutedScope(session, scopeSession)
if (member is IrSimpleFunction) { if (member is IrSimpleFunction) {
val firFunction = declarationStorage.findOverriddenFirFunction(member, classId) ?: return val firSuperFunction = declarationStorage.findOverriddenFirFunction(member, superClassId) ?: return
val function = generateDelegatedFunction(subClass, irField, member, firFunction) var firSubFunction: FirSimpleFunction? = null
subClass.addMember(function) scope.processFunctionsByName(member.name) {
if (it.callableId.classId == firSubClass.classId) {
var overriddenFunctionSymbol = it.overriddenSymbol
while (overriddenFunctionSymbol != null) {
if (overriddenFunctionSymbol.fir == firSuperFunction) {
firSubFunction = it.fir as FirSimpleFunction
break
}
overriddenFunctionSymbol = overriddenFunctionSymbol.overriddenSymbol
}
}
}
val irSubFunction = generateDelegatedFunction(subClass, irField, member, firSuperFunction)
firSubFunction?.let { declarationStorage.cacheIrSimpleFunction(it, irSubFunction) }
subClass.addMember(irSubFunction)
} else if (member is IrProperty) { } else if (member is IrProperty) {
val firProperty = declarationStorage.findOverriddenFirProperty(member, classId) ?: return val firSuperProperty = declarationStorage.findOverriddenFirProperty(member, superClassId) ?: return
generateDelegatedProperty(subClass, irField, member, firProperty) var firSubProperty: FirProperty? = null
scope.processPropertiesByName(member.name) {
if (it.callableId.classId == firSubClass.classId) {
var overriddenPropertySymbol = it.overriddenSymbol
while (overriddenPropertySymbol != null) {
if (overriddenPropertySymbol.fir == firSuperProperty) {
firSubProperty = it.fir as FirProperty
break
}
overriddenPropertySymbol = overriddenPropertySymbol.overriddenSymbol
}
}
}
val irSubProperty = generateDelegatedProperty(subClass, irField, member, firSuperProperty)
firSubProperty?.let { declarationStorage.cacheIrProperty(it, irSubProperty) }
} }
} }
} }
@@ -305,12 +335,12 @@ internal class DelegatedMemberGenerator(
irField: IrField, irField: IrField,
superProperty: IrProperty, superProperty: IrProperty,
firSuperProperty: FirProperty firSuperProperty: FirProperty
) { ): IrProperty {
val startOffset = irField.startOffset val startOffset = irField.startOffset
val endOffset = irField.endOffset val endOffset = irField.endOffset
val descriptor = WrappedPropertyDescriptor() val descriptor = WrappedPropertyDescriptor()
val modality = if (superProperty.modality == Modality.ABSTRACT) Modality.OPEN else superProperty.modality val modality = if (superProperty.modality == Modality.ABSTRACT) Modality.OPEN else superProperty.modality
symbolTable.declareProperty( return symbolTable.declareProperty(
startOffset, endOffset, startOffset, endOffset,
IrDeclarationOrigin.DELEGATED_MEMBER, descriptor, superProperty.isDelegated IrDeclarationOrigin.DELEGATED_MEMBER, descriptor, superProperty.isDelegated
) { symbol -> ) { symbol ->
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A<T> { interface A<T> {
fun id(t: T): T fun id(t: T): T
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A<T> { interface A<T> {
var zzzValue : T var zzzValue : T
fun zzz() : T fun zzz() : T
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
@@ -1,6 +1,5 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME // WITH_RUNTIME
// IGNORE_BACKEND_FIR: JVM_IR
inline class Wrapper(val id: Int) inline class Wrapper(val id: Int)
@@ -1,5 +1,4 @@
// !LANGUAGE: -AdditionalBuiltInsMembers // !LANGUAGE: -AdditionalBuiltInsMembers
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_JDK6 // SKIP_JDK6
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Tr<T> { interface Tr<T> {
val prop: T val prop: T
} }