[K/N][IR] Refactored outer this field creation

This commit is contained in:
Igor Chevdar
2022-08-05 11:24:41 +03:00
committed by Space
parent 87038e7d8a
commit 9f26f8f227
6 changed files with 69 additions and 79 deletions
@@ -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<IrClass, IrField>()
}
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<IrClass, IrField>()
private val internalLoweredEnums = mutableMapOf<IrClass, InternalLoweredEnum>()
private val externalLoweredEnums = mutableMapOf<IrClass, ExternalLoweredEnum>()
@@ -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<T>(val initializer: Context.() -> T) {
operator fun getValue(thisRef: Context, property: KProperty<*>): T = thisRef.getValue(this)
@@ -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
}
@@ -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)
@@ -466,7 +466,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
*/
fun getDeclaredFields(): List<FieldInfo> {
val outerThisField = if (irClass.isInner)
context.specialDeclarationsFactory.getOuterThisField(irClass)
context.innerClassesSupport.getOuterThisField(irClass)
else null
val packageFragment = irClass.getPackageFragment()
if (packageFragment is IrExternalPackageFragment) {
@@ -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
}
@@ -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,