Merge "Dump timing when system proterty com.android.tools.r8.printtimes is set"
diff --git a/src/bspatch/java/com/android/tools/r8/dex/BSPatch.java b/src/bspatch/java/com/android/tools/r8/dex/BSPatch.java
index 00cb542..0a633f3 100644
--- a/src/bspatch/java/com/android/tools/r8/dex/BSPatch.java
+++ b/src/bspatch/java/com/android/tools/r8/dex/BSPatch.java
@@ -316,14 +316,14 @@
@Override
public void writeResult() throws IOException {
if (dexPath != null) {
- Segment[] segments = DexFileReader.parseMapFrom(dexPath);
- for (Segment segment : segments) {
- int y = segment.offset / width;
+ DexSection[] sections = DexParser.parseMapFrom(dexPath);
+ for (DexSection section : sections) {
+ int y = section.offset / width;
for (int x = 0; x < width; x++) {
int val = (x / 10) % 2 == 0 ? 0 : 0xffffff;
image.setRGB(x, y, val);
}
- System.out.println(segment);
+ System.out.println(section);
}
}
ImageIO.write(image, "png", output.toFile());
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
index 908372a..8c6574c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
@@ -11,6 +11,7 @@
public class DexDebugEntry {
+ public final boolean lineEntry;
public final int address;
public final int line;
public final DexString sourceFile;
@@ -21,6 +22,7 @@
public final Position callerPosition;
public DexDebugEntry(
+ boolean lineEntry,
int address,
int line,
DexString sourceFile,
@@ -29,6 +31,7 @@
ImmutableMap<Integer, DebugLocalInfo> locals,
DexMethod method,
Position callerPosition) {
+ this.lineEntry = lineEntry;
this.address = address;
this.line = line;
this.sourceFile = sourceFile;
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
index a1bc201..b672e26 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
@@ -98,6 +98,7 @@
@Override
public void visit(DexDebugEvent.AdvancePC advancePC) {
positionState.visit(advancePC);
+ entryEventReceived(false);
}
@Override
@@ -113,7 +114,7 @@
@Override
public void visit(DexDebugEvent.Default defaultEvent) {
positionState.visit(defaultEvent);
- defaultEventReceived();
+ entryEventReceived(true);
}
@Override
@@ -153,11 +154,12 @@
getEntry(restartLocal.registerNum).reset();
}
- public void defaultEventReceived() {
+ private void entryEventReceived(boolean lineEntry) {
if (pending != null) {
// Local changes contribute to the pending position entry.
entries.add(
new DexDebugEntry(
+ pending.lineEntry,
pending.address,
pending.line,
pending.sourceFile,
@@ -169,6 +171,7 @@
}
pending =
new DexDebugEntry(
+ lineEntry,
positionState.getCurrentPc(),
positionState.getCurrentLine(),
positionState.getCurrentFile(),
@@ -184,7 +187,7 @@
public List<DexDebugEntry> build() {
// Flush any pending entry.
if (pending != null) {
- defaultEventReceived(); // To flush 'pending'.
+ entryEventReceived(false); // To flush 'pending'.
pending = null;
}
List<DexDebugEntry> result = entries;
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index bee0910..69fb348 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -216,7 +216,9 @@
private void emitLocalChanges(int pc) {
// If pc advanced since the locals changed and locals indeed have changed, emit the changes.
if (localsChanged()) {
- emitAdvancementEvents(emittedPc, emittedPosition, pc, emittedPosition, events, factory);
+ assert emittedPc != pc;
+ int pcDelta = emittedPc == NO_PC_INFO ? pc : pc - emittedPc;
+ events.add(factory.createAdvancePC(pcDelta));
emittedPc = pc;
emitLocalChangeEvents(emittedLocals, pendingLocals, lastKnownLocals, events, factory);
pendingLocalChanges = false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index bb4891b..ff8bd02 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.CfgPrinter;
+import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -44,11 +45,15 @@
public final boolean hasDebugPositions;
+ private final InternalOptions options;
+
public IRCode(
+ InternalOptions options,
DexEncodedMethod method,
LinkedList<BasicBlock> blocks,
ValueNumberGenerator valueNumberGenerator,
boolean hasDebugPositions) {
+ this.options = options;
this.method = method;
this.blocks = blocks;
this.valueNumberGenerator = valueNumberGenerator;
@@ -251,7 +256,10 @@
ImmutableList.Builder<BasicBlock> builder = ImmutableList.builder();
BasicBlock entryBlock = blocks.getFirst();
depthFirstSorting(visitedBlock, entryBlock, builder);
- return builder.build().reverse();
+ ImmutableList<BasicBlock> ordered = builder.build().reverse();
+ return options.testing.placeExceptionalBlocksLast
+ ? reorderExceptionalBlocksLastForTesting(ordered)
+ : ordered;
}
private void depthFirstSorting(Set<BasicBlock> visitedBlock, BasicBlock block,
@@ -265,6 +273,23 @@
}
}
+ // Reorder the blocks forcing all exceptional blocks to be at the end.
+ private static ImmutableList<BasicBlock> reorderExceptionalBlocksLastForTesting(
+ ImmutableList<BasicBlock> blocks) {
+ ImmutableList.Builder<BasicBlock> reordered = ImmutableList.builder();
+ for (BasicBlock block : blocks) {
+ if (!block.entry().isMoveException()) {
+ reordered.add(block);
+ }
+ }
+ for (BasicBlock block : blocks) {
+ if (block.entry().isMoveException()) {
+ reordered.add(block);
+ }
+ }
+ return reordered.build();
+ }
+
public void print(CfgPrinter printer) {
ensureBlockNumbering();
for (BasicBlock block : blocks) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Not.java b/src/main/java/com/android/tools/r8/ir/code/Not.java
index baf97f6..82840f8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Not.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Not.java
@@ -52,6 +52,7 @@
@Override
public void buildDex(DexBuilder builder) {
+ assert builder.getOptions().canUseNotInstruction();
com.android.tools.r8.code.Instruction instruction;
int dest = builder.allocatedRegister(dest(), getNumber());
int src = builder.allocatedRegister(source(), getNumber());
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 140184d..55e4b83 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
@@ -234,7 +234,7 @@
currentPosition = Position.none();
} else {
currentPosition = getCanonicalPositionAppendCaller(current);
- if (current.address == offset) {
+ if (current.lineEntry && current.address == offset) {
builder.addDebugPosition(currentPosition);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 0a27017..98c1015 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -390,7 +390,7 @@
joinPredecessorsWithIdenticalPhis();
// Package up the IR code.
- IRCode ir = new IRCode(method, blocks, valueNumberGenerator, hasDebugPositions);
+ IRCode ir = new IRCode(options, method, blocks, valueNumberGenerator, hasDebugPositions);
// Split critical edges to make sure that we have a place to insert phi moves if
// necessary.
@@ -1258,7 +1258,13 @@
public void addNot(NumericType type, int dest, int value) {
Value in = readNumericRegister(value, type);
Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
- Not instruction = new Not(type, out, in);
+ Instruction instruction;
+ if (options.canUseNotInstruction()) {
+ instruction = new Not(type, out, in);
+ } else {
+ Value minusOne = readLiteral(ValueType.fromNumericType(type), -1);
+ instruction = new Xor(type, out, in, minusOne);
+ }
assert !instruction.instructionTypeCanThrow();
addInstruction(instruction);
}
@@ -1616,6 +1622,22 @@
return readRegister(register, ValueType.fromNumericType(type));
}
+ public Value readLiteral(ValueType type, long constant) {
+ if (type == ValueType.INT) {
+ return readIntLiteral(constant);
+ } else {
+ assert type == ValueType.LONG;
+ return readLongLiteral(constant);
+ }
+ }
+
+ public Value readLongLiteral(long constant) {
+ Value value = new Value(valueNumberGenerator.next(), ValueType.LONG, null);
+ ConstNumber number = new ConstNumber(value, constant);
+ add(number);
+ return number.outValue();
+ }
+
public Value readIntLiteral(long constant) {
Value value = new Value(valueNumberGenerator.next(), ValueType.INT, null);
ConstNumber number = new ConstNumber(value, constant);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index b851352..6fc9e17 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -392,6 +392,7 @@
Function.identity();
public boolean invertConditionals = false;
+ public boolean placeExceptionalBlocksLast = false;
}
public boolean canUseInvokePolymorphicOnVarHandle() {
diff --git a/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTest.java b/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTest.java
new file mode 100644
index 0000000..0142dba
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTest.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// 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.
+package com.android.tools.r8.debug;
+
+public class BreakAtTryAndCatchTest {
+ int i = 0;
+
+ void foo() {
+ try { bar(); } catch (RuntimeException e) { baz(); }
+ baz();
+ }
+
+ int bar() {
+ if (i++ % 2 == 0) {
+ System.out.println("bar return " + i);
+ return i;
+ }
+ System.out.println("bar throw " + i);
+ throw new RuntimeException("" + i);
+ }
+
+ void baz() {
+ System.out.println("baz");
+ }
+
+ public static void main(String[] args) {
+ BreakAtTryAndCatchTest test = new BreakAtTryAndCatchTest();
+ test.foo();
+ test.foo();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java b/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java
new file mode 100644
index 0000000..54c906b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/BreakAtTryAndCatchTestRunner.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// 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.
+package com.android.tools.r8.debug;
+
+import com.android.tools.r8.ToolHelper;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.Collections;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class BreakAtTryAndCatchTestRunner extends DebugTestBase {
+
+ private static final Class CLASS = BreakAtTryAndCatchTest.class;
+ private static final String FILE = CLASS.getSimpleName() + ".java";
+ private static final String NAME = CLASS.getCanonicalName();
+
+ private final String name;
+ private final DebugTestConfig config;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> setup() {
+ DelayedDebugTestConfig cf =
+ temp -> new CfDebugTestConfig().addPaths(ToolHelper.getClassPathForTests());
+ DelayedDebugTestConfig d8 =
+ temp -> new D8DebugTestConfig().compileAndAddClasses(temp, CLASS);
+ DelayedDebugTestConfig d8Reordered =
+ temp -> new D8DebugTestConfig().compileAndAdd(
+ temp,
+ Collections.singletonList(ToolHelper.getClassFileForTestClass(CLASS)),
+ options -> options.testing.placeExceptionalBlocksLast = true);
+ return ImmutableList.of(
+ new Object[]{"CF", cf},
+ new Object[]{"D8", d8},
+ new Object[]{"D8/reorder", d8Reordered}
+ );
+ }
+
+ public BreakAtTryAndCatchTestRunner(String name, DelayedDebugTestConfig config) {
+ this.name = name;
+ this.config = config.getConfig(temp);
+ }
+
+ @Test
+ public void testHitOnEntryOnly() throws Throwable {
+ Assume.assumeFalse("b/72933440", name.equals("D8/reorder"));
+ runDebugTest(
+ config,
+ NAME,
+ breakpoint(NAME, "foo", 10),
+ run(),
+ checkLine(FILE, 10), // hit line entry, bar does not throw
+ run(),
+ checkLine(FILE, 10), // hit line entry, bar does throw
+ breakpoint(NAME, "main", 31),
+ run(),
+ checkLine(FILE, 31), // No more hits on line, continue to main.
+ run());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java b/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java
index b588590..002635f 100644
--- a/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/LocalChangeOnSameLineTestRunner.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.ToolHelper;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
-import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -36,7 +35,6 @@
/** Test that only hit the break point at line 15 once. */
@Test
public void testHitBreakpointOnce() throws Throwable {
- Assume.assumeFalse("b/72933440 : invalid line info table", config instanceof D8DebugTestConfig);
runDebugTest(
config,
NAME,
diff --git a/src/test/java/com/android/tools/r8/debuginfo/DebugInfoInspector.java b/src/test/java/com/android/tools/r8/debuginfo/DebugInfoInspector.java
index 5d15735..4ce3b5a 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/DebugInfoInspector.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/DebugInfoInspector.java
@@ -125,14 +125,14 @@
}
private void checkConsistentEntries() {
- DexDebugEntry previousEntry = null;
+ DexDebugEntry previousLineEntry = null;
for (DexDebugEntry entry : entries) {
- if (previousEntry != null) {
+ if (entry.lineEntry) {
assertTrue(
"More than one entry defined for PC " + StringUtils.hexString(entry.address, 2),
- entry.address > previousEntry.address);
+ previousLineEntry == null || entry.address > previousLineEntry.address);
+ previousLineEntry = entry;
}
- previousEntry = entry;
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
index d6f86d8..2da7d8c 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
@@ -123,9 +123,10 @@
LinkedList<BasicBlock> blocks = new LinkedList<>();
blocks.add(block);
- IRCode code = new IRCode(null, blocks, new ValueNumberGenerator(), false);
+ InternalOptions options = new InternalOptions();
+ IRCode code = new IRCode(options, null, blocks, new ValueNumberGenerator(), false);
PeepholeOptimizer.optimize(code,
- new MockLinearScanRegisterAllocator(code, new InternalOptions()));
+ new MockLinearScanRegisterAllocator(code, options));
// Check that all four constant number instructions remain.
assertEquals(4,
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
index 699ebb4..6e02a17 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
@@ -62,7 +62,7 @@
// Check that the goto in block0 remains. There was a bug in the trivial goto elimination
// that ended up removing that goto changing the code to start with the unreachable
// throw.
- IRCode code = new IRCode(null, blocks, new ValueNumberGenerator(), false);
+ IRCode code = new IRCode(null, null, blocks, new ValueNumberGenerator(), false);
CodeRewriter.collapsTrivialGotos(null, code);
assertTrue(code.blocks.get(0).isTrivialGoto());
assertTrue(blocks.contains(block0));
@@ -130,7 +130,7 @@
// Check that the goto in block0 remains. There was a bug in the trivial goto elimination
// that ended up removing that goto changing the code to start with the unreachable
// throw.
- IRCode code = new IRCode(null, blocks, new ValueNumberGenerator(), false);
+ IRCode code = new IRCode(null, null, blocks, new ValueNumberGenerator(), false);
CodeRewriter.collapsTrivialGotos(null, code);
assertTrue(block0.getInstructions().get(1).isIf());
assertEquals(block1, block0.getInstructions().get(1).asIf().fallthroughBlock());
diff --git a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
index af8382e..0623f01 100644
--- a/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
+++ b/src/test/java/com/android/tools/r8/jdwp/RunJdwpTests.java
@@ -116,9 +116,8 @@
static final Map<String, TestPredicate> FAILING_TESTS =
ImmutableMap.<String, TestPredicate>builder()
- // ART line-table currently returns too many line entries.
- .put("LineTableDuplicatesTest", RunJdwpTests::isJava)
// Other failures on various older runtimes.
+ .put("LineTableDuplicatesTest", RunJdwpTests::isAndroidLOrAbove)
.put("ArrayReference.GetValuesTest", RunJdwpTests::isAndroidLOrAbove)
.put("ArrayReference.LengthTest", RunJdwpTests::isAndroidLOrAbove)
.put("ArrayReference.SetValues003Test", RunJdwpTests::isAndroidNOrAbove)
diff --git a/tools/asmifier.py b/tools/asmifier.py
new file mode 100755
index 0000000..4d2b973
--- /dev/null
+++ b/tools/asmifier.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+# 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.
+
+import gradle
+import os
+import subprocess
+import sys
+import utils
+
+def run(args, build=True):
+ if build:
+ gradle.RunGradle(['copyMavenDeps'])
+ cmd = []
+ cmd.append('java')
+ cmd.extend(['-cp', 'build/deps/asm-6.0.jar:build/deps/asm-util-6.0.jar'])
+ cmd.append('org.objectweb.asm.util.ASMifier')
+ cmd.extend(args)
+ utils.PrintCmd(cmd)
+ result = subprocess.check_output(cmd)
+ print(result)
+ return result
+
+def main():
+ build = True
+ args = []
+ for arg in sys.argv[1:]:
+ if arg in ("--build", "--no-build"):
+ build = arg == "--build"
+ else:
+ args.append(arg)
+ try:
+ run(args, build)
+ except subprocess.CalledProcessError as e:
+ # In case anything relevant was printed to stdout, normally this is already
+ # on stderr.
+ print(e.output)
+ return e.returncode
+
+if __name__ == '__main__':
+ sys.exit(main())