Introduce CHECK_TAIL_CALL_OPTIMIZATION directive
This directive generates TailCallOptimizationChecker in package helpers. The check for tail call optimization is based on coroutine stack traces bug (feature?): when tail call optimization hits, the continuation object is not generated. Thus, there is no debug metadata for this suspend function. Consequently, the coroutines stack trace does not contain stack trace element for that function. This check is performed by TailCallOptimizationChecker. Since this is runtime check, unlike bytecode tests, it does not require test data adjustments on each codegen or inliner change. Since the check is based on debug metadata, which is JVM specific, there is not support for other backends yet.
This commit is contained in:
-1
@@ -3,7 +3,6 @@
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
@@ -1,13 +1,14 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_BYTECODE_LISTING
|
||||
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
suspend fun dummy(): Unit = Unit
|
||||
suspend fun dummy() = TailCallOptimizationChecker.saveStackTrace()
|
||||
suspend fun test(): Int = 1.also {
|
||||
dummy()
|
||||
}
|
||||
@@ -21,5 +22,6 @@ fun box(): String {
|
||||
builder {
|
||||
res = test()
|
||||
}
|
||||
TailCallOptimizationChecker.checkStateMachineIn("test")
|
||||
return if (res == 1) "OK" else "FAIL"
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class AlsoKt$box$1 {
|
||||
synthetic final field $res: kotlin.jvm.internal.Ref$IntRef
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
inner class AlsoKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$IntRef, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class AlsoKt$test$1 {
|
||||
field I$0: int
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
inner class AlsoKt$test$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class AlsoKt {
|
||||
inner class AlsoKt$box$1
|
||||
inner class AlsoKt$test$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method dummy(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method test(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
@kotlin.Metadata
|
||||
final class AlsoKt$box$1 {
|
||||
synthetic final field $res: kotlin.jvm.internal.Ref$IntRef
|
||||
field L$0: java.lang.Object
|
||||
inner class AlsoKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$IntRef, p1: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class AlsoKt$test$1 {
|
||||
field I$0: int
|
||||
field L$0: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
inner class AlsoKt$test$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 AlsoKt {
|
||||
inner class AlsoKt$box$1
|
||||
inner class AlsoKt$test$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method dummy(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method test(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt$box$1$invokeSuspend$$inlined$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
inner class EpamKt$box$1$invokeSuspend$$inlined$zip$1
|
||||
public method <init>(p0: MyDeferred, p1: MyDeferred, p2: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class EpamKt$box$1 {
|
||||
synthetic final field $first: MyDeferred
|
||||
synthetic final field $result: kotlin.jvm.internal.Ref$IntRef
|
||||
synthetic final field $second: MyDeferred
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
inner class EpamKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$IntRef, p1: MyDeferred, p2: MyDeferred, p3: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class EpamKt$box$first$1 {
|
||||
field label: int
|
||||
inner class EpamKt$box$first$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class EpamKt$box$second$1 {
|
||||
field label: int
|
||||
inner class EpamKt$box$second$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
synthetic final field $zipper: kotlin.jvm.functions.Function2
|
||||
field label: int
|
||||
inner class EpamKt$zip$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2, p1: MyDeferred, p2: MyDeferred, p3: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt {
|
||||
inner class EpamKt$box$1
|
||||
inner class EpamKt$box$first$1
|
||||
inner class EpamKt$box$second$1
|
||||
inner class EpamKt$zip$1
|
||||
public final static @org.jetbrains.annotations.NotNull method async(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): MyDeferred
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method zip(@org.jetbrains.annotations.NotNull p0: MyDeferred, @org.jetbrains.annotations.NotNull p1: MyDeferred, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function2): MyDeferred
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MyDeferred {
|
||||
private final @org.jetbrains.annotations.NotNull field t: kotlin.jvm.functions.Function1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final @org.jetbrains.annotations.Nullable method await(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final @org.jetbrains.annotations.NotNull method getT(): kotlin.jvm.functions.Function1
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt$box$1$doResume$$inlined$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
field L$0: java.lang.Object
|
||||
inner class EpamKt$box$1$doResume$$inlined$zip$1
|
||||
public method <init>(p0: MyDeferred, p1: MyDeferred, p2: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class EpamKt$box$1 {
|
||||
synthetic final field $first: MyDeferred
|
||||
synthetic final field $result: kotlin.jvm.internal.Ref$IntRef
|
||||
synthetic final field $second: MyDeferred
|
||||
field L$0: java.lang.Object
|
||||
inner class EpamKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$IntRef, p1: MyDeferred, p2: MyDeferred, p3: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class EpamKt$box$first$1 {
|
||||
inner class EpamKt$box$first$1
|
||||
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class EpamKt$box$second$1 {
|
||||
inner class EpamKt$box$second$1
|
||||
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt$zip$1 {
|
||||
synthetic final field $source1: MyDeferred
|
||||
synthetic final field $source2: MyDeferred
|
||||
synthetic final field $zipper: kotlin.jvm.functions.Function2
|
||||
inner class EpamKt$zip$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2, p1: MyDeferred, p2: MyDeferred, p3: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class EpamKt {
|
||||
inner class EpamKt$box$1
|
||||
inner class EpamKt$box$first$1
|
||||
inner class EpamKt$box$second$1
|
||||
inner class EpamKt$zip$1
|
||||
public final static @org.jetbrains.annotations.NotNull method async(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): MyDeferred
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method zip(@org.jetbrains.annotations.NotNull p0: MyDeferred, @org.jetbrains.annotations.NotNull p1: MyDeferred, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function2): MyDeferred
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MyDeferred {
|
||||
private final @org.jetbrains.annotations.NotNull field t: kotlin.jvm.functions.Function1
|
||||
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final @org.jetbrains.annotations.Nullable method await(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final @org.jetbrains.annotations.NotNull method getT(): kotlin.jvm.functions.Function1
|
||||
}
|
||||
+8
-6
@@ -1,15 +1,15 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
// CHECK_BYTECODE_LISTING
|
||||
// CHECK_NEW_COUNT: function=suspendHere count=1
|
||||
// CHECK_NEW_COUNT: function=mainSuspend count=1
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
inline suspend fun suspendThere(v: String): String = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
TailCallOptimizationChecker.saveStackTrace(x)
|
||||
x.resume(v)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
@@ -30,5 +30,7 @@ fun box(): String {
|
||||
result = mainSuspend()
|
||||
}
|
||||
|
||||
TailCallOptimizationChecker.checkStateMachineIn("mainSuspend")
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class InlineWithStateMachineKt$box$1 {
|
||||
synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
inner class InlineWithStateMachineKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class InlineWithStateMachineKt$mainSuspend$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
inner class InlineWithStateMachineKt$mainSuspend$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class InlineWithStateMachineKt$suspendHere$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
inner class InlineWithStateMachineKt$suspendHere$1
|
||||
public method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class InlineWithStateMachineKt {
|
||||
inner class InlineWithStateMachineKt$box$1
|
||||
inner class InlineWithStateMachineKt$mainSuspend$1
|
||||
inner class InlineWithStateMachineKt$suspendHere$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method mainSuspend(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
private final static @org.jetbrains.annotations.Nullable method suspendHere$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
private final static @org.jetbrains.annotations.Nullable method suspendThere$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
Vendored
-50
@@ -1,50 +0,0 @@
|
||||
@kotlin.Metadata
|
||||
final class InlineWithStateMachineKt$box$1 {
|
||||
synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
|
||||
field L$0: java.lang.Object
|
||||
inner class InlineWithStateMachineKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class InlineWithStateMachineKt$mainSuspend$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
inner class InlineWithStateMachineKt$mainSuspend$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 InlineWithStateMachineKt$suspendHere$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
inner class InlineWithStateMachineKt$suspendHere$1
|
||||
public 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 InlineWithStateMachineKt {
|
||||
inner class InlineWithStateMachineKt$box$1
|
||||
inner class InlineWithStateMachineKt$mainSuspend$1
|
||||
inner class InlineWithStateMachineKt$suspendHere$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method mainSuspend(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
private final static @org.jetbrains.annotations.Nullable method suspendHere$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
private final static @org.jetbrains.annotations.Nullable method suspendThere$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_BYTECODE_LISTING
|
||||
// CHECK_NEW_COUNT: function=suspendHere count=0
|
||||
// COMMON_COROUTINES_TEST
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
suspend fun suspendThere(v: String): String = suspendCoroutineUninterceptedOrReturn { x ->
|
||||
TailCallOptimizationChecker.saveStackTrace(x)
|
||||
x.resume(v)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
@@ -25,6 +26,7 @@ fun box(): String {
|
||||
builder {
|
||||
result = suspendHere()
|
||||
}
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("suspendHere")
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class SimpleKt$box$1 {
|
||||
synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
inner class SimpleKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class SimpleKt {
|
||||
inner class SimpleKt$box$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
@kotlin.Metadata
|
||||
final class SimpleKt$box$1 {
|
||||
synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
|
||||
field L$0: java.lang.Object
|
||||
inner class SimpleKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class SimpleKt {
|
||||
inner class SimpleKt$box$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method suspendThere(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
fun check() = true
|
||||
|
||||
suspend fun f_1(): Unit {
|
||||
return f_2()
|
||||
}
|
||||
|
||||
private inline suspend fun f_2(): Unit {
|
||||
if (check()) return
|
||||
return suspendCoroutineUninterceptedOrReturn {
|
||||
TailCallOptimizationChecker.saveStackTrace(it)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder { f_1() }
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("f_1")
|
||||
return "OK"
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
var p: Int = 5846814
|
||||
private suspend fun withoutInline() {
|
||||
val c = { c: Continuation<Unit> ->
|
||||
TailCallOptimizationChecker.saveStackTrace(c)
|
||||
if (p > 52158) Unit else COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
return suspendCoroutineUninterceptedOrReturn(c)
|
||||
}
|
||||
|
||||
private suspend fun withInline() {
|
||||
return suspendCoroutineUninterceptedOrReturn { c ->
|
||||
TailCallOptimizationChecker.saveStackTrace(c)
|
||||
if (p > 52158) Unit else COROUTINE_SUSPENDED
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
withoutInline()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("withoutInline")
|
||||
withInline()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("withInline")
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
suspend fun empty() = TailCallOptimizationChecker.saveStackTrace()
|
||||
suspend fun withoutReturn() { empty() }
|
||||
suspend fun withReturn() { return empty() }
|
||||
suspend fun notTailCall() { empty(); empty() }
|
||||
suspend fun lambdaAsParameter(c: suspend ()->Unit) { c() }
|
||||
suspend fun lambdaAsParameterNotTailCall(c: suspend ()->Unit) { c(); c() }
|
||||
suspend fun lambdaAsParameterReturn(c: suspend ()->Unit) { return c() }
|
||||
suspend fun returnsInt() = 42.also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
// This should not be tail-call, since the caller should push Unit.INSTANCE on stack
|
||||
suspend fun callsIntNotTailCall() { returnsInt() }
|
||||
suspend fun multipleExitPoints(b: Boolean) { if (b) empty() else withoutReturn() }
|
||||
suspend fun multipleExitPointsNotTailCall(b: Boolean) { if (b) empty() else returnsInt() }
|
||||
|
||||
fun ordinary() = 1
|
||||
inline fun ordinaryInline() { ordinary() }
|
||||
suspend fun multipleExitPointsWithOrdinaryInline(b: Boolean) { if (b) empty() else ordinaryInline() }
|
||||
|
||||
suspend fun multipleExitPointsWhen(i: Int) {
|
||||
when(i) {
|
||||
1 -> empty()
|
||||
2 -> withReturn()
|
||||
3 -> withoutReturn()
|
||||
else -> lambdaAsParameter {}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T> generic() = (Unit as T).also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
suspend fun useGenericReturningUnit() {
|
||||
generic<Unit>()
|
||||
}
|
||||
|
||||
class Generic<T> {
|
||||
suspend fun foo() = generic<T>()
|
||||
}
|
||||
suspend fun useGenericClass(g: Generic<Unit>) {
|
||||
g.foo()
|
||||
}
|
||||
|
||||
suspend fun <T> genericInferType(c: () -> T) = c().also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
suspend fun useGenericInferType() {
|
||||
genericInferType {}
|
||||
}
|
||||
|
||||
suspend fun nullableUnit(): Unit? = null.also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
suspend fun useNullableUnit() {
|
||||
nullableUnit()
|
||||
}
|
||||
|
||||
suspend fun useRunRunRunRunRun() {
|
||||
run {
|
||||
run {
|
||||
run {
|
||||
run {
|
||||
run {
|
||||
empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
withoutReturn()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("withoutReturn")
|
||||
|
||||
withReturn()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("withReturn")
|
||||
|
||||
notTailCall()
|
||||
TailCallOptimizationChecker.checkStateMachineIn("notTailCall")
|
||||
|
||||
lambdaAsParameter { TailCallOptimizationChecker.saveStackTrace() }
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("lambdaAsParameter")
|
||||
|
||||
lambdaAsParameterNotTailCall { TailCallOptimizationChecker.saveStackTrace() }
|
||||
TailCallOptimizationChecker.checkStateMachineIn("lambdaAsParameterNotTailCall")
|
||||
|
||||
lambdaAsParameterReturn { TailCallOptimizationChecker.saveStackTrace() }
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("lambdaAsParameterReturn")
|
||||
|
||||
callsIntNotTailCall()
|
||||
TailCallOptimizationChecker.checkStateMachineIn("callsIntNotTailCall")
|
||||
|
||||
multipleExitPoints(false)
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("multipleExitPoints")
|
||||
|
||||
multipleExitPointsNotTailCall(false)
|
||||
TailCallOptimizationChecker.checkStateMachineIn("multipleExitPointsNotTailCall")
|
||||
|
||||
multipleExitPointsWithOrdinaryInline(true)
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("multipleExitPointsWithOrdinaryInline")
|
||||
|
||||
multipleExitPointsWhen(1)
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("multipleExitPointsWhen")
|
||||
|
||||
useGenericReturningUnit()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useGenericReturningUnit")
|
||||
|
||||
useGenericClass(Generic())
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useGenericClass")
|
||||
|
||||
useGenericInferType()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useGenericInferType")
|
||||
|
||||
useNullableUnit()
|
||||
TailCallOptimizationChecker.checkStateMachineIn("useNullableUnit")
|
||||
|
||||
useRunRunRunRunRun()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useRunRunRunRunRun")
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
suspend fun catchException(): String {
|
||||
try {
|
||||
return suspendWithException()
|
||||
}
|
||||
catch(e: Exception) {
|
||||
return e.message!!
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun suspendWithException(): String = "OK".also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL"
|
||||
builder {
|
||||
res = catchException()
|
||||
}
|
||||
TailCallOptimizationChecker.checkStateMachineIn("catchException")
|
||||
return res
|
||||
}
|
||||
+172
-11
@@ -1,26 +1,187 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
suspend fun twoReturns(c: suspend () -> Unit) {
|
||||
return c()
|
||||
throw RuntimeException("FAIL 1")
|
||||
suspend fun empty() = TailCallOptimizationChecker.saveStackTrace()
|
||||
suspend fun withoutReturn() {
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun withReturn() {
|
||||
return empty()
|
||||
return empty()
|
||||
}
|
||||
|
||||
suspend fun notTailCall() {
|
||||
empty()
|
||||
return empty()
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun lambdaAsParameter(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend fun lambdaAsParameterNotTailCall(c: suspend () -> Unit) {
|
||||
c()
|
||||
return c()
|
||||
c()
|
||||
}
|
||||
|
||||
suspend fun lambdaAsParameterReturn(c: suspend () -> Unit) {
|
||||
return c()
|
||||
c()
|
||||
}
|
||||
|
||||
suspend fun returnsInt() = 42.also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
// This should not be tail-call, since the caller should push Unit.INSTANCE on stack
|
||||
suspend fun callsIntNotTailCall() {
|
||||
returnsInt()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun multipleExitPoints(b: Boolean) {
|
||||
if (b) empty() else withoutReturn()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun multipleExitPointsNotTailCall(b: Boolean) {
|
||||
if (b) empty() else returnsInt()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
fun ordinary() = 1
|
||||
inline fun ordinaryInline() {
|
||||
ordinary()
|
||||
}
|
||||
|
||||
suspend fun multipleExitPointsWithOrdinaryInline(b: Boolean) {
|
||||
if (b) empty() else ordinaryInline()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun multipleExitPointsWhen(i: Int) {
|
||||
when (i) {
|
||||
1 -> empty()
|
||||
2 -> withReturn()
|
||||
3 -> withoutReturn()
|
||||
else -> lambdaAsParameter {}
|
||||
}
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun <T> generic() = (Unit as T).also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
suspend fun useGenericReturningUnit() {
|
||||
generic<Unit>()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
class Generic<T> {
|
||||
suspend fun foo() = generic<T>()
|
||||
}
|
||||
|
||||
suspend fun useGenericClass(g: Generic<Unit>) {
|
||||
g.foo()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun <T> genericInferType(c: () -> T) = c().also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
suspend fun useGenericInferType() {
|
||||
genericInferType {}
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun nullableUnit(): Unit? = null.also { TailCallOptimizationChecker.saveStackTrace() }
|
||||
suspend fun useNullableUnit() {
|
||||
nullableUnit()
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
suspend fun useRunRunRunRunRun() {
|
||||
run {
|
||||
run {
|
||||
run {
|
||||
run {
|
||||
run {
|
||||
empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
empty()
|
||||
}
|
||||
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL"
|
||||
builder {
|
||||
twoReturns {
|
||||
res = "OK"
|
||||
}
|
||||
withoutReturn()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("withoutReturn")
|
||||
|
||||
withReturn()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("withReturn")
|
||||
|
||||
notTailCall()
|
||||
TailCallOptimizationChecker.checkStateMachineIn("notTailCall")
|
||||
|
||||
lambdaAsParameter { TailCallOptimizationChecker.saveStackTrace() }
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("lambdaAsParameter")
|
||||
|
||||
lambdaAsParameterNotTailCall { TailCallOptimizationChecker.saveStackTrace() }
|
||||
TailCallOptimizationChecker.checkStateMachineIn("lambdaAsParameterNotTailCall")
|
||||
|
||||
lambdaAsParameterReturn { TailCallOptimizationChecker.saveStackTrace() }
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("lambdaAsParameterReturn")
|
||||
|
||||
callsIntNotTailCall()
|
||||
TailCallOptimizationChecker.checkStateMachineIn("callsIntNotTailCall")
|
||||
|
||||
multipleExitPoints(false)
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("multipleExitPoints")
|
||||
|
||||
multipleExitPointsNotTailCall(false)
|
||||
TailCallOptimizationChecker.checkStateMachineIn("multipleExitPointsNotTailCall")
|
||||
|
||||
multipleExitPointsWithOrdinaryInline(true)
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("multipleExitPointsWithOrdinaryInline")
|
||||
|
||||
multipleExitPointsWhen(1)
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("multipleExitPointsWhen")
|
||||
|
||||
useGenericReturningUnit()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useGenericReturningUnit")
|
||||
|
||||
useGenericClass(Generic())
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useGenericClass")
|
||||
|
||||
useGenericInferType()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useGenericInferType")
|
||||
|
||||
useNullableUnit()
|
||||
TailCallOptimizationChecker.checkStateMachineIn("useNullableUnit")
|
||||
|
||||
useRunRunRunRunRun()
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("useRunRunRunRunRun")
|
||||
}
|
||||
return res
|
||||
return "OK"
|
||||
}
|
||||
|
||||
+16
-5
@@ -1,10 +1,12 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
// CHECK_BYTECODE_LISTING
|
||||
// CHECK_TAIL_CALL_OPTIMIZATION
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.coroutines.intrinsics.*
|
||||
|
||||
sealed class X {
|
||||
class A : X()
|
||||
@@ -13,8 +15,15 @@ sealed class X {
|
||||
|
||||
var log = ""
|
||||
|
||||
suspend fun process(a: X.A) { log = "${log}from A;" }
|
||||
suspend fun process(b: X.B) { log = "${log}from B;" }
|
||||
suspend fun process(a: X.A) {
|
||||
log = "${log}from A;"
|
||||
TailCallOptimizationChecker.saveStackTrace()
|
||||
}
|
||||
|
||||
suspend fun process(b: X.B) {
|
||||
log = "${log}from B;"
|
||||
TailCallOptimizationChecker.saveStackTrace()
|
||||
}
|
||||
|
||||
suspend fun process(x: X) = when (x) {
|
||||
is X.A -> process(x)
|
||||
@@ -28,7 +37,9 @@ fun builder(c: suspend () -> Unit) {
|
||||
fun box(): String {
|
||||
builder {
|
||||
process(X.A())
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("process")
|
||||
process(X.B())
|
||||
TailCallOptimizationChecker.checkNoStateMachineIn("process")
|
||||
}
|
||||
if (log != "from A;from B;") return log
|
||||
return "OK"
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class WhenUnitKt$box$1 {
|
||||
field label: int
|
||||
inner class WhenUnitKt$box$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class WhenUnitKt {
|
||||
private static @org.jetbrains.annotations.NotNull field log: java.lang.String
|
||||
inner class WhenUnitKt$box$1
|
||||
static method <clinit>(): void
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method getLog(): java.lang.String
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$A, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$B, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static method setLog(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$A {
|
||||
inner class X$A
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$B {
|
||||
inner class X$B
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public abstract class X {
|
||||
inner class X$A
|
||||
inner class X$B
|
||||
private method <init>(): void
|
||||
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
@kotlin.Metadata
|
||||
final class WhenUnitKt$box$1 {
|
||||
inner class WhenUnitKt$box$1
|
||||
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class WhenUnitKt {
|
||||
private static @org.jetbrains.annotations.NotNull field log: java.lang.String
|
||||
inner class WhenUnitKt$box$1
|
||||
static method <clinit>(): void
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
public final static @org.jetbrains.annotations.NotNull method getLog(): java.lang.String
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$A, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X$B, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method process(@org.jetbrains.annotations.NotNull p0: X, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static method setLog(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$A {
|
||||
inner class X$A
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class X$B {
|
||||
inner class X$B
|
||||
public method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public abstract class X {
|
||||
inner class X$A
|
||||
inner class X$B
|
||||
private method <init>(): void
|
||||
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
}
|
||||
Reference in New Issue
Block a user