[JS IR] Add init function for properties

^KT-43222 fixed
This commit is contained in:
Ilya Goncharov
2020-10-27 13:47:50 +03:00
parent 003ea4bcdf
commit d752b7439e
2 changed files with 126 additions and 0 deletions
@@ -109,6 +109,16 @@ class ModuleLowering(
override val modulePhase: NamedCompilerPhase<JsIrBackendContext, Iterable<IrModuleFragment>>
) : Lowering(name)
class FileLowering(
name: String,
description: String,
prerequisite: Set<NamedCompilerPhase<JsIrBackendContext, *>> = emptySet(),
private val factory: (JsIrBackendContext) -> FileLoweringPass
) : Lowering(name) {
override val modulePhase: NamedCompilerPhase<JsIrBackendContext, Iterable<IrModuleFragment>> =
makeJsModulePhase(factory, name, description, prerequisite)
}
private fun makeDeclarationTransformerPhase(
lowering: (JsIrBackendContext) -> DeclarationTransformer,
name: String,
@@ -123,6 +133,13 @@ private fun makeBodyLoweringPhase(
prerequisite: Set<Lowering> = emptySet()
) = BodyLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
private fun makeFileLoweringPhase(
lowering: (JsIrBackendContext) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<Lowering> = emptySet()
) = FileLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
fun NamedCompilerPhase<JsIrBackendContext, Iterable<IrModuleFragment>>.toModuleLowering() = ModuleLowering(this.name, this)
private val validateIrBeforeLowering = makeCustomJsModulePhase(
@@ -352,6 +369,12 @@ private val forLoopsLoweringPhase = makeBodyLoweringPhase(
description = "[Optimization] For loops lowering"
)
private val propertyLazyInitLoweringPhase = makeFileLoweringPhase(
::PropertyLazyInitLowering,
name = "PropertyLazyInitLowering",
description = "Make property init as lazy"
)
private val propertyAccessorInlinerLoweringPhase = makeBodyLoweringPhase(
::PropertyAccessorInlineLowering,
name = "PropertyAccessorInlineLowering",
@@ -727,6 +750,7 @@ val loweringList = listOf<Lowering>(
rangeContainsLoweringPhase,
forLoopsLoweringPhase,
primitiveCompanionLoweringPhase,
propertyLazyInitLoweringPhase,
propertyAccessorInlinerLoweringPhase,
foldConstantLoweringPhase,
privateMembersLoweringPhase,
@@ -0,0 +1,102 @@
/*
* 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.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrSetField
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
class PropertyLazyInitLowering(private val context: JsIrBackendContext) : FileLoweringPass {
private val irBuiltIns
get() = context.irBuiltIns
override fun lower(irFile: IrFile) {
val initializers = PropertyInitializerMover(context).process(irFile)
val irFactory = context.irFactory
if (initializers.isNotEmpty()) {
irFactory.addFunction(irFile) {
name = Name.identifier("init properties ${irFile.kotlinFqName}")
returnType = irBuiltIns.unitType
origin = JsIrBuilder.SYNTHESIZED_DECLARATION
}.apply {
body = irFactory.createBlockBody(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
initializers
.map { (field, expression) ->
createIrSetField(field, expression)
}
)
}
}
}
private fun createIrSetField(field: IrField, expression: IrExpression): IrSetField {
return IrSetFieldImpl(
field.startOffset,
field.endOffset,
field.symbol,
null,
expression,
expression.type
)
}
}
private class PropertyInitializerMover(
private val context: JsIrBackendContext
) : IrElementTransformerVoid() {
private val fieldToInitializers = mutableListOf<Pair<IrField, IrExpression>>()
fun process(irFile: IrFile): List<Pair<IrField, IrExpression>> {
irFile.transformChildrenVoid(this)
return fieldToInitializers
}
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement {
declaration.correspondingPropertySymbol
?.owner
?.takeIf { !it.isConst }
?.takeIf { !it.isDelegated }
?.backingField
?.takeIf { it.initializer != null }
?.let { field ->
fieldToInitializers.add(field to field.initializer!!.expression)
}
fieldToInitializers.forEach { it.first.initializer = null }
return super.visitSimpleFunction(declaration)
}
override fun visitFieldAccess(expression: IrFieldAccessExpression): IrExpression {
return super.visitFieldAccess(expression)
}
override fun visitField(declaration: IrField): IrStatement {
return super.visitField(declaration)
}
override fun visitBody(body: IrBody): IrBody {
return super.visitBody(body)
}
}