[JVM_IR] Optimize properties delegated to const val

We can omit `get` call to delegated property and inline
constant value directly. If we are not going to
do that, we can get a runtime exception because
all usages of const property will be inlined and the property
itself will be dropped.

#KT-63567 Fixed
#KT-63580 Fixed
This commit is contained in:
Ivan Kylchik
2023-11-27 14:09:49 +01:00
committed by Space Team
parent 1f97c268e1
commit 2b6845c032
24 changed files with 221 additions and 14 deletions
@@ -15478,12 +15478,24 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -15478,12 +15478,24 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -15419,12 +15419,24 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -15419,12 +15419,24 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -15419,12 +15419,24 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.util.getPackageFragment
import org.jetbrains.kotlin.ir.util.shallowCopyOrNull
import org.jetbrains.kotlin.ir.util.statements
internal val IrSimpleFunction.returnsResultOfStdlibCall: Boolean
@@ -68,3 +69,14 @@ internal fun IrProperty.getSingletonOrConstantForOptimizableDelegatedProperty():
fun IrProperty.isJvmOptimizableDelegate(): Boolean =
isDelegated && !isFakeOverride && backingField != null && // fast path
(getPropertyReferenceForOptimizableDelegatedProperty() != null || getSingletonOrConstantForOptimizableDelegatedProperty() != null)
internal val IrMemberAccessExpression<*>.constInitializer: IrExpression?
get() {
if (this !is IrPropertyReference) return null
val constPropertyField = if (field == null) {
symbol.owner.takeIf { it.isConst }?.backingField
} else {
field!!.owner.takeIf { it.isFinal && it.isStatic }
}
return constPropertyField?.initializer?.expression?.shallowCopyOrNull()
}
@@ -41,9 +41,14 @@ private class PropertyReferenceDelegationLowering(val context: JvmBackendContext
}
private class PropertyReferenceDelegationTransformer(val context: JvmBackendContext) : IrElementTransformerVoid() {
private fun IrSimpleFunction.accessorBody(delegate: IrPropertyReference, receiverFieldOrExpression: IrStatement?) =
private fun IrSimpleFunction.accessorBody(delegate: IrPropertyReference, receiverFieldOrExpression: IrStatement?): IrBody =
context.createIrBuilder(symbol, startOffset, endOffset).run {
val value = valueParameters.singleOrNull()?.let(::irGet)
val isGetter = value == null
if (isGetter) {
delegate.constInitializer?.let { return@run irExprBody(it) }
}
var boundReceiver = when (receiverFieldOrExpression) {
null -> null
is IrField -> irGetField(dispatchReceiverParameter?.let(::irGet), receiverFieldOrExpression)
@@ -54,7 +59,7 @@ private class PropertyReferenceDelegationTransformer(val context: JvmBackendCont
val unboundReceiver = extensionReceiverParameter ?: dispatchReceiverParameter
val field = delegate.field?.owner
val access = if (field == null) {
val accessor = if (value == null) delegate.getter!! else delegate.setter!!
val accessor = if (isGetter) delegate.getter!! else delegate.setter!!
irCall(accessor).apply {
// This has the same assumptions about receivers as `PropertyReferenceLowering.propertyReferenceKindFor`:
// only one receiver can be bound, and if the property has both, the extension receiver cannot be bound.
@@ -72,7 +77,7 @@ private class PropertyReferenceDelegationTransformer(val context: JvmBackendCont
}
} else {
val receiver = if (field.isStatic) null else boundReceiver ?: irGet(unboundReceiver!!)
if (value == null) irGetField(receiver, field) else irSetField(receiver, field, value)
if (isGetter) irGetField(receiver, field) else irSetField(receiver, field, value!!)
}
irExprBody(access)
}
@@ -67,17 +67,6 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : IrEle
private val IrMemberAccessExpression<*>.field: IrFieldSymbol?
get() = (this as? IrPropertyReference)?.field
private val IrMemberAccessExpression<*>.constInitializer: IrExpression?
get() {
if (this !is IrPropertyReference) return null
val constPropertyField = if (field == null) {
symbol.owner.takeIf { it.isConst }?.backingField
} else {
field!!.owner.takeIf { it.isFinal && it.isStatic }
}
return constPropertyField?.initializer?.expression?.shallowCopyOrNull()
}
private val arrayItemGetter =
context.ir.symbols.array.owner.functions.single { it.name.asString() == "get" }
@@ -0,0 +1,21 @@
// WITH_STDLIB
var sideEffect = "Fail"
object Property {
init {
sideEffect = "OK"
}
const val PROPERTY_VALUE: String = "O"
}
const val TOP_LEVEL_PROPERTY_VALUE: String = "K"
val value1: String by Property::PROPERTY_VALUE
val value2: String by ::TOP_LEVEL_PROPERTY_VALUE
fun box(): String {
if (sideEffect != "OK") return "Side effect wasn't executed"
return value1 + value2
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// WITH_STDLIB
// FILE: A.java
public class A {
public static final String OK = "OK";
}
// FILE: main.kt
val value: String by A::OK
fun box(): String {
return value
}
@@ -15053,12 +15053,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -15419,12 +15419,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -15419,12 +15419,24 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@Test
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@Test
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
@@ -12669,11 +12669,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstructorParameter.kt");
}
@TestMetadata("delegateToJavaFinalStaticField.kt")
public void testDelegateToJavaFinalStaticField() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToJavaFinalStaticField.kt");
}
@TestMetadata("delegateWithPrivateSet.kt")
public void testDelegateWithPrivateSet() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateWithPrivateSet.kt");
@@ -11525,6 +11525,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -11525,6 +11525,12 @@ public class FirJsES6CodegenBoxTestGenerated extends AbstractFirJsES6CodegenBoxT
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -11525,6 +11525,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -11525,6 +11525,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -12550,6 +12550,12 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -12844,6 +12844,12 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -12256,6 +12256,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -12551,6 +12551,12 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -11501,6 +11501,12 @@ public class FirWasmCodegenBoxTestGenerated extends AbstractFirWasmCodegenBoxTes
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {
@@ -11501,6 +11501,12 @@ public class K1WasmCodegenBoxTestGenerated extends AbstractK1WasmCodegenBoxTest
runTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@Test
@TestMetadata("delegateToConstVal.kt")
public void testDelegateToConstVal() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/delegateToConstVal.kt");
}
@Test
@TestMetadata("delegateToConstructorParameter.kt")
public void testDelegateToConstructorParameter() throws Exception {