Version 0.1.8 Merge: Fix addition/exclusion of Jasmin code in Art tests. CL: https://r8-review.googlesource.com/c/r8/+/5621 Merge: Reapply "Instructions can be targeted by both normal and exceptional flow. CL: https://r8-review.googlesource.com/c/r8/+/5622 Change-Id: I821f9fa26819c17fa483402639910da8317c2e17
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java index c997595..5e43513 100644 --- a/src/main/java/com/android/tools/r8/D8.java +++ b/src/main/java/com/android/tools/r8/D8.java
@@ -55,7 +55,7 @@ */ public final class D8 { - private static final String VERSION = "v0.1.7"; + private static final String VERSION = "v0.1.8"; private static final int STATUS_ERROR = 1; private D8() {}
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java index 6b127da..e8efb59 100644 --- a/src/main/java/com/android/tools/r8/R8.java +++ b/src/main/java/com/android/tools/r8/R8.java
@@ -71,7 +71,7 @@ public class R8 { - private static final String VERSION = "v0.1.7"; + private static final String VERSION = "v0.1.8"; private final Timing timing = new Timing("R8"); private final InternalOptions options;
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java index 3dff4f3..61ed928 100644 --- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java +++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -27,6 +27,7 @@ } public void setPosition(DebugPosition position) { + assert this.position == null; this.position = position; }
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 9e07ad6..d1c42ee 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
@@ -26,6 +26,7 @@ import com.android.tools.r8.code.MoveResultWide; import com.android.tools.r8.code.SwitchPayload; import com.android.tools.r8.code.Throw; +import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.DebugLocalInfo; import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexCode; @@ -39,6 +40,7 @@ import com.android.tools.r8.graph.DexProto; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.ir.code.CatchHandlers; +import com.android.tools.r8.ir.code.DebugPosition; import com.android.tools.r8.ir.code.MoveType; import java.util.ArrayList; import java.util.HashMap; @@ -161,6 +163,17 @@ } @Override + public int getMoveExceptionRegister() { + // No register, move-exception is manually entered during construction. + return -1; + } + + @Override + public DebugPosition getDebugPositionAtOffset(int offset) { + throw new Unreachable(); + } + + @Override public boolean verifyCurrentInstructionCanThrow() { return currentDexInstruction.canThrow(); }
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 aa86057..7a1212a 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
@@ -93,6 +93,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -124,6 +125,15 @@ } } + private static class MoveExceptionWorklistItem extends WorklistItem { + private final int targetOffset; + + private MoveExceptionWorklistItem(BasicBlock block, int targetOffset) { + super(block, -1); + this.targetOffset = targetOffset; + } + } + /** * Representation of lists of values that can be used as keys in maps. A list of * values is equal to another list of values if it contains exactly the same values @@ -449,6 +459,11 @@ setCurrentBlock(item.block); blocks.add(currentBlock); currentBlock.setNumber(nextBlockNumber++); + // Process synthesized move-exception block specially. + if (item instanceof MoveExceptionWorklistItem) { + processMoveExceptionItem((MoveExceptionWorklistItem) item); + continue; + } // Build IR for each dex instruction in the block. for (int i = item.firstInstructionIndex; i < source.instructionCount(); ++i) { if (currentBlock == null) { @@ -467,6 +482,22 @@ } } + private void processMoveExceptionItem(MoveExceptionWorklistItem moveExceptionItem) { + // TODO(zerny): Link with outer try-block handlers, if any. b/65203529 + int moveExceptionDest = source.getMoveExceptionRegister(); + assert moveExceptionDest >= 0; + int targetIndex = source.instructionIndex(moveExceptionItem.targetOffset); + Value out = writeRegister(moveExceptionDest, MoveType.OBJECT, ThrowingInfo.NO_THROW, null); + MoveException moveException = new MoveException(out); + moveException.setPosition(source.getDebugPositionAtOffset(moveExceptionItem.targetOffset)); + currentBlock.add(moveException); + currentBlock.add(new Goto()); + BasicBlock targetBlock = getTarget(moveExceptionItem.targetOffset); + currentBlock.link(targetBlock); + addToWorklist(targetBlock, targetIndex); + closeCurrentBlock(); + } + // Helper to resolve switch payloads and build switch instructions (dex code only). public void resolveAndBuildSwitch(int value, int fallthroughOffset, int payloadOffset) { source.resolveAndBuildSwitch(value, fallthroughOffset, payloadOffset, this); @@ -1567,9 +1598,7 @@ // Private instruction helpers. private void addInstruction(Instruction ir) { attachLocalChanges(ir); - if (currentDebugPosition != null && !ir.isMoveException()) { - flushCurrentDebugPosition(); - } + flushCurrentDebugPosition(ir); currentBlock.add(ir); if (ir.instructionTypeCanThrow()) { assert source.verifyCurrentInstructionCanThrow(); @@ -1578,18 +1607,33 @@ assert !throwingInstructionInCurrentBlock; throwingInstructionInCurrentBlock = true; List<BasicBlock> targets = new ArrayList<>(catchHandlers.getAllTargets().size()); - for (int targetOffset : catchHandlers.getAllTargets()) { - BasicBlock target = getTarget(targetOffset); - addToWorklist(target, source.instructionIndex(targetOffset)); - targets.add(target); + int moveExceptionDest = source.getMoveExceptionRegister(); + if (moveExceptionDest < 0) { + for (int targetOffset : catchHandlers.getAllTargets()) { + BasicBlock target = getTarget(targetOffset); + addToWorklist(target, source.instructionIndex(targetOffset)); + targets.add(target); + } + } else { + // If there is a well-defined move-exception destination register (eg, compiling from + // Java-bytecode) then we construct move-exception header blocks for each unique target. + Map<BasicBlock, BasicBlock> moveExceptionHeaders = + new IdentityHashMap<>(catchHandlers.getUniqueTargets().size()); + for (int targetOffset : catchHandlers.getAllTargets()) { + BasicBlock target = getTarget(targetOffset); + BasicBlock header = moveExceptionHeaders.get(target); + if (header == null) { + header = new BasicBlock(); + header.incrementUnfilledPredecessorCount(); + moveExceptionHeaders.put(target, header); + ssaWorklist.add(new MoveExceptionWorklistItem(header, targetOffset)); + } + targets.add(header); + } } currentBlock.linkCatchSuccessors(catchHandlers.getGuards(), targets); } } - if (currentDebugPosition != null) { - assert ir.isMoveException(); - flushCurrentDebugPosition(); - } } private void attachLocalChanges(Instruction ir) { @@ -1976,26 +2020,23 @@ public void updateCurrentDebugPosition(int line, DexString file) { // Stack-trace support requires position information in both debug and release mode. - flushCurrentDebugPosition(); + flushCurrentDebugPosition(null); currentDebugPosition = new DebugPosition(line, file); attachLocalChanges(currentDebugPosition); } - private void flushCurrentDebugPosition() { + private void flushCurrentDebugPosition(Instruction instruction) { if (currentDebugPosition != null) { DebugPosition position = currentDebugPosition; currentDebugPosition = null; - if (!currentBlock.getInstructions().isEmpty()) { - MoveException move = currentBlock.getInstructions().getLast().asMoveException(); - if (move != null && move.getPosition() == null) { - // Set the position on the move-exception instruction. - // ART/DX associates the move-exception pc with the catch-declaration line. - // See debug.ExceptionTest.testStepOnCatch(). - move.setPosition(position); - return; - } + if (instruction != null && instruction.isMoveException()) { + // Set the position on the move-exception instruction. + // ART/DX associates the move-exception pc with the catch-declaration line. + // See debug.ExceptionTest.testStepOnCatch(). + instruction.asMoveException().setPosition(position); + } else { + addInstruction(position); } - addInstruction(position); } }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java index 8d36ef7..d7a0428 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -21,6 +21,7 @@ import com.android.tools.r8.ir.code.CatchHandlers; import com.android.tools.r8.ir.code.Cmp.Bias; import com.android.tools.r8.ir.code.ConstType; +import com.android.tools.r8.ir.code.DebugPosition; import com.android.tools.r8.ir.code.If; import com.android.tools.r8.ir.code.Invoke; import com.android.tools.r8.ir.code.MemberType; @@ -132,10 +133,10 @@ "([Ljava/lang/Object;)Ljava/lang/Object;"; // Language types. - private static final Type CLASS_TYPE = Type.getObjectType("java/lang/Class"); - private static final Type STRING_TYPE = Type.getObjectType("java/lang/String"); - private static final Type INT_ARRAY_TYPE = Type.getObjectType(INT_ARRAY_DESC); - private static final Type THROWABLE_TYPE = Type.getObjectType("java/lang/Throwable"); + static final Type CLASS_TYPE = Type.getObjectType("java/lang/Class"); + static final Type STRING_TYPE = Type.getObjectType("java/lang/String"); + static final Type INT_ARRAY_TYPE = Type.getObjectType(INT_ARRAY_DESC); + static final Type THROWABLE_TYPE = Type.getObjectType("java/lang/Throwable"); private static final int[] NO_TARGETS = {}; @@ -361,14 +362,6 @@ state.recordStateForTarget(0, this); for (JarStateWorklistItem item = worklist.poll(); item != null; item = worklist.poll()) { state.restoreState(item.instructionIndex); - // If the block being restored is a try-catch handler push the exception on the stack. - for (int i = 0; i < node.tryCatchBlocks.size(); i++) { - TryCatchBlockNode tryCatchBlockNode = (TryCatchBlockNode) node.tryCatchBlocks.get(i); - if (tryCatchBlockNode.handler == getInstruction(item.instructionIndex)) { - state.push(THROWABLE_TYPE); - break; - } - } // Iterate each of the instructions in the block to compute the outgoing JarState. for (int i = item.instructionIndex; i <= instructionCount(); ++i) { // If we are at the end of the instruction stream or if we have reached the start @@ -426,10 +419,8 @@ private void buildExceptionalPostlude(IRBuilder builder) { assert isSynchronized(); generatingMethodSynchronization = true; - int exceptionRegister = 0; // We are exiting the method so we just overwrite register 0. - builder.addMoveException(exceptionRegister); buildMonitorExit(builder); - builder.addThrow(exceptionRegister); + builder.addThrow(getMoveExceptionRegister()); generatingMethodSynchronization = false; } @@ -459,14 +450,6 @@ // If a new block is starting here, we restore the computed JarState. if (builder.getCFG().containsKey(instructionIndex) || instructionIndex == 0) { state.restoreState(instructionIndex); - // If the block being restored is a try-catch handler push the exception on the stack. - for (int i = 0; i < node.tryCatchBlocks.size(); i++) { - TryCatchBlockNode tryCatchBlockNode = (TryCatchBlockNode) node.tryCatchBlocks.get(i); - if (tryCatchBlockNode.handler == insn) { - builder.addMoveException(state.push(THROWABLE_TYPE)); - break; - } - } } String preInstructionState; @@ -537,6 +520,11 @@ } @Override + public int getMoveExceptionRegister() { + return state.startOfStack; + } + + @Override public boolean verifyCurrentInstructionCanThrow() { return generatingMethodSynchronization || canThrow(currentInstruction); } @@ -2792,6 +2780,23 @@ builder.updateCurrentDebugPosition(insn.line, null); } + @Override + public DebugPosition getDebugPositionAtOffset(int offset) { + int index = instructionIndex(offset); + if (index < 0 || instructionCount() <= index) { + return null; + } + AbstractInsnNode insn = node.instructions.get(index); + if (insn instanceof LabelNode) { + insn = insn.getNext(); + } + if (insn instanceof LineNumberNode) { + LineNumberNode line = (LineNumberNode) insn; + return new DebugPosition(line.line, null); + } + return null; + } + // Printing helpers. @Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java index 0801216..ebe220b 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
@@ -165,7 +165,7 @@ } } - private final int startOfStack; + final int startOfStack; private int topOfStack; // Locals are split into three parts based on types: @@ -470,7 +470,10 @@ } public boolean recordStateForExceptionalTarget(int target, JarSourceCode source) { - return recordStateForTarget(target, locals.clone(), ImmutableList.of(), source); + return recordStateForTarget(target, + locals.clone(), + ImmutableList.of(new Slot(startOfStack, JarSourceCode.THROWABLE_TYPE)), + source); } private boolean recordStateForTarget(int target, Local[] locals, ImmutableList<Slot> stack,
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java index b1f9a14..70e6218 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
@@ -6,6 +6,7 @@ import com.android.tools.r8.graph.DebugLocalInfo; import com.android.tools.r8.ir.code.CatchHandlers; +import com.android.tools.r8.ir.code.DebugPosition; /** * Abstraction of the input/source code for the IRBuilder. @@ -26,6 +27,8 @@ DebugLocalInfo getCurrentLocal(int register); + DebugPosition getDebugPositionAtOffset(int offset); + /** * Trace block structure of the source-program. * @@ -57,6 +60,7 @@ void resolveAndBuildNewArrayFilledData(int arrayRef, int payloadOffset, IRBuilder builder); CatchHandlers<Integer> getCurrentCatchHandlers(); + int getMoveExceptionRegister(); // For debugging/verification purpose. boolean verifyRegister(int register);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java index 3857c1f..ea26926 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -27,6 +27,7 @@ import com.android.tools.r8.ir.code.BasicBlock; import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo; import com.android.tools.r8.ir.code.CatchHandlers; +import com.android.tools.r8.ir.code.DebugPosition; import com.android.tools.r8.ir.code.Div; import com.android.tools.r8.ir.code.IRCode; import com.android.tools.r8.ir.code.Instruction; @@ -928,6 +929,16 @@ } @Override + public int getMoveExceptionRegister() { + throw new Unreachable(); + } + + @Override + public DebugPosition getDebugPositionAtOffset(int offset) { + throw new Unreachable(); + } + + @Override public boolean verifyCurrentInstructionCanThrow() { // TODO(sgjesse): Check more here? return true;
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SingleBlockSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SingleBlockSourceCode.java index bd7efce..410e4b8 100644 --- a/src/main/java/com/android/tools/r8/ir/synthetic/SingleBlockSourceCode.java +++ b/src/main/java/com/android/tools/r8/ir/synthetic/SingleBlockSourceCode.java
@@ -12,6 +12,7 @@ import com.android.tools.r8.graph.DexType; import com.android.tools.r8.ir.code.Argument; import com.android.tools.r8.ir.code.CatchHandlers; +import com.android.tools.r8.ir.code.DebugPosition; import com.android.tools.r8.ir.code.MoveType; import com.android.tools.r8.ir.code.Value; import com.android.tools.r8.ir.conversion.IRBuilder; @@ -196,6 +197,16 @@ } @Override + public int getMoveExceptionRegister() { + throw new Unreachable(); + } + + @Override + public DebugPosition getDebugPositionAtOffset(int offset) { + throw new Unreachable(); + } + + @Override public final boolean verifyCurrentInstructionCanThrow() { return true; }
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java index ab350a7..3a6277c 100644 --- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java +++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -3,11 +3,11 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8; -import static com.android.tools.r8.TestCondition.compilers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import com.android.tools.r8.JctfTestSpecifications.Outcome; +import com.android.tools.r8.TestCondition.RuntimeSet; import com.android.tools.r8.ToolHelper.ArtCommandBuilder; import com.android.tools.r8.ToolHelper.DexVm; import com.android.tools.r8.ToolHelper.ProcessResult; @@ -82,6 +82,12 @@ private static final String ART_TESTS_NATIVE_LIBRARY_DIR = "tests/2017-07-27/art/lib64"; private static final String ART_LEGACY_TESTS_NATIVE_LIBRARY_DIR = "tests/2016-12-19/art/lib64"; + private static final RuntimeSet LEGACY_RUNTIME = TestCondition.runtimes( + DexVm.ART_4_4_4, + DexVm.ART_5_1_1, + DexVm.ART_6_0_1, + DexVm.ART_7_0_0); + // Input jar for jctf tests. private static final String JCTF_COMMON_JAR = "build/libs/jctfCommon.jar"; @@ -527,8 +533,6 @@ // keeps the instances alive is dead and could be garbage collected. The compiler reuses // the register for the list and therefore there are no live instances. .put("099-vmdebug", TestCondition.any()) - // This test relies on output on stderr, which we currently do not collect. - .put("143-string-value", TestCondition.any()) .put( "800-smali", TestCondition.match( @@ -577,7 +581,7 @@ "370-dex-v37", TestCondition.match( TestCondition.tools(DexTool.JACK, DexTool.DX), - compilers(CompilerUnderTest.R8, CompilerUnderTest.D8), + TestCondition.compilers(CompilerUnderTest.R8, CompilerUnderTest.D8), TestCondition.runtimes(DexVm.ART_4_4_4, DexVm.ART_5_1_1, DexVm.ART_6_0_1))) // Array index out of bounds exception. .put("449-checker-bce", TestCondition.any()) @@ -680,21 +684,15 @@ // iput on a static field. .put("600-verifier-fails", TestCondition.match(TestCondition.R8_COMPILER)) // Contains a method that falls off the end without a return. - .put("606-erroneous-class", TestCondition - .match(TestCondition.tools(DexTool.DX, DexTool.JACK), - TestCondition.R8_NOT_AFTER_D8_COMPILER)) - .put("064-field-access", TestCondition - .match(TestCondition.tools(DexTool.NONE), TestCondition.D8_COMPILER)) + .put("606-erroneous-class", TestCondition.match( + TestCondition.tools(DexTool.DX, DexTool.JACK), + TestCondition.R8_NOT_AFTER_D8_COMPILER, + LEGACY_RUNTIME)) .build(); // Tests that are invalid dex files and on which R8/D8 fails and that is OK. private static final Multimap<String, TestCondition> expectedToFailWithCompiler = new ImmutableListMultimap.Builder<String, TestCondition>() - // When starting from the Dex frontend we see two definitions of the same class coming - // from two differents dex files. - .put("064-field-access", - TestCondition.match(TestCondition.tools(DexTool.DX, DexTool.JACK), - TestCondition.runtimes(DexVm.ART_DEFAULT))) // When starting from the Jar frontend we see the A$B class both from the Java source // code and from the smali dex code. We reject that because there are then two definitions // of the same class in the application. When running from the final dex files there is @@ -702,18 +700,8 @@ .put("121-modifiers", TestCondition.match(TestCondition.tools(DexTool.NONE))) // This test uses register r1 in method that is declared to only use 1 register (r0). .put("142-classloader2", TestCondition.match(TestCondition.R8_COMPILER)) - // When starting from the Dex frontend we see two definitions of the same class coming - // from two differents dex files. - .put("162-method-resolution", - TestCondition.match(TestCondition.tools(DexTool.DX, DexTool.JACK))) // This test uses an uninitialized register. .put("471-uninitialized-locals", TestCondition.match(TestCondition.R8_COMPILER)) - // When starting from the Dex frontend we see two definitions of the same class coming - // from two differents dex files. - .put("606-erroneous-class", - TestCondition - .match(TestCondition.tools(DexTool.DX, DexTool.JACK), TestCondition.D8_COMPILER, - TestCondition.runtimes(DexVm.ART_DEFAULT))) // This test is starting from invalid dex code. It splits up a double value and uses // the first register of a double with the second register of another double. .put("800-smali", TestCondition.match(TestCondition.R8_COMPILER)) @@ -729,9 +717,7 @@ // Tests that does not have valid input for us to be compatible with jack/dx running. private static List<String> noInputJar = ImmutableList.of( - "064-field-access", // Missing classes2 dir (has src2) "097-duplicate-method", // No input class files. - "162-method-resolution", // Based on multiple jasmin files "630-safecast-array", // No input class files. "801-VoidCheckCast", // No input class files. "804-class-extends-itself", // No input class files. @@ -767,12 +753,19 @@ // Tests to skip on some conditions private static final Multimap<String, TestCondition> testToSkip = new ImmutableListMultimap.Builder<String, TestCondition>() + // When running R8 on dex input (D8, DX or JACK) this test non-deterministically fails + // with a compiler exception, due to invoke-virtual on an interface, or it completes but + // the output when run on Art is not as expected. b/65233869 + .put("162-method-resolution", + TestCondition.match( + TestCondition.tools(DexTool.DX, DexTool.JACK), TestCondition.R8_COMPILER)) // Old runtimes used the legacy test directory which does not contain input for tools // NONE and DX. .put("952-invoke-custom", TestCondition.match( TestCondition.tools(DexTool.NONE, DexTool.DX), - TestCondition.runtimes( - DexVm.ART_4_4_4, DexVm.ART_5_1_1, DexVm.ART_6_0_1, DexVm.ART_7_0_0))) + LEGACY_RUNTIME)) + // No input dex files for DX + .put("952-invoke-custom-kinds", TestCondition.match(TestCondition.tools(DexTool.DX))) .build(); public static List<String> requireInliningToBeDisabled = ImmutableList.of( @@ -956,7 +949,7 @@ private static Map<SpecificationKey, TestSpecification> getTestsMap( CompilerUnderTest compilerUnderTest, CompilationMode compilationMode, DexVm dexVm) { File artTestDir = new File(ART_TESTS_DIR); - if (dexVm != DexVm.ART_DEFAULT) { + if (LEGACY_RUNTIME.set.contains(dexVm)) { artTestDir = new File(ART_LEGACY_TESTS_DIR); } if (!artTestDir.exists()) { @@ -1447,25 +1440,20 @@ File[] inputFiles; if (toolchain == DexTool.NONE) { - File classes = new File(specification.directory, "classes"); - inputFiles = - com.google.common.io.Files.fileTreeTraverser().breadthFirstTraversal(classes).filter( - (File f) -> !f.isDirectory()).toArray(File.class); + inputFiles = addFileTree(new File[0], new File(specification.directory, "classes")); + inputFiles = addFileTree(inputFiles, new File(specification.directory, "jasmin_classes")); File smali = new File(specification.directory, "smali"); if (smali.exists()) { File smaliDex = new File(smali, "out.dex"); assert smaliDex.exists(); inputFiles = ObjectArrays.concat(inputFiles, smaliDex); } - File classes2 = new File(specification.directory, "classes2"); - if (classes2.exists()) { - inputFiles = ObjectArrays.concat(inputFiles, - com.google.common.io.Files.fileTreeTraverser().breadthFirstTraversal(classes2).filter( - (File f) -> !f.isDirectory()).toArray(File.class), File.class); - } + inputFiles = addFileTree(inputFiles, new File(specification.directory, "classes2")); + inputFiles = addFileTree(inputFiles, new File(specification.directory, "jasmin_classes2")); } else { inputFiles = - specification.directory.listFiles((File file) -> file.getName().endsWith(".dex")); + specification.directory.listFiles((File file) -> + file.getName().endsWith(".dex") && !file.getName().startsWith("jasmin")); } List<String> fileNames = new ArrayList<>(); for (File file : inputFiles) { @@ -1504,6 +1492,18 @@ } } + private File[] addFileTree(File[] files, File directory) { + if (!directory.exists()) { + return files; + } + return ObjectArrays.concat( + files, + com.google.common.io.Files.fileTreeTraverser().breadthFirstTraversal(directory) + .filter(f -> !f.isDirectory()) + .toArray(File.class), + File.class); + } + private void runArtTestDoRunOnArt( DexVm version, CompilerUnderTest compilerUnderTest,
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java index a296a3e..32f5174 100644 --- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java +++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -36,6 +36,7 @@ import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; import com.android.tools.r8.ir.code.CatchHandlers; +import com.android.tools.r8.ir.code.DebugPosition; import com.android.tools.r8.ir.code.IRCode; import com.android.tools.r8.ir.conversion.IRBuilder; import com.android.tools.r8.ir.conversion.SourceCode; @@ -689,6 +690,16 @@ } @Override + public int getMoveExceptionRegister() { + throw new Unreachable(); + } + + @Override + public DebugPosition getDebugPositionAtOffset(int offset) { + throw new Unreachable(); + } + + @Override public boolean verifyRegister(int register) { throw new Unreachable(); }