From 9f26f8f22700adaf89afcad902d76eef3ce6bff3 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Fri, 5 Aug 2022 11:24:41 +0300 Subject: [PATCH] [K/N][IR] Refactored outer this field creation --- .../jetbrains/kotlin/backend/konan/Context.kt | 104 ++++++------------ .../backend/konan/KonanBackendContext.kt | 2 +- .../kotlin/backend/konan/ToplevelPhases.kt | 4 +- .../konan/descriptors/ClassLayoutBuilder.kt | 2 +- .../backend/konan/lower/InnerClassLowering.kt | 34 +++++- .../konan/serialization/KonanIrlinker.kt | 2 +- 6 files changed, 69 insertions(+), 79 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 877a30e55b0..844b0de81f2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -6,56 +6,56 @@ package org.jetbrains.kotlin.backend.konan import llvm.* +import org.jetbrains.kotlin.backend.common.DefaultDelegateFactory +import org.jetbrains.kotlin.backend.common.DefaultMapping import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.KonanIr -import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.backend.konan.llvm.* +import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD +import org.jetbrains.kotlin.backend.konan.lower.InnerClassesSupport +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.optimizations.DevirtualizationAnalysis import org.jetbrains.kotlin.backend.konan.optimizations.ExternalModulesDFG import org.jetbrains.kotlin.backend.konan.optimizations.ModuleDFG -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.types.IrTypeSystemContext -import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl -import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl -import org.jetbrains.kotlin.konan.target.CompilerOutputKind -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.descriptorUtil.module -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver -import java.lang.System.out -import kotlin.LazyThreadSafetyMode.PUBLICATION -import kotlin.reflect.KProperty -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport -import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields import org.jetbrains.kotlin.backend.konan.serialization.SerializedInlineFunctionReference +import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass import org.jetbrains.kotlin.ir.deepCopyWithVariables import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl +import org.jetbrains.kotlin.ir.types.IrTypeSystemContext +import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.konan.library.KonanLibraryLayout import org.jetbrains.kotlin.konan.target.Architecture +import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.library.SerializedIrModule -import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal -import org.jetbrains.kotlin.konan.library.KonanLibraryLayout +import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import java.lang.System.out +import kotlin.LazyThreadSafetyMode.PUBLICATION +import kotlin.reflect.KProperty + +internal class NativeMapping : DefaultMapping() { + val outerThisFields = DefaultDelegateFactory.newDeclarationToDeclarationMapping() +} internal class InlineFunctionOriginInfo(val irFunction: IrFunction, val irFile: IrFile, val startOffset: Int, val endOffset: Int) @@ -65,7 +65,6 @@ internal class InlineFunctionOriginInfo(val irFunction: IrFunction, val irFile: internal class SpecialDeclarationsFactory(val context: Context) { private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } - private val outerThisFields = mutableMapOf() private val internalLoweredEnums = mutableMapOf() private val externalLoweredEnums = mutableMapOf() @@ -81,46 +80,6 @@ internal class SpecialDeclarationsFactory(val context: Context) { } } - object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS : - IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") - - fun getOuterThisField(innerClass: IrClass): IrField { - assert(innerClass.isInner) { "Class is not inner: ${innerClass.render()}" } - return outerThisFields.getOrPut(innerClass) { - val outerClass = innerClass.parent as? IrClass - ?: throw AssertionError("No containing class for inner class ${innerClass.descriptor}") - - val receiver = ReceiverParameterDescriptorImpl( - innerClass.descriptor, - ImplicitClassReceiver(innerClass.descriptor, null), - Annotations.EMPTY - ) - val descriptor = PropertyDescriptorImpl.create( - innerClass.descriptor, Annotations.EMPTY, Modality.FINAL, - DescriptorVisibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE, false, false, false, false, false, false - ).apply { - this.setType(outerClass.descriptor.defaultType, emptyList(), receiver, null, emptyList()) - initialize(null, null) - } - - IrFieldImpl( - startOffset = innerClass.startOffset, - endOffset = innerClass.endOffset, - origin = DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS, - symbol = IrFieldSymbolImpl(descriptor), - name = descriptor.name, - type = outerClass.defaultType, - visibility = descriptor.visibility, - isFinal = !descriptor.isVar, - isExternal = descriptor.isEffectivelyExternal(), - isStatic = descriptor.dispatchReceiverParameter == null - ).apply { - parent = innerClass - } - } - } - fun getLoweredEnumOrNull(enumClass: IrClass): LoweredEnumAccess? { assert(enumClass.kind == ClassKind.ENUM_CLASS) { "Expected enum class but was: ${enumClass.descriptor}" } return if (!context.llvmModuleSpecification.containsDeclaration(enumClass)) { @@ -245,6 +204,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { } val specialDeclarationsFactory = SpecialDeclarationsFactory(this) + val innerClassesSupport by lazy { InnerClassesSupport(mapping, irFactory) } open class LazyMember(val initializer: Context.() -> T) { operator fun getValue(thisRef: Context, property: KProperty<*>): T = thisRef.getValue(this) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt index 6806f3a06bd..87ba25b03a7 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt @@ -49,7 +49,7 @@ internal abstract class KonanBackendContext(val config: KonanConfig) : CommonBac override val internalPackageFqn = KonanFqNames.internalPackageName - override val mapping: Mapping = DefaultMapping() + override val mapping: NativeMapping = NativeMapping() override val irFactory: IrFactory = IrFactoryImpl } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index fbc2bf095b8..8669f7014e1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -421,7 +421,7 @@ internal val exportInternalAbiPhase = makeKonanModuleOpPhase( function.body = irBlockBody { +irReturn(irGetField( irGet(function.valueParameters[0]), - context.specialDeclarationsFactory.getOuterThisField(declaration)) + context.innerClassesSupport.getOuterThisField(declaration)) ) } } @@ -507,7 +507,7 @@ internal val useInternalAbiPhase = makeKonanModuleOpPhase( return when { context.llvmModuleSpecification.containsDeclaration(field) -> expression - irClass?.isInner == true && context.specialDeclarationsFactory.getOuterThisField(irClass) == field -> { + irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> { val accessor = outerThisAccessors.getOrPut(irClass) { context.irFactory.buildFun { name = InternalAbi.getInnerClassOuterThisAccessorName(irClass) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt index acfe4fea2c2..0fac59efb07 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt @@ -466,7 +466,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) { */ fun getDeclaredFields(): List { val outerThisField = if (irClass.isInner) - context.specialDeclarationsFactory.getOuterThisField(irClass) + context.innerClassesSupport.getOuterThisField(irClass) else null val packageFragment = irClass.getPackageFragment() if (packageFragment is IrExternalPackageFragment) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt index 4b6ba379907..8cdf0214c95 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -7,9 +7,14 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.getOrPut import org.jetbrains.kotlin.backend.common.lower.callsSuper import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.NativeMapping +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.declarations.buildField import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -24,6 +29,31 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +internal class InnerClassesSupport(mapping: NativeMapping, private val irFactory: IrFactory) { + private val outerThisFields = mapping.outerThisFields + + fun getOuterThisField(innerClass: IrClass): IrField { + require(innerClass.isInner) { "Expected an inner class: ${innerClass.render()}" } + return outerThisFields.getOrPut(innerClass) { + val outerClass = innerClass.parentClassOrNull ?: error("No containing class for inner class ${innerClass.render()}") + + irFactory.buildField { + startOffset = innerClass.startOffset + endOffset = innerClass.endOffset + origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS + name = "this$0".synthesizedName // TODO: other backends have "$this" here. + type = outerClass.defaultType + visibility = DescriptorVisibilities.PROTECTED + isFinal = true + isExternal = false + isStatic = false + }.also { + it.parent = innerClass + } + } + } +} + internal class OuterThisLowering(val context: Context) : ClassLoweringPass { override fun lower(irClass: IrClass) { if (!irClass.isInner) return @@ -95,7 +125,7 @@ internal class OuterThisLowering(val context: Context) : ClassLoweringPass { return expression } - val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass) + val outerThisField = context.innerClassesSupport.getOuterThisField(innerClass) irThis = IrGetFieldImpl( startOffset, endOffset, outerThisField.symbol, outerThisField.type, @@ -130,7 +160,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { } private fun createOuterThisField() { - val outerThisField = context.specialDeclarationsFactory.getOuterThisField(irClass) + val outerThisField = context.innerClassesSupport.getOuterThisField(irClass) irClass.declarations += outerThisField outerThisFieldSymbol = outerThisField.symbol } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt index 63f14543fe5..663c780c870 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -549,7 +549,7 @@ internal class KonanIrLinker( protoFieldsMap[name] = it } - val outerThisIndex = fields.indexOfFirst { it.irField?.origin == SpecialDeclarationsFactory.DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS } + val outerThisIndex = fields.indexOfFirst { it.irField?.origin == IrDeclarationOrigin.FIELD_FOR_OUTER_THIS } val compatibleMode = CompatibilityMode(libraryAbiVersion).oldSignatures return SerializedClassFields( fileDeserializationState.fileIndex,