From 78ab957bfe25b373a52f15802be5f18317f9f5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Mon, 31 Aug 2020 14:59:44 +0200 Subject: [PATCH] JVM IR: Fix mangling for suspend functions with inline class params (KT-41374) --- .../jvm/lower/inlineclasses/InlineClassAbi.kt | 13 +++++++++++-- .../inlineClasses/suspendFunctionMangling.kt | 19 +++++++++++++++++++ .../codegen/BytecodeTextTestGenerated.java | 5 +++++ .../ir/IrBytecodeTextTestGenerated.java | 5 +++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeText/inlineClasses/suspendFunctionMangling.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt index 283edd93c3d..b4006b03595 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/InlineClassAbi.kt @@ -100,8 +100,17 @@ object InlineClassAbi { fun returnHashSuffix(irFunction: IrFunction) = md5base64(":${irFunction.returnType.eraseToString()}") - private fun hashSuffix(irFunction: IrFunction) = - md5base64(irFunction.fullValueParameterList.joinToString { it.type.eraseToString() }) + private fun hashSuffix(irFunction: IrFunction): String { + val signatureElementsForMangling = + irFunction.fullValueParameterList.mapTo(mutableListOf()) { it.type.eraseToString() } + if (irFunction.isSuspend) { + // The JVM backend computes mangled names after creating suspend function views, but before default argument + // stub insertion. It would be nice if this part of the continuation lowering happened earlier in the pipeline. + // TODO: Move suspend function view creation before JvmInlineClassLowering. + signatureElementsForMangling += "Lkotlin.coroutines.Continuation;" + } + return md5base64(signatureElementsForMangling.joinToString()) + } private fun IrType.eraseToString() = buildString { append('L') diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/suspendFunctionMangling.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/suspendFunctionMangling.kt new file mode 100644 index 00000000000..730fcca579d --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/suspendFunctionMangling.kt @@ -0,0 +1,19 @@ +// KT-41374 +// !LANGUAGE: +InlineClasses +// FILE: test.kt + +package a + +inline class P(val i: Int) + +suspend fun foo(p: P = P(1)) {} + +suspend fun bar(p: P) {} + +// The mangled name for a suspend function includes the continuation parameter in the hash computation, but not the +// default argument mask and handler. + +// 1 public final static foo-zMJ7EWY\(ILkotlin/coroutines/Continuation;\)Ljava/lang/Object; +// 1 public static synthetic foo-zMJ7EWY\$default\(ILkotlin/coroutines/Continuation;ILjava/lang/Object;\)Ljava/lang/Object; +// 1 INVOKESTATIC a/TestKt.foo-zMJ7EWY \(ILkotlin/coroutines/Continuation;\)Ljava/lang/Object; +// 1 public final static bar-zMJ7EWY\(ILkotlin/coroutines/Continuation;\)Ljava/lang/Object; \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index b832243ea32..74027e3f652 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3157,6 +3157,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/inlineClasses/skipCallToUnderlyingValueOfInlineClass.kt"); } + @TestMetadata("suspendFunctionMangling.kt") + public void testSuspendFunctionMangling() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/inlineClasses/suspendFunctionMangling.kt"); + } + @TestMetadata("toStringIsCalledByInlineClass.kt") public void testToStringIsCalledByInlineClass() throws Exception { runTest("compiler/testData/codegen/bytecodeText/inlineClasses/toStringIsCalledByInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 239929bd763..57d45823a6a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3252,6 +3252,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/inlineClasses/skipCallToUnderlyingValueOfInlineClass.kt"); } + @TestMetadata("suspendFunctionMangling.kt") + public void testSuspendFunctionMangling() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/inlineClasses/suspendFunctionMangling.kt"); + } + @TestMetadata("toStringIsCalledByInlineClass.kt") public void testToStringIsCalledByInlineClass() throws Exception { runTest("compiler/testData/codegen/bytecodeText/inlineClasses/toStringIsCalledByInlineClass.kt");