diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index 4998096ce05..fde67d392f2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -136,8 +136,6 @@ class CoroutineTransformerMethodVisitor( UninitializedStoresProcessor(methodNode, shouldPreserveClassInitialization).run() - updateLvtAccordingToLiveness(methodNode, isForNamedFunction) - val spilledToVariableMapping = spillVariables(suspensionPoints, methodNode) val suspendMarkerVarIndex = methodNode.maxLocals++ @@ -194,6 +192,8 @@ class CoroutineTransformerMethodVisitor( dropUnboxInlineClassMarkers(methodNode, suspensionPoints) methodNode.removeEmptyCatchBlocks() + updateLvtAccordingToLiveness(methodNode, isForNamedFunction) + if (languageVersionSettings.isReleaseCoroutines()) { writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping) } @@ -1298,7 +1298,6 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction: method.localVariables.clear() // Skip `this` for suspend lambda val start = if (isForNamedFunction) 0 else 1 - val oldLvtNodeToLatestNewLvtNode = mutableMapOf() for (variableIndex in start until method.maxLocals) { if (oldLvt.none { it.index == variableIndex }) continue var startLabel: LabelNode? = null @@ -1337,10 +1336,7 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction: // startLabel can be null in case of parameters @Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index) - if (lvtRecord !in oldLvtNodeToLatestNewLvtNode) { - method.localVariables.add(node) - } - oldLvtNodeToLatestNewLvtNode[lvtRecord] = node + method.localVariables.add(node) } } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/debug/thisAndResultInLvt.kt b/compiler/testData/codegen/bytecodeText/coroutines/debug/thisAndResultInLvt.kt index 8d82b4840f7..967f79eda03 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/debug/thisAndResultInLvt.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/debug/thisAndResultInLvt.kt @@ -21,7 +21,7 @@ class A { // BEs generate continuation classes differently, JVM_IR generates more correctly // foo, c's lambda and foo's continuation -// 3 LOCALVARIABLE \$result Ljava/lang/Object; +// 8 LOCALVARIABLE \$result Ljava/lang/Object; // foo x 3 since we split the local over restore code for the two calls to block(), and // 4 LOCALVARIABLE this LA; diff --git a/compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt b/compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt index 71f61f61bb4..4ead75c2b6a 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt @@ -22,4 +22,4 @@ class MyBlockingAdapter() { } } -// 1 LOCALVARIABLE \$this\$extensionFun\$iv\$iv LAtomicInt; +// 2 LOCALVARIABLE \$this\$extensionFun\$iv\$iv LAtomicInt; diff --git a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt index 88f3783d8ce..c158d26224e 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt @@ -43,7 +43,7 @@ fun box(): String { // 1 LOCALVARIABLE i Ljava/lang/String; L.* 3 // We merge LVT records for two consequent branches, but we split the local over the restore code. -// 2 LOCALVARIABLE s Ljava/lang/String; L.* 3 +// 3 LOCALVARIABLE s Ljava/lang/String; L.* 3 // 1 PUTFIELD VarValueConflictsWithTableSameSortKt\$box\$1.L\$0 : Ljava/lang/Object; /* 1 load in the catch (e: Throwable) { throw e } block which is implicitly wrapped around try/finally */ // 1 ALOAD 3\s+ATHROW