Do not ignore copy operations while finding source instructions

in redundant locals elimination.

Since IgnoringCopySourceInterpreter ignores ALOADs and ASTOREs,
the source instruction of ALOAD K in {ALOAD N, ASTORE K, ALOAD K}
sequence is not ASTORE K. In this case we cannot simply replace K
with N, since there can be multiple {ALOAD N, ASTORE K} sequences
in separate branches. After replacement we get different stack
frames.
This change resolves this.

However, in ReturnUnitMethodTransformer we want to ignore copies
of the same GETSTATIC kotlin/Unit.INSTANCE, since we do not mess
with local variables and just replace ASTORE with ARETURN to help
tail-call optimization.
 #KT-23373: Fixed
This commit is contained in:
Ilmir Usmanov
2018-03-21 23:52:57 +03:00
parent 15b46cdda9
commit 481dbee96a
7 changed files with 114 additions and 5 deletions
@@ -0,0 +1,43 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
private var prevSender: String = "FAIL"
class ChatServer {
suspend fun who(sender: String) {
prevSender = sender
}
suspend fun sendTo(recipient: String, sender: String, message: String) { }
suspend fun message(sender: String, message: String) { }
}
private val server = ChatServer()
private suspend fun receivedMessage(id: String, command: String) {
when {
command.startsWith("/who") -> server.who(id)
command.startsWith("/user") -> {
val newName = command.removePrefix("/user").trim()
when {
newName.isEmpty() -> server.sendTo(id, "server::help", "/user [newName]")
else -> server.message(id, newName)
}
}
command.startsWith("/") -> server.sendTo(id, "server::help", "Unknown command ${command.takeWhile { !it.isWhitespace() }}")
else -> server.message(id, command)
}
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
builder {
receivedMessage("OK", "/who")
}
return prevSender
}