JVM IR: Don't produce CHECKCASTs on null constants (KT-36650)
This commit is contained in:
committed by
Alexander Udalov
parent
7503f134c2
commit
53fe30eb45
+1
-1
@@ -718,7 +718,7 @@ class ExpressionCodegen(
|
|||||||
is Float -> mv.fconst(value)
|
is Float -> mv.fconst(value)
|
||||||
is Double -> mv.dconst(value)
|
is Double -> mv.dconst(value)
|
||||||
is Number -> mv.iconst(value.toInt())
|
is Number -> mv.iconst(value.toInt())
|
||||||
else -> mv.aconst(value)
|
else -> if (expression.kind == IrConstKind.Null) return nullConstant else mv.aconst(value)
|
||||||
}
|
}
|
||||||
return expression.onStack
|
return expression.onStack
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
|||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -162,3 +163,12 @@ val IrType.unboxed: IrType
|
|||||||
// A Non-materialized value of Unit type that is only materialized through coercion.
|
// A Non-materialized value of Unit type that is only materialized through coercion.
|
||||||
val ExpressionCodegen.unitValue: PromisedValue
|
val ExpressionCodegen.unitValue: PromisedValue
|
||||||
get() = MaterialValue(this, Type.VOID_TYPE, context.irBuiltIns.unitType)
|
get() = MaterialValue(this, Type.VOID_TYPE, context.irBuiltIns.unitType)
|
||||||
|
|
||||||
|
val ExpressionCodegen.nullConstant: PromisedValue
|
||||||
|
get() = object : PromisedValue(this, AsmTypes.OBJECT_TYPE, context.irBuiltIns.nothingNType) {
|
||||||
|
override fun materializeAt(target: Type, irTarget: IrType) {
|
||||||
|
mv.aconst(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun discard() {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// The IR prduced by FIR implicitly casts `null` of type `Nothing?` to type `Int` instead of `Int?` in `getColumnCount`.
|
||||||
|
|
||||||
public class StockMarketTableModel() {
|
public class StockMarketTableModel() {
|
||||||
|
|
||||||
public fun getColumnCount() : Int {
|
public fun getColumnCount() : Int {
|
||||||
|
|||||||
-4
@@ -2,7 +2,6 @@
|
|||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||||
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$1 {
|
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1$1 {
|
||||||
field L$0: java.lang.Object
|
field L$0: java.lang.Object
|
||||||
field L$1: java.lang.Object
|
|
||||||
field label: int
|
field label: int
|
||||||
synthetic field result: java.lang.Object
|
synthetic field result: java.lang.Object
|
||||||
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
|
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1
|
||||||
@@ -98,7 +97,6 @@ public final class CrossinlineKt$consumeEach$2 {
|
|||||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||||
public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||||
field L$0: java.lang.Object
|
field L$0: java.lang.Object
|
||||||
field L$1: java.lang.Object
|
|
||||||
field label: int
|
field label: int
|
||||||
synthetic field result: java.lang.Object
|
synthetic field result: java.lang.Object
|
||||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
|
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
|
||||||
@@ -190,7 +188,6 @@ public final class CrossinlineKt$range$$inlined$source$1$1 {
|
|||||||
field I$1: int
|
field I$1: int
|
||||||
field L$0: java.lang.Object
|
field L$0: java.lang.Object
|
||||||
field L$1: java.lang.Object
|
field L$1: java.lang.Object
|
||||||
field L$2: java.lang.Object
|
|
||||||
field label: int
|
field label: int
|
||||||
synthetic field result: java.lang.Object
|
synthetic field result: java.lang.Object
|
||||||
synthetic final field this$0: CrossinlineKt$range$$inlined$source$1
|
synthetic final field this$0: CrossinlineKt$range$$inlined$source$1
|
||||||
@@ -216,7 +213,6 @@ public final class CrossinlineKt$range$$inlined$source$1 {
|
|||||||
public final class CrossinlineKt$source$1$consume$1 {
|
public final class CrossinlineKt$source$1$consume$1 {
|
||||||
// source: 'crossinline.kt'
|
// source: 'crossinline.kt'
|
||||||
field L$0: java.lang.Object
|
field L$0: java.lang.Object
|
||||||
field L$1: java.lang.Object
|
|
||||||
field label: int
|
field label: int
|
||||||
synthetic field result: java.lang.Object
|
synthetic field result: java.lang.Object
|
||||||
synthetic final field this$0: CrossinlineKt$source$1
|
synthetic final field this$0: CrossinlineKt$source$1
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TODO KT-36650 Don't generate CHECKCAST on null values in JVM_IR
|
|
||||||
// KT-15411 Unnecessary CHECKCAST bytecode when dealing with null
|
|
||||||
|
|
||||||
fun test1(): String? {
|
fun test1(): String? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-6
@@ -16,14 +16,12 @@ fun test(ss: List<String?>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
|
||||||
// 2 POP
|
|
||||||
// 0 INVOKESTATIC java/lang/Boolean\.valueOf
|
// 0 INVOKESTATIC java/lang/Boolean\.valueOf
|
||||||
// 0 CHECKCAST java/lang/Boolean
|
// 0 CHECKCAST java/lang/Boolean
|
||||||
// 0 ACONST_NULL
|
// 0 ACONST_NULL
|
||||||
|
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// 2 POP
|
// 2 POP
|
||||||
// 0 INVOKESTATIC java/lang/Boolean\.valueOf
|
|
||||||
// 1 CHECKCAST java/lang/Boolean
|
// JVM_IR_TEMPLATES
|
||||||
// 1 ACONST_NULL
|
// 1 POP
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ suspend fun test() {
|
|||||||
blackhole(a)
|
blackhole(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// jsut before suspension point
|
// 2 PUTFIELD .*L\$0 : Ljava/lang/Object;
|
||||||
|
|
||||||
|
// JVM_TEMPLATES:
|
||||||
|
// just before suspension point
|
||||||
// 1 ACONST_NULL
|
// 1 ACONST_NULL
|
||||||
// 2 PUTFIELD .*L\$0 : Ljava/lang/Object;
|
|
||||||
|
// JVM_IR_TEMPLATES:
|
||||||
|
// two stores to initialize the `a` variable and one null constant to store in the spill slot.
|
||||||
|
// 3 ACONST_NULL
|
||||||
|
|||||||
Reference in New Issue
Block a user