JVM_IR: do not erase constant non-static field initializers...

...unless in 1.4 mode.
This commit is contained in:
pyos
2019-11-25 12:13:09 +01:00
committed by Alexander Udalov
parent fc6b03b08f
commit e4b1599457
5 changed files with 18 additions and 8 deletions
@@ -51,14 +51,21 @@ abstract class InitializersLoweringBase(open val context: CommonBackendContext)
irClass.declarations.removeAll { it is IrAnonymousInitializer && filter(it) } irClass.declarations.removeAll { it is IrAnonymousInitializer && filter(it) }
} }
protected open fun shouldEraseFieldInitializer(irField: IrField): Boolean = true
private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? = private fun handleField(irClass: IrClass, declaration: IrField): IrStatement? =
declaration.initializer?.run { declaration.initializer?.run {
val receiver = if (!declaration.isStatic) // TODO isStaticField val receiver = if (!declaration.isStatic) // TODO isStaticField
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol) IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol)
else else
null null
declaration.initializer = null val value = if (shouldEraseFieldInitializer(declaration)) {
IrSetFieldImpl(startOffset, endOffset, declaration.symbol, receiver, expression, context.irBuiltIns.unitType) declaration.initializer = null
expression
} else {
expression.deepCopyWithSymbols()
}
IrSetFieldImpl(startOffset, endOffset, declaration.symbol, receiver, value, context.irBuiltIns.unitType)
} }
private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement = private fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement =
@@ -173,8 +173,13 @@ private val staticInitializersPhase = makeIrFilePhase(
description = "Move code from object init blocks and static field initializers to a new <clinit> function" description = "Move code from object init blocks and static field initializers to a new <clinit> function"
) )
private val initializersPhase = makeIrFilePhase( private val initializersPhase = makeIrFilePhase<JvmBackendContext>(
::InitializersLowering, { context ->
object : InitializersLowering(context) {
override fun shouldEraseFieldInitializer(irField: IrField): Boolean =
irField.constantValue(context) == null
}
},
name = "Initializers", name = "Initializers",
description = "Merge init blocks and field initializers into constructors", description = "Merge init blocks and field initializers into constructors",
stickyPostconditions = setOf(fun(irFile: IrFile) { stickyPostconditions = setOf(fun(irFile: IrFile) {
@@ -33,12 +33,12 @@ fun IrField.constantValue(context: JvmBackendContext? = null): IrConst<*>? {
// JVM has a ConstantValue attribute which does two things: // JVM has a ConstantValue attribute which does two things:
// 1. allows the field to be inlined into other modules; // 1. allows the field to be inlined into other modules;
// 2. implicitly generates an initialization of that field in <clinit> // 2. implicitly generates an initialization of that field in <clinit>
// It is only allowed on static final fields of primitive/string types. Java and Kotlin < 1.4 // It is only allowed on final fields of primitive/string types. Java and Kotlin < 1.4
// apply it whenever possible; Kotlin >= 1.4 only applies it to `const val`s to avoid making // apply it whenever possible; Kotlin >= 1.4 only applies it to `const val`s to avoid making
// values part of the library's ABI unless explicitly requested by the author. // values part of the library's ABI unless explicitly requested by the author.
val allowImplicitConst = val allowImplicitConst =
context != null && !context.state.languageVersionSettings.supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals) context != null && !context.state.languageVersionSettings.supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals)
val implicitConst = isStatic && isFinal && (origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB || val implicitConst = isFinal && ((isStatic && origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) ||
(allowImplicitConst && (type.isPrimitiveType() || type.isStringClassType()))) (allowImplicitConst && (type.isPrimitiveType() || type.isStringClassType())))
return if (implicitConst || correspondingPropertySymbol?.owner?.isConst == true) value else null return if (implicitConst || correspondingPropertySymbol?.owner?.isConst == true) value else null
} }
@@ -1,5 +1,4 @@
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals +JvmFieldInInterface // !LANGUAGE: -NoConstantValueAttributeForNonConstVals +JvmFieldInInterface
// IGNORE_BACKEND: JVM_IR
class C { class C {
val testClassVal = 100 val testClassVal = 100
@@ -1,5 +1,4 @@
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals // !LANGUAGE: -NoConstantValueAttributeForNonConstVals
// IGNORE_BACKEND: JVM_IR
//ALLOW_AST_ACCESS //ALLOW_AST_ACCESS
package test package test