JVM IR: Avoid unnecessary CHECKCASTs in enum classes
This commit is contained in:
committed by
max-kammerer
parent
cb3a4727cf
commit
b6b8dd1eab
+11
-1
@@ -539,7 +539,17 @@ class ExpressionCodegen(
|
|||||||
ownerType.internalName
|
ownerType.internalName
|
||||||
} ?: typeMapper.mapClass(callee.parentAsClass).internalName
|
} ?: typeMapper.mapClass(callee.parentAsClass).internalName
|
||||||
return if (expression is IrSetField) {
|
return if (expression is IrSetField) {
|
||||||
expression.value.accept(this, data).materializeAt(fieldType, callee.type)
|
val value = expression.value.accept(this, data)
|
||||||
|
|
||||||
|
// We only initialize enum entries with a subtype of `fieldType` and can avoid the CHECKCAST.
|
||||||
|
// This is important for some tools which analyze bytecode for enum classes by looking at the
|
||||||
|
// initializer of the $VALUES field.
|
||||||
|
if (callee.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) {
|
||||||
|
value.materialize()
|
||||||
|
} else {
|
||||||
|
value.materializeAt(fieldType, callee.type)
|
||||||
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
isStatic -> mv.putstatic(ownerName, fieldName, fieldType.descriptor)
|
isStatic -> mv.putstatic(ownerName, fieldName, fieldType.descriptor)
|
||||||
else -> mv.putfield(ownerName, fieldName, fieldType.descriptor)
|
else -> mv.putfield(ownerName, fieldName, fieldType.descriptor)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
enum class Foo {
|
||||||
|
A, B, C { override fun result() = "OK" };
|
||||||
|
open fun result() = "Fail"
|
||||||
|
}
|
||||||
|
|
||||||
|
// JVM_TEMPLATES:
|
||||||
|
// There are two CHECKCASTs, one in Foo.valueOf and one in Foo.values
|
||||||
|
// 2 CHECKCAST
|
||||||
|
|
||||||
|
// JVM_IR_TEMPLATES:
|
||||||
|
// There should be only one CHECKCAST in Foo.valueOf
|
||||||
|
// 1 CHECKCAST
|
||||||
@@ -1855,6 +1855,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/enum"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/enum"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("enumCheckcasts.kt")
|
||||||
|
public void testEnumCheckcasts() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/enum/enumCheckcasts.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt18731.kt")
|
@TestMetadata("kt18731.kt")
|
||||||
public void testKt18731() throws Exception {
|
public void testKt18731() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/enum/kt18731.kt");
|
runTest("compiler/testData/codegen/bytecodeText/enum/kt18731.kt");
|
||||||
|
|||||||
+5
@@ -1810,6 +1810,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/enum"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/enum"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("enumCheckcasts.kt")
|
||||||
|
public void testEnumCheckcasts() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/enum/enumCheckcasts.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt18731.kt")
|
@TestMetadata("kt18731.kt")
|
||||||
public void testKt18731() throws Exception {
|
public void testKt18731() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/enum/kt18731.kt");
|
runTest("compiler/testData/codegen/bytecodeText/enum/kt18731.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user