From d87468ef39badb19f6e94dbdf6b0535846a00efe Mon Sep 17 00:00:00 2001 From: mcpiroman Date: Sat, 4 Mar 2023 14:18:16 +0100 Subject: [PATCH] Simplify and optimize JvmLateinitLowering --- .../backend/jvm/lower/JvmLateinitLowering.kt | 110 +++++------------- 1 file changed, 30 insertions(+), 80 deletions(-) diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLateinitLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLateinitLowering.kt index 9230bcac9be..fa58269b73c 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLateinitLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLateinitLowering.kt @@ -43,18 +43,24 @@ class JvmLateinitLowering( ) : FileLoweringPass { override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(Transformer(context)) + val transformer = Transformer(context) + irFile.transformChildrenVoid(transformer) + + for (variable in transformer.lateinitVariables) { + variable.isLateinit = false + } } private class Transformer(private val backendContext: JvmBackendContext) : IrElementTransformerVoid() { - private val backingVariables = HashMap() + val lateinitVariables = mutableListOf() override fun visitField(declaration: IrField): IrStatement { if (declaration.isLateinitBackingField()) { assert(declaration.initializer == null) { "lateinit property backing field should not have an initializer:\n${declaration.dump()}" } - return getOrBuildLateinitBackingField(declaration) + + declaration.type = declaration.type.makeNullable() } declaration.transformChildrenVoid() @@ -63,30 +69,23 @@ class JvmLateinitLowering( override fun visitVariable(declaration: IrVariable): IrStatement { declaration.transformChildrenVoid(this) - if (!declaration.isLateinit) return declaration - return getOrBuildLateinitBackingVar(declaration) - } - private fun getOrBuildLateinitBackingVar(declaration: IrVariable): IrVariable = - backingVariables.getOrPut(declaration) { - buildVariable( - declaration.parent, - declaration.startOffset, - declaration.endOffset, - declaration.origin, - declaration.name, - declaration.type.makeNullable(), - isVar = true, - ).also { - it.initializer = - IrConstImpl.constNull(declaration.startOffset, declaration.endOffset, backendContext.irBuiltIns.nothingNType) - } + if (declaration.isLateinit) { + declaration.type = declaration.type.makeNullable() + declaration.isVar = true + declaration.initializer = + IrConstImpl.constNull(declaration.startOffset, declaration.endOffset, backendContext.irBuiltIns.nothingNType) + + lateinitVariables += declaration } + return declaration + } + override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement { val property = declaration.correspondingPropertySymbol?.owner if (property != null && property.isRealLateinit() && declaration == property.getter) { - transformGetter(getOrBuildLateinitBackingField(property.backingField!!), declaration) + transformGetter(property.backingField!!, declaration) return declaration } @@ -99,59 +98,28 @@ class JvmLateinitLowering( if (irValue !is IrVariable || !irValue.isLateinit) { return expression } - val irBackingVar = backingVariables[irValue] - ?: throw AssertionError("Lateinit variable reference before use: ${expression.dump()}") return backendContext.createIrBuilder( - (irBackingVar.parent as IrSymbolOwner).symbol, + (irValue.parent as IrSymbolOwner).symbol, expression.startOffset, expression.endOffset ).run { irIfThenElse( expression.type, - irEqualsNull(irGet(irBackingVar)), - backendContext.throwUninitializedPropertyAccessException(this, irBackingVar.name.asString()), - irGet(irBackingVar) + irEqualsNull(irGet(irValue)), + backendContext.throwUninitializedPropertyAccessException(this, irValue.name.asString()), + irGet(irValue) ) } } - override fun visitSetValue(expression: IrSetValue): IrExpression { - expression.transformChildrenVoid(this) - val irValue = expression.symbol.owner - if (irValue !is IrVariable || !irValue.isLateinit) { - return expression - } - - val irBackingVar = backingVariables[expression.symbol.owner] - ?: throw AssertionError("Lateinit variable reference before use: ${expression.dump()}") - return with(expression) { - IrSetValueImpl(startOffset, endOffset, type, irBackingVar.symbol, value, origin) - } - } - override fun visitGetField(expression: IrGetField): IrExpression { expression.transformChildrenVoid(this) val irField = expression.symbol.owner - if (!irField.isLateinitBackingField()) { - return expression - } - val newField = getOrBuildLateinitBackingField(irField) - return with(expression) { - IrGetFieldImpl(startOffset, endOffset, newField.symbol, newField.type, receiver, origin, superQualifierSymbol) - } - } - - override fun visitSetField(expression: IrSetField): IrExpression { - expression.transformChildrenVoid(this) - val irField = expression.symbol.owner - if (!irField.isLateinitBackingField()) { - return expression - } - val newField = getOrBuildLateinitBackingField(irField) - return with(expression) { - IrSetFieldImpl(startOffset, endOffset, newField.symbol, receiver, value, type, origin, superQualifierSymbol) + if (irField.isLateinitBackingField()) { + expression.type = expression.type.makeNullable() } + return expression } private fun IrField.isLateinitBackingField(): Boolean { @@ -177,10 +145,9 @@ class JvmLateinitLowering( } val backingField = property.backingField ?: throw AssertionError("Lateinit property is supposed to have a backing field") - val newField = getOrBuildLateinitBackingField(backingField) backendContext.createIrBuilder(it.symbol, expression.startOffset, expression.endOffset).run { irNotEquals( - irGetField(it.dispatchReceiver, newField), + irGetField(it.dispatchReceiver, backingField), irNull() ) } @@ -198,7 +165,7 @@ class JvmLateinitLowering( val irBuilder = backendContext.createIrBuilder(getter.symbol, startOffset, endOffset) irBuilder.run { val resultVar = scope.createTmpVariable( - irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField) + irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField, backingField.type.makeNullable()) ) resultVar.parent = getter statements.add(resultVar) @@ -215,22 +182,5 @@ class JvmLateinitLowering( private fun IrBuilderWithScope.throwUninitializedPropertyAccessException(name: String) = backendContext.throwUninitializedPropertyAccessException(this, name) - - private fun getOrBuildLateinitBackingField(originalField: IrField): IrField = - if (originalField.type.isMarkedNullable()) - originalField - else - backendContext.mapping.lateInitFieldToNullableField.getOrPut(originalField) { - backendContext.irFactory.buildField { - updateFrom(originalField) - type = originalField.type.makeNullable() - name = originalField.name - }.apply { - parent = originalField.parent - correspondingPropertySymbol = originalField.correspondingPropertySymbol - annotations = originalField.annotations - } - } - } -} \ No newline at end of file +}