From f34ae686a049f769f66a4f64eb683dda7bb432e6 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 23 Jun 2022 02:55:50 +0200 Subject: [PATCH] JVM: Make coroutines spilling tests runtime instead of bytecode text ones. Check the content of continuation object instead of bytecode, since this is less prone to changes during changes in coroutines codegen. #KT-48678 --- .../FirBlackBoxCodegenTestGenerated.java | 58 +++++++++++++ .../codegen/FirBytecodeTextTestGenerated.java | 58 ------------- .../varSpilling/cleanup/backEdge.kt | 56 +++++++++++++ .../box/coroutines/varSpilling/cleanup/if.kt | 65 ++++++++++++++ .../varSpilling/cleanup/nullCleanup.kt | 51 +++++++++++ .../varSpilling/cleanup/nullNotSpill.kt | 49 +++++++++++ .../coroutines/varSpilling/cleanup/simple.kt | 53 ++++++++++++ .../coroutines/varSpilling/cleanup/twoRefs.kt | 55 ++++++++++++ .../cleanup/unusedParamNotSpill.kt | 43 ++++++++++ .../coroutines/varSpilling/cleanup/when.kt | 84 +++++++++++++++++++ .../coroutines/cleanup/backEdge.kt | 16 ---- .../bytecodeText/coroutines/cleanup/if.kt | 24 ------ .../coroutines/cleanup/nullCleanup.kt | 18 ---- .../coroutines/cleanup/nullNotSpill.kt | 15 ---- .../bytecodeText/coroutines/cleanup/simple.kt | 14 ---- .../coroutines/cleanup/twoRefs.kt | 9 -- .../coroutines/cleanup/unusedParamNotSpill.kt | 5 -- .../bytecodeText/coroutines/cleanup/when.kt | 34 -------- .../codegen/BlackBoxCodegenTestGenerated.java | 58 +++++++++++++ .../codegen/BytecodeTextTestGenerated.java | 58 ------------- .../IrBlackBoxCodegenTestGenerated.java | 58 +++++++++++++ .../codegen/IrBytecodeTextTestGenerated.java | 58 ------------- .../LightAnalysisModeTestGenerated.java | 53 ++++++++++++ .../js/test/JsCodegenBoxTestGenerated.java | 10 +++ .../test/ir/IrJsCodegenBoxTestGenerated.java | 10 +++ .../IrCodegenBoxWasmTestGenerated.java | 13 +++ .../NativeCodegenBoxTestGenerated.java | 12 +++ 27 files changed, 728 insertions(+), 309 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt create mode 100644 compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt delete mode 100644 compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt 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 63c972bcc46..e4f5d577be0 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 @@ -13163,6 +13163,64 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + public class Cleanup { + @Test + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("backEdge.kt") + public void testBackEdge() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt"); + } + + @Test + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt"); + } + + @Test + @TestMetadata("nullCleanup.kt") + public void testNullCleanup() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt"); + } + + @Test + @TestMetadata("nullNotSpill.kt") + public void testNullNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt"); + } + + @Test + @TestMetadata("twoRefs.kt") + public void testTwoRefs() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt"); + } + + @Test + @TestMetadata("unusedParamNotSpill.kt") + public void testUnusedParamNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt"); + } + + @Test + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); + } + } } } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java index 75172b07786..79da42d8d61 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java @@ -1752,64 +1752,6 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt"); } - @Nested - @TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/cleanup") - @TestDataPath("$PROJECT_ROOT") - public class Cleanup { - @Test - public void testAllFilesPresentInCleanup() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/coroutines/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); - } - - @Test - @TestMetadata("backEdge.kt") - public void testBackEdge() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt"); - } - - @Test - @TestMetadata("if.kt") - public void testIf() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt"); - } - - @Test - @TestMetadata("nullCleanup.kt") - public void testNullCleanup() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt"); - } - - @Test - @TestMetadata("nullNotSpill.kt") - public void testNullNotSpill() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt"); - } - - @Test - @TestMetadata("simple.kt") - public void testSimple() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt"); - } - - @Test - @TestMetadata("twoRefs.kt") - public void testTwoRefs() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt"); - } - - @Test - @TestMetadata("unusedParamNotSpill.kt") - public void testUnusedParamNotSpill() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt"); - } - - @Test - @TestMetadata("when.kt") - public void testWhen() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt"); - } - } - @Nested @TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/debug") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt new file mode 100644 index 00000000000..2e2a889a4e5 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt @@ -0,0 +1,56 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_BACKEND: JVM +// 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) { + // Should be cleanup, since there is a back edge from the rest of the loop + saveSpilledVariables() + val a = "a" + saveSpilledVariables() + blackhole(a) + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + if (spilledVariables != setOf("label" to "1", "I$0" to "0", "L$0" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "I$0" to "0", "L$0" to "a")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "1", "I$0" to "1", "L$0" to "null")) return "FAIL 3: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "I$0" to "1", "L$0" to "a")) return "FAIL 4: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "I$0" to "1", "L$0" to "a")) return "FAIL 5: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt new file mode 100644 index 00000000000..e7a4b126b42 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt @@ -0,0 +1,65 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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(check: Boolean) { + if (check) { + val a = "a1" + saveSpilledVariables() + blackhole(a) + } else { + val a = "a2" + val b = "b2" + saveSpilledVariables() + blackhole(a, b) + } + // Cleanup both a and b, since the compiler does not know, which branch is going to executed + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test(true) + } + if (spilledVariables != setOf("label" to "1", "L$0" to "a1", "L$1" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "null", "L$1" to "null")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "null", "L$1" to "null")) return "FAIL 3: $spilledVariables" + + builder { + test(false) + } + if (spilledVariables != setOf("label" to "2", "L$0" to "a2", "L$1" to "b2")) return "FAIL 4: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "null", "L$1" to "null")) return "FAIL 5: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "null", "L$1" to "null")) return "FAIL 6: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt new file mode 100644 index 00000000000..f633b0cfbba --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt @@ -0,0 +1,51 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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() { + var a: String? = "a" + saveSpilledVariables() + blackhole(a) + a = null + // a is null, known at compile time, do not spill, but cleanup + saveSpilledVariables() + blackhole(a) +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + if (spilledVariables != setOf("label" to "1", "L$0" to "a")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to "null")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to "null")) return "FAIL 3: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt new file mode 100644 index 00000000000..b50e4a04d4b --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt @@ -0,0 +1,49 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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() { + val a = null + // a is null, known at compile time, do not spill + saveSpilledVariables() + blackhole(a) + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + if (spilledVariables != setOf("label" to "1")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2")) return "FAIL 3: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt new file mode 100644 index 00000000000..0daa44830b4 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt @@ -0,0 +1,53 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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() { + val a = "a" + saveSpilledVariables() + blackhole(a) + // a is dead, cleanup + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + if (spilledVariables != setOf("label" to "1", "L$0" to "a")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to "null")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to "null")) 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/cleanup/twoRefs.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt new file mode 100644 index 00000000000..0052ab168df --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt @@ -0,0 +1,55 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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(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") + } + if (spilledVariables != setOf("label" to "1", "L$0" to "a", "L$1" to "b")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "2", "L$0" to "b", "L$1" to "null")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "null", "L$1" to "null")) return "FAIL 3: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "3", "L$0" to "null", "L$1" to "null")) 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/cleanup/unusedParamNotSpill.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt new file mode 100644 index 00000000000..3d2e33ec771 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt @@ -0,0 +1,43 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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 +} + +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/cleanup/when.kt b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt new file mode 100644 index 00000000000..5bd6729d54c --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt @@ -0,0 +1,84 @@ +// WITH_STDLIB +// FULL_JDK +// TARGET_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(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) + } + } + // Cleanup both a and b, but c is primitive, so no need to clean it up + saveSpilledVariables() +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test(0) + } + if (spilledVariables != setOf("label" to "1", "I$0" to "0", "L$0" to "a0", "L$1" to "null")) return "FAIL 1: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "0", "L$0" to "null", "L$1" to "null")) return "FAIL 2: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "0", "L$0" to "null", "L$1" to "null")) return "FAIL 3: $spilledVariables" + + builder { + test(1) + } + if (spilledVariables != setOf("label" to "2", "I$0" to "0", "L$0" to "a1", "L$1" to "b1")) return "FAIL 4: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "0", "L$0" to "null", "L$1" to "null")) return "FAIL 5: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "0", "L$0" to "null", "L$1" to "null")) return "FAIL 6: $spilledVariables" + + builder { + test(2) + } + if (spilledVariables != setOf("label" to "3", "I$0" to "1", "L$0" to "a2", "L$1" to "b2")) return "FAIL 7: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "1", "L$0" to "null", "L$1" to "null")) return "FAIL 8: $spilledVariables" + c?.resume(Unit) + if (spilledVariables != setOf("label" to "4", "I$0" to "1", "L$0" to "null", "L$1" to "null")) return "FAIL 9: $spilledVariables" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt deleted file mode 100644 index 9c045b5e977..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt +++ /dev/null @@ -1,16 +0,0 @@ -fun blackhole(vararg a: Any?) {} - -suspend fun dummy() {} - -suspend fun test() { - for (i in 0..10) { - // Should be cleanup, since there is a back edge from the rest of the loop - dummy() - val a = "" - dummy() - blackhole(a) - } -} - -// 1 ACONST_NULL -// 2 PUTFIELD .*L\$0 : Ljava/lang/Object; \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt deleted file mode 100644 index 131b8ffe505..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt +++ /dev/null @@ -1,24 +0,0 @@ -fun blackhole(vararg a: Any?) {} - -suspend fun dummy() {} - -fun check(): Boolean = true - -suspend fun test() { - if (check()) { - val a = "" - dummy() - blackhole(a) - } else { - val a = "" - val b = "" - dummy() - blackhole(a, b) - } - // Cleanup both a and b, since the compiler does not know, which branch is going to executed - dummy() -} - -// 2 ACONST_NULL -// 3 PUTFIELD .*L\$0 : Ljava/lang/Object; -// 2 PUTFIELD .*L\$1 : Ljava/lang/Object; \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt deleted file mode 100644 index 66b1e5d4abe..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt +++ /dev/null @@ -1,18 +0,0 @@ -fun blackhole(vararg a: Any?) {} - -suspend fun dummy() {} - -suspend fun test() { - var a: String? = "" - dummy() - blackhole(a) - a = null - // a is null, known at compile time, do not spill, but cleanup - dummy() - blackhole(a) -} - -// 2 PUTFIELD .*L\$0 : Ljava/lang/Object; - -// two stores to initialize the `a` variable and one null constant to store in the spill slot. -// 3 ACONST_NULL diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt deleted file mode 100644 index ccf01963f63..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt +++ /dev/null @@ -1,15 +0,0 @@ -fun blackhole(vararg a: Any?) {} - -suspend fun dummy() {} - -suspend fun test() { - val a = null - // a is null, known at compile time, do not spill - dummy() - blackhole(a) - dummy() -} - -// before and after suspension point -// 2 ACONST_NULL -// 0 PUTFIELD .*L\$0 : Ljava/lang/Object; \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt deleted file mode 100644 index d497ddadffa..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt +++ /dev/null @@ -1,14 +0,0 @@ -fun blackhole(vararg a: Any?) {} - -suspend fun dummy() {} - -suspend fun test() { - val a = "" - dummy() - blackhole(a) - // a is dead, cleanup - dummy() -} - -// 1 ACONST_NULL -// 2 PUTFIELD .*L\$0 : Ljava/lang/Object; \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt deleted file mode 100644 index fd3423fe0c4..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt +++ /dev/null @@ -1,9 +0,0 @@ -suspend fun blackhole(a: Any?) {} - -suspend fun cleanUpExample(a: String, b: String) { - blackhole(a) // 1 - blackhole(b) // 2 -} - -// 3 ACONST_NULL -// 2 PUTFIELD .*L\$0 : .*; diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt deleted file mode 100644 index 16eef815b9f..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt +++ /dev/null @@ -1,5 +0,0 @@ -val f: suspend (Int) -> Unit = { unused -> -} - -// 0 GETFIELD .*I\$0 -// 0 PUTFIELD .*I\$0 diff --git a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt b/compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt deleted file mode 100644 index be51a324aaf..00000000000 --- a/compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt +++ /dev/null @@ -1,34 +0,0 @@ -fun blackhole(vararg a: Any?) {} - -suspend fun dummy() {} - -fun check(): Int = 1 - -suspend fun test() { - when (check()) { - 0 -> { - val a = "" - dummy() - blackhole(a) - } - 1 -> { - val a = "" - val b = "" - dummy() - blackhole(a, b) - } - else -> { - val a = "" - val b = "" - val c = 1 - dummy() - blackhole(a, b, c) - } - } - // Cleanup both a and b, but c is primitive, so no need to clean it up - dummy() -} - -// 2 ACONST_NULL -// 4 PUTFIELD .*L\$0 : Ljava/lang/Object; -// 3 PUTFIELD .*L\$1 : Ljava/lang/Object; \ 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 465cdcd7053..310bcc0cf2a 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 @@ -13043,6 +13043,64 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + public class Cleanup { + @Test + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @Test + @TestMetadata("backEdge.kt") + public void testBackEdge() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt"); + } + + @Test + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt"); + } + + @Test + @TestMetadata("nullCleanup.kt") + public void testNullCleanup() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt"); + } + + @Test + @TestMetadata("nullNotSpill.kt") + public void testNullNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt"); + } + + @Test + @TestMetadata("twoRefs.kt") + public void testTwoRefs() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt"); + } + + @Test + @TestMetadata("unusedParamNotSpill.kt") + public void testUnusedParamNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt"); + } + + @Test + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); + } + } } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java index c3390769e75..ef7cb5bf24b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java @@ -1716,64 +1716,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt"); } - @Nested - @TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/cleanup") - @TestDataPath("$PROJECT_ROOT") - public class Cleanup { - @Test - public void testAllFilesPresentInCleanup() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/coroutines/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); - } - - @Test - @TestMetadata("backEdge.kt") - public void testBackEdge() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt"); - } - - @Test - @TestMetadata("if.kt") - public void testIf() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt"); - } - - @Test - @TestMetadata("nullCleanup.kt") - public void testNullCleanup() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt"); - } - - @Test - @TestMetadata("nullNotSpill.kt") - public void testNullNotSpill() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt"); - } - - @Test - @TestMetadata("simple.kt") - public void testSimple() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt"); - } - - @Test - @TestMetadata("twoRefs.kt") - public void testTwoRefs() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt"); - } - - @Test - @TestMetadata("unusedParamNotSpill.kt") - public void testUnusedParamNotSpill() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt"); - } - - @Test - @TestMetadata("when.kt") - public void testWhen() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt"); - } - } - @Nested @TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/debug") @TestDataPath("$PROJECT_ROOT") 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 48b0aeff6ae..b3c8351d781 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 @@ -13163,6 +13163,64 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + public class Cleanup { + @Test + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("backEdge.kt") + public void testBackEdge() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt"); + } + + @Test + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt"); + } + + @Test + @TestMetadata("nullCleanup.kt") + public void testNullCleanup() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt"); + } + + @Test + @TestMetadata("nullNotSpill.kt") + public void testNullNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt"); + } + + @Test + @TestMetadata("twoRefs.kt") + public void testTwoRefs() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt"); + } + + @Test + @TestMetadata("unusedParamNotSpill.kt") + public void testUnusedParamNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt"); + } + + @Test + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); + } + } } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java index 09a9a26615d..71637d814ec 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java @@ -1752,64 +1752,6 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt"); } - @Nested - @TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/cleanup") - @TestDataPath("$PROJECT_ROOT") - public class Cleanup { - @Test - public void testAllFilesPresentInCleanup() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/coroutines/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); - } - - @Test - @TestMetadata("backEdge.kt") - public void testBackEdge() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/backEdge.kt"); - } - - @Test - @TestMetadata("if.kt") - public void testIf() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/if.kt"); - } - - @Test - @TestMetadata("nullCleanup.kt") - public void testNullCleanup() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullCleanup.kt"); - } - - @Test - @TestMetadata("nullNotSpill.kt") - public void testNullNotSpill() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/nullNotSpill.kt"); - } - - @Test - @TestMetadata("simple.kt") - public void testSimple() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/simple.kt"); - } - - @Test - @TestMetadata("twoRefs.kt") - public void testTwoRefs() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/twoRefs.kt"); - } - - @Test - @TestMetadata("unusedParamNotSpill.kt") - public void testUnusedParamNotSpill() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/unusedParamNotSpill.kt"); - } - - @Test - @TestMetadata("when.kt") - public void testWhen() throws Exception { - runTest("compiler/testData/codegen/bytecodeText/coroutines/cleanup/when.kt"); - } - } - @Nested @TestMetadata("compiler/testData/codegen/bytecodeText/coroutines/debug") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 1f1fc38f542..fed2f7327c8 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10539,6 +10539,59 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Cleanup extends AbstractLightAnalysisModeTest { + @TestMetadata("backEdge.kt") + public void ignoreBackEdge() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/backEdge.kt"); + } + + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/if.kt"); + } + + @TestMetadata("nullCleanup.kt") + public void testNullCleanup() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullCleanup.kt"); + } + + @TestMetadata("nullNotSpill.kt") + public void testNullNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/nullNotSpill.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/simple.kt"); + } + + @TestMetadata("twoRefs.kt") + public void testTwoRefs() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/twoRefs.kt"); + } + + @TestMetadata("unusedParamNotSpill.kt") + public void testUnusedParamNotSpill() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/unusedParamNotSpill.kt"); + } + + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/cleanup/when.kt"); + } + } } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java index fae7cc16e2b..c61fa00228e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java @@ -9715,6 +9715,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + public class Cleanup { + @Test + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + } } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index 45fd592f668..7018d4dd62e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -9757,6 +9757,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + public class Cleanup { + @Test + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + } } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 6f7178af7eb..623c73fe145 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -8624,6 +8624,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Cleanup extends AbstractIrCodegenBoxWasmTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); + } + + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); + } + } } } diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index 83c04e45c23..9dd93e72829 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -10685,6 +10685,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest public void testSafeCallElvis() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/safeCallElvis.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/coroutines/varSpilling/cleanup") + @TestDataPath("$PROJECT_ROOT") + @Tag("codegen") + @UseExtTestCaseGroupProvider() + public class Cleanup { + @Test + public void testAllFilesPresentInCleanup() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/coroutines/varSpilling/cleanup"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true); + } + } } }