diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 220141b85d7..7c0ff190d1d 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -13227,6 +13227,64 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); } } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/debugMode") + @TestDataPath("$PROJECT_ROOT") + public class DebugMode { + @Test + public void testAllFilesPresentInDebugMode() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/debugMode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("backEdge.kt") + public void testBackEdge() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/backEdge.kt"); + } + + @Test + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/if.kt"); + } + + @Test + @TestMetadata("nullCleanup.kt") + public void testNullCleanup() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullCleanup.kt"); + } + + @Test + @TestMetadata("nullNotSpill.kt") + public void testNullNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullNotSpill.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/simple.kt"); + } + + @Test + @TestMetadata("twoRefs.kt") + public void testTwoRefs() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/twoRefs.kt"); + } + + @Test + @TestMetadata("unusedParamNotSpill.kt") + public void testUnusedParamNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/unusedParamNotSpill.kt"); + } + + @Test + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/when.kt"); + } + } } } diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index db0ecfc323d..fe4f852fb8f 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -28,6 +28,8 @@ where advanced options include: -Xir-do-not-clear-binding-context When using the IR backend, do not clear BindingContext between psi2ir and lowerings -Xemit-jvm-type-annotations Emit JVM type annotations in bytecode + -Xdebug Enable debug mode for compilation. + Currently this includes spilling all variables in a suspending context regardless their liveness. -Xjvm-enable-preview Allow using features from Java language that are in preview phase. Works as `--enable-preview` in Java. All class files are marked as preview-generated thus it won't be possible to use them in release environment -Xenhance-type-parameter-types-to-def-not-null diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/backEdge.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/backEdge.kt new file mode 100644 index 00000000000..38057f1fa95 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/backEdge.kt @@ -0,0 +1,57 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + spilledVariables += field.name to "${field.get(continuation)}" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test() { + for (i in 0..1) { + saveSpilledVariables() + val a = "a" + saveSpilledVariables() + blackhole(a) + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + + val continuationName = "Continuation at BackEdgeKt\$box\$1.invokeSuspend(backEdge.kt:42)" + if (spilledVariables != setOf("label" to "1", "I$0" to "0", "L$0" to continuationName, "L$1" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "I$0" to "0", "L$0" to continuationName, "L$1" to "a")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "1", "I$0" to "1", "L$0" to continuationName, "L$1" to "a")) return "FAIL 3: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "I$0" to "1", "L$0" to continuationName, "L$1" to "a")) return "FAIL 4: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "I$0" to "1", "L$0" to continuationName, "L$1" to "a")) return "FAIL 5: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/if.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/if.kt new file mode 100644 index 00000000000..0df3640d240 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/if.kt @@ -0,0 +1,76 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + val fieldValue = when (val obj = field.get(continuation)) { + is Array<*> -> obj.joinToString(prefix = "[", postfix = "]") + else -> obj + } + spilledVariables += field.name to "$fieldValue" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test(check: Boolean) { + if (check) { + val a = "a1" + saveSpilledVariables() + blackhole(a) + } else { + val a = "a2" + val b = "b2" + saveSpilledVariables() + blackhole(a, b) + } + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test(true) + } + + var continuationName = "Continuation at IfKt\$box\$1.invokeSuspend(if.kt:51)" + if (spilledVariables != setOf("label" to "1", "Z$0" to "true", "L$0" to continuationName, "L$1" to "a1", "L$2" to "null")) + return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "Z$0" to "true", "L$0" to continuationName, "L$1" to "a1", "L$2" to "[a1]")) + return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "Z$0" to "true", "L$0" to continuationName, "L$1" to "a1", "L$2" to "[a1]")) + return "FAIL 3: $spilledVariables" + + builder { + test(false) + } + + continuationName = "Continuation at IfKt\$box\$2.invokeSuspend(if.kt:65)" + if (spilledVariables != setOf("label" to "2", "Z$0" to "false", "L$0" to continuationName, "L$1" to "a2", "L$2" to "b2")) return "FAIL 4: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "Z$0" to "false", "L$0" to continuationName, "L$1" to "a2", "L$2" to "b2")) return "FAIL 5: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "Z$0" to "false", "L$0" to continuationName, "L$1" to "a2", "L$2" to "b2")) return "FAIL 6: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullCleanup.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullCleanup.kt new file mode 100644 index 00000000000..c170169c100 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullCleanup.kt @@ -0,0 +1,57 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + val fieldValue = when (val obj = field.get(continuation)) { + is Array<*> -> obj.joinToString(prefix = "[", postfix = "]") + else -> obj + } + spilledVariables += field.name to "$fieldValue" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test() { + var a: String? = "a" + saveSpilledVariables() + blackhole(a) + a = null + saveSpilledVariables() + blackhole(a) +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + + val continuationName = "Continuation at NullCleanupKt\$box\$1.invokeSuspend(nullCleanup.kt:46)" + if (spilledVariables != setOf("label" to "1", "L$0" to continuationName, "L$1" to "a")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to continuationName, "L$1" to "[a]")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to continuationName, "L$1" to "[a]")) return "FAIL 3: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullNotSpill.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullNotSpill.kt new file mode 100644 index 00000000000..e75a7482605 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullNotSpill.kt @@ -0,0 +1,55 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + val fieldValue = when (val obj = field.get(continuation)) { + is Array<*> -> obj.joinToString(prefix = "[", postfix = "]") + else -> obj + } + spilledVariables += field.name to "$fieldValue" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test() { + val a = null + saveSpilledVariables() + blackhole(a) + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + + val continuationName = "Continuation at NullNotSpillKt\$box\$1.invokeSuspend(nullNotSpill.kt:44)" + if (spilledVariables != setOf("label" to "1", "L$0" to continuationName, "L$1" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to continuationName, "L$1" to "[null]")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to continuationName, "L$1" to "[null]")) return "FAIL 3: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/simple.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/simple.kt new file mode 100644 index 00000000000..ece156fbaf8 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/simple.kt @@ -0,0 +1,59 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + val fieldValue = when (val obj = field.get(continuation)) { + is Array<*> -> obj.joinToString(prefix = "[", postfix = "]") + else -> obj + } + spilledVariables += field.name to "$fieldValue" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test() { + val a = "a" + saveSpilledVariables() + blackhole(a) + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + + val continuationName = "Continuation at SimpleKt\$box\$1.invokeSuspend(simple.kt:44)" + if (spilledVariables != setOf("label" to "1", "L$0" to continuationName, "L$1" to "a", "L$2" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to continuationName, "L$1" to "a", "L$2" to "[a]")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to continuationName, "L$1" to "a", "L$2" to "[a]")) return "FAIL 3: $spilledVariables" + + return "OK" +} + +fun main() { + println(box()) +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/twoRefs.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/twoRefs.kt new file mode 100644 index 00000000000..0709e752bf0 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/twoRefs.kt @@ -0,0 +1,62 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + val fieldValue = when (val obj = field.get(continuation)) { + is Array<*> -> obj.joinToString(prefix = "[", postfix = "]") + else -> obj + } + spilledVariables += field.name to "$fieldValue" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test(a: String, b: String) { + saveSpilledVariables() + blackhole(a) + saveSpilledVariables() + blackhole(b) + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test("a", "b") + } + + val continuationName = "Continuation at TwoRefsKt\$box\$1.invokeSuspend(twoRefs.kt:45)" + if (spilledVariables != setOf("label" to "1", "L$0" to "a", "L$1" to "b", "L$2" to continuationName, "L$3" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to "a", "L$1" to "b", "L$2" to continuationName, "L$3" to "[a]")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "a", "L$1" to "b", "L$2" to continuationName, "L$3" to "[b]")) return "FAIL 3: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "a", "L$1" to "b", "L$2" to continuationName, "L$3" to "[b]")) return "FAIL 4: $spilledVariables" + + return "OK" +} + +fun main() { + println(box()) +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/unusedParamNotSpill.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/unusedParamNotSpill.kt new file mode 100644 index 00000000000..8648f7469ca --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/unusedParamNotSpill.kt @@ -0,0 +1,44 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + spilledVariables += field.name to "${field.get(continuation)}" + } + c = continuation + COROUTINE_SUSPENDED +} + +val test: suspend (Int) -> Unit = { unused -> + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test(1) + } + + if (spilledVariables != setOf("label" to "1")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "1")) return "FAIL 2: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/when.kt b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/when.kt new file mode 100644 index 00000000000..ffcd6692b0e --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/debugMode/when.kt @@ -0,0 +1,103 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun blackhole(vararg a: Any?) {} + +val spilledVariables = mutableSetOf>() + +var c: Continuation? = null + +suspend fun saveSpilledVariables() = suspendCoroutineUninterceptedOrReturn { continuation -> + spilledVariables.clear() + for (field in continuation.javaClass.declaredFields) { + if (field.name != "label" && (field.name.length != 3 || field.name[1] != '$')) continue + field.isAccessible = true + val fieldValue = when (val obj = field.get(continuation)) { + is Array<*> -> obj.joinToString(prefix = "[", postfix = "]") + else -> obj + } + spilledVariables += field.name to "$fieldValue" + } + c = continuation + COROUTINE_SUSPENDED +} + +suspend fun test(check: Int) { + when (check) { + 0 -> { + val a = "a0" + saveSpilledVariables() + blackhole(a) + } + 1 -> { + val a = "a1" + val b = "b1" + saveSpilledVariables() + blackhole(a, b) + } + else -> { + val a = "a2" + val b = "b2" + val c = 1 + saveSpilledVariables() + blackhole(a, b, c) + } + } + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test(0) + } + + var continuationName = "Continuation at WhenKt\$box\$1.invokeSuspend(when.kt:61)" + if (spilledVariables != setOf("label" to "1", "I$0" to "0", "I$1" to "0", "I$2" to "0", "L$0" to continuationName, "L$1" to "a0", "L$2" to "null")) + return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "0", "I$1" to "0", "I$2" to "0", "L$0" to continuationName, "L$1" to "a0", "L$2" to "[a0]")) + return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "0", "I$1" to "0", "I$2" to "0", "L$0" to continuationName, "L$1" to "a0", "L$2" to "[a0]")) + return "FAIL 3: $spilledVariables" + + builder { + test(1) + } + + continuationName = "Continuation at WhenKt\$box\$2.invokeSuspend(when.kt:75)" + if (spilledVariables != setOf("label" to "2", "I$0" to "1", "I$1" to "1", "I$2" to "0", "L$0" to continuationName, "L$1" to "a1", "L$2" to "b1")) + return "FAIL 4: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "1", "I$1" to "1", "I$2" to "0", "L$0" to continuationName, "L$1" to "a1", "L$2" to "b1")) + return "FAIL 5: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "1", "I$1" to "1", "I$2" to "0", "L$0" to continuationName, "L$1" to "a1", "L$2" to "b1")) + return "FAIL 6: $spilledVariables" + + builder { + test(2) + } + + continuationName = "Continuation at WhenKt\$box\$3.invokeSuspend(when.kt:89)" + if (spilledVariables != setOf("label" to "3", "I$0" to "2", "I$1" to "2", "I$2" to "1", "L$0" to continuationName, "L$1" to "a2", "L$2" to "b2")) + return "FAIL 7: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "2", "I$1" to "2", "I$2" to "1", "L$0" to continuationName, "L$1" to "a2", "L$2" to "b2")) + return "FAIL 8: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "2", "I$1" to "2", "I$2" to "1", "L$0" to continuationName, "L$1" to "a2", "L$2" to "b2")) + return "FAIL 9: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 4677e8f201a..c173dc0c0d8 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -13107,6 +13107,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); } } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/debugMode") + @TestDataPath("$PROJECT_ROOT") + public class DebugMode { + @Test + public void testAllFilesPresentInDebugMode() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/debugMode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + } } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 8d5933d16d6..d84b05dfb1e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -13227,6 +13227,64 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); } } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/debugMode") + @TestDataPath("$PROJECT_ROOT") + public class DebugMode { + @Test + public void testAllFilesPresentInDebugMode() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/debugMode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("backEdge.kt") + public void testBackEdge() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/backEdge.kt"); + } + + @Test + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/if.kt"); + } + + @Test + @TestMetadata("nullCleanup.kt") + public void testNullCleanup() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullCleanup.kt"); + } + + @Test + @TestMetadata("nullNotSpill.kt") + public void testNullNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/nullNotSpill.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/simple.kt"); + } + + @Test + @TestMetadata("twoRefs.kt") + public void testTwoRefs() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/twoRefs.kt"); + } + + @Test + @TestMetadata("unusedParamNotSpill.kt") + public void testUnusedParamNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/unusedParamNotSpill.kt"); + } + + @Test + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/debugMode/when.kt"); + } + } } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt index 36c0c25d753..621cd5eda4e 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt @@ -77,4 +77,6 @@ object JvmEnvironmentConfigurationDirectives : SimpleDirectivesContainer() { description = "Enable serialization of JVM IR", additionalParser = JvmSerializeIrMode.Companion::fromString ) + + val ENABLE_DEBUG_MODE by directive("Enable debug mode for compilation") } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/codegen/AbstractJvmBlackBoxCodegenTestBase.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/codegen/AbstractJvmBlackBoxCodegenTestBase.kt index 315dd6a8493..2e694e85e4f 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/codegen/AbstractJvmBlackBoxCodegenTestBase.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/codegen/AbstractJvmBlackBoxCodegenTestBase.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.USE_JAVAC_BASE import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JDK_KIND import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JVM_TARGET import org.jetbrains.kotlin.test.directives.ConfigurationDirectives.WITH_STDLIB +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.ENABLE_DEBUG_MODE import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticsHandler import org.jetbrains.kotlin.test.model.* @@ -81,6 +82,12 @@ abstract class AbstractJvmBlackBoxCodegenTestBase