Extend LVT record of alive variables to end of next suspension point
Otherwise, arguments of suspend call become invisible in async stack trace #KT-44714
This commit is contained in:
+9
-10
@@ -1217,18 +1217,18 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
fun isAlive(insnIndex: Int, variableIndex: Int): Boolean =
|
||||
liveness[insnIndex].isAlive(variableIndex)
|
||||
|
||||
fun nextSuspensionPointLabel(insn: AbstractInsnNode): LabelNode {
|
||||
fun nextSuspensionPointEndLabel(insn: AbstractInsnNode): LabelNode {
|
||||
val suspensionPoint =
|
||||
InsnSequence(insn, method.instructions.last).firstOrNull { isAfterSuspendMarker(it) } ?: method.instructions.last
|
||||
return suspensionPoint as? LabelNode ?: suspensionPoint.findNextOrNull { it is LabelNode } as LabelNode
|
||||
}
|
||||
|
||||
fun nextSuspensionPointStartLabel(insn: AbstractInsnNode): LabelNode {
|
||||
val suspensionPoint =
|
||||
InsnSequence(insn, method.instructions.last).firstOrNull { isBeforeSuspendMarker(it) } ?: method.instructions.last
|
||||
return suspensionPoint as? LabelNode ?: suspensionPoint.findPreviousOrNull { it is LabelNode } as LabelNode
|
||||
}
|
||||
|
||||
fun previousSuspensionPointLabel(insn: AbstractInsnNode): LabelNode {
|
||||
val suspensionPoint =
|
||||
InsnSequence(method.instructions.first, insn).lastOrNull { isAfterSuspendMarker(it) } ?: method.instructions.first
|
||||
return suspensionPoint as? LabelNode ?: suspensionPoint.findNextOrNull { it is LabelNode } as LabelNode
|
||||
}
|
||||
|
||||
fun min(a: LabelNode, b: LabelNode): LabelNode =
|
||||
if (method.instructions.indexOf(a) < method.instructions.indexOf(b)) a else b
|
||||
|
||||
@@ -1259,7 +1259,7 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
val lvtRecord = oldLvt.findRecord(insnIndex, variableIndex) ?: continue
|
||||
if (lvtRecord.name == CONTINUATION_VARIABLE_NAME) continue
|
||||
// Extend lvt record to the next suspension point
|
||||
val endLabel = min(lvtRecord.end, nextSuspensionPointLabel(insn))
|
||||
val endLabel = min(lvtRecord.end, nextSuspensionPointEndLabel(insn))
|
||||
// startLabel can be null in case of parameters
|
||||
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
|
||||
// Attempt to extend existing local variable node corresponding to the record in
|
||||
@@ -1280,7 +1280,6 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
|
||||
val deadVariables = arrayListOf<Int>()
|
||||
outer@for (variableIndex in start until method.maxLocals) {
|
||||
if (oldLvt.none { it.index == variableIndex }) continue
|
||||
if (oldLvt.none { it.index == variableIndex }) continue
|
||||
for (insnIndex in 0 until (method.instructions.size() - 1)) {
|
||||
if (isAlive(insnIndex, variableIndex)) continue@outer
|
||||
@@ -1312,7 +1311,7 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
||||
variable.desc,
|
||||
variable.signature,
|
||||
variable.start,
|
||||
nextSuspensionPointLabel(variable.start),
|
||||
nextSuspensionPointStartLabel(variable.start),
|
||||
variable.index
|
||||
)
|
||||
)
|
||||
|
||||
+6
-5
@@ -14,12 +14,13 @@ fun main(args: Array<String>) {
|
||||
@BuilderInference
|
||||
suspend fun SequenceScope<Int>.awaitSeq(): Int = 42
|
||||
|
||||
|
||||
// 1 LOCALVARIABLE a I L[0-9]+ L19
|
||||
|
||||
/* TODO: JVM_IR does not generate LINENUMBER at the end of the lambda */
|
||||
// JVM_TEMPLATES
|
||||
// 1 LINENUMBER 9 L19
|
||||
|
||||
// JVM_IR_TEMPLATES
|
||||
// 1 LOCALVARIABLE a I L[0-9]+ L4
|
||||
|
||||
// JVM_TEMPLATES
|
||||
// 1 LOCALVARIABLE a I L[0-9]+ L19
|
||||
// TODO: Old BE generates LINENUMBER label after suspension point, unlike JVM_BE
|
||||
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
@@ -4,7 +4,7 @@ Connected to the target VM
|
||||
suspendMain.kt:15
|
||||
Thread stack trace:
|
||||
CoroutinePreflightFrame invokeSuspend:!LINE_NUMBER!, SuspendMainKt$main$2 (continuation)
|
||||
($result, this)
|
||||
($result, $this$coroutineScope, this)
|
||||
CoroutineInfo: -1 coroutine UNKNOWN
|
||||
CoroutineStackFrame startUndispatchedOrReturn:!LINE_NUMBER!, UndispatchedKt (kotlinx.coroutines.intrinsics)
|
||||
($i$a$-undispatchedResult-UndispatchedKt$startUndispatchedOrReturn$2, $i$f$undispatchedResult, $this$startUndispatchedOrReturn, $this$undispatchedResult$iv, block, receiver)
|
||||
|
||||
Reference in New Issue
Block a user