diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java index 946d4094edd..986cc39c2f4 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt index 24735061dde..93e34a2398f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt @@ -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 } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/inlineClassBoxingInSuspendFunReturn_Primitive.kt b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/inlineClassBoxingInSuspendFunReturn_Primitive.kt index 0782f7f426a..35bfd5f8ee4 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/inlineClassBoxingInSuspendFunReturn_Primitive.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/inlineClassBoxingInSuspendFunReturn_Primitive.kt @@ -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 diff --git a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_Any.kt b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_Any.kt index 9ab22dfd5f8..290373dda7b 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_Any.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_Any.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR - inline class ICAny(val x: Any) suspend fun suspendICAny(): ICAny = ICAny("") diff --git a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_InlineAny.kt b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_InlineAny.kt index 4ac93d801b9..617db2dcf86 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_InlineAny.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_InlineAny.kt @@ -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' diff --git a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_SameJvmType.kt b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_SameJvmType.kt index 672c1425b5a..a2fc9698db4 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_SameJvmType.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_SameJvmType.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR - interface I inline class ICI(val i: I): I diff --git a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_String.kt b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_String.kt index 4eb6420ef96..47971706b75 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_String.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/inlineClasses/noInlineClassBoxingInSuspendFunReturn_String.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR - inline class ICString(val x: String) suspend fun suspendICString(): ICString = ICString("") diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/boxThisOfInlineClass.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/boxThisOfInlineClass.kt index 93298f7e82c..b4c4c832047 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/boxThisOfInlineClass.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/boxThisOfInlineClass.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/boxUnboxOfInlineClassesWithFunctionalTypes.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/boxUnboxOfInlineClassesWithFunctionalTypes.kt index eb644fb398d..7fbaa78c2f9 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/boxUnboxOfInlineClassesWithFunctionalTypes.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/boxUnboxOfInlineClassesWithFunctionalTypes.kt @@ -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) diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/boxingForNonLocalAndLabeledReturnsOfInlineClasses.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/boxingForNonLocalAndLabeledReturnsOfInlineClasses.kt index fdfcfd7e46f..d79c33e0f20 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/boxingForNonLocalAndLabeledReturnsOfInlineClasses.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/boxingForNonLocalAndLabeledReturnsOfInlineClasses.kt @@ -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 \ No newline at end of file +// 0 intValue + +// JVM_TEMPLATES: +// 3 INVOKESTATIC ULong\.box + +// JVM_IR_TEMPLATES: +// 2 INVOKESTATIC ULong\.box diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt index b0ab4ce7a36..78a8a23365e 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/callMemberMethodsInsideInlineClass.kt @@ -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 \ No newline at end of file +// 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; \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt new file mode 100644 index 00000000000..9ee6911cf9d --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt @@ -0,0 +1,6 @@ +// !LANGUAGE: +InlineClasses + +inline class A(val a: Any?) + +// In equals-impl +// 1 INVOKEVIRTUAL A\.unbox-impl \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/uIntArrayIteratorWithoutBoxing.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/uIntArrayIteratorWithoutBoxing.kt index 1470cec631d..e0956f0beab 100644 --- a/compiler/testData/codegen/bytecodeText/inlineClasses/uIntArrayIteratorWithoutBoxing.kt +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/uIntArrayIteratorWithoutBoxing.kt @@ -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) diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java index 767a79d6fb2..36a0822605d 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java @@ -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 { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java index c571c834edb..61755a1a2ad 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java @@ -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 {