Optimize line numbers, enabled only for testing.
Proguard-map output is not yet implemented.
Bug:
Change-Id: Id65ded0e0ac7d9b2c6b7cac6f4273f645e5c930c
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 85741e2..8c76c6c 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -106,25 +106,32 @@
// PositionRemapper is a stateful function which takes a position (represented by a
// DexDebugPositionState) and returns a remapped Position.
- private static class PositionRemapper {
- private int nextLineNumber;
+ private interface PositionRemapper {
+ Position createRemappedPosition(DexDebugPositionState positionState);
+ }
- PositionRemapper(int nextLineNumber) {
- this.nextLineNumber = nextLineNumber;
- }
-
- private Position createRemappedPosition(DexDebugPositionState positionState) {
- // TODO(tamaskenez) Actual remapping is to be implemented here.
- // For now this is only identity-mapping.
+ private static class IdentityPositionRemapper implements PositionRemapper {
+ public Position createRemappedPosition(DexDebugPositionState positionState) {
return new Position(
positionState.getCurrentLine(),
positionState.getCurrentFile(),
positionState.getCurrentMethod(),
positionState.getCurrentCallerPosition());
}
+ }
- int getNextLineNumber() {
- return nextLineNumber;
+ private static class OptimizingPositionRemapper implements PositionRemapper {
+ private int nextLineNumber = 1;
+
+ public Position createRemappedPosition(DexDebugPositionState positionState) {
+ Position newPosition =
+ new Position(
+ nextLineNumber,
+ positionState.getCurrentFile(),
+ positionState.getCurrentMethod(),
+ null);
+ ++nextLineNumber;
+ return newPosition;
}
}
@@ -210,7 +217,10 @@
return DexEncodedMethod.slowCompare(lhs, rhs);
});
}
- int nextLineNumber = 1;
+
+ PositionRemapper positionRemapper =
+ identityMapping ? new IdentityPositionRemapper() : new OptimizingPositionRemapper();
+
for (DexEncodedMethod method : methods) {
// Do the actual processing for each method.
DexCode dexCode = method.getCode().asDexCode();
@@ -222,7 +232,6 @@
// [processedEvents]
PositionEventEmitter positionEventEmitter =
new PositionEventEmitter(application.dexItemFactory, method.method, processedEvents);
- PositionRemapper positionRemapper = new PositionRemapper(nextLineNumber);
EventFilter eventFilter =
new EventFilter(
@@ -236,7 +245,7 @@
for (DexDebugEvent event : debugInfo.events) {
event.accept(eventFilter);
}
- nextLineNumber = positionRemapper.getNextLineNumber();
+
DexDebugInfo optimizedDebugInfo =
new DexDebugInfo(
positionEventEmitter.getStartLine(),
diff --git a/src/test/debugTestResources/Inlining2.java b/src/test/debugTestResources/Inlining2.java
index 38f854c..a570ba3 100644
--- a/src/test/debugTestResources/Inlining2.java
+++ b/src/test/debugTestResources/Inlining2.java
@@ -2,6 +2,31 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
public class Inlining2 {
public static void inlineThisFromAnotherFile() {
System.out.println("inlineThisFromAnotherFile");
diff --git a/src/test/debugTestResources/LineNumberOptimization1.java b/src/test/debugTestResources/LineNumberOptimization1.java
index c25ecc6..a97fc6d 100644
--- a/src/test/debugTestResources/LineNumberOptimization1.java
+++ b/src/test/debugTestResources/LineNumberOptimization1.java
@@ -8,7 +8,17 @@
LineNumberOptimization2.callThisFromAnotherFile();
}
+ private static void callThisFromSameFile(int a) {
+ System.out.println("callThisFromSameFile second overload");
+ }
+
+ private static void callThisFromSameFile(int a, int b) {
+ System.out.println("callThisFromSameFile third overload");
+ }
+
public static void main(String[] args) {
callThisFromSameFile();
+ callThisFromSameFile(1);
+ callThisFromSameFile(1, 2);
}
}
diff --git a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
index d8649c7..2d109e3 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
@@ -4,7 +4,11 @@
package com.android.tools.r8.debug;
import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.Command;
+import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -12,33 +16,64 @@
public class DebugInfoWhenInliningTest extends DebugTestBase {
public static final String SOURCE_FILE = "Inlining1.java";
- private static DebuggeePath debuggeePath;
+ private static DebuggeePath debuggeePathNotOptimized;
+ private static DebuggeePath debuggeePathOptimized;
+
+ private static DebuggeePath makeDex(LineNumberOptimization lineNumberOptimization)
+ throws Exception {
+ return DebuggeePath.makeDex(
+ compileToDexViaR8(
+ oc -> {
+ oc.lineNumberOptimization = lineNumberOptimization;
+ },
+ null,
+ DEBUGGEE_JAR,
+ Collections.<String>emptyList(),
+ true,
+ CompilationMode.RELEASE));
+ }
@BeforeClass
public static void initDebuggeePath() throws Exception {
- debuggeePath =
- DebuggeePath.makeDex(
- compileToDexViaR8(
- null,
- null,
- DEBUGGEE_JAR,
- Collections.<String>emptyList(),
- true,
- CompilationMode.RELEASE));
+ debuggeePathNotOptimized = makeDex(LineNumberOptimization.OFF);
+ debuggeePathOptimized = makeDex(LineNumberOptimization.ON);
}
@Test
- public void testEachLine() throws Throwable {
+ public void testEachLineNotOptimized() throws Throwable {
+ // The reason why the not-optimized test contains half as many line numbers as the optimized
+ // one:
+ //
+ // In the Java source (Inlining1) each call is duplicated. Since they end up on the same line
+ // (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
+ // are emitted duplicated in the dex code, the debugger stops only when there's a change.
+ int[] lineNumbers = {7, 32, 11, 7};
+ testEachLine(debuggeePathNotOptimized, lineNumbers);
+ }
+
+ @Test
+ public void testEachLineOptimized() throws Throwable {
+ int[] lineNumbers = {1, 2, 3, 4, 5, 6, 7, 8};
+ testEachLine(debuggeePathOptimized, lineNumbers);
+ }
+
+ private void testEachLine(DebuggeePath debuggeePath, int[] lineNumbers) throws Throwable {
final String className = "Inlining1";
- final String methodName = "main";
- final String signature = "([Ljava/lang/String;)V";
- runDebugTest(
- debuggeePath,
- className,
- breakpoint(className, methodName, signature),
- run(),
- checkMethod(className, methodName, signature),
- // TODO(tamaskenez) to be continued as the feature is implemented in class Inliner
- run());
+ final String mainSignature = "([Ljava/lang/String;)V";
+ List<Command> commands = new ArrayList<Command>();
+ commands.add(breakpoint(className, "main", mainSignature));
+ commands.add(run());
+ boolean first = true;
+ for (int i : lineNumbers) {
+ if (first) {
+ first = false;
+ } else {
+ commands.add(stepOver());
+ }
+ commands.add(checkMethod(className, "main", mainSignature));
+ commands.add(checkLine(SOURCE_FILE, i));
+ }
+ commands.add(run());
+ runDebugTest(debuggeePath, className, commands);
}
}
diff --git a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
index 33a4b64..74a46ab 100644
--- a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
@@ -17,12 +17,6 @@
private static DebuggeePath debuggeePathNotOptimized;
private static DebuggeePath debuggeePathIdentityTest;
- private final String class1 = "LineNumberOptimization1";
- private final String class2 = "LineNumberOptimization2";
- private final String file1 = class1 + ".java";
- private final String file2 = class2 + ".java";
- private final String mainSignature = "([Ljava/lang/String;)V";
-
private static DebuggeePath makeDex(LineNumberOptimization lineNumberOptimization)
throws Exception {
return DebuggeePath.makeDex(
@@ -47,43 +41,63 @@
@Test
public void testNotOptimized() throws Throwable {
- runDebugTest(
- debuggeePathNotOptimized,
- class1,
- breakpoint(class1, "main", mainSignature),
- run(),
- checkMethod(class1, "main", mainSignature),
- checkLine(file1, 12),
- stepInto(),
- checkMethod(class1, "callThisFromSameFile", "()V"),
- checkLine(file1, 7),
- stepOver(),
- checkMethod(class1, "callThisFromSameFile", "()V"),
- checkLine(file1, 8),
- stepInto(INTELLIJ_FILTER),
- checkMethod(class2, "callThisFromAnotherFile", "()V"),
- checkLine(file2, 28),
- run());
+ int[] lineNumbers = {20, 7, 8, 28, 8, 20, 21, 12, 21, 22, 16, 22};
+ test(debuggeePathNotOptimized, lineNumbers);
}
@Test
public void testOptimized() throws Throwable {
+ int[] lineNumbers = {1, 1, 2, 1, 2, 1, 2, 3, 2, 3, 4, 3};
+ test(debuggeePathOptimized, lineNumbers);
+ }
+
+ private void test(DebuggeePath debuggeePath, int[] lineNumbers) throws Throwable {
+ final String class1 = "LineNumberOptimization1";
+ final String class2 = "LineNumberOptimization2";
+ final String file1 = class1 + ".java";
+ final String file2 = class2 + ".java";
+ final String mainSignature = "([Ljava/lang/String;)V";
+
runDebugTest(
- debuggeePathOptimized,
+ debuggeePath,
class1,
breakpoint(class1, "main", mainSignature),
run(),
checkMethod(class1, "main", mainSignature),
- checkLine(file1, 12),
+ checkLine(file1, lineNumbers[0]),
stepInto(),
checkMethod(class1, "callThisFromSameFile", "()V"),
- checkLine(file1, 7),
+ checkLine(file1, lineNumbers[1]),
stepOver(),
checkMethod(class1, "callThisFromSameFile", "()V"),
- checkLine(file1, 8),
+ checkLine(file1, lineNumbers[2]),
stepInto(INTELLIJ_FILTER),
checkMethod(class2, "callThisFromAnotherFile", "()V"),
- checkLine(file2, 28),
+ checkLine(file2, lineNumbers[3]),
+ stepOver(),
+ checkMethod(class1, "callThisFromSameFile", "()V"),
+ checkLine(file1, lineNumbers[4]),
+ stepOver(),
+ checkMethod(class1, "main", mainSignature),
+ checkLine(file1, lineNumbers[5]),
+ stepOver(),
+ checkMethod(class1, "main", mainSignature),
+ checkLine(file1, lineNumbers[6]),
+ stepInto(),
+ checkMethod(class1, "callThisFromSameFile", "(I)V"),
+ checkLine(file1, lineNumbers[7]),
+ stepOver(),
+ checkMethod(class1, "main", mainSignature),
+ checkLine(file1, lineNumbers[8]),
+ stepOver(),
+ checkMethod(class1, "main", mainSignature),
+ checkLine(file1, lineNumbers[9]),
+ stepInto(),
+ checkMethod(class1, "callThisFromSameFile", "(II)V"),
+ checkLine(file1, lineNumbers[10]),
+ stepOver(),
+ checkMethod(class1, "main", mainSignature),
+ checkLine(file1, lineNumbers[11]),
run());
}
}