Support new strategy for suspend inline functions

The main idea is to leave all the inline functions as is, without
state machines (but keeping suspend-calls markers) and
determine whether we need a state machine from the bytecode
after inlining into a non-inline function

 #KT-17585 In Progress
 #KT-16603 In Progress
 #KT-16448 Fixed
This commit is contained in:
Denis Zharkov
2017-05-04 11:48:55 +03:00
parent 5d0aeb4ef6
commit 5b5f612a7c
20 changed files with 612 additions and 164 deletions
@@ -0,0 +1,31 @@
// IGNORE_BACKEND: JS
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
// CHECK_BYTECODE_LISTING
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
inline suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
x.resume(v)
COROUTINE_SUSPENDED
}
// There's no state machine in the suspendHere, since it's inline
inline suspend fun suspendHere(): String = suspendThere("O") + suspendThere("K")
// There should be a state machine for mainSuspend as it has two suspend non-tail calls inlined
suspend fun mainSuspend() = suspendHere()
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var result = ""
builder {
result = mainSuspend()
}
return result
}
@@ -0,0 +1,31 @@
@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 @org.jetbrains.annotations.Nullable 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
final class InlineWithStateMachineKt$mainSuspend$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
inner class InlineWithStateMachineKt$mainSuspend$1
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object
}
@kotlin.Metadata
public final class InlineWithStateMachineKt {
inner class InlineWithStateMachineKt$box$1
inner class InlineWithStateMachineKt$mainSuspend$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
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
}
@@ -0,0 +1,38 @@
// IGNORE_BACKEND: NATIVE
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
// CHECK_BYTECODE_LISTING
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
inline suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
x.resume(v)
COROUTINE_SUSPENDED
}
suspend fun suspendHere(): String = suspendThere("O")
// There is a kind of redundant state machine generated for complexSuspend:
// it's basically has the only suspend call just before return, but there is
// a redundant CHECKCAST String in the run's lambda, so we have to insert the state machine.
// TODO: Think of avoiding such redundant casts
suspend fun complexSuspend(): String {
return run {
suspendThere("K")
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var result = ""
builder {
result = suspendHere() + complexSuspend()
}
return result
}
@@ -0,0 +1,32 @@
@kotlin.Metadata
final class InlineWithoutStateMachineKt$box$1 {
synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
field L$0: java.lang.Object
field L$1: java.lang.Object
inner class InlineWithoutStateMachineKt$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 @org.jetbrains.annotations.Nullable 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
final class InlineWithoutStateMachineKt$complexSuspend$1 {
field L$0: java.lang.Object
field L$1: java.lang.Object
inner class InlineWithoutStateMachineKt$complexSuspend$1
method <init>(p0: kotlin.coroutines.experimental.Continuation): void
public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object
}
@kotlin.Metadata
public final class InlineWithoutStateMachineKt {
inner class InlineWithoutStateMachineKt$box$1
inner class InlineWithoutStateMachineKt$complexSuspend$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 complexSuspend(@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
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
}
@@ -0,0 +1,28 @@
// IGNORE_BACKEND: NATIVE
// WITH_RUNTIME
// WITH_COROUTINES
// CHECK_BYTECODE_LISTING
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
x.resume(v)
COROUTINE_SUSPENDED
}
suspend fun suspendHere(): String = suspendThere("OK")
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var result = ""
builder {
result = suspendHere()
}
return result
}
@@ -0,0 +1,20 @@
@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 @org.jetbrains.annotations.Nullable 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 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
}
@@ -1,17 +1,19 @@
@kotlin.Metadata
final class Controller$multipleSuspensions$1 {
field L$0: java.lang.Object
synthetic final field this$0: Controller
inner class Controller$multipleSuspensions$1
method <init>(p0: Controller, p1: 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
public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object
}
@kotlin.Metadata
final class Controller$nonTailCall$1 {
field L$0: java.lang.Object
synthetic final field this$0: Controller
inner class Controller$nonTailCall$1
method <init>(p0: Controller, p1: 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
public final @org.jetbrains.annotations.Nullable method doResume(): java.lang.Object
}
@kotlin.Metadata
@@ -28,9 +30,9 @@ public final class Controller {
@kotlin.Metadata
final class CoroutineFieldsKt$box$1 {
synthetic final field $result: kotlin.jvm.internal.Ref$ObjectRef
private field J$0: long
private field L$0: java.lang.Object
private field L$1: java.lang.Object
field J$0: long
field L$0: java.lang.Object
field L$1: java.lang.Object
private field p$: Controller
inner class CoroutineFieldsKt$box$1
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.coroutines.experimental.Continuation): void