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()); } }