From 325ad14ac9b3bffd8d2825df370435357045e470 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 20 Feb 2020 18:49:06 +0100 Subject: [PATCH] JVM_IR: Treat suspend main wrapper as always tail-call function In other words, never generate suspend call markers inside it. --- .../kotlin/backend/jvm/codegen/CoroutineCodegen.kt | 6 +++++- .../testData/codegen/bytecodeText/coroutines/suspendMain.kt | 6 ++++++ .../jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java | 5 +++++ .../kotlin/codegen/ir/IrBytecodeTextTestGenerated.java | 5 +++++ 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/bytecodeText/coroutines/suspendMain.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index a3254b35347..6755c7e7f1c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -113,6 +113,10 @@ internal fun IrFunction.isInvokeSuspendOfContinuation(): Boolean = internal fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean = isSuspend && name.asString() == "invoke" && parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL +// Wrapper of suspend main is always tail-call and it is not generated as suspend function. +private fun IrFunction.isInvokeOfSuspendMainWrapper(): Boolean = !isSuspend && name.asString() == "invoke" && + parentAsClass.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL + internal fun IrFunction.isKnownToBeTailCall(): Boolean = when (origin) { IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, @@ -125,7 +129,7 @@ internal fun IrFunction.isKnownToBeTailCall(): Boolean = IrDeclarationOrigin.BRIDGE, IrDeclarationOrigin.BRIDGE_SPECIAL, IrDeclarationOrigin.DELEGATED_MEMBER -> true - else -> isInvokeOfSuspendCallableReference() + else -> isInvokeOfSuspendMainWrapper() || isInvokeOfSuspendCallableReference() } internal fun IrFunction.shouldNotContainSuspendMarkers(): Boolean = diff --git a/compiler/testData/codegen/bytecodeText/coroutines/suspendMain.kt b/compiler/testData/codegen/bytecodeText/coroutines/suspendMain.kt new file mode 100644 index 00000000000..5ac3fb83012 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/coroutines/suspendMain.kt @@ -0,0 +1,6 @@ +// WITH_COROUTINES +// TREAT_AS_ONE_FILE + +suspend fun main() {} + +// 0 INVOKESTATIC kotlin/jvm/internal/InlineMarker.mark \ 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 c78b24f070d..f2b03872fee 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1371,6 +1371,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTestWithPackageReplacement("compiler/testData/codegen/bytecodeText/coroutines/returnUnitInLambda.kt", "kotlin.coroutines"); } + @TestMetadata("suspendMain.kt") + public void testSuspendMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/coroutines/suspendMain.kt"); + } + @TestMetadata("throwOnFailure.kt") public void testThrowOnFailure() throws Exception { runTest("compiler/testData/codegen/bytecodeText/coroutines/throwOnFailure.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index d8b8339682d..f08b76cdee8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -1376,6 +1376,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTestWithPackageReplacement("compiler/testData/codegen/bytecodeText/coroutines/returnUnitInLambda.kt", "kotlin.coroutines"); } + @TestMetadata("suspendMain.kt") + public void testSuspendMain() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/coroutines/suspendMain.kt"); + } + @TestMetadata("throwOnFailure.kt") public void testThrowOnFailure() throws Exception { runTest("compiler/testData/codegen/bytecodeText/coroutines/throwOnFailure.kt");