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 bd22ea4aeb6..34966f1bb37 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -132,7 +132,7 @@ class CoroutineTransformerMethodVisitor( UninitializedStoresProcessor(methodNode, shouldPreserveClassInitialization).run() - updateLvtAccordingToLiveness(methodNode) + updateLvtAccordingToLiveness(methodNode, isForNamedFunction) val spilledToVariableMapping = spillVariables(suspensionPoints, methodNode) @@ -1000,3 +1000,73 @@ internal fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, contin methodNode.instructions.set(fakeContinuation, VarInsnNode(Opcodes.ALOAD, continuationIndex)) } } + +/* We do not want to spill dead variables, thus, we shrink its LVT record to region, where the variable is alive, + * so, the variable will not be visible in debugger. User can still prolong life span of the variable by using it. + * + * This means, that function parameters do not longer span the whole function, including `this`. + * This might and will break some bytecode processors, including old versions of R8. See KT-24510. + */ +private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction: Boolean) { + val liveness = analyzeLiveness(method) + + fun List.findRecord(insnIndex: Int, variableIndex: Int): LocalVariableNode? { + for (variable in this) { + if (variable.index == variableIndex && + method.instructions.indexOf(variable.start) <= insnIndex && + insnIndex < method.instructions.indexOf(variable.end) + ) return variable + } + return null + } + + fun isAlive(insnIndex: Int, variableIndex: Int): Boolean = + liveness[insnIndex].isAlive(variableIndex) + + val oldLvt = arrayListOf() + for (record in method.localVariables) { + oldLvt += record + } + method.localVariables.clear() + // Skip `this` for suspend lamdba + val start = if (isForNamedFunction) 0 else 1 + for (variableIndex in start until method.maxLocals) { + if (oldLvt.none { it.index == variableIndex }) continue + var startLabel: LabelNode? = null + for (insnIndex in 0 until (method.instructions.size() - 1)) { + val insn = method.instructions[insnIndex] + if (!isAlive(insnIndex, variableIndex) && isAlive(insnIndex + 1, variableIndex)) { + startLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode + } + if (isAlive(insnIndex, variableIndex) && !isAlive(insnIndex + 1, variableIndex)) { + // No variable in LVT -> do not add one + val lvtRecord = oldLvt.findRecord(insnIndex, variableIndex) ?: continue + if (lvtRecord.name == CONTINUATION_VARIABLE_NAME) continue + val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue + // startLabel can be null in case of parameters + @Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start + // No LINENUMBER in range -> no way to put a breakpoint -> do not bother adding a record + if (InsnSequence(startLabel, endLabel).none { it is LineNumberNode }) continue + method.localVariables.add( + LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index) + ) + } + } + } + + for (variable in oldLvt) { + // $completion, $continuation and $result are dead, but they are used by debugger, as well as fake inliner variables + // For example, $continuation is used to create async stack trace + if (variable.name == SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME || + variable.name == CONTINUATION_VARIABLE_NAME || + variable.name == SUSPEND_CALL_RESULT_NAME || + isFakeLocalVariableForInline(variable.name) + ) { + method.localVariables.add(variable) + } + // this acts like $continuation for lambdas. For example, it is used by debugger to create async stack trace. Keep it. + if (variable.name == "this" && !isForNamedFunction) { + method.localVariables.add(variable) + } + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt index 0d680b49ca9..23e6df14244 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/variableLiveness.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.codegen.optimization.common -import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_CALL_RESULT_NAME -import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME -import org.jetbrains.kotlin.codegen.inline.isFakeLocalVariableForInline -import org.jetbrains.org.objectweb.asm.tree.* +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.IincInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.VarInsnNode import java.util.* @@ -59,65 +59,4 @@ private fun useVar(frame: VariableLivenessFrame, insn: AbstractInsnNode) { } else if (insn is IincInsnNode) { frame.markAlive(insn.`var`) } -} - -/* We do not want to spill dead variables, thus, we shrink its LVT record to region, where the variable is alive, - * so, the variable will not be visible in debugger. User can still prolong life span of the variable by using it. - * - * This means, that function parameters do not longer span the whole function, including `this`. - * This might and will break some bytecode processors, including old versions of R8. See KT-24510. - */ -fun updateLvtAccordingToLiveness(method: MethodNode) { - val liveness = analyzeLiveness(method) - - fun List.findRecord(insnIndex: Int, variableIndex: Int): LocalVariableNode? { - for (variable in this) { - if (variable.index == variableIndex && - method.instructions.indexOf(variable.start) <= insnIndex && - insnIndex < method.instructions.indexOf(variable.end) - ) return variable - } - return null - } - - fun isAlive(insnIndex: Int, variableIndex: Int): Boolean = - liveness[insnIndex].isAlive(variableIndex) - - val oldLvt = arrayListOf() - for (record in method.localVariables) { - oldLvt += record - } - method.localVariables.clear() - for (variableIndex in 0 until method.maxLocals) { - if (oldLvt.none { it.index == variableIndex }) continue - var startLabel: LabelNode? = null - for (insnIndex in 0 until (method.instructions.size() - 1)) { - val insn = method.instructions[insnIndex] - if (!isAlive(insnIndex, variableIndex) && isAlive(insnIndex + 1, variableIndex)) { - startLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode - } - if (isAlive(insnIndex, variableIndex) && !isAlive(insnIndex + 1, variableIndex)) { - // No variable in LVT -> do not add one - val lvtRecord = oldLvt.findRecord(insnIndex, variableIndex) ?: continue - val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue - // startLabel can be null in case of parameters - @Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start - // No LINENUMBER in range -> no way to put a breakpoint -> do not bother adding a record - if (InsnSequence(startLabel, endLabel).none { it is LineNumberNode }) continue - method.localVariables.add( - LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index) - ) - } - } - } - - for (variable in oldLvt) { - // $completion and $result are dead, but they are used by debugger, as well as fake inliner variables - if (variable.name == SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME || - variable.name == SUSPEND_CALL_RESULT_NAME || - isFakeLocalVariableForInline(variable.name) - ) { - method.localVariables.add(variable) - } - } -} +} \ No newline at end of file diff --git a/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/nonStaticStateMachine.kt b/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/nonStaticStateMachine.kt index cbe38fa23eb..fb176ef39f2 100644 --- a/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/nonStaticStateMachine.kt +++ b/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/nonStaticStateMachine.kt @@ -5,6 +5,7 @@ class A { suspend fun foo1(l: Long) { foo() foo() + val dead = l } } @@ -12,5 +13,5 @@ class A { // VARIABLE : NAME=this TYPE=LA; INDEX=0 // VARIABLE : NAME=l TYPE=J INDEX=1 // VARIABLE : NAME=$completion TYPE=Lkotlin/coroutines/Continuation; INDEX=3 -// VARIABLE : NAME=$continuation TYPE=Lkotlin/coroutines/Continuation; INDEX=5 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=4 \ No newline at end of file +// VARIABLE : NAME=$continuation TYPE=Lkotlin/coroutines/Continuation; INDEX=7 +// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=6 \ No newline at end of file diff --git a/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachine.kt b/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachine.kt index c968854ff84..2e10b36cc70 100644 --- a/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachine.kt +++ b/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachine.kt @@ -4,10 +4,11 @@ suspend fun foo() {} suspend fun foo1(l: Long) { foo() foo() + val dead = l } // METHOD : StaticStateMachineKt.foo1(JLkotlin/coroutines/Continuation;)Ljava/lang/Object; // VARIABLE : NAME=l TYPE=J INDEX=0 // VARIABLE : NAME=$completion TYPE=Lkotlin/coroutines/Continuation; INDEX=2 -// VARIABLE : NAME=$continuation TYPE=Lkotlin/coroutines/Continuation; INDEX=4 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=3 \ No newline at end of file +// VARIABLE : NAME=$continuation TYPE=Lkotlin/coroutines/Continuation; INDEX=6 +// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=5 \ No newline at end of file diff --git a/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachineReceiver.kt b/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachineReceiver.kt index 8c6b7f486e5..182219e5861 100644 --- a/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachineReceiver.kt +++ b/compiler/testData/checkLocalVariablesTable/completionInSuspendFunction/staticStateMachineReceiver.kt @@ -6,11 +6,12 @@ suspend fun A.foo() {} suspend fun A.foo1(l: Long) { foo() foo() + val dead = l } // METHOD : StaticStateMachineReceiverKt.foo1(LA;JLkotlin/coroutines/Continuation;)Ljava/lang/Object; // VARIABLE : NAME=$this$foo1 TYPE=LA; INDEX=0 // VARIABLE : NAME=l TYPE=J INDEX=1 // VARIABLE : NAME=$completion TYPE=Lkotlin/coroutines/Continuation; INDEX=3 -// VARIABLE : NAME=$continuation TYPE=Lkotlin/coroutines/Continuation; INDEX=5 -// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=4 \ No newline at end of file +// VARIABLE : NAME=$continuation TYPE=Lkotlin/coroutines/Continuation; INDEX=7 +// VARIABLE : NAME=$result TYPE=Ljava/lang/Object; INDEX=6 \ No newline at end of file diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt index 55270f96d5d..606349833cf 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/dataClass.kt @@ -18,7 +18,6 @@ suspend fun foo(data: Data, body: suspend (Data) -> Unit) { // METHOD : DataClassKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; // JVM_TEMPLATES -// VARIABLE : NAME=$dstr$x_param$y_param TYPE=LData; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=y_param TYPE=I INDEX=4 // VARIABLE : NAME=this TYPE=LDataClassKt$test$2; INDEX=0 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt index 9e8d8eecfd6..d50235a0b16 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/extensionComponents.kt @@ -12,7 +12,9 @@ object B { suspend fun B.bar(): String { operator fun A.component3() = z - return foo(A("O", "K", 123)) { (x_param, y_param, z_param) -> x_param + y_param + z_param.toString() } + return foo(A("O", "K", 123)) { (x_param, y_param, z_param) -> + x_param + y_param + z_param.toString() + } } suspend fun test() = B.bar() @@ -26,7 +28,6 @@ suspend fun test() = B.bar() // JVM_TEMPLATES // METHOD : ExtensionComponentsKt$bar$3.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; -// VARIABLE : NAME=$dstr$x_param$y_param$z_param TYPE=LA; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=4 // VARIABLE : NAME=z_param TYPE=I INDEX=5 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt index 0ef5c3d80da..42e3451e76c 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/generic.kt @@ -4,7 +4,9 @@ data class A(val x: T, val y: F) suspend fun foo(a: A, block: suspend (A) -> String) = block(a) -suspend fun test() = foo(A("OK", 1)) { (x_param, y_param) -> x_param + (y_param.toString()) } +suspend fun test() = foo(A("OK", 1)) { (x_param, y_param) -> + x_param + (y_param.toString()) +} // Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. // However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). @@ -13,7 +15,6 @@ suspend fun test() = foo(A("OK", 1)) { (x_param, y_param) -> x_param + (y_param. // METHOD : GenericKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; // JVM_TEMPLATES -// VARIABLE : NAME=$dstr$x_param$y_param TYPE=LA; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=y_param TYPE=I INDEX=4 // VARIABLE : NAME=this TYPE=LGenericKt$test$2; INDEX=0 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt index 426b9fdabad..5cdaa5ccfa4 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/otherParameters.kt @@ -3,7 +3,9 @@ data class A(val x: String, val y: String) suspend fun foo(a: A, block: suspend (Int, A, String) -> String): String = block(1, a, "#") -suspend fun test() = foo(A("O", "K")) { i_param, (x_param, y_param), v_param -> i_param.toString() + x_param + y_param + v_param } +suspend fun test() = foo(A("O", "K")) { i_param, (x_param, y_param), v_param -> + i_param.toString() + x_param + y_param + v_param +} // Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. // However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). @@ -13,7 +15,6 @@ suspend fun test() = foo(A("O", "K")) { i_param, (x_param, y_param), v_param -> // JVM_TEMPLATES // VARIABLE : NAME=i_param TYPE=I INDEX=2 -// VARIABLE : NAME=$dstr$x_param$y_param TYPE=LA; INDEX=3 // VARIABLE : NAME=v_param TYPE=Ljava/lang/String; INDEX=4 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=5 // VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=6 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt index 3572a208fe1..b1dca03400e 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/parameters.kt @@ -20,7 +20,6 @@ suspend fun foo(data: Data, body: suspend Long.(String, Data, Int) -> Unit) { // JVM_TEMPLATES // VARIABLE : NAME=$this$foo TYPE=J INDEX=2 // VARIABLE : NAME=str TYPE=Ljava/lang/String; INDEX=4 -// VARIABLE : NAME=$dstr$x$_u24__u24$z TYPE=LData; INDEX=5 // VARIABLE : NAME=i TYPE=I INDEX=6 // VARIABLE : NAME=x TYPE=Ljava/lang/String; INDEX=7 // VARIABLE : NAME=z TYPE=I INDEX=8 diff --git a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/underscoreNames.kt b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/underscoreNames.kt index 88d8f116352..6bb5f313fe8 100644 --- a/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/underscoreNames.kt +++ b/compiler/testData/checkLocalVariablesTable/parametersInSuspendLambda/underscoreNames.kt @@ -7,7 +7,9 @@ class A { suspend fun foo(a: A, block: suspend (A) -> String): String = block(a) -suspend fun test() = foo(A()) { (x_param, _, y_param) -> x_param + y_param } +suspend fun test() = foo(A()) { (x_param, _, y_param) -> + x_param + y_param +} // Parameters (including anonymous destructuring parameters) are moved to fields in the Continuation class for the suspend lambda class. // However, in non-IR, the fields are first stored in local variables, and they are not read directly (even for destructuring components). @@ -16,7 +18,6 @@ suspend fun test() = foo(A()) { (x_param, _, y_param) -> x_param + y_param } // METHOD : UnderscoreNamesKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; // JVM_TEMPLATES -// VARIABLE : NAME=$dstr$x_param$_u24__u24$y_param TYPE=LA; INDEX=2 // VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3 // VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=4 // VARIABLE : NAME=this TYPE=LUnderscoreNamesKt$test$2; INDEX=0 diff --git a/compiler/testData/codegen/bytecodeText/oldLanguageVersions/coroutines/varValueConflictsWithTableSameSort_1_2.kt b/compiler/testData/codegen/bytecodeText/oldLanguageVersions/coroutines/varValueConflictsWithTableSameSort_1_2.kt index 8ef31be39bc..feaf753e6be 100644 --- a/compiler/testData/codegen/bytecodeText/oldLanguageVersions/coroutines/varValueConflictsWithTableSameSort_1_2.kt +++ b/compiler/testData/codegen/bytecodeText/oldLanguageVersions/coroutines/varValueConflictsWithTableSameSort_1_2.kt @@ -22,6 +22,7 @@ fun box(): String { try { var i: String = "abc" i = "123" + println(i) } finally { } // This variable should take the same slot as 'i' had @@ -46,4 +47,5 @@ fun box(): String { // 0 PUTFIELD VarValueConflictsWithTableSameSort_1_2Kt\$box\$1.L\$0 : Ljava/lang/Object; /* 1 load in try/finally */ /* 1 load in result = s */ -// 2 ALOAD 3 +/* 1 load in println */ +// 3 ALOAD 3 diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.kt b/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.kt index 7a9fc16789e..eac4f2f15c9 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.kt @@ -5,12 +5,15 @@ suspend fun main() { val b = 7 none() foo() + val dead1 = a + val dead2 = b } suspend fun foo() { val x = "foo" none() bar() + val dead = x } suspend fun bar() { @@ -19,6 +22,7 @@ suspend fun bar() { val z = "bar" //Breakpoint! val a = 5 + val dead = y } suspend fun none() {} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.out b/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.out index cb29027ccce..ece1ea78584 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/asyncStackTrace/asyncFunctions.out @@ -1,11 +1,11 @@ -LineBreakpoint created at asyncFunctions.kt:21 +LineBreakpoint created at asyncFunctions.kt:24 Run Java Connected to the target VM -asyncFunctions.kt:21 +asyncFunctions.kt:24 Async stack trace: - asyncFunctions.AsyncFunctionsKt:18 + asyncFunctions.AsyncFunctionsKt:21 y = "zoo" - asyncFunctions.AsyncFunctionsKt:13 + asyncFunctions.AsyncFunctionsKt:15 x = "foo" asyncFunctions.AsyncFunctionsKt:7 a = 5 diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt index a42ae359594..3af3539cc8d 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt @@ -19,7 +19,7 @@ suspend fun test1(i: Int): Int { suspend fun a(aParam: String) { val a = "a" b(a) - a + 1 + a + aParam } suspend fun b(bParam: String) { diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt index 87b2731fe61..ae825dcd3c2 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt @@ -9,7 +9,7 @@ fun main() { runBlocking { val rootCoroutineVal = mainTestVal TestSuspendA().a() - print("") + print(rootCoroutineVal) } } @@ -18,7 +18,7 @@ class TestSuspendA { suspend fun a() { val methodVal = "" InClassB().b() - print("") + print(methodVal) } class InClassB { @@ -27,7 +27,7 @@ class TestSuspendA { suspend fun b() { val inClassBMethodVal = "" InClassC().c() - print("") + print(inClassBMethodVal) } inner class InClassC { @@ -37,7 +37,7 @@ class TestSuspendA { yield() val inClassCMethodVal = "" //Breakpoint! - print("") + print(inClassCMethodVal) } } } diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out index 3fa27e9a77d..03098c150ce 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out @@ -4,12 +4,12 @@ Connected to the target VM suspendFunWithInner.kt:40 Thread stack trace: CoroutinePreflightFrame c:!LINE_NUMBER!, TestSuspendA$InClassB$InClassC (continuation) - ($completion, $continuation, $result, inClassCMethodVal, this) + ($completion, $continuation, $result, inClassCMethodVal) CoroutineInfo: 1 coroutine RUNNING CoroutineStackFrame b:!LINE_NUMBER!, TestSuspendA$InClassB (continuation) - (inClassBMethodVal, this) + (inClassBMethodVal) CoroutineStackFrame a:!LINE_NUMBER!, TestSuspendA (continuation) - (methodVal, this) + (methodVal) CoroutineStackFrame invokeSuspend:!LINE_NUMBER!, SuspendFunWithInnerKt$main$1 (continuation) (rootCoroutineVal) CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/frame/suspendContinuation.kt b/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/frame/suspendContinuation.kt index 510a96dd03d..2831042e0d7 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/frame/suspendContinuation.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/frame/suspendContinuation.kt @@ -4,7 +4,7 @@ suspend fun main() { val a = 5 foo() //Breakpoint! - val b = 4 + val b = a } suspend fun foo() {} diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.kt b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.kt index bf177b1aa5f..4dd00ffb590 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.kt @@ -14,16 +14,18 @@ fun main() { suspend fun a() { val a = "a" b(a) - val aLate = "a" // to prevent stackFrame to collapse + val aLate = a // to prevent stackFrame to collapse } suspend fun b(paramA: String) { yield() val b = "b" c(b) + val dead = paramA } suspend fun c(paramB: String) { val c = "c" //Breakpoint! + val dead = paramB } \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out index 84e485de817..89717f056a7 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out @@ -1,7 +1,7 @@ -LineBreakpoint created at coroutineSuspendFun.kt:29 +LineBreakpoint created at coroutineSuspendFun.kt:30 Run Java Connected to the target VM -coroutineSuspendFun.kt:29 +coroutineSuspendFun.kt:30 Thread stack trace: KotlinStackFrame c:!LINE_NUMBER!, CoroutineSuspendFunKt (continuation) ($completion, c, paramB) diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt index b8fc57ed17c..3d056591543 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt @@ -14,16 +14,18 @@ fun main() { suspend fun a() { val a = "a" b(a) - val aLate = "a" // to prevent stackFrame to collapse + val aLate = a // to prevent stackFrame to collapse } suspend fun b(paramA: String) { yield() val b = "b" c(b) + val dead = paramA } suspend fun c(paramB: String) { val c = "c" //Breakpoint! + val dead = paramB } \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out index de27ef7975a..15ac1159ac9 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out @@ -1,7 +1,7 @@ -LineBreakpoint created at coroutineSuspendFun136.kt:29 +LineBreakpoint created at coroutineSuspendFun136.kt:30 Run Java Connected to the target VM -coroutineSuspendFun136.kt:29 +coroutineSuspendFun136.kt:30 Thread stack trace: KotlinStackFrame c:!LINE_NUMBER!, CoroutineSuspendFun136Kt (continuation) ($completion, c, paramB) diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out index 0476934ae0a..96f82fe8447 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out @@ -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$coroutineScope, this) + ($result, 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)