[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 -> {
if (declaration.isSynthetic) {
declarationStorage.createIrFieldAndDelegatedMembers(declaration, parent as IrClass)
declarationStorage.createIrFieldAndDelegatedMembers(declaration, containingClass!!, parent as IrClass)
} else {
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(
signature: IdSignature?,
containerSource: DeserializedContainerSource?,
@@ -737,12 +741,16 @@ class Fir2IrDeclarationStorage(
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 createIrFieldAndDelegatedMembers(field: FirField, parent: IrClass): IrField {
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass<*>, irClass: IrClass): IrField {
val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE)
irField.setAndModifyParent(parent)
delegatedMemberGenerator.generate(irField, parent)
irField.setAndModifyParent(irClass)
delegatedMemberGenerator.generate(irField, owner, irClass)
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.buildValueParameterCopy
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.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -54,7 +55,7 @@ internal class DelegatedMemberGenerator(
) : Fir2IrComponents by components {
// 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 subClasses = mutableMapOf(delegateClass to mutableListOf(subClass))
DFS.dfs(
@@ -73,21 +74,50 @@ internal class DelegatedMemberGenerator(
)
for ((superClass, mayOverride) in subClasses) {
val classId = superClass.classId ?: continue
if (classId == irBuiltIns.anyClass.owner.classId) continue
val superClassId = superClass.classId ?: continue
if (superClassId == irBuiltIns.anyClass.owner.classId) continue
for (member in superClass.declarations) {
val delegatable = member.isDelegatable() && !DFS.ifAny(mayOverride, { subClasses[it] ?: emptyList() }) {
// Delegate to the most specific version of each member.
it.declarations.any { !it.isFakeOverride && it.overrides(member) }
}
if (!delegatable) continue
val scope = firSubClass.unsubstitutedScope(session, scopeSession)
if (member is IrSimpleFunction) {
val firFunction = declarationStorage.findOverriddenFirFunction(member, classId) ?: return
val function = generateDelegatedFunction(subClass, irField, member, firFunction)
subClass.addMember(function)
val firSuperFunction = declarationStorage.findOverriddenFirFunction(member, superClassId) ?: return
var firSubFunction: FirSimpleFunction? = null
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) {
val firProperty = declarationStorage.findOverriddenFirProperty(member, classId) ?: return
generateDelegatedProperty(subClass, irField, member, firProperty)
val firSuperProperty = declarationStorage.findOverriddenFirProperty(member, superClassId) ?: return
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,
superProperty: IrProperty,
firSuperProperty: FirProperty
) {
): IrProperty {
val startOffset = irField.startOffset
val endOffset = irField.endOffset
val descriptor = WrappedPropertyDescriptor()
val modality = if (superProperty.modality == Modality.ABSTRACT) Modality.OPEN else superProperty.modality
symbolTable.declareProperty(
return symbolTable.declareProperty(
startOffset, endOffset,
IrDeclarationOrigin.DELEGATED_MEMBER, descriptor, superProperty.isDelegated
) { symbol ->
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A<T> {
fun id(t: T): T
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A<T> {
var zzzValue : T
fun zzz() : T
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
@@ -1,6 +1,5 @@
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
// IGNORE_BACKEND_FIR: JVM_IR
inline class Wrapper(val id: Int)
@@ -1,5 +1,4 @@
// !LANGUAGE: -AdditionalBuiltInsMembers
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_JDK6
// TARGET_BACKEND: JVM
// WITH_RUNTIME
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Tr<T> {
val prop: T
}