IR: refuse to copy classes in InitializersLowering
This commit is contained in:
+14
-23
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
|
|
||||||
object SYNTHESIZED_INIT_BLOCK : IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
object SYNTHESIZED_INIT_BLOCK : IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
||||||
|
|
||||||
open class InitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context), BodyLoweringPass {
|
class InitializersLowering(context: CommonBackendContext) : InitializersLoweringBase(context), BodyLoweringPass {
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
runOnFilePostfix(irFile, true)
|
runOnFilePostfix(irFile, true)
|
||||||
}
|
}
|
||||||
@@ -29,31 +29,22 @@ open class InitializersLowering(context: CommonBackendContext) : InitializersLow
|
|||||||
if (container !is IrConstructor) return
|
if (container !is IrConstructor) return
|
||||||
|
|
||||||
val irClass = container.constructedClass
|
val irClass = container.constructedClass
|
||||||
|
|
||||||
val instanceInitializerStatements = extractInitializers(irClass) {
|
val instanceInitializerStatements = extractInitializers(irClass) {
|
||||||
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
||||||
}
|
}
|
||||||
|
val block = IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||||
|
// Check that the initializers contain no local classes. Deep-copying them is a disaster for code size, and liable to break randomly.
|
||||||
|
block.accept(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) =
|
||||||
|
element.acceptChildren(this, null)
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass) =
|
||||||
|
throw AssertionError("class in initializer should have been moved out by LocalClassPopupLowering: ${declaration.render()}")
|
||||||
|
}, null)
|
||||||
|
|
||||||
container.body?.transformChildrenVoid(object : IrElementTransformerVoid() {
|
container.body?.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression =
|
||||||
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
block.deepCopyWithSymbols(container)
|
||||||
.deepCopyWithSymbols(container).also {
|
|
||||||
// Handle declarations, copied from initializers
|
|
||||||
// Otherwise local classes inside them won't get processed.
|
|
||||||
// Yes, there are such cases - see testData/codegen/box/properties/complexPropertyInitializer.kt
|
|
||||||
it.acceptVoid(object : IrElementVisitorVoid {
|
|
||||||
override fun visitElement(element: IrElement) {
|
|
||||||
element.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitConstructor(declaration: IrConstructor) {
|
|
||||||
super.visitConstructor(declaration)
|
|
||||||
|
|
||||||
declaration.body?.let { lower(it, declaration) }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +52,7 @@ open class InitializersLowering(context: CommonBackendContext) : InitializersLow
|
|||||||
abstract class InitializersLoweringBase(open val context: CommonBackendContext) {
|
abstract class InitializersLoweringBase(open val context: CommonBackendContext) {
|
||||||
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
|
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
|
||||||
// TODO What about fields that were added by lowerings? e.g. captured outer class or locals?
|
// TODO What about fields that were added by lowerings? e.g. captured outer class or locals?
|
||||||
ArrayList(irClass.declarations).mapNotNull { if (it is IrProperty) it.backingField else it }.filter(filter).mapNotNull {
|
irClass.declarations.mapNotNull { if (it is IrProperty) it.backingField else it }.filter(filter).mapNotNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrField -> handleField(irClass, it)
|
is IrField -> handleField(irClass, it)
|
||||||
is IrAnonymousInitializer -> handleAnonymousInitializer(it)
|
is IrAnonymousInitializer -> handleAnonymousInitializer(it)
|
||||||
|
|||||||
@@ -504,7 +504,9 @@ private val initializersLoweringPhase = makeBodyLoweringPhase(
|
|||||||
::InitializersLowering,
|
::InitializersLowering,
|
||||||
name = "InitializersLowering",
|
name = "InitializersLowering",
|
||||||
description = "Merge init block and field initializers into [primary] constructor",
|
description = "Merge init block and field initializers into [primary] constructor",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase, annotationConstructorLowering)
|
prerequisite = setOf(
|
||||||
|
enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase, annotationConstructorLowering, localClassExtractionPhase
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initializersCleanupLoweringPhase = makeDeclarationTransformerPhase(
|
private val initializersCleanupLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
|
|||||||
+1
-1
@@ -228,7 +228,7 @@ private val initializersLoweringPhase = makeWasmModulePhase(
|
|||||||
::InitializersLowering,
|
::InitializersLowering,
|
||||||
name = "InitializersLowering",
|
name = "InitializersLowering",
|
||||||
description = "Merge init block and field initializers into [primary] constructor",
|
description = "Merge init block and field initializers into [primary] constructor",
|
||||||
prerequisite = setOf(primaryConstructorLoweringPhase)
|
prerequisite = setOf(primaryConstructorLoweringPhase, localClassExtractionPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initializersCleanupLoweringPhase = makeWasmModulePhase(
|
private val initializersCleanupLoweringPhase = makeWasmModulePhase(
|
||||||
|
|||||||
Reference in New Issue
Block a user