From 32a94c70e9825b11ec38771f445af2808527da8e Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Tue, 9 Jan 2018 19:19:27 +0300 Subject: [PATCH] Use tail call optimization if ARETURN has multiple sources #KT-21977: Fixed --- .../CoroutineTransformerMethodVisitor.kt | 11 +++++----- .../bytecodeListing/tailCallIntrinsics.kt | 18 +++++++++++++++++ .../bytecodeListing/tailCallIntrinsics.txt | 20 +++++++++++++++++++ .../codegen/BytecodeListingTestGenerated.java | 6 ++++++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.kt create mode 100644 compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index c8364e88a5b..847a5a60739 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -701,12 +701,11 @@ private fun allSuspensionPointsAreTailCalls( if (insideTryBlock) return@all false safelyReachableReturns[endIndex + 1]?.all { returnIndex -> - val sourceInsn = - sourceFrames[returnIndex].top().sure { - "There must be some value on stack to return" - }.insns.singleOrNull() - - sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex + sourceFrames[returnIndex].top().sure { + "There must be some value on stack to return" + }.insns.all { sourceInsn -> + sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex + } } ?: false } } diff --git a/compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.kt b/compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.kt new file mode 100644 index 00000000000..2db6f7e9522 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.kt @@ -0,0 +1,18 @@ +// WITH_RUNTIME +import kotlin.coroutines.experimental.* +import kotlin.coroutines.experimental.intrinsics.* + +var p: Int = 5846814 +private suspend fun withoutInline() { + val c = { c: Continuation -> + if (p > 52158) Unit else COROUTINE_SUSPENDED + } + + return suspendCoroutineOrReturn(c) +} + +private suspend fun withInline() { + return suspendCoroutineOrReturn { c -> + if (p > 52158) Unit else COROUTINE_SUSPENDED + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.txt b/compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.txt new file mode 100644 index 00000000000..f9d255385e3 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.txt @@ -0,0 +1,20 @@ +@kotlin.Metadata +final class TailCallIntrinsicsKt$withoutInline$c$1 { + public final static field INSTANCE: TailCallIntrinsicsKt$withoutInline$c$1 + inner class TailCallIntrinsicsKt$withoutInline$c$1 + static method (): void + method (): void + public final @org.jetbrains.annotations.NotNull method invoke(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object + public synthetic method invoke(p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class TailCallIntrinsicsKt { + private static field p: int + inner class TailCallIntrinsicsKt$withoutInline$c$1 + static method (): void + public final static method getP(): int + public final static method setP(p0: int): void + final static @org.jetbrains.annotations.Nullable method withInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object + final static @org.jetbrains.annotations.Nullable method withoutInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index f3d8c381f3c..7d21f53917c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -151,6 +151,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { doTest(fileName); } + @TestMetadata("tailCallIntrinsics.kt") + public void testTailCallIntrinsics() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/tailCallIntrinsics.kt"); + doTest(fileName); + } + @TestMetadata("tailSuspendUnitFun.kt") public void testTailSuspendUnitFun() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/tailSuspendUnitFun.kt");