Disable tail call optimization, if the call is inside try block

#KT-21165: Fixed
This commit is contained in:
Ilmir Usmanov
2018-01-09 17:13:19 +03:00
parent 3cfe43f83a
commit 5dbab2f907
9 changed files with 102 additions and 0 deletions
@@ -692,6 +692,14 @@ private fun allSuspensionPointsAreTailCalls(
val beginIndex = instructions.indexOf(suspensionPoint.suspensionCallBegin)
val endIndex = instructions.indexOf(suspensionPoint.suspensionCallEnd)
val insideTryBlock = methodNode.tryCatchBlocks.any { block ->
val tryBlockStartIndex = instructions.indexOf(block.start)
val tryBlockEndIndex = instructions.indexOf(block.end)
beginIndex in tryBlockStartIndex..tryBlockEndIndex
}
if (insideTryBlock) return@all false
safelyReachableReturns[endIndex + 1]?.all { returnIndex ->
val sourceInsn =
sourceFrames[returnIndex].top().sure {
@@ -0,0 +1,37 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
val postponedActions = ArrayList<() -> Unit>()
suspend fun suspendWithException(): String = suspendCoroutine { x ->
postponedActions.add {
x.resumeWithException(Exception("OK"))
}
}
suspend fun catchException(): String {
try {
return suspendWithException()
}
catch(e: Exception) {
return e.message!!
}
}
fun run(c: suspend () -> String): String {
var res: String = "FAIL 0"
c.startCoroutine(handleResultContinuation {
res = it
})
postponedActions[0]()
return res
}
fun box(): String {
return run {
catchException()
}
}
@@ -0,0 +1,10 @@
suspend fun catchException(): String {
try {
return suspendWithException()
}
catch(e: Exception) {
return e.message!!
}
}
suspend fun suspendWithException(): String = TODO()
@@ -0,0 +1,17 @@
@kotlin.Metadata
final class TryCatchTailCallKt$catchException$1 {
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
inner class TryCatchTailCallKt$catchException$1
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
synthetic final method getLabel(): int
synthetic final method setLabel(p0: int): void
}
@kotlin.Metadata
public final class TryCatchTailCallKt {
inner class TryCatchTailCallKt$catchException$1
public final static @org.jetbrains.annotations.Nullable method catchException(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
public final static @org.jetbrains.annotations.Nullable method suspendWithException(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
}
@@ -6388,6 +6388,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/simple.kt");
doTest(fileName);
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
@@ -6388,6 +6388,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/simple.kt");
doTest(fileName);
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
@@ -157,6 +157,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
doTest(fileName);
}
@TestMetadata("tryCatchTailCall.kt")
public void testTryCatchTailCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/tryCatchTailCall.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/bytecodeListing/annotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -6388,6 +6388,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/simple.kt");
doTest(fileName);
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")
@@ -6946,6 +6946,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/simple.kt");
doTest(fileName);
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/tryCatch.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/coroutines/tailOperations")