JVM: Break infinite loop in finding meaningful instruction
during tail-call optimization.
There can be code, where all next instructions are non-meaningful and
there is a back-edge, for example, while(true){}. Previously, analyzer
incorrectly assumed, that this cannot happen. Now, it keeps track of
visited instructions and says, that there is no meaningful instruction
in such case.
#KT-56815 Fixed
This commit is contained in:
committed by
Space Team
parent
550b4f1f11
commit
b3890885c4
+12
-5
@@ -76,11 +76,18 @@ internal fun MethodNode.addCoroutineSuspendedChecks(suspensionPoints: List<Suspe
|
||||
}
|
||||
}
|
||||
|
||||
private tailrec fun AbstractInsnNode?.skipUntilMeaningful(): AbstractInsnNode? = when {
|
||||
this == null -> null
|
||||
opcode == Opcodes.NOP || !isMeaningful -> next.skipUntilMeaningful()
|
||||
opcode == Opcodes.GOTO -> (this as JumpInsnNode).label.skipUntilMeaningful()
|
||||
else -> this
|
||||
private fun AbstractInsnNode?.skipUntilMeaningful(): AbstractInsnNode? {
|
||||
var cursor: AbstractInsnNode? = this ?: return null
|
||||
val visited = mutableSetOf<AbstractInsnNode>()
|
||||
while (cursor != null) {
|
||||
if (!visited.add(cursor)) return null
|
||||
when {
|
||||
cursor.opcode == Opcodes.NOP || !cursor.isMeaningful -> cursor = cursor.next
|
||||
cursor.opcode == Opcodes.GOTO -> cursor = (cursor as JumpInsnNode).label
|
||||
else -> return cursor
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private val AbstractInsnNode.nextMeaningful: AbstractInsnNode?
|
||||
|
||||
+6
@@ -10291,6 +10291,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -10291,6 +10291,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlin.coroutines.*
|
||||
|
||||
suspend fun test() {
|
||||
Nexus.initialize1()
|
||||
while (true) { }
|
||||
}
|
||||
|
||||
object Nexus {
|
||||
suspend fun initialize1() {
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(Continuation(EmptyCoroutineContext) {
|
||||
it.getOrThrow()
|
||||
})
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
suspendCoroutine<Unit> {}
|
||||
test()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -10069,6 +10069,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -10291,6 +10291,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+5
@@ -7927,6 +7927,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineFunInGenericClass.kt");
|
||||
|
||||
+6
@@ -7083,6 +7083,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -7179,6 +7179,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -7179,6 +7179,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -7179,6 +7179,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -8136,6 +8136,12 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
+6
@@ -8047,6 +8047,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
|
||||
Generated
+5
@@ -6317,6 +6317,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/coroutines/indirectInlineUsedAsNonInline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("infiniteLoopInNextMeaningful.kt")
|
||||
public void testInfiniteLoopInNextMeaningful() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/infiniteLoopInNextMeaningful.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineFunInGenericClass.kt")
|
||||
public void testInlineFunInGenericClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/inlineFunInGenericClass.kt");
|
||||
|
||||
Reference in New Issue
Block a user