Do not mark fake inliner variables as alive

This prevents them from spilling.
 #KT-29317 Fixed
This commit is contained in:
Ilmir Usmanov
2019-01-16 21:10:57 +03:00
committed by Stanislav Erokhin
parent 7e4e1b9a4d
commit e8c52e0a8f
5 changed files with 43 additions and 12 deletions
@@ -498,12 +498,6 @@ class CoroutineTransformerMethodVisitor(
val frames = performRefinedTypeAnalysis(methodNode, containingClassInternalName)
fun AbstractInsnNode.index() = instructions.indexOf(this)
fun Int.isInlinerFakeVariable(index: Int) = methodNode.localVariables.any {
(it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT) || it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION))
&& it.index == this
&& it.start.index() <= index && index <= it.end.index()
}
// We postpone these actions because they change instruction indices that we use when obtaining frames
val postponedActions = mutableListOf<() -> Unit>()
val maxVarsCountByType = mutableMapOf<Type, Int>()
@@ -545,9 +539,8 @@ class CoroutineTransformerMethodVisitor(
// k + 2 - exception
val variablesToSpill =
(0 until localsCount)
.filterNot {
it in setOf(continuationIndex, dataIndex, exceptionIndex) || it.isInlinerFakeVariable(suspensionCallBegin.index())
}.map { Pair(it, frame.getLocal(it)) }
.filterNot { it in setOf(continuationIndex, dataIndex, exceptionIndex) }
.map { Pair(it, frame.getLocal(it)) }
.filter { (index, value) ->
(index == 0 && needDispatchReceiver && isForNamedFunction) ||
(value != StrictBasicValue.UNINITIALIZED_VALUE && livenessFrame.isAlive(index))
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.IincInsnNode
@@ -78,11 +79,13 @@ private fun useVar(
) {
val index = node.instructions.indexOf(insn)
node.localVariables.filter {
node.instructions.indexOf(it.start) < index && index < node.instructions.indexOf(it.end) &&
// Inliner fake variables, despite being present in LVT, are not read, thus are always dead
!it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT) && !it.name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) &&
node.instructions.indexOf(it.start) < index && index < node.instructions.indexOf(it.end) &&
Type.getType(it.desc).sort == typeAnnotatedFrame?.getLocal(it.index)?.type?.sort
}.forEach {
frame.markAlive(it.index)
}
frame.markAlive(it.index)
}
if (insn is VarInsnNode && insn.isLoadOperation()) {
frame.markAlive(insn.`var`)