Use GETFIELD instead of unbox-impl inside inline classes
#KT-36783 Fixed
This commit is contained in:
+6
@@ -3512,6 +3512,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericNoUnbox.kt")
|
||||
public void testGenericNoUnbox() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("hashCodeIsCalledByInlineClass.kt")
|
||||
public void testHashCodeIsCalledByInlineClass() throws Exception {
|
||||
|
||||
+14
-2
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.v
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isTypeParameter
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
@@ -51,7 +53,17 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
|
||||
}
|
||||
|
||||
!isFromTypeUnboxed && isToTypeUnboxed -> {
|
||||
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
|
||||
val irClass = codegen.irFunction.parentAsClass
|
||||
if (irClass.isInline && irClass.symbol == irType.classifierOrNull && !irType.isNullable()) {
|
||||
// Use getfield instead of unbox-impl inside inline classes
|
||||
codegen.v.getfield(
|
||||
typeMapper.classInternalName(irClass),
|
||||
irClass.inlineClassFieldName.asString(),
|
||||
typeMapper.mapType(irType).descriptor
|
||||
)
|
||||
} else {
|
||||
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class ICInt(val x: Int) // unbox-impl in generated 'equals'
|
||||
|
||||
suspend fun suspendICInt(): ICInt = ICInt(1) // box-impl
|
||||
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class ICAny(val x: Any)
|
||||
|
||||
suspend fun suspendICAny(): ICAny = ICAny("")
|
||||
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class IC0(val x: Any) // IC0.unbox-impl in generated 'equals'
|
||||
inline class IC1(val x: IC0) // IC1.unbox-impl in generated 'equals'
|
||||
|
||||
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface I
|
||||
|
||||
inline class ICI(val i: I): I
|
||||
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class ICString(val x: String)
|
||||
|
||||
suspend fun suspendICString(): ICString = ICString("")
|
||||
|
||||
@@ -20,10 +20,5 @@ fun takeNullable(a: UInt?) {}
|
||||
// -- 1 before takeAnyInside
|
||||
// 2 INVOKESTATIC UInt\.box
|
||||
|
||||
// JVM_TEMPLATES:
|
||||
// -- equals-impl
|
||||
// 1 INVOKEVIRTUAL UInt\.unbox
|
||||
|
||||
// JVM_IR_TEMPLATES:
|
||||
// -- getA, toString, hashCode, equals-impl, equals
|
||||
// 5 INVOKEVIRTUAL UInt\.unbox
|
||||
Vendored
-3
@@ -1,7 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36783 Consider generating GETFIELD instructions instead of unbox-impl calls in special methods of inline classes in JVM_IR
|
||||
|
||||
inline class UInt(val value: Int)
|
||||
inline class ULong(val value: Long)
|
||||
|
||||
+7
-4
@@ -1,6 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
// FILE: utils.kt
|
||||
|
||||
@@ -29,8 +27,13 @@ fun labeled(): ULong? {
|
||||
}
|
||||
|
||||
// @TestKt.class:
|
||||
// 3 INVOKESTATIC ULong\.box
|
||||
// 0 INVOKEVIRTUAL ULong.unbox
|
||||
|
||||
// 0 valueOf
|
||||
// 0 intValue
|
||||
// 0 intValue
|
||||
|
||||
// JVM_TEMPLATES:
|
||||
// 3 INVOKESTATIC ULong\.box
|
||||
|
||||
// JVM_IR_TEMPLATES:
|
||||
// 2 INVOKESTATIC ULong\.box
|
||||
|
||||
+7
-5
@@ -1,7 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36783 Consider generating GETFIELD instructions instead of unbox-impl calls in special methods of inline classes in JVM_IR
|
||||
|
||||
inline class Foo(val x: Int) {
|
||||
fun empty() {}
|
||||
@@ -19,7 +16,12 @@ inline class Foo(val x: Int) {
|
||||
// 1 INVOKESTATIC Foo\.withParam-impl \(ILjava/lang/String;\)V
|
||||
// 1 INVOKESTATIC Foo\.withInlineClassParam-GWb7d6U \(II\)V
|
||||
// 5 INVOKEVIRTUAL
|
||||
// 2 INVOKEVIRTUAL java/lang/StringBuilder\.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder;
|
||||
// 1 INVOKEVIRTUAL java/lang/StringBuilder\.append \(I\)Ljava/lang/StringBuilder;
|
||||
// 1 INVOKEVIRTUAL java/lang/StringBuilder.toString \(\)Ljava/lang/String;
|
||||
// 1 INVOKEVIRTUAL Foo.unbox-impl \(\)I
|
||||
// 1 INVOKEVIRTUAL Foo.unbox-impl \(\)I
|
||||
|
||||
// JVM_TEMPLATES:
|
||||
// 2 INVOKEVIRTUAL java/lang/StringBuilder\.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder;
|
||||
|
||||
// JVM_IR_TEMPLATES:
|
||||
// 1 INVOKEVIRTUAL java/lang/StringBuilder\.append \(Ljava/lang/String;\)Ljava/lang/StringBuilder;
|
||||
@@ -0,0 +1,6 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class A<T>(val a: Any?)
|
||||
|
||||
// In equals-impl
|
||||
// 1 INVOKEVIRTUAL A\.unbox-impl
|
||||
-3
@@ -1,7 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36783 Consider generating GETFIELD instructions instead of unbox-impl calls in special methods of inline classes in JVM_IR
|
||||
|
||||
inline class UInt(private val value: Int)
|
||||
|
||||
|
||||
+6
@@ -3380,6 +3380,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericNoUnbox.kt")
|
||||
public void testGenericNoUnbox() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("hashCodeIsCalledByInlineClass.kt")
|
||||
public void testHashCodeIsCalledByInlineClass() throws Exception {
|
||||
|
||||
+6
@@ -3512,6 +3512,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericNoUnbox.kt")
|
||||
public void testGenericNoUnbox() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("hashCodeIsCalledByInlineClass.kt")
|
||||
public void testHashCodeIsCalledByInlineClass() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user