Skip to content

Commit 102736f

Browse files
ilmirusSpace
authored andcommitted
Fixup end label of local variable if it is before start label
In that case, put end label to next label after start label.
1 parent b07cf8a commit 102736f

File tree

9 files changed

+113
-0
lines changed

9 files changed

+113
-0
lines changed

compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InplaceArgumentsMethodTransformer.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.codegen.inline
77

88
import org.jetbrains.kotlin.codegen.optimization.boxing.isMethodInsnWith
99
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
10+
import org.jetbrains.kotlin.codegen.optimization.common.findNextOrNull
1011
import org.jetbrains.kotlin.codegen.optimization.common.removeUnusedLocalVariables
1112
import org.jetbrains.kotlin.codegen.optimization.common.updateMaxStack
1213
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -25,6 +26,8 @@ class InplaceArgumentsMethodTransformer : MethodTransformer() {
2526

2627
transformMethod(methodContext)
2728

29+
methodNode.fixupLVT()
30+
2831
methodNode.removeUnusedLocalVariables()
2932
methodNode.updateMaxStack()
3033
}
@@ -356,4 +359,16 @@ class InplaceArgumentsMethodTransformer : MethodTransformer() {
356359
insn = insn.next
357360
}
358361
}
362+
}
363+
364+
// HACK: if new end label is before start label, change to the next one
365+
private fun MethodNode.fixupLVT() {
366+
for (localVariable in localVariables) {
367+
val startIndex = instructions.indexOf(localVariable.start)
368+
val endIndex = instructions.indexOf(localVariable.end)
369+
if (endIndex < startIndex) {
370+
val newEnd = localVariable.start.findNextOrNull { it is LabelNode } as? LabelNode
371+
localVariable.end = newEnd ?: localVariable.start
372+
}
373+
}
359374
}

compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// WITH_RUNTIME
2+
// FULL_JDK
3+
4+
import kotlin.coroutines.*
5+
6+
fun ticker(
7+
delayMillis: Long,
8+
initialDelayMillis: Long = delayMillis
9+
): ReceiveChannel<Unit> = object : ReceiveChannel<Unit> {
10+
override fun cancel() {}
11+
override fun receive() {}
12+
}
13+
14+
suspend fun <T> withTimeoutOrNull(timeMillis: Long, block: suspend CoroutineScope.() -> T): T? = null
15+
16+
interface ReceiveChannel<out E> {
17+
fun receive(): E
18+
fun cancel()
19+
}
20+
21+
interface CoroutineScope
22+
23+
suspend fun delay(i: Int) {}
24+
25+
suspend fun test() {
26+
val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
27+
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
28+
println("Initial element is available immediately: $nextElement") // no initial delay
29+
30+
nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
31+
println("Next element is not ready in 50 ms: $nextElement")
32+
33+
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
34+
println("Next element is ready in 100 ms: $nextElement")
35+
36+
// Emulate large consumption delays
37+
println("Consumer pauses for 150ms")
38+
delay(150)
39+
// Next element is available immediately
40+
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
41+
println("Next element is available immediately after large consumer delay: $nextElement")
42+
// Note that the pause between `receive` calls is taken into account and next element arrives faster
43+
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
44+
println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
45+
46+
tickerChannel.cancel() // indicate that no more elements are needed
47+
}
48+
49+
fun builder(c: suspend () -> Unit) {
50+
c.startCoroutine(Continuation(EmptyCoroutineContext) {
51+
it.getOrThrow()
52+
})
53+
}
54+
55+
fun box(): String {
56+
builder {
57+
test()
58+
}
59+
return "OK"
60+
}

compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)