From 8e347f9f399568c88414dce5009712d7f5ad1ee5 Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Thu, 20 Sep 2018 18:09:26 +0300 Subject: [PATCH] [JS IR BE] lateinit support * Functions with IrExpressionBody are lowered to IrBlockBody * Implemented throwUninitializedPropertyAccessException function --- .../backend/common/lower/LateinitLowering.kt | 9 +++++---- .../kotlin/ir/backend/js/JsIrBackendContext.kt | 9 ++------- .../backend/js/lower/BlockDecomposerLowering.kt | 17 ++++++++++++----- .../codegen/box/properties/lateinit/accessor.kt | 1 - .../properties/lateinit/accessorException.kt | 1 - .../box/properties/lateinit/exceptionField.kt | 1 - .../box/properties/lateinit/exceptionGetter.kt | 1 - .../codegen/box/properties/lateinit/override.kt | 1 - .../properties/lateinit/overrideException.kt | 1 - .../box/properties/lateinit/privateSetter.kt | 1 - .../lateinit/privateSetterFromLambda.kt | 1 - .../lateinit/privateSetterViaSubclass.kt | 1 - .../box/properties/lateinit/simpleVar.kt | 1 - .../lateinit/topLevel/accessorException.kt | 1 - .../topLevel/accessorForTopLevelLateinit.kt | 1 - .../lateinit/topLevel/topLevelLateinit.kt | 1 - .../topLevel/uninitializedMemberAccess.kt | 1 - .../lateinit/topLevel/uninitializedRead.kt | 1 - .../testData/box/initialize/lateinit.kt | 1 - .../box/initialize/uninitializedLateinit.kt | 2 +- libraries/stdlib/js/irRuntime/exceptions.kt | 6 +++++- 21 files changed, 25 insertions(+), 34 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt index da63924928c..38254229985 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlock +import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl @@ -50,19 +51,19 @@ class LateinitLowering( val endOffset = getter.endOffset val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset) irBuilder.run { - val block = irBlock(type) + val body = IrBlockBodyImpl(startOffset, endOffset) val resultVar = scope.createTemporaryVariable( irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField) ) - block.statements.add(resultVar) + body.statements.add(resultVar) val throwIfNull = irIfThenElse( context.irBuiltIns.nothingType, irNotEquals(irGet(resultVar), irNull()), irReturn(irGet(resultVar)), throwUninitializedPropertyAccessException(backingField) ) - block.statements.add(throwIfNull) - getter.body = IrExpressionBodyImpl(startOffset, endOffset, block) + body.statements.add(throwIfNull) + getter.body = body } } }) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 8b4650a9bd7..0e6ea87fd0d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -193,13 +193,8 @@ class JsIrBackendContext( override val ThrowTypeCastException get () = irBuiltIns.throwCceSymbol - override val ThrowUninitializedPropertyAccessException = symbolTable.referenceSimpleFunction( - irBuiltIns.defineOperator( - "throwUninitializedPropertyAccessException", - builtIns.nothingType, - listOf(builtIns.stringType) - ).descriptor - ) + override val ThrowUninitializedPropertyAccessException= + symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwUninitializedPropertyAccessException")).single()) override val stringBuilder get() = TODO("not implemented") diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt index 3e8104213e2..1902c215342 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt @@ -38,9 +38,19 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine } fun lower(irFunction: IrFunction) { + (irFunction.body as? IrExpressionBody)?.apply { + irFunction.body = toBlockBody(irFunction) + } irFunction.accept(decomposerTransformer, null) } + private fun IrExpressionBody.toBlockBody(containingFunction: IrFunction): IrBlockBody { + val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType) + return IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply { + statements += returnStatement + } + } + fun lower(irField: IrField, container: IrDeclarationContainer): List { irField.initializer?.apply { val initFunction = JsIrBuilder.buildFunction(irField.name.asString() + "\$init\$", irField.visibility).also { @@ -48,17 +58,14 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine it.returnType = expression.type } - val returnStatement = JsIrBuilder.buildReturn(initFunction.symbol, expression, nothingType) - val newBody = IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply { - statements += returnStatement - } + val newBody = toBlockBody(initFunction) initFunction.body = newBody lower(initFunction) val lastStatement = newBody.statements.last() - if (lastStatement != returnStatement || (lastStatement as IrReturn).value != expression) { + if (newBody.statements.size > 1 || lastStatement !is IrReturn || lastStatement.value != expression) { expression = JsIrBuilder.buildCall(initFunction.symbol, expression.type) return listOf(initFunction, irField) } diff --git a/compiler/testData/codegen/box/properties/lateinit/accessor.kt b/compiler/testData/codegen/box/properties/lateinit/accessor.kt index 56824de49d1..441bc5ec592 100644 --- a/compiler/testData/codegen/box/properties/lateinit/accessor.kt +++ b/compiler/testData/codegen/box/properties/lateinit/accessor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR public class A { fun setMyStr() { diff --git a/compiler/testData/codegen/box/properties/lateinit/accessorException.kt b/compiler/testData/codegen/box/properties/lateinit/accessorException.kt index 66a53163d43..8650a0fad11 100644 --- a/compiler/testData/codegen/box/properties/lateinit/accessorException.kt +++ b/compiler/testData/codegen/box/properties/lateinit/accessorException.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR public class A { fun getMyStr(): String { diff --git a/compiler/testData/codegen/box/properties/lateinit/exceptionField.kt b/compiler/testData/codegen/box/properties/lateinit/exceptionField.kt index e5d76b16878..76120e7eff5 100644 --- a/compiler/testData/codegen/box/properties/lateinit/exceptionField.kt +++ b/compiler/testData/codegen/box/properties/lateinit/exceptionField.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class A { private lateinit var str: String diff --git a/compiler/testData/codegen/box/properties/lateinit/exceptionGetter.kt b/compiler/testData/codegen/box/properties/lateinit/exceptionGetter.kt index 714b261829e..35449a38fad 100644 --- a/compiler/testData/codegen/box/properties/lateinit/exceptionGetter.kt +++ b/compiler/testData/codegen/box/properties/lateinit/exceptionGetter.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class A { public lateinit var str: String } diff --git a/compiler/testData/codegen/box/properties/lateinit/override.kt b/compiler/testData/codegen/box/properties/lateinit/override.kt index 476288b219c..02d05d723be 100644 --- a/compiler/testData/codegen/box/properties/lateinit/override.kt +++ b/compiler/testData/codegen/box/properties/lateinit/override.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR interface Intf { val str: String } diff --git a/compiler/testData/codegen/box/properties/lateinit/overrideException.kt b/compiler/testData/codegen/box/properties/lateinit/overrideException.kt index ed8db88250e..ffc98f1f128 100644 --- a/compiler/testData/codegen/box/properties/lateinit/overrideException.kt +++ b/compiler/testData/codegen/box/properties/lateinit/overrideException.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR interface Intf { val str: String } diff --git a/compiler/testData/codegen/box/properties/lateinit/privateSetter.kt b/compiler/testData/codegen/box/properties/lateinit/privateSetter.kt index 5a598c66fb9..75bdc125e64 100644 --- a/compiler/testData/codegen/box/properties/lateinit/privateSetter.kt +++ b/compiler/testData/codegen/box/properties/lateinit/privateSetter.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class My { lateinit var x: String private set diff --git a/compiler/testData/codegen/box/properties/lateinit/privateSetterFromLambda.kt b/compiler/testData/codegen/box/properties/lateinit/privateSetterFromLambda.kt index d3ade4535e3..80baa4ec688 100644 --- a/compiler/testData/codegen/box/properties/lateinit/privateSetterFromLambda.kt +++ b/compiler/testData/codegen/box/properties/lateinit/privateSetterFromLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class My { lateinit var x: String private set diff --git a/compiler/testData/codegen/box/properties/lateinit/privateSetterViaSubclass.kt b/compiler/testData/codegen/box/properties/lateinit/privateSetterViaSubclass.kt index f524b9089ed..be73743b028 100644 --- a/compiler/testData/codegen/box/properties/lateinit/privateSetterViaSubclass.kt +++ b/compiler/testData/codegen/box/properties/lateinit/privateSetterViaSubclass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR open class A { lateinit var x: String private set diff --git a/compiler/testData/codegen/box/properties/lateinit/simpleVar.kt b/compiler/testData/codegen/box/properties/lateinit/simpleVar.kt index ece5390bc35..b5314ead1c8 100644 --- a/compiler/testData/codegen/box/properties/lateinit/simpleVar.kt +++ b/compiler/testData/codegen/box/properties/lateinit/simpleVar.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class A { public lateinit var str: String } diff --git a/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorException.kt b/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorException.kt index a3a79242460..a6ecf9ab272 100644 --- a/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorException.kt +++ b/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorException.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // LANGUAGE_VERSION: 1.2 // WITH_RUNTIME // FILE: lateinit.kt diff --git a/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorForTopLevelLateinit.kt b/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorForTopLevelLateinit.kt index 27caf2d77a8..aca5474f004 100644 --- a/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorForTopLevelLateinit.kt +++ b/compiler/testData/codegen/box/properties/lateinit/topLevel/accessorForTopLevelLateinit.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // LANGUAGE_VERSION: 1.2 // FILE: lateinit.kt diff --git a/compiler/testData/codegen/box/properties/lateinit/topLevel/topLevelLateinit.kt b/compiler/testData/codegen/box/properties/lateinit/topLevel/topLevelLateinit.kt index 9f2c1d793ef..2eb9c779585 100644 --- a/compiler/testData/codegen/box/properties/lateinit/topLevel/topLevelLateinit.kt +++ b/compiler/testData/codegen/box/properties/lateinit/topLevel/topLevelLateinit.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // LANGUAGE_VERSION: 1.2 lateinit var ok: String diff --git a/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedMemberAccess.kt b/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedMemberAccess.kt index f53adfa1842..0c496b9005b 100644 --- a/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedMemberAccess.kt +++ b/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedMemberAccess.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // LANGUAGE_VERSION: 1.2 // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedRead.kt b/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedRead.kt index c011c4cf402..bc4af80a0c4 100644 --- a/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedRead.kt +++ b/compiler/testData/codegen/box/properties/lateinit/topLevel/uninitializedRead.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // LANGUAGE_VERSION: 1.2 // WITH_RUNTIME diff --git a/js/js.translator/testData/box/initialize/lateinit.kt b/js/js.translator/testData/box/initialize/lateinit.kt index 5478c21619d..0abe25f70e5 100644 --- a/js/js.translator/testData/box/initialize/lateinit.kt +++ b/js/js.translator/testData/box/initialize/lateinit.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1233 class Greeting { val noon = xrun { diff --git a/js/js.translator/testData/box/initialize/uninitializedLateinit.kt b/js/js.translator/testData/box/initialize/uninitializedLateinit.kt index b98f18e81e8..ddd8023fe0a 100644 --- a/js/js.translator/testData/box/initialize/uninitializedLateinit.kt +++ b/js/js.translator/testData/box/initialize/uninitializedLateinit.kt @@ -1,4 +1,4 @@ -// IGNORE_BACKEND: JS_IR + // EXPECTED_REACHABLE_NODES: 1336 // MODULE: lib // FILE: lib.kt diff --git a/libraries/stdlib/js/irRuntime/exceptions.kt b/libraries/stdlib/js/irRuntime/exceptions.kt index 9fa5eb860cc..4a8c9c7941c 100644 --- a/libraries/stdlib/js/irRuntime/exceptions.kt +++ b/libraries/stdlib/js/irRuntime/exceptions.kt @@ -98,4 +98,8 @@ fun THROW_NPE() { throw NullPointerException() } -fun error(s: String): Nothing = throw IllegalStateException(s, null) \ No newline at end of file +fun error(s: String): Nothing = throw IllegalStateException(s, null) + +@PublishedApi +internal fun throwUninitializedPropertyAccessException(name: String): Nothing = + throw UninitializedPropertyAccessException("lateinit property $name has not been initialized") \ No newline at end of file