[JS IR BE] Fix state machine generation in case of composition of loops, inline functions and finally blocks

* lower finally blocks in any cases
 * do not optimize exit blocks for if-statements
This commit is contained in:
Roman Artemev
2019-05-17 19:03:40 +03:00
committed by romanart
parent 9c7d47789c
commit dfa38f4a4d
13 changed files with 351 additions and 257 deletions
@@ -0,0 +1,53 @@
// KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
import COROUTINES_PACKAGE.intrinsics.*
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendCoroutineUninterceptedOrReturn { c ->
c.resume(value)
COROUTINE_SUSPENDED
}
}
suspend fun lock(owner: Controller) {
owner.result += "L"
}
fun unlock(owner: Controller) {
owner.result += "U"
}
public suspend inline fun doInline(owner: Controller, action: () -> Unit): Unit {
lock(owner)
try {
return action()
} finally {
unlock(owner)
}
}
fun builder(c: suspend Controller.() -> Unit): String {
val controller = Controller()
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
fun box(): String {
val value = builder {
doInline(this) {
result += "X"
}
}
if (value != "LXU") return "fail: $value"
return "OK"
}
@@ -0,0 +1,73 @@
// KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
import COROUTINES_PACKAGE.intrinsics.*
class Controller {
var result = ""
suspend fun <T> suspendWithResult(value: T): T = suspendCoroutineUninterceptedOrReturn { c ->
c.resume(value)
COROUTINE_SUSPENDED
}
}
fun Controller.consumeCancel(c: Throwable?) {
result += if (c == null) "?" else "!"
}
fun newIterator() = Iterator()
class Iterator() {
var hasNextX = true
public suspend fun hasNext(): Boolean {
val tmp = hasNextX
hasNextX = false
return tmp
}
public suspend fun next(): String = "OK"
}
public inline fun Controller.consume(action: Controller.() -> String?): String? {
var cause: Throwable? = null
try {
return action()
} catch(x: Exception) {
cause = x
throw x
} finally {
consumeCancel(cause)
}
}
public suspend fun Controller.doTest(): String? {
return consume {
val iterator = newIterator()
if (!iterator.hasNext())
return null
return iterator.next()
}
}
fun builder(c: suspend Controller.() -> Unit): String {
val controller = Controller()
c.startCoroutine(controller, EmptyContinuation)
return controller.result
}
fun Controller.add(s: String?) {
result += s
}
fun box(): String {
val value = builder {
add(doTest())
}
return if (value != "?OK") return "Fail: $value" else "OK"
}