[JS IR] Fix boxing/unboxing of inline classes in coroutine scope

- don't box/unbox when value is known to be an inline class
 - add unbox state when coroutine resumed
 - correctly handle suspension in case of inline class
 - add tests
This commit is contained in:
Roman Artemev
2019-11-13 17:30:41 +03:00
committed by romanart
parent 52b24ead91
commit f2093a1763
12 changed files with 284 additions and 19 deletions
@@ -0,0 +1,96 @@
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
import COROUTINES_PACKAGE.intrinsics.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
@Suppress("UNSUPPORTED_FEATURE")
inline class IC(val s: String)
class Test1() {
suspend fun <T> foo(value: T): T {
return suspendCoroutineUninterceptedOrReturn {
it.resume(value)
COROUTINE_SUSPENDED
}
}
suspend fun qux(ss: IC): IC = IC(ss.s)
suspend fun <T> quz(t: T): T = t
suspend fun bar(): IC {
return foo(qux(quz(IC("OK"))))
}
suspend fun test() = bar().s
}
class Test2 {
suspend fun foo(value: IC): IC {
return suspendCoroutineUninterceptedOrReturn {
it.resume(value)
COROUTINE_SUSPENDED
}
}
suspend fun qux(s: String): IC = IC(s)
suspend fun quz(): String = "OK"
suspend fun bar(): IC {
return foo(qux(quz()))
}
suspend fun test() = bar().s
}
class Test3 {
suspend fun <T> foo(value: T): T {
return suspendCoroutineUninterceptedOrReturn {
it.resume(value)
COROUTINE_SUSPENDED
}
}
suspend fun bar(): IC {
return foo(IC("OK"))
}
suspend fun test() = bar().s
}
fun box(): String {
var result = "FAIL"
builder {
result = Test1().test()
}
if (result != "OK") return "FAIL 1 $result"
result = "FAIL2"
builder {
result = Test2().test()
}
if (result != "OK") return "FAIL 2 $result"
result = "FAIL 3"
builder {
result = Test3().test()
}
return result
}
@@ -0,0 +1,41 @@
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
import helpers.*
import COROUTINES_PACKAGE.*
import COROUTINES_PACKAGE.intrinsics.*
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
@Suppress("UNSUPPORTED_FEATURE")
inline class IC(val s: String)
interface I {
suspend fun foo(s: String): IC
}
class D: I {
override suspend fun foo(s: String): IC {
return IC(s)
}
}
class C(val d: I) : I by d
fun box(): String {
var result = "FAIL"
val d = D()
builder {
result = C(d).foo("OK").s
}
if (result != "OK") return "FAIL: $result"
return result
}