[IR][codegen] Ignore SET_FIELD with default values

The runtime guarantees all newly allocated objects to be zeroed out, hence it is
redundant to initialize fields with default values. See KT-39100 for details.
This commit is contained in:
Igor Chevdar
2020-08-10 15:07:19 +05:00
parent 955521eaf0
commit 494916b19d
2 changed files with 27 additions and 2 deletions
@@ -1584,8 +1584,33 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
return !irClass.isFrozen
}
private fun isZeroConstValue(value: IrExpression): Boolean {
if (value !is IrConst<*>) return false
return when (value.kind) {
IrConstKind.Null -> true
IrConstKind.Boolean -> (value.value as Boolean) == false
IrConstKind.Byte -> (value.value as Byte) == 0.toByte()
IrConstKind.Char -> (value.value as Char) == 0.toChar()
IrConstKind.Short -> (value.value as Short) == 0.toShort()
IrConstKind.Int -> (value.value as Int) == 0
IrConstKind.Long -> (value.value as Long) == 0L
IrConstKind.Float -> (value.value as Float).toRawBits() == 0
IrConstKind.Double -> (value.value as Double).toRawBits() == 0L
IrConstKind.String -> false
}
}
private fun evaluateSetField(value: IrSetField): LLVMValueRef {
context.log{"evaluateSetField : ${ir2string(value)}"}
if (value.origin == IrStatementOrigin.INITIALIZE_FIELD
&& isZeroConstValue(value.value)) {
check(value.receiver is IrGetValue) { "Only IrGetValue expected for receiver of a field initializer" }
// All newly allocated objects are zeroed out, so it is redundant to initialize their
// fields with the default values. This is also aligned with the Kotlin/JVM behavior.
// See https://youtrack.jetbrains.com/issue/KT-39100 for details.
return codegen.theUnitInstanceRef.llvm
}
val valueToAssign = evaluateExpression(value.value)
val store = if (!value.symbol.owner.isStatic) {
val thisPtr = evaluateExpression(value.receiver!!)
@@ -69,7 +69,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
val initExpression = initializer.expression
initializers.add(IrBlockImpl(startOffset, endOffset,
context.irBuiltIns.unitType,
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
IrStatementOrigin.INITIALIZE_FIELD,
listOf(
IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
IrGetValueImpl(
@@ -78,7 +78,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
),
initExpression,
context.irBuiltIns.unitType,
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER)))
IrStatementOrigin.INITIALIZE_FIELD)))
)
// We shall keep initializer for constants for compile-time instantiation.