Implement unit suspend functions tail-call optimisation

Unlike previously, this optimisation works on every callee return type.
Tail-calls inside unit functions can be either
INVOKE...
ARETURN
or
INVOKE
POP
GETSTATIC kotlin/Unit.INSTANCE
ARETURN
The first pattern is already covered. The second one is a bit tricky,
since we cannot just assume than the function is tail-call, we also need
to check whether the callee returned COROUTINE_SUSPENDED marker.
Thus, resulting bytecode of function's 'epilogue' look like
DUP
INVOKESTATIC getCOROUTINE_SUSPENDED
IF_ACMPNE LN
ARETURN
LN:
POP

 #KT-28938 Fixed
This commit is contained in:
Ilmir Usmanov
2019-07-23 17:32:00 +03:00
parent a16e03681b
commit cc06798e2c
13 changed files with 156 additions and 327 deletions
@@ -96,11 +96,11 @@ fun createTextForHelpers(isReleaseCoroutines: Boolean, checkStateMachine: Boolea
fun check(numberOfSuspensions: Int) {
for (i in 1..numberOfSuspensions) {
if (counter != i) error("Wrong state-machine generated: suspendHere called should be called exactly once in one state. Expected " + i + ", got " + counter)
if (counter != i) error("Wrong state-machine generated: suspendHere should be called exactly once in one state. Expected " + i + ", got " + counter)
proceed()
}
if (counter != numberOfSuspensions)
error("Wrong state-machine generated: suspendHere called should be called exactly once in one state. Expected " + numberOfSuspensions + ", got " + counter)
error("Wrong state-machine generated: wrong number of overall suspensions. Expected " + numberOfSuspensions + ", got " + counter)
if (finished) error("Wrong state-machine generated: it is finished early")
proceed()
if (!finished) error("Wrong state-machine generated: it is not finished yet")