Add inlining in kotlin debug testcase
By using inlined functions, we make kotlin generate
unused-and-uninitialized local variables that appear in the local
variable table, thus accessible to a debugger. These local variables
are essential for correct Kotlin debugging experience.
This testcase serves as regression test in order to make sure that d8
correctly emits these local variables.
Bug: 63608278
Change-Id: Iedece254d4ea9a1275bde86db54f91fe6196bb4b
diff --git a/src/test/debugTestResourcesKotlin/KotlinApp.kt b/src/test/debugTestResourcesKotlin/KotlinApp.kt
index 7c15337..7fa2be1 100644
--- a/src/test/debugTestResourcesKotlin/KotlinApp.kt
+++ b/src/test/debugTestResourcesKotlin/KotlinApp.kt
@@ -8,6 +8,7 @@
println("Hello world!")
val instance = KotlinApp()
instance.processObject(instance, instance::printObject)
+ instance.invokeInlinedFunctions()
}
}
@@ -18,4 +19,26 @@
fun printObject(obj: Any) {
println(obj)
}
+
+ fun invokeInlinedFunctions() {
+ inlinedA {
+ val inA = 1
+ inlinedB {
+ val inB = 2
+ foo(inA, inB)
+ }
+ }
+ }
+
+ inline fun inlinedA(f: () -> Unit) {
+ f()
+ }
+
+ inline fun inlinedB(f: () -> Unit) {
+ f()
+ }
+
+ fun foo(a: Int, b: Int) {
+ println("a=$a, b=$b")
+ }
}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/debug/KotlinTest.java b/src/test/java/com/android/tools/r8/debug/KotlinTest.java
index 1700964..8caa3c1 100644
--- a/src/test/java/com/android/tools/r8/debug/KotlinTest.java
+++ b/src/test/java/com/android/tools/r8/debug/KotlinTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;
+import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.junit.Assert;
import org.junit.Test;
@@ -10,6 +11,7 @@
@Test
public void testKotlinApp() throws Throwable {
+ final String inliningMethodName = "invokeInlinedFunctions";
runDebugTestKotlin("KotlinApp",
breakpoint("KotlinApp$Companion", "main"),
run(),
@@ -32,6 +34,67 @@
s.checkLocal("args");
s.checkLocal("instance");
}),
+ stepOver(),
+ inspect(s -> {
+ Assert.assertEquals(11, s.getLineNumber());
+ s.checkLocal("this");
+ s.checkLocal("args");
+ s.checkLocal("instance");
+ }),
+ stepInto(),
+ inspect(s -> {
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ Assert.assertEquals(24, s.getLineNumber());
+ s.checkLocal("this");
+ }),
+ stepInto(),
+ inspect(s -> {
+ // We must have stepped into the code of the inlined method but the actual current method
+ // did not change.
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ // TODO(shertz) get the original line if JSR45 is supported by the targeted ART runtime.
+ s.checkLocal("this");
+ }),
+ stepInto(),
+ inspect(s -> {
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ Assert.assertEquals(25, s.getLineNumber());
+ s.checkLocal("this");
+ }),
+ stepInto(),
+ inspect(s -> {
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ Assert.assertEquals(26, s.getLineNumber());
+ s.checkLocal("this");
+ s.checkLocal("inA", Value.createInt(1));
+ // This is a "hidden" lv added by Kotlin (which is neither initialized nor used).
+ s.checkLocal("$i$f$inlinedA");
+ s.checkLocal("$i$a$1$inlinedA");
+ }),
+ stepInto(),
+ inspect(s -> {
+ // We must have stepped into the code of the second inlined method but the actual current
+ // method did not change.
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ // TODO(shertz) get the original line if JSR45 is supported by the targeted ART runtime.
+ s.checkLocal("this");
+ }),
+ stepInto(),
+ inspect(s -> {
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ Assert.assertEquals(27, s.getLineNumber());
+ s.checkLocal("this");
+ }),
+ stepInto(),
+ inspect(s -> {
+ Assert.assertEquals(inliningMethodName, s.getMethodName());
+ Assert.assertEquals(28, s.getLineNumber());
+ s.checkLocal("this");
+ s.checkLocal("inB", Value.createInt(2));
+ // This is a "hidden" lv added by Kotlin (which is neither initialized nor used).
+ s.checkLocal("$i$f$inlinedB");
+ s.checkLocal("$i$a$1$inlinedB");
+ }),
run());
}