IR: rename DeclarationFactory to InnerClassesSupport, move out of context

Methods of the common interface DeclarationFactory were only used in
lowerings in InnerClassesLowering, which were used in JVM and JS, not
Native. Therefore, it makes sense to have this as a separate interface
and pass its implementation to these lowerings directly, instead of
declaring it in the common context (which is not going to be implemented
in Native).
This commit is contained in:
Alexander Udalov
2020-07-08 18:40:23 +02:00
parent cf884fb048
commit c7f9dc1c40
14 changed files with 144 additions and 130 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.backend.common package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -32,7 +31,6 @@ interface BackendContext {
val builtIns: KotlinBuiltIns val builtIns: KotlinBuiltIns
val irBuiltIns: IrBuiltIns val irBuiltIns: IrBuiltIns
val sharedVariablesManager: SharedVariablesManager val sharedVariablesManager: SharedVariablesManager
val declarationFactory: DeclarationFactory
val internalPackageFqn: FqName val internalPackageFqn: FqName
val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol> val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
val lateinitNullableFields: MutableMap<IrField, IrField> val lateinitNullableFields: MutableMap<IrField, IrField>
@@ -1,16 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.ir
import org.jetbrains.kotlin.ir.declarations.*
interface DeclarationFactory {
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS", isSynthetic = true)
fun getOuterThisField(innerClass: IrClass): IrField
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor
fun getInnerClassOriginalPrimaryConstructorOrNull(innerClass: IrClass): IrConstructor?
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irSetField import org.jetbrains.kotlin.ir.builders.irSetField
@@ -23,24 +22,30 @@ import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
class InnerClassesLowering(val context: BackendContext) : DeclarationTransformer { interface InnerClassesSupport {
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS", isSynthetic = true)
fun getOuterThisField(innerClass: IrClass): IrField
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor
fun getInnerClassOriginalPrimaryConstructorOrNull(innerClass: IrClass): IrConstructor?
}
class InnerClassesLowering(val context: BackendContext, private val innerClassesSupport: InnerClassesSupport) : DeclarationTransformer {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
runPostfix(true).toFileLoweringPass().lower(irFile) runPostfix(true).toFileLoweringPass().lower(irFile)
} }
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? { override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
if (declaration is IrClass && declaration.isInner) { if (declaration is IrClass && declaration.isInner) {
stageController.unrestrictDeclarationListsAccess { stageController.unrestrictDeclarationListsAccess {
declaration.declarations += context.declarationFactory.getOuterThisField(declaration) declaration.declarations += innerClassesSupport.getOuterThisField(declaration)
} }
} else if (declaration is IrConstructor) { } else if (declaration is IrConstructor) {
val irClass = declaration.parentAsClass val irClass = declaration.parentAsClass
if (!irClass.isInner) return null if (!irClass.isInner) return null
val newConstructor = lowerConstructor(declaration) val newConstructor = lowerConstructor(declaration)
val oldConstructorParameterToNew = context.primaryConstructorParameterMap(declaration) val oldConstructorParameterToNew = innerClassesSupport.primaryConstructorParameterMap(declaration)
for ((oldParam, newParam) in oldConstructorParameterToNew.entries) { for ((oldParam, newParam) in oldConstructorParameterToNew.entries) {
newParam.defaultValue = oldParam.defaultValue?.let { oldDefault -> newParam.defaultValue = oldParam.defaultValue?.let { oldDefault ->
IrExpressionBodyImpl(oldDefault.startOffset, oldDefault.endOffset) { IrExpressionBodyImpl(oldDefault.startOffset, oldDefault.endOffset) {
@@ -56,11 +61,11 @@ class InnerClassesLowering(val context: BackendContext) : DeclarationTransformer
} }
private fun lowerConstructor(irConstructor: IrConstructor): IrConstructor { private fun lowerConstructor(irConstructor: IrConstructor): IrConstructor {
val loweredConstructor = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(irConstructor) val loweredConstructor = innerClassesSupport.getInnerClassConstructorWithOuterThisParameter(irConstructor)
val outerThisParameter = loweredConstructor.valueParameters[0] val outerThisParameter = loweredConstructor.valueParameters[0]
val irClass = irConstructor.parentAsClass val irClass = irConstructor.parentAsClass
val parentThisField = context.declarationFactory.getOuterThisField(irClass) val parentThisField = innerClassesSupport.getOuterThisField(irClass)
val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}") val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
@@ -79,7 +84,7 @@ class InnerClassesLowering(val context: BackendContext) : DeclarationTransformer
} }
patchDeclarationParents(loweredConstructor) patchDeclarationParents(loweredConstructor)
val oldConstructorParameterToNew = context.primaryConstructorParameterMap(irConstructor) val oldConstructorParameterToNew = innerClassesSupport.primaryConstructorParameterMap(irConstructor)
transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew)) transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew))
} }
@@ -88,10 +93,10 @@ class InnerClassesLowering(val context: BackendContext) : DeclarationTransformer
} }
private fun BackendContext.primaryConstructorParameterMap(originalConstructor: IrConstructor): Map<IrValueParameter, IrValueParameter> { private fun InnerClassesSupport.primaryConstructorParameterMap(originalConstructor: IrConstructor): Map<IrValueParameter, IrValueParameter> {
val oldConstructorParameterToNew = HashMap<IrValueParameter, IrValueParameter>() val oldConstructorParameterToNew = HashMap<IrValueParameter, IrValueParameter>()
val loweredConstructor = declarationFactory.getInnerClassConstructorWithOuterThisParameter(originalConstructor) val loweredConstructor = getInnerClassConstructorWithOuterThisParameter(originalConstructor)
originalConstructor.valueParameters.forEach { old -> originalConstructor.valueParameters.forEach { old ->
oldConstructorParameterToNew[old] = loweredConstructor.valueParameters[old.index + 1] oldConstructorParameterToNew[old] = loweredConstructor.valueParameters[old.index + 1]
@@ -101,7 +106,7 @@ private fun BackendContext.primaryConstructorParameterMap(originalConstructor: I
} }
class InnerClassesMemberBodyLowering(val context: BackendContext) : BodyLoweringPass { class InnerClassesMemberBodyLowering(val context: BackendContext, private val innerClassesSupport: InnerClassesSupport) : BodyLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
runOnFilePostfix(irFile, true) runOnFilePostfix(irFile, true)
} }
@@ -123,9 +128,9 @@ class InnerClassesMemberBodyLowering(val context: BackendContext) : BodyLowering
if (!irClass.isInner) return if (!irClass.isInner) return
if (container is IrField || container is IrAnonymousInitializer || container is IrValueParameter) { if (container is IrField || container is IrAnonymousInitializer || container is IrValueParameter) {
val primaryConstructor = context.declarationFactory.getInnerClassOriginalPrimaryConstructorOrNull(irClass) val primaryConstructor = innerClassesSupport.getInnerClassOriginalPrimaryConstructorOrNull(irClass)
if (primaryConstructor != null) { if (primaryConstructor != null) {
val oldConstructorParameterToNew = context.primaryConstructorParameterMap(primaryConstructor) val oldConstructorParameterToNew = innerClassesSupport.primaryConstructorParameterMap(primaryConstructor)
irBody.transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew)) irBody.transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew))
} }
} }
@@ -133,7 +138,7 @@ class InnerClassesMemberBodyLowering(val context: BackendContext) : BodyLowering
irBody.fixThisReference(irClass, container) irBody.fixThisReference(irClass, container)
} }
fun IrBody.fixThisReference(irClass: IrClass, container: IrDeclaration) { private fun IrBody.fixThisReference(irClass: IrClass, container: IrDeclaration) {
val enclosingFunction: IrDeclaration? = run { val enclosingFunction: IrDeclaration? = run {
var current: IrDeclaration? = container var current: IrDeclaration? = container
while (current != null && current !is IrFunction) { while (current != null && current !is IrFunction) {
@@ -171,7 +176,7 @@ class InnerClassesMemberBodyLowering(val context: BackendContext) : BodyLowering
// an attempt to access the field. Good thing we have a local variable as well. // an attempt to access the field. Good thing we have a local variable as well.
IrGetValueImpl(startOffset, endOffset, function.valueParameters[0].symbol, origin) IrGetValueImpl(startOffset, endOffset, function.valueParameters[0].symbol, origin)
} else { } else {
val outerThisField = context.declarationFactory.getOuterThisField(innerClass) val outerThisField = innerClassesSupport.getOuterThisField(innerClass)
IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, outerThisField.type, irThis, origin) IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, outerThisField.type, irThis, origin)
} }
innerClass = innerClass.parentAsClass innerClass = innerClass.parentAsClass
@@ -182,13 +187,7 @@ class InnerClassesMemberBodyLowering(val context: BackendContext) : BodyLowering
} }
} }
val innerClassConstructorCallsPhase = makeIrFilePhase( class InnerClassConstructorCallsLowering(val context: BackendContext, val innerClassesSupport: InnerClassesSupport) : BodyLoweringPass {
::InnerClassConstructorCallsLowering,
name = "InnerClassConstructorCalls",
description = "Handle constructor calls for inner classes"
)
class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLoweringPass {
override fun lower(irBody: IrBody, container: IrDeclaration) { override fun lower(irBody: IrBody, container: IrDeclaration) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() { irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
@@ -199,7 +198,7 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val parent = callee.owner.parentAsClass val parent = callee.owner.parentAsClass
if (!parent.isInner) return expression if (!parent.isInner) return expression
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner) val newCallee = innerClassesSupport.getInnerClassConstructorWithOuterThisParameter(callee.owner)
val classTypeParametersCount = expression.typeArgumentsCount - expression.constructorTypeArgumentsCount val classTypeParametersCount = expression.typeArgumentsCount - expression.constructorTypeArgumentsCount
val newCall = IrConstructorCallImpl.fromSymbolOwner( val newCall = IrConstructorCallImpl.fromSymbolOwner(
expression.startOffset, expression.endOffset, expression.type, newCallee.symbol, classTypeParametersCount, expression.origin expression.startOffset, expression.endOffset, expression.type, newCallee.symbol, classTypeParametersCount, expression.origin
@@ -221,7 +220,7 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val classConstructor = expression.symbol.owner val classConstructor = expression.symbol.owner
if (!classConstructor.parentAsClass.isInner) return expression if (!classConstructor.parentAsClass.isInner) return expression
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor) val newCallee = innerClassesSupport.getInnerClassConstructorWithOuterThisParameter(classConstructor)
val newCall = IrDelegatingConstructorCallImpl( val newCall = IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee.symbol, expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee.symbol,
typeArgumentsCount = expression.typeArgumentsCount, typeArgumentsCount = expression.typeArgumentsCount,
@@ -243,10 +242,10 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val parent = callee.owner.parent as? IrClass ?: return expression val parent = callee.owner.parent as? IrClass ?: return expression
if (!parent.isInner) return expression if (!parent.isInner) return expression
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner) val newCallee = innerClassesSupport.getInnerClassConstructorWithOuterThisParameter(callee.owner)
val newReflectionTarget = expression.reflectionTarget?.let { reflectionTarget -> val newReflectionTarget = expression.reflectionTarget?.let { reflectionTarget ->
if (reflectionTarget is IrConstructorSymbol) { if (reflectionTarget is IrConstructorSymbol) {
context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(reflectionTarget.owner) innerClassesSupport.getInnerClassConstructorWithOuterThisParameter(reflectionTarget.owner)
} else { } else {
null null
} }
@@ -282,4 +281,3 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
}) })
} }
} }
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsDeclarationFactory import org.jetbrains.kotlin.ir.backend.js.lower.JsInnerClassesSupport
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -134,7 +134,7 @@ class JsIrBackendContext(
get() = testContainerFuns get() = testContainerFuns
override val mapping = JsMapping() override val mapping = JsMapping()
override val declarationFactory = JsDeclarationFactory(mapping) val innerClassesSupport = JsInnerClassesSupport(mapping)
companion object { companion object {
val KOTLIN_PACKAGE_FQN = FqName.fromSegments(listOf("kotlin")) val KOTLIN_PACKAGE_FQN = FqName.fromSegments(listOf("kotlin"))
@@ -375,20 +375,20 @@ private val localClassExtractionPhase = makeBodyLoweringPhase(
) )
private val innerClassesLoweringPhase = makeDeclarationTransformerPhase( private val innerClassesLoweringPhase = makeDeclarationTransformerPhase(
::InnerClassesLowering, { context -> InnerClassesLowering(context, context.innerClassesSupport) },
name = "InnerClassesLowering", name = "InnerClassesLowering",
description = "Capture outer this reference to inner class" description = "Capture outer this reference to inner class"
) )
private val innerClassesMemberBodyLoweringPhase = makeBodyLoweringPhase( private val innerClassesMemberBodyLoweringPhase = makeBodyLoweringPhase(
::InnerClassesMemberBodyLowering, { context -> InnerClassesMemberBodyLowering(context, context.innerClassesSupport) },
name = "InnerClassesMemberBody", name = "InnerClassesMemberBody",
description = "Replace `this` with 'outer this' field references", description = "Replace `this` with 'outer this' field references",
prerequisite = setOf(innerClassesLoweringPhase) prerequisite = setOf(innerClassesLoweringPhase)
) )
private val innerClassConstructorCallsLoweringPhase = makeBodyLoweringPhase( private val innerClassConstructorCallsLoweringPhase = makeBodyLoweringPhase(
::InnerClassConstructorCallsLowering, { context -> InnerClassConstructorCallsLowering(context, context.innerClassesSupport) },
name = "InnerClassConstructorCallsLowering", name = "InnerClassConstructorCallsLowering",
description = "Replace inner class constructor invocation" description = "Replace inner class constructor invocation"
) )
@@ -3,10 +3,10 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.backend.js package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.getOrPut import org.jetbrains.kotlin.backend.common.getOrPut
import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class JsDeclarationFactory(mapping: JsMapping) : DeclarationFactory { class JsInnerClassesSupport(mapping: JsMapping) : InnerClassesSupport {
private val outerThisFieldSymbols = mapping.outerThisFieldSymbols private val outerThisFieldSymbols = mapping.outerThisFieldSymbols
private val innerClassConstructors = mapping.innerClassConstructors private val innerClassConstructors = mapping.innerClassConstructors
private val originalInnerClassPrimaryConstructorByClass = mapping.originalInnerClassPrimaryConstructorByClass private val originalInnerClassPrimaryConstructorByClass = mapping.originalInnerClassPrimaryConstructorByClass
@@ -36,7 +36,7 @@ class JsDeclarationFactory(mapping: JsMapping) : DeclarationFactory {
?: throw AssertionError("No containing class for inner class ${innerClass.dump()}") ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}")
buildField { buildField {
origin = DeclarationFactory.FIELD_FOR_OUTER_THIS origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
name = Name.identifier("\$this") name = Name.identifier("\$this")
type = outerClass.defaultType type = outerClass.defaultType
visibility = Visibilities.PROTECTED visibility = Visibilities.PROTECTED
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
import org.jetbrains.kotlin.backend.jvm.lower.CollectionStubComputer import org.jetbrains.kotlin.backend.jvm.lower.CollectionStubComputer
import org.jetbrains.kotlin.backend.jvm.lower.JvmInnerClassesSupport
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -67,8 +68,8 @@ class JvmBackendContext(
val typeMapper = IrTypeMapper(this) val typeMapper = IrTypeMapper(this)
val methodSignatureMapper = MethodSignatureMapper(this) val methodSignatureMapper = MethodSignatureMapper(this)
override val declarationFactory: JvmDeclarationFactory = internal val innerClassesSupport = JvmInnerClassesSupport()
JvmDeclarationFactory(this, methodSignatureMapper, state.languageVersionSettings) internal val declarationFactory = JvmDeclarationFactory(this, methodSignatureMapper, state.languageVersionSettings)
override val mapping: Mapping = DefaultMapping() override val mapping: Mapping = DefaultMapping()
@@ -190,19 +190,25 @@ private val interfacePhase = makeIrFilePhase(
) )
private val innerClassesPhase = makeIrFilePhase( private val innerClassesPhase = makeIrFilePhase(
::InnerClassesLowering, { context -> InnerClassesLowering(context, context.innerClassesSupport) },
name = "InnerClasses", name = "InnerClasses",
description = "Add 'outer this' fields to inner classes", description = "Add 'outer this' fields to inner classes",
prerequisite = setOf(localDeclarationsPhase) prerequisite = setOf(localDeclarationsPhase)
) )
private val innerClassesMemberBodyPhase = makeIrFilePhase( private val innerClassesMemberBodyPhase = makeIrFilePhase(
::InnerClassesMemberBodyLowering, { context -> InnerClassesMemberBodyLowering(context, context.innerClassesSupport) },
name = "InnerClassesMemberBody", name = "InnerClassesMemberBody",
description = "Replace `this` with 'outer this' field references", description = "Replace `this` with 'outer this' field references",
prerequisite = setOf(innerClassesPhase) prerequisite = setOf(innerClassesPhase)
) )
private val innerClassConstructorCallsPhase = makeIrFilePhase<JvmBackendContext>(
{ context -> InnerClassConstructorCallsLowering(context, context.innerClassesSupport) },
name = "InnerClassConstructorCalls",
description = "Handle constructor calls for inner classes"
)
private val staticInitializersPhase = makeIrFilePhase( private val staticInitializersPhase = makeIrFilePhase(
::StaticInitializersLowering, ::StaticInitializersLowering,
name = "StaticInitializers", name = "StaticInitializers",
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.backend.jvm.descriptors package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.ir.* import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
@@ -14,12 +16,13 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.copyCorrespondingPropertyFrom import org.jetbrains.kotlin.backend.jvm.ir.copyCorrespondingPropertyFrom
import org.jetbrains.kotlin.backend.jvm.ir.replaceThisByStaticReference import org.jetbrains.kotlin.backend.jvm.ir.replaceThisByStaticReference
import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.setSourceRange import org.jetbrains.kotlin.ir.builders.setSourceRange
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -29,18 +32,14 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import java.util.*
class JvmDeclarationFactory( class JvmDeclarationFactory(
private val context: JvmBackendContext, private val context: JvmBackendContext,
private val methodSignatureMapper: MethodSignatureMapper, private val methodSignatureMapper: MethodSignatureMapper,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings
) : DeclarationFactory { ) {
private val singletonFieldDeclarations = HashMap<IrSymbolOwner, IrField>() private val singletonFieldDeclarations = HashMap<IrSymbolOwner, IrField>()
private val interfaceCompanionFieldDeclarations = HashMap<IrSymbolOwner, IrField>() private val interfaceCompanionFieldDeclarations = HashMap<IrSymbolOwner, IrField>()
private val outerThisDeclarations = HashMap<IrClass, IrField>()
private val innerClassConstructors = HashMap<IrConstructor, IrConstructor>()
private val originalInnerClassPrimaryConstructorByClass = HashMap<IrClass, IrConstructor>()
private val staticBackingFields = HashMap<IrProperty, IrField>() private val staticBackingFields = HashMap<IrProperty, IrField>()
private val defaultImplsMethods = HashMap<IrSimpleFunction, IrSimpleFunction>() private val defaultImplsMethods = HashMap<IrSimpleFunction, IrSimpleFunction>()
@@ -61,59 +60,6 @@ class JvmDeclarationFactory(
} }
} }
override fun getOuterThisField(innerClass: IrClass): IrField =
outerThisDeclarations.getOrPut(innerClass) {
assert(innerClass.isInner) { "Class is not inner: ${innerClass.dump()}" }
buildField {
name = Name.identifier("this$0")
type = innerClass.parentAsClass.defaultType
origin = DeclarationFactory.FIELD_FOR_OUTER_THIS
visibility = JavaVisibilities.PACKAGE_VISIBILITY
isFinal = true
}.apply {
parent = innerClass
}
}
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor {
val innerClass = innerClassConstructor.parent as IrClass
assert(innerClass.isInner) { "Class is not inner: ${(innerClassConstructor.parent as IrClass).dump()}" }
return innerClassConstructors.getOrPut(innerClassConstructor) {
createInnerClassConstructorWithOuterThisParameter(innerClassConstructor)
}.also {
if (innerClassConstructor.isPrimary) {
originalInnerClassPrimaryConstructorByClass[innerClass] = innerClassConstructor
}
}
}
override fun getInnerClassOriginalPrimaryConstructorOrNull(innerClass: IrClass): IrConstructor? {
assert(innerClass.isInner) { "Class is not inner: $innerClass" }
return originalInnerClassPrimaryConstructorByClass[innerClass]
}
private fun createInnerClassConstructorWithOuterThisParameter(oldConstructor: IrConstructor): IrConstructor =
buildConstructor(oldConstructor.descriptor) {
updateFrom(oldConstructor)
returnType = oldConstructor.returnType
}.apply {
annotations = oldConstructor.annotations.map { it.deepCopyWithSymbols(this) }
parent = oldConstructor.parent
returnType = oldConstructor.returnType
copyTypeParametersFrom(oldConstructor)
val outerThisValueParameter = buildValueParameter(this) {
origin = JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS
name = Name.identifier(AsmUtil.CAPTURED_THIS_FIELD)
index = 0
type = oldConstructor.parentAsClass.parentAsClass.defaultType
}
valueParameters = listOf(outerThisValueParameter) + oldConstructor.valueParameters.map { it.copyTo(this, index = it.index + 1) }
metadata = oldConstructor.metadata
}
fun getFieldForObjectInstance(singleton: IrClass): IrField = fun getFieldForObjectInstance(singleton: IrClass): IrField =
singletonFieldDeclarations.getOrPut(singleton) { singletonFieldDeclarations.getOrPut(singleton) {
val originalVisibility = singleton.visibility val originalVisibility = singleton.visibility
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.ir.* import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
@@ -427,7 +428,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
addField { addField {
name = Name.identifier("this$0") name = Name.identifier("this$0")
type = it.type type = it.type
origin = DeclarationFactory.FIELD_FOR_OUTER_THIS origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
visibility = JavaVisibilities.PACKAGE_VISIBILITY visibility = JavaVisibilities.PACKAGE_VISIBILITY
isFinal = true isFinal = true
} }
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name
class JvmInnerClassesSupport : InnerClassesSupport {
private val outerThisDeclarations = HashMap<IrClass, IrField>()
private val innerClassConstructors = HashMap<IrConstructor, IrConstructor>()
private val originalInnerClassPrimaryConstructorByClass = HashMap<IrClass, IrConstructor>()
override fun getOuterThisField(innerClass: IrClass): IrField =
outerThisDeclarations.getOrPut(innerClass) {
assert(innerClass.isInner) { "Class is not inner: ${innerClass.dump()}" }
buildField {
name = Name.identifier("this$0")
type = innerClass.parentAsClass.defaultType
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
visibility = JavaVisibilities.PACKAGE_VISIBILITY
isFinal = true
}.apply {
parent = innerClass
}
}
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor {
val innerClass = innerClassConstructor.parent as IrClass
assert(innerClass.isInner) { "Class is not inner: ${(innerClassConstructor.parent as IrClass).dump()}" }
return innerClassConstructors.getOrPut(innerClassConstructor) {
createInnerClassConstructorWithOuterThisParameter(innerClassConstructor)
}.also {
if (innerClassConstructor.isPrimary) {
originalInnerClassPrimaryConstructorByClass[innerClass] = innerClassConstructor
}
}
}
override fun getInnerClassOriginalPrimaryConstructorOrNull(innerClass: IrClass): IrConstructor? {
assert(innerClass.isInner) { "Class is not inner: $innerClass" }
return originalInnerClassPrimaryConstructorByClass[innerClass]
}
private fun createInnerClassConstructorWithOuterThisParameter(oldConstructor: IrConstructor): IrConstructor =
buildConstructor(oldConstructor.descriptor) {
updateFrom(oldConstructor)
returnType = oldConstructor.returnType
}.apply {
annotations = oldConstructor.annotations.map { it.deepCopyWithSymbols(this) }
parent = oldConstructor.parent
returnType = oldConstructor.returnType
copyTypeParametersFrom(oldConstructor)
val outerThisValueParameter = buildValueParameter(this) {
origin = JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS
name = Name.identifier(AsmUtil.CAPTURED_THIS_FIELD)
index = 0
type = oldConstructor.parentAsClass.parentAsClass.defaultType
}
valueParameters = listOf(outerThisValueParameter) + oldConstructor.valueParameters.map { it.copyTo(this, index = it.index + 1) }
metadata = oldConstructor.metadata
}
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.wasm
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsDeclarationFactory import org.jetbrains.kotlin.ir.backend.js.lower.JsInnerClassesSupport
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
@@ -52,7 +52,7 @@ class WasmBackendContext(
override val mapping = JsMapping() override val mapping = JsMapping()
override val declarationFactory = JsDeclarationFactory(mapping) val innerClassesSupport = JsInnerClassesSupport(mapping)
val objectToGetInstanceFunction = mutableMapOf<IrClassSymbol, IrSimpleFunction>() val objectToGetInstanceFunction = mutableMapOf<IrClassSymbol, IrSimpleFunction>()
override val internalPackageFqn = FqName("kotlin.wasm") override val internalPackageFqn = FqName("kotlin.wasm")
@@ -100,6 +100,3 @@ class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSym
override val signature: IdSignature override val signature: IdSignature
get() = error("Operation is unsupported") get() = error("Operation is unsupported")
} }
@@ -149,20 +149,20 @@ private val localClassExtractionPhase = makeWasmModulePhase(
) )
private val innerClassesLoweringPhase = makeWasmModulePhase( private val innerClassesLoweringPhase = makeWasmModulePhase(
::InnerClassesLowering, { context -> InnerClassesLowering(context, context.innerClassesSupport) },
name = "InnerClassesLowering", name = "InnerClassesLowering",
description = "Capture outer this reference to inner class" description = "Capture outer this reference to inner class"
) )
private val innerClassesMemberBodyLoweringPhase = makeWasmModulePhase( private val innerClassesMemberBodyLoweringPhase = makeWasmModulePhase(
::InnerClassesMemberBodyLowering, { context -> InnerClassesMemberBodyLowering(context, context.innerClassesSupport) },
name = "InnerClassesMemberBody", name = "InnerClassesMemberBody",
description = "Replace `this` with 'outer this' field references", description = "Replace `this` with 'outer this' field references",
prerequisite = setOf(innerClassesLoweringPhase) prerequisite = setOf(innerClassesLoweringPhase)
) )
private val innerClassConstructorCallsLoweringPhase = makeWasmModulePhase( private val innerClassConstructorCallsLoweringPhase = makeWasmModulePhase(
::InnerClassConstructorCallsLowering, { context -> InnerClassConstructorCallsLowering(context, context.innerClassesSupport) },
name = "InnerClassConstructorCallsLowering", name = "InnerClassConstructorCallsLowering",
description = "Replace inner class constructor invocation" description = "Replace inner class constructor invocation"
) )
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.backend.common.serialization package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.overrides.PlatformFakeOverrideClassFilter import org.jetbrains.kotlin.backend.common.overrides.PlatformFakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.peek import org.jetbrains.kotlin.backend.common.peek
@@ -1363,7 +1363,7 @@ abstract class IrFileDeserializer(
} }
private val allKnownDeclarationOrigins = private val allKnownDeclarationOrigins =
IrDeclarationOrigin::class.nestedClasses.toList() + DeclarationFactory.FIELD_FOR_OUTER_THIS::class IrDeclarationOrigin::class.nestedClasses.toList() + InnerClassesSupport.FIELD_FOR_OUTER_THIS::class
private val declarationOriginIndex = private val declarationOriginIndex =
allKnownDeclarationOrigins.map { it.objectInstance as IrDeclarationOriginImpl }.associateBy { it.name } allKnownDeclarationOrigins.map { it.objectInstance as IrDeclarationOriginImpl }.associateBy { it.name }