diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InplaceArgumentsMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InplaceArgumentsMethodTransformer.kt index 3fd9b7912bd..db22f398999 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InplaceArgumentsMethodTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InplaceArgumentsMethodTransformer.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.inline import org.jetbrains.kotlin.codegen.optimization.boxing.isMethodInsnWith import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence +import org.jetbrains.kotlin.codegen.optimization.common.findNextOrNull import org.jetbrains.kotlin.codegen.optimization.common.removeUnusedLocalVariables import org.jetbrains.kotlin.codegen.optimization.common.updateMaxStack import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer @@ -25,6 +26,8 @@ class InplaceArgumentsMethodTransformer : MethodTransformer() { transformMethod(methodContext) + methodNode.fixupLVT() + methodNode.removeUnusedLocalVariables() methodNode.updateMaxStack() } @@ -368,4 +371,16 @@ class InplaceArgumentsMethodTransformer : MethodTransformer() { insn = insn.next } } +} + +// HACK: if new end label is before start label, change to the next one +private fun MethodNode.fixupLVT() { + for (localVariable in localVariables) { + val startIndex = instructions.indexOf(localVariable.start) + val endIndex = instructions.indexOf(localVariable.end) + if (endIndex < startIndex) { + val newEnd = localVariable.start.findNextOrNull { it is LabelNode } as? LabelNode + localVariable.end = newEnd ?: localVariable.start + } + } } \ No newline at end of file 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 dc245a1516f..ab1a192dfcb 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 @@ -12355,6 +12355,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @Test + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @Test @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt b/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt new file mode 100644 index 00000000000..f8da86f0abf --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt @@ -0,0 +1,60 @@ +// WITH_RUNTIME +// FULL_JDK + +import kotlin.coroutines.* + +fun ticker( + delayMillis: Long, + initialDelayMillis: Long = delayMillis +): ReceiveChannel = object : ReceiveChannel { + override fun cancel() {} + override fun receive() {} +} + +suspend fun withTimeoutOrNull(timeMillis: Long, block: suspend CoroutineScope.() -> T): T? = null + +interface ReceiveChannel { + fun receive(): E + fun cancel() +} + +interface CoroutineScope + +suspend fun delay(i: Int) {} + +suspend fun test() { + val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel + var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() } + println("Initial element is available immediately: $nextElement") // no initial delay + + nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay + println("Next element is not ready in 50 ms: $nextElement") + + nextElement = withTimeoutOrNull(60) { tickerChannel.receive() } + println("Next element is ready in 100 ms: $nextElement") + + // Emulate large consumption delays + println("Consumer pauses for 150ms") + delay(150) + // Next element is available immediately + nextElement = withTimeoutOrNull(1) { tickerChannel.receive() } + println("Next element is available immediately after large consumer delay: $nextElement") + // Note that the pause between `receive` calls is taken into account and next element arrives faster + nextElement = withTimeoutOrNull(60) { tickerChannel.receive() } + println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement") + + tickerChannel.cancel() // indicate that no more elements are needed +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext) { + it.getOrThrow() + }) +} + +fun box(): String { + builder { + test() + } + 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 d5acf51e039..7668c85b9a5 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 @@ -12277,6 +12277,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @Test + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @Test @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { 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 1796eec1fad..cc76f549d8f 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 @@ -12355,6 +12355,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @Test + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @Test @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index d893542b426..d36cd008613 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -9893,6 +9893,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/nullSpilling.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index db31da25348..8bfdaea319f 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -8787,6 +8787,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/nullSpilling.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 14226cd9581..9c9202e6638 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -8193,6 +8193,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/nullSpilling.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 4cf00937436..118d6477167 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -8173,6 +8173,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt"); } + @TestMetadata("lvtWithInlineOnly.kt") + public void testLvtWithInlineOnly() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt"); + } + @TestMetadata("nullSpilling.kt") public void testNullSpilling() throws Exception { runTest("compiler/testData/codegen/box/coroutines/varSpilling/nullSpilling.kt");