Add caller-preserving positions to CfSourceCode and enable CF in test.
... in the test DebugInfoWhenInlining.
Change-Id: I54f926420bc7ac61d1d84168c81df3b9975c78c8
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index b8e0bd8..776cc42 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -19,6 +19,7 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import java.util.Collections;
import java.util.List;
import org.objectweb.asm.Label;
@@ -230,7 +231,13 @@
throw new Unimplemented(
"Converting CfCode to IR not supported for DEX output of synchronized methods.");
}
- CfSourceCode source = new CfSourceCode(this, encodedMethod, callerPosition, origin);
+ CfSourceCode source =
+ new CfSourceCode(
+ this,
+ encodedMethod,
+ callerPosition,
+ origin,
+ options.lineNumberOptimization == LineNumberOptimization.ON);
IRBuilder builder =
(generator == null)
? new IRBuilder(encodedMethod, appInfo, source, options)
diff --git a/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java b/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java
index 8db07f6..66456cd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CanonicalPositions.java
@@ -18,13 +18,14 @@
private final Map<Position, Position> canonicalPositions;
private final Position preamblePosition;
- /**
- * For callerPosition and preserveCaller see canonicalizeCallerPosition. initialCapacity will be
- * passed to the HashMap constructor.
- */
+ /** For callerPosition and preserveCaller see canonicalizeCallerPosition. */
public CanonicalPositions(
- Position callerPosition, boolean preserveCaller, int initialCapacity, DexMethod method) {
- canonicalPositions = new HashMap<>(initialCapacity);
+ Position callerPosition,
+ boolean preserveCaller,
+ int expectedPositionsCount,
+ DexMethod method) {
+ canonicalPositions =
+ new HashMap<>(1 + (callerPosition == null ? 0 : 1) + expectedPositionsCount);
this.preserveCaller = preserveCaller;
this.callerPosition = callerPosition;
if (callerPosition != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index 4cbebcf..92645c4 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -21,6 +21,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.code.CanonicalPositions;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueType;
@@ -184,8 +185,6 @@
private final Position callerPosition;
private final Origin origin;
- // Synthetic position with line = 0.
- private final Position preamblePosition;
private final Reference2IntMap<CfLabel> labelOffsets = new Reference2IntOpenHashMap<>();
private TryHandlerList cachedTryHandlerList;
private LocalVariableList cachedLocalVariableList;
@@ -196,21 +195,31 @@
private Int2ReferenceMap<Int2ObjectMap<DebugLocalInfo>> definitelyLiveIncomingLocals =
new Int2ReferenceOpenHashMap<>();
private Int2ReferenceMap<CfState.Snapshot> incomingState = new Int2ReferenceOpenHashMap<>();
+ private final CanonicalPositions canonicalPositions;
public CfSourceCode(
- CfCode code, DexEncodedMethod method, Position callerPosition, Origin origin) {
+ CfCode code,
+ DexEncodedMethod method,
+ Position callerPosition,
+ Origin origin,
+ boolean preserveCaller) {
this.code = code;
this.method = method;
this.callerPosition = callerPosition;
this.origin = origin;
- preamblePosition = Position.synthetic(0, method.method, null);
+ int cfPositionCount = 0;
for (int i = 0; i < code.getInstructions().size(); i++) {
CfInstruction instruction = code.getInstructions().get(i);
if (instruction instanceof CfLabel) {
labelOffsets.put((CfLabel) instruction, instructionOffset(i));
}
+ if (instruction instanceof CfPosition) {
+ ++cfPositionCount;
+ }
}
this.state = new CfState(origin);
+ canonicalPositions =
+ new CanonicalPositions(callerPosition, preserveCaller, cfPositionCount, this.method.method);
}
@Override
@@ -383,7 +392,21 @@
}
state.clear();
} else {
- instruction.buildIR(builder, state, this);
+ if (instruction instanceof CfPosition) {
+ CfPosition cfPosition = (CfPosition) instruction;
+ Position position = cfPosition.getPosition();
+ Position newPosition =
+ canonicalPositions.getCanonical(
+ new Position(
+ position.line,
+ position.file,
+ position.method,
+ canonicalPositions.canonicalizeCallerPosition(position.callerPosition)));
+ CfPosition newCfPosition = new CfPosition(cfPosition.getLabel(), newPosition);
+ newCfPosition.buildIR(builder, state, this);
+ } else {
+ instruction.buildIR(builder, state, this);
+ }
ensureDebugValueLiveness(builder);
if (builder.getCFG().containsKey(currentInstructionIndex + 1)) {
recordStateForTarget(currentInstructionIndex + 1, state.getSnapshot());
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
index e0c47da..9a9b836 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
@@ -93,7 +93,7 @@
new CanonicalPositions(
callerPosition,
preserveCaller,
- 1 + (callerPosition == null ? 0 : 1) + (debugEntries == null ? 0 : debugEntries.size()),
+ debugEntries == null ? 0 : debugEntries.size(),
this.method);
}
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 f2e96b3..f010357 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
@@ -3,11 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;
+
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.Command;
+import com.android.tools.r8.debug.DebugTestConfig.RuntimeKind;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.google.common.collect.ImmutableList;
@@ -25,45 +27,64 @@
@RunWith(Parameterized.class)
public class DebugInfoWhenInliningTest extends DebugTestBase {
+ public enum Config {
+ CF,
+ DEX_NO_FORCE_JUMBO,
+ DEX_FORCE_JUMBO
+ };
+
private static final String SOURCE_FILE = "Inlining1.java";
private DebugTestConfig makeConfig(
LineNumberOptimization lineNumberOptimization,
- boolean writeProguardMap)
+ boolean writeProguardMap,
+ RuntimeKind runtimeKind)
throws Exception {
- AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
+ DebugTestConfig config = null;
Path outdir = temp.newFolder().toPath();
- Path outjar = outdir.resolve("dex_r8_compiled.jar");
- Path proguardMapPath = writeProguardMap ? outdir.resolve("proguard.map") : null;
+ Path outjar = outdir.resolve("r8_compiled.jar");
R8Command.Builder builder =
- R8Command.builder()
- .addProgramFiles(DEBUGGEE_JAR)
- .setMinApiLevel(minSdk.getLevel())
- .addLibraryFiles(ToolHelper.getAndroidJar(minSdk))
- .setMode(CompilationMode.RELEASE)
- .setOutput(outjar, OutputMode.DexIndexed);
- if (proguardMapPath != null) {
- builder.setProguardMapOutputPath(proguardMapPath);
+ R8Command.builder().addProgramFiles(DEBUGGEE_JAR).setMode(CompilationMode.RELEASE);
+
+ if (runtimeKind == RuntimeKind.DEX) {
+ AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
+ builder
+ .setMinApiLevel(minSdk.getLevel())
+ .addLibraryFiles(ToolHelper.getAndroidJar(minSdk))
+ .setOutput(outjar, OutputMode.DexIndexed);
+ config = new DexDebugTestConfig(outjar);
+ } else {
+ assert (runtimeKind == RuntimeKind.CF);
+ builder.setOutput(outjar, OutputMode.ClassFile);
+ config = new CfDebugTestConfig(outjar);
}
+
+ if (writeProguardMap) {
+ Path proguardMapPath = outdir.resolve("proguard.map");
+ builder.setProguardMapOutputPath(proguardMapPath);
+ config.setProguardMap(proguardMapPath);
+ }
+
ToolHelper.runR8(
builder.build(), options -> {
options.lineNumberOptimization = lineNumberOptimization;
options.testing.forceJumboStringProcessing = forceJumboStringProcessing;
});
- DebugTestConfig config = new DexDebugTestConfig(outjar);
- config.setProguardMap(proguardMapPath);
+
return config;
}
private boolean forceJumboStringProcessing;
+ private RuntimeKind runtimeKind;
- @Parameters(name="forceJumbo: {0}")
- public static Collection<Boolean> data() {
- return Arrays.asList(true, false);
+ @Parameters(name = "config: {0}")
+ public static Collection<Config> data() {
+ return Arrays.asList(Config.values());
}
- public DebugInfoWhenInliningTest(boolean forceJumboStringProcessing) {
- this.forceJumboStringProcessing = forceJumboStringProcessing;
+ public DebugInfoWhenInliningTest(Config config) {
+ this.forceJumboStringProcessing = config == Config.DEX_FORCE_JUMBO;
+ this.runtimeKind = config == Config.CF ? RuntimeKind.CF : RuntimeKind.DEX;
}
@Test
@@ -75,7 +96,7 @@
// (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(makeConfig(LineNumberOptimization.OFF, false), lineNumbers);
+ testEachLine(makeConfig(LineNumberOptimization.OFF, false, runtimeKind), lineNumbers);
}
@Test
@@ -87,13 +108,13 @@
// (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(makeConfig(LineNumberOptimization.OFF, true), lineNumbers);
+ testEachLine(makeConfig(LineNumberOptimization.OFF, true, runtimeKind), lineNumbers);
}
@Test
public void testEachLineOptimized() throws Throwable {
int[] lineNumbers = {1, 2, 3, 4, 5, 6, 7, 8};
- testEachLine(makeConfig(LineNumberOptimization.ON, false), lineNumbers);
+ testEachLine(makeConfig(LineNumberOptimization.ON, false, runtimeKind), lineNumbers);
}
@Test
@@ -130,7 +151,7 @@
new SignatureAndLine("void Inlining2.differentFileMultilevelInliningLevel1()", 36),
new SignatureAndLine("void main(java.lang.String[])", 26)));
testEachLine(
- makeConfig(LineNumberOptimization.ON, true), lineNumbers, inlineFramesList);
+ makeConfig(LineNumberOptimization.ON, true, runtimeKind), lineNumbers, inlineFramesList);
}
private void testEachLine(DebugTestConfig config, int[] lineNumbers) throws Throwable {