From a5bcd3495e0ce50b36308dd38bdce3bba95e1492 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 11 Oct 2018 18:56:48 +0300 Subject: [PATCH] Simplify tail-call optimisation check Check, that all suspension points are immediately followed by ARETURN and do not check that all these ARETURNs are immediately preceded by suspension points. #KT-27190 Fixed --- .../CoroutineTransformerMethodVisitor.kt | 8 +------- .../tailcall/tailCallIfReturnUnit.kt | 16 ++++++++++++++++ .../tailcall/tailCallIfReturnUnit.txt | 6 ++++++ .../codegen/BytecodeListingTestGenerated.java | 5 +++++ 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.kt create mode 100644 compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.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 eb00961a062..6ae746d1eae 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -944,13 +944,7 @@ private fun allSuspensionPointsAreTailCalls( } if (insideTryBlock) return@all false - safelyReachableReturns[endIndex + 1]?.all { returnIndex -> - sourceFrames[returnIndex].top().sure { - "There must be some value on stack to return" - }.insns.all { sourceInsn -> - sourceInsn?.let(instructions::indexOf) in beginIndex..endIndex - } - } ?: false + safelyReachableReturns[endIndex + 1] != null } } diff --git a/compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.kt b/compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.kt new file mode 100644 index 00000000000..91c8cacdf76 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.kt @@ -0,0 +1,16 @@ +// WITH_RUNTIME + +import kotlin.coroutines.intrinsics.* + +fun check() = true + +suspend fun f(i: Int): Unit { + return f_2() +} + +private inline suspend fun f_2(): Unit { + if (check()) return + return suspendCoroutineUninterceptedOrReturn { + COROUTINE_SUSPENDED + } +} diff --git a/compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.txt b/compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.txt new file mode 100644 index 00000000000..7fb7923b1ca --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.txt @@ -0,0 +1,6 @@ +@kotlin.Metadata +public final class TailCallIfReturnUnitKt { + public final static method check(): boolean + public final static @org.jetbrains.annotations.Nullable method f(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object + private synthetic final static method f_2(p0: kotlin.coroutines.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 defe1acdcce..c8ebdbe19f9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -493,6 +493,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/tailcall"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("tailCallIfReturnUnit.kt") + public void testTailCallIfReturnUnit() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/tailcall/tailCallIfReturnUnit.kt"); + } + @TestMetadata("tailCallIntrinsics.kt") public void testTailCallIntrinsics_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/bytecodeListing/tailcall/tailCallIntrinsics.kt", "kotlin.coroutines.experimental");