2dee506022
if they are not inlined, but directly called. Previously, all inline and crossinline lambda calls were treated by codegen as if they are always going to be inlined. However, this is not always the case. Note, that we cannot generate these markers during codegen, since we can inline code with no suspension points, but the whole inlined code will become one giant suspension point. This, of course, breaks tail-call optimization and, hence, slows down cold streams. Because of that, we generate these markers, when we are sure, that they are not going to be inlined. The only place, in which we know that, is the inliner. During inlining of the inline function, we check, whether the parameter is inline or crossinline and whether it is not an inline lambda. If these checks pass, we generate the markers. Noinline parameters are already covered by the codegen. #KT-30706 Fixed #KT-26925 Fixed #KT-26418 Fixed
150 lines
3.4 KiB
Kotlin
Vendored
150 lines
3.4 KiB
Kotlin
Vendored
// IGNORE_BACKEND: JVM_IR
|
|
// COMMON_COROUTINES_TEST
|
|
// WITH_RUNTIME
|
|
// WITH_COROUTINES
|
|
// NO_CHECK_LAMBDA_INLINING
|
|
// CHECK_STATE_MACHINE
|
|
|
|
// FILE: inline.kt
|
|
|
|
import helpers.*
|
|
|
|
interface SuspendRunnable {
|
|
suspend fun run()
|
|
}
|
|
|
|
inline fun inlineMe1(crossinline c: suspend () -> Unit) =
|
|
object : SuspendRunnable {
|
|
override suspend fun run() {
|
|
c()
|
|
c()
|
|
}
|
|
}
|
|
|
|
inline fun inlineMe2(crossinline c: suspend () -> Unit) = suspend {
|
|
c()
|
|
c()
|
|
}
|
|
|
|
inline suspend fun inlineMe3(crossinline c: suspend () -> Unit) {
|
|
c()
|
|
c()
|
|
}
|
|
|
|
inline suspend fun inlineMe4(c: suspend () -> Unit) {
|
|
c()
|
|
c()
|
|
}
|
|
|
|
inline fun inlineMe5(noinline c: suspend () -> Unit) =
|
|
object : SuspendRunnable {
|
|
override suspend fun run() {
|
|
c()
|
|
c()
|
|
}
|
|
}
|
|
|
|
inline fun inlineMe6(noinline c: suspend () -> Unit) = suspend {
|
|
c()
|
|
c()
|
|
}
|
|
|
|
inline suspend fun inlineMe7(noinline c: suspend () -> Unit) {
|
|
c()
|
|
c()
|
|
}
|
|
|
|
inline fun inlineMe11(crossinline c: suspend () -> Unit) = inlineMe1(c)
|
|
inline fun inlineMe12(crossinline c: suspend () -> Unit) = inlineMe2(c)
|
|
inline suspend fun inlineMe13(crossinline c: suspend () -> Unit) = inlineMe3(c)
|
|
inline suspend fun inlineMe14(crossinline c: suspend () -> Unit) = inlineMe4(c)
|
|
|
|
// FILE: box.kt
|
|
// COMMON_COROUTINES_TEST
|
|
|
|
import helpers.*
|
|
import COROUTINES_PACKAGE.*
|
|
|
|
fun builder(c: suspend () -> Unit) {
|
|
c.startCoroutine(CheckStateMachineContinuation)
|
|
}
|
|
|
|
fun box(): String {
|
|
val lambda = suspend {
|
|
StateMachineChecker.suspendHere()
|
|
StateMachineChecker.suspendHere()
|
|
}
|
|
|
|
builder {
|
|
val r = inlineMe1(lambda)
|
|
r.run()
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe2(lambda)()
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe3(lambda)
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe4(lambda)
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
val r = inlineMe5(lambda)
|
|
r.run()
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe6(lambda)()
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe7(lambda)
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
val r = inlineMe11 {
|
|
StateMachineChecker.suspendHere()
|
|
StateMachineChecker.suspendHere()
|
|
}
|
|
r.run()
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe12 {
|
|
StateMachineChecker.suspendHere()
|
|
StateMachineChecker.suspendHere()
|
|
}()
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe13 {
|
|
StateMachineChecker.suspendHere()
|
|
StateMachineChecker.suspendHere()
|
|
}
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
StateMachineChecker.reset()
|
|
builder {
|
|
inlineMe14 {
|
|
StateMachineChecker.suspendHere()
|
|
StateMachineChecker.suspendHere()
|
|
}
|
|
}
|
|
StateMachineChecker.check(numberOfSuspensions = 4)
|
|
|
|
return "OK"
|
|
} |