[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:
+25
@@ -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!!)
|
||||
|
||||
+2
-2
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user