Merge "Prevent class merging from hiding IncompatibleClassChangeErrors"
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 86ff5a5..9fcca89 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -531,7 +531,8 @@
InternalOptions getInternalOptions() {
InternalOptions internal = new InternalOptions(proguardConfiguration, getReporter());
assert !internal.debug;
- internal.debug = getMode() == CompilationMode.DEBUG;
+ internal.debug = getMode() == CompilationMode.DEBUG
+ || (forceProguardCompatibility && !proguardConfiguration.isObfuscating());
internal.programConsumer = getProgramConsumer();
internal.minApiLevel = getMinApiLevel();
internal.enableDesugaring = getEnableDesugaring();
diff --git a/src/test/java/com/android/tools/r8/debug/DebugStreamComparator.java b/src/test/java/com/android/tools/r8/debug/DebugStreamComparator.java
index 22e8537..59ce62f 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugStreamComparator.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugStreamComparator.java
@@ -13,7 +13,9 @@
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
+import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -44,6 +46,60 @@
}
}
+ private static class StreamState {
+ static final int ENTRY_LINE = -1;
+ static final int PLACEHOLDER_LINE = -2;
+
+ final Iterator<DebuggeeState> iterator;
+ final Deque<Integer> frameEntryLines = new ArrayDeque<>();
+ int currentLine = ENTRY_LINE;
+
+ StreamState(Stream<DebuggeeState> stream) {
+ iterator = stream.iterator();
+ }
+
+ DebuggeeState next() {
+ while (true) {
+ DebuggeeState state = iterator.next();
+ if (state == null) {
+ return null;
+ }
+ int nextDepth = state.getFrameDepth();
+ int nextLine = state.getLineNumber();
+ if (nextDepth == frameEntryLines.size()) {
+ currentLine = nextLine;
+ return state;
+ }
+ if (nextDepth > frameEntryLines.size()) {
+ frameEntryLines.push(currentLine);
+ while (nextDepth > frameEntryLines.size()) {
+ // If the depth grows by more than one we have entered into filtered out frames, eg,
+ // java/android internals. In this case push placeholder lines on the stack.
+ frameEntryLines.push(PLACEHOLDER_LINE);
+ }
+ currentLine = nextLine;
+ assert nextDepth == frameEntryLines.size();
+ return state;
+ }
+ currentLine = nextLine;
+ while (frameEntryLines.size() > nextDepth + 1) {
+ // If the depth decreases by more than one we have popped the filtered frames.
+ // Verify they are placeholder lines.
+ int placeholder = frameEntryLines.pop();
+ assert placeholder == PLACEHOLDER_LINE;
+ }
+ int lineOnEntry = frameEntryLines.pop();
+ assert nextDepth == frameEntryLines.size();
+ if (lineOnEntry != nextLine) {
+ return state;
+ }
+ // A frame was popped and the current line is the same as when the frame was entered.
+ // In this case we advance again to avoid comparing that a function call returns to the
+ // same line (which may not be the case if no stores are needed after the call).
+ }
+ }
+ }
+
private boolean verifyLines = true;
private boolean verifyFiles = true;
private boolean verifyMethods = true;
@@ -140,13 +196,13 @@
}
private void internal() {
- List<Iterator<DebuggeeState>> iterators =
- streams.stream().map(Stream::iterator).collect(Collectors.toList());
+ List<StreamState> streamStates =
+ streams.stream().map(StreamState::new).collect(Collectors.toList());
while (true) {
- List<DebuggeeState> states = new ArrayList<>(iterators.size());
+ List<DebuggeeState> states = new ArrayList<>(streamStates.size());
boolean done = false;
- for (Iterator<DebuggeeState> iterator : iterators) {
- DebuggeeState state = iterator.next();
+ for (StreamState streamState : streamStates) {
+ DebuggeeState state = streamState.next();
states.add(state);
if (state == null) {
done = true;
diff --git a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
index 02e995f..6de20c6 100644
--- a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
@@ -75,7 +75,7 @@
@Test
public void testBridgeMethod() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
+ // TODO(b/79671093): D8 has local variables with empty names.
testDebuggingJvmOnly("bridge", "BridgeMethod");
}
@@ -122,8 +122,7 @@
@Test
public void testInstanceVariable() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("instancevariable", "InstanceVariable");
+ testDebugging("instancevariable", "InstanceVariable");
}
@Test
@@ -133,8 +132,7 @@
@Test
public void testInvoke() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("invoke", "Invoke");
+ testDebugging("invoke", "Invoke");
}
@Test
@@ -155,8 +153,7 @@
@Test
public void testNewArray() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("newarray", "NewArray");
+ testDebugging("newarray", "NewArray");
}
@Test
@@ -166,8 +163,7 @@
@Test
public void testReturns() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("returns", "Returns");
+ testDebugging("returns", "Returns");
}
@Test
@@ -222,8 +218,7 @@
@Test
public void testInvokeEmpty() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("invokeempty", "InvokeEmpty");
+ testDebugging("invokeempty", "InvokeEmpty");
}
@Test
@@ -233,21 +228,17 @@
@Test
public void testRegress2() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("regress2", "Regress2");
+ testDebugging("regress2", "Regress2");
}
- @Ignore("TODO(mathiasr): Different behavior CfSourceCode vs JarSourceCode")
@Test
public void testRegress37726195() throws Exception {
- // TODO(b/79671093): We don't match JVM's behavior on this example.
- testDebuggingJvmOutputOnly("regress_37726195", "Regress");
+ testDebugging("regress_37726195", "Regress");
}
@Test
public void testRegress37658666() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("regress_37658666", "Regress");
+ testDebugging("regress_37658666", "Regress");
}
@Test
@@ -257,8 +248,7 @@
@Test
public void testRegress37955340() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("regress_37955340", "Regress");
+ testDebugging("regress_37955340", "Regress");
}
@Test
@@ -304,8 +294,7 @@
@Test
public void testMemberrebinding2() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("memberrebinding2", "Memberrebinding");
+ testDebugging("memberrebinding2", "Memberrebinding");
}
@Test
@@ -315,14 +304,12 @@
@Test
public void testMinification() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("minification", "Minification");
+ testDebugging("minification", "Minification");
}
@Test
public void testEnclosingmethod() throws Exception {
- // TODO(b/79671093): D8 has different line number info during stepping.
- testDebuggingJvmOnly("enclosingmethod", "Main");
+ testDebugging("enclosingmethod", "Main");
}
@Test