From 1bb864bbb066e68e785aaf103d0922cecc746179 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Tue, 8 Dec 2020 09:30:05 +0100 Subject: [PATCH] [JVM] Add tests that expose problem with locals collapsing. The collapsing happens during suspend function state machine transformation. --- .../CoroutineTransformerMethodVisitor.kt | 1 + .../inlineLocalsStateMachineTransform.kt | 43 ++++++++++++++++ .../suspend/localsStateMachineTransform.kt | 50 +++++++++++++++++++ .../IrLocalVariableTestGenerated.java | 12 +++++ .../LocalVariableTestGenerated.java | 12 +++++ 5 files changed, 118 insertions(+) create mode 100644 compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt create mode 100644 compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index 26e7d78fb87..d43f9884a96 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.codegen.coroutines +import com.sun.org.apache.bcel.internal.generic.StoreInstruction import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.optimization.common.* diff --git a/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt b/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt new file mode 100644 index 00000000000..d29c27117cf --- /dev/null +++ b/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt @@ -0,0 +1,43 @@ +// WITH_COROUTINES +// FILE: test.kt +inline fun hasLocal(): Int { + val x = 41 + return x + 1 +} + +suspend fun h() { } + +suspend fun box() { + // Force state machine transformation. + h() + // Local `x` should be visible in the inlined code. + hasLocal() + // Local `x` is not visible here. + 42 + // Local `x` (different one) is visible in the inlined code. + hasLocal() +} + +// LOCAL VARIABLES +// test.kt:10 box: +// CoroutineUtil.kt:28 getContext: + +// LOCAL VARIABLES JVM_IR +// test.kt:-1 : $completion:kotlin.coroutines.Continuation=helpers.ResultContinuation + +// LOCAL VARIABLES JVM +// test.kt:-1 : + +// LOCAL VARIABLES +// test.kt:10 box: +// test.kt:12 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:8 h: $completion:kotlin.coroutines.Continuation=TestKt$box$1 +// test.kt:12 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:14 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:4 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, $i$f$hasLocal:int=0:int +// test.kt:5 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, $i$f$hasLocal:int=0:int, x$iv:int=41:int +// test.kt:16 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x$iv:int=41:int +// test.kt:18 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x$iv:int=41:int +// test.kt:4 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x$iv:int=41:int, $i$f$hasLocal:int=0:int +// test.kt:5 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x$iv:int=41:int, $i$f$hasLocal:int=0:int +// test.kt:19 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null diff --git a/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt b/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt new file mode 100644 index 00000000000..1048cc68a54 --- /dev/null +++ b/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt @@ -0,0 +1,50 @@ +// WITH_COROUTINES +// FILE: test.kt +suspend fun h() { } + +fun f(x: Int) = x + +suspend fun box() { + // Force state machine transformation. + h() + for (x in 0..1) { + f(x) + } + // Local `x` is NOT visible here. + 42 + for (x in 0..1) { + f(x) + } +} + +// The current backend does not have `x` visible in the locals table for the for loop at all. +// IGNORE_BACKEND: JVM + +// LOCAL VARIABLES +// test.kt:7 box: +// CoroutineUtil.kt:28 getContext: +// test.kt:-1 : $completion:kotlin.coroutines.Continuation=helpers.ResultContinuation +// test.kt:7 box: +// test.kt:9 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:3 h: $completion:kotlin.coroutines.Continuation=TestKt$box$1 +// test.kt:9 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:10 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:11 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=0:int +// test.kt:5 f: x:int=0:int +// test.kt:11 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=0:int +// test.kt:10 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=0:int +// test.kt:11 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:5 f: x:int=1:int +// test.kt:11 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:10 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:14 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:15 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:16 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=0:int +// test.kt:5 f: x:int=0:int +// test.kt:16 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=0:int +// test.kt:15 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:16 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:5 f: x:int=1:int +// test.kt:16 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null, x:int=1:int +// test.kt:15 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null +// test.kt:18 box: $continuation:kotlin.coroutines.Continuation=TestKt$box$1, $result:java.lang.Object=null diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/IrLocalVariableTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/IrLocalVariableTestGenerated.java index 06f802eb132..9cff4f76673 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/IrLocalVariableTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/IrLocalVariableTestGenerated.java @@ -154,6 +154,18 @@ public class IrLocalVariableTestGenerated extends AbstractIrLocalVariableTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/debug/localVariables/suspend"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("inlineLocalsStateMachineTransform.kt") + public void testInlineLocalsStateMachineTransform() throws Exception { + runTest("compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt"); + } + + @Test + @TestMetadata("localsStateMachineTransform.kt") + public void testLocalsStateMachineTransform() throws Exception { + runTest("compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt"); + } + @Test @TestMetadata("simple.kt") public void testSimple() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/LocalVariableTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/LocalVariableTestGenerated.java index abcc2223d1a..588933c69fd 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/LocalVariableTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/debugInformation/LocalVariableTestGenerated.java @@ -154,6 +154,18 @@ public class LocalVariableTestGenerated extends AbstractLocalVariableTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/debug/localVariables/suspend"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("inlineLocalsStateMachineTransform.kt") + public void testInlineLocalsStateMachineTransform() throws Exception { + runTest("compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt"); + } + + @Test + @TestMetadata("localsStateMachineTransform.kt") + public void testLocalsStateMachineTransform() throws Exception { + runTest("compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt"); + } + @Test @TestMetadata("simple.kt") public void testSimple() throws Exception {