Use CFG to recognize suspension point's end

Previously it was linear scan, failing on unbalanced suspension markers.
Now, I use CFG to find end markers, which are reachable from start
markers. Using CFG allows to walk through suspension point instructions
only, since they form region.
If, for some reason, end marker does not exist (inliner or unreachable
code elimination pass remove unreachable code) or is unreachable,
just ignore the whole suspension point, as before.
 #KT-33172 Fixed
 #KT-28507 Fixed
This commit is contained in:
Ilmir Usmanov
2019-08-07 17:07:51 +03:00
parent 570d66be46
commit e88dce3e19
8 changed files with 170 additions and 69 deletions
@@ -0,0 +1,56 @@
// IGNORE_BACKEND: JVM_IR
// FILE: inline.kt
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
// WITH_COROUTINES
// FULL_JDK
// NO_CHECK_LAMBDA_INLINING
// CHECK_STATE_MACHINE
import helpers.*
import COROUTINES_PACKAGE.intrinsics.*
fun check() = true
inline suspend fun inlineMe(): Unit {
suspendCoroutineUninterceptedOrReturn<Nothing> {
if (check()) error("O") else error("Not this one")
}
}
// FILE: box.kt
// WITH_COROUTINES
import COROUTINES_PACKAGE.*
import helpers.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(CheckStateMachineContinuation)
}
suspend fun withoutTryCatch(): String {
StateMachineChecker.suspendHere()
inlineMe()
return "" // To prevent tail-call optimization
}
fun box(): String {
var result = "FAIL 0"
builder {
result = try {
StateMachineChecker.suspendHere()
inlineMe()
"FAIL 1"
} catch (e: IllegalStateException) {
e.message!!
}
try {
withoutTryCatch()
result += "FAIL 2"
} catch (e: IllegalStateException) {
result += "K"
}
}
StateMachineChecker.check(numberOfSuspensions = 2)
return result
}