Merge "Add a public ArchiveProgramResourceProvider utility to the API."
diff --git a/src/main/java/com/android/tools/r8/DexRoundTrip.java b/src/main/java/com/android/tools/r8/DexRoundTrip.java
new file mode 100644
index 0000000..01af3b8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/DexRoundTrip.java
@@ -0,0 +1,58 @@
+// Copyright (c) 2017, 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;
+
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidAppConsumers;
+import com.android.tools.r8.utils.ExceptionUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.io.ByteStreams;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class DexRoundTrip {
+
+ public static AndroidApp process(Collection<ProgramResource> dexResources)
+ throws CompilationFailedException {
+ InternalOptions options = new InternalOptions();
+ options.useTreeShaking = false;
+ options.skipMinification = true;
+ options.ignoreMissingClasses = true;
+ options.enableDesugaring = false;
+ AndroidAppConsumers consumer = new AndroidAppConsumers(options);
+ AndroidApp.Builder builder = AndroidApp.builder();
+ ExceptionUtils.withR8CompilationHandler(
+ options.reporter,
+ () -> {
+ for (ProgramResource resource : dexResources) {
+ try (InputStream stream = resource.getByteStream()) {
+ builder.addDexProgramData(ByteStreams.toByteArray(stream), resource.getOrigin());
+ }
+ }
+ R8.runForTesting(builder.build(), options);
+ });
+ return consumer.build();
+ }
+
+ public static void main(String[] args) throws CompilationFailedException, IOException {
+ List<ProgramResource> resources = new ArrayList<>(args.length);
+ for (String arg : args) {
+ Path file = Paths.get(arg);
+ if (!FileUtils.isDexFile(file)) {
+ throw new IllegalArgumentException(
+ "Only DEX files are supported as inputs. Invalid file: " + file);
+ }
+ resources.add(ProgramResource.fromFile(Kind.DEX, file));
+ }
+ AndroidApp result = process(resources);
+ process(result.getDexProgramResources());
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/Disassemble.java b/src/main/java/com/android/tools/r8/Disassemble.java
index 3b8dd04..e51e4d4 100644
--- a/src/main/java/com/android/tools/r8/Disassemble.java
+++ b/src/main/java/com/android/tools/r8/Disassemble.java
@@ -25,20 +25,21 @@
public static class DisassembleCommand extends BaseCommand {
private final Path outputPath;
+ private final StringResource proguardMap;
- public static class Builder
- extends BaseCommand.Builder<DisassembleCommand, DisassembleCommand.Builder> {
+ public static class Builder extends BaseCommand.Builder<DisassembleCommand, Builder> {
private Path outputPath = null;
+ private Path proguardMapFile = null;
private boolean useSmali = false;
@Override
- DisassembleCommand.Builder self() {
+ Builder self() {
return this;
}
- public DisassembleCommand.Builder setProguardMapFile(Path path) {
- guard(() -> getAppBuilder().setProguardMapFile(path));
+ public Builder setProguardMapFile(Path path) {
+ proguardMapFile = path;
return this;
}
@@ -46,12 +47,12 @@
return outputPath;
}
- public DisassembleCommand.Builder setOutputPath(Path outputPath) {
+ public Builder setOutputPath(Path outputPath) {
this.outputPath = outputPath;
return this;
}
- public DisassembleCommand.Builder setUseSmali(boolean useSmali) {
+ public Builder setUseSmali(boolean useSmali) {
this.useSmali = useSmali;
return this;
}
@@ -62,10 +63,11 @@
if (isPrintHelp() || isPrintVersion()) {
return new DisassembleCommand(isPrintHelp(), isPrintVersion());
}
-
- DisassembleCommand command = new DisassembleCommand(getAppBuilder().build(),
- getOutputPath(), useSmali);
- return command;
+ return new DisassembleCommand(
+ getAppBuilder().build(),
+ getOutputPath(),
+ proguardMapFile == null ? null : StringResource.fromFile(proguardMapFile),
+ useSmali);
}
}
@@ -82,17 +84,17 @@
private final boolean useSmali;
- public static DisassembleCommand.Builder builder() {
- return new DisassembleCommand.Builder();
+ public static Builder builder() {
+ return new Builder();
}
- public static DisassembleCommand.Builder parse(String[] args) {
- DisassembleCommand.Builder builder = builder();
+ public static Builder parse(String[] args) {
+ Builder builder = builder();
parse(args, builder);
return builder;
}
- private static void parse(String[] args, DisassembleCommand.Builder builder) {
+ private static void parse(String[] args, Builder builder) {
for (int i = 0; i < args.length; i++) {
String arg = args[i].trim();
if (arg.length() == 0) {
@@ -118,16 +120,19 @@
}
}
- private DisassembleCommand(AndroidApp inputApp, Path outputPath, boolean useSmali) {
+ private DisassembleCommand(
+ AndroidApp inputApp, Path outputPath, StringResource proguardMap, boolean useSmali) {
super(inputApp);
this.outputPath = outputPath;
+ this.proguardMap = proguardMap;
this.useSmali = useSmali;
}
private DisassembleCommand(boolean printHelp, boolean printVersion) {
super(printHelp, printVersion);
- this.outputPath = null;
- this.useSmali = false;
+ outputPath = null;
+ proguardMap = null;
+ useSmali = false;
}
public Path getOutputPath() {
@@ -168,7 +173,8 @@
ExecutorService executor = ThreadUtils.getExecutorService(options);
Timing timing = new Timing("disassemble");
try {
- DexApplication application = new ApplicationReader(app, options, timing).read(executor);
+ DexApplication application =
+ new ApplicationReader(app, options, timing).read(command.proguardMap, executor);
DexByteCodeWriter writer = command.useSmali()
? new SmaliWriter(application, options)
: new AssemblyWriter(application, options);
diff --git a/src/main/java/com/android/tools/r8/PrintClassList.java b/src/main/java/com/android/tools/r8/PrintClassList.java
index 69b2781..ea43a00 100644
--- a/src/main/java/com/android/tools/r8/PrintClassList.java
+++ b/src/main/java/com/android/tools/r8/PrintClassList.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
@@ -32,8 +33,9 @@
public static void main(String[] args) throws IOException, ExecutionException {
List<String> dexFiles = Arrays.asList(args);
Builder builder = AndroidApp.builder();
+ Path proguardMapFile = null;
if (args[0].endsWith("map")) {
- builder.setProguardMapFile(Paths.get(args[0]));
+ proguardMapFile = Paths.get(args[0]);
dexFiles = dexFiles.subList(1, dexFiles.size());
}
builder.addProgramFiles(ListUtils.map(dexFiles, Paths::get));
@@ -41,7 +43,10 @@
ExecutorService executorService = Executors.newCachedThreadPool();
DexApplication application =
new ApplicationReader(builder.build(), new InternalOptions(), new Timing("PrintClassList"))
- .read(executorService);
+ .read(
+ proguardMapFile == null ? null : StringResource.fromFile(proguardMapFile),
+ executorService
+ );
ClassNameMapper map = application.getProguardMap();
for (DexProgramClass clazz : application.classes()) {
System.out.print(maybeDeobfuscateType(map, clazz.type));
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 2e12cb1..304dde3 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -154,10 +154,6 @@
private void run(AndroidApp inputApp, ExecutorService executorService)
throws IOException, CompilationException {
assert options.programConsumer != null;
-
- // Read Proguard-map only with the "applymapping" feature.
- assert inputApp.getProguardMap() == null;
-
if (options.quiet) {
System.setOut(new PrintStream(ByteStreams.nullOutputStream()));
}
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index b6edebe..cae894d 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -42,7 +42,7 @@
private Optional<Boolean> discardedChecker = Optional.empty();
private Optional<Boolean> minification = Optional.empty();
private boolean forceProguardCompatibility = false;
- private Path proguardMapOutput = null;
+ private StringConsumer proguardMapConsumer = null;
protected Path proguardCompatibilityRulesOutput = null;
private StringConsumer mainDexListConsumer = null;
@@ -124,22 +124,37 @@
return self();
}
- /**
- * Add proguard configuration for automatic main dex list calculation.
- */
+ /** Add proguard rules for automatic main-dex-list calculation. */
public Builder addMainDexRules(List<String> lines, Origin origin) {
guard(() -> mainDexRules.add(
new ProguardConfigurationSourceStrings(lines, Paths.get("."), origin)));
return self();
}
+ /**
+ * Set an output destination to which main-dex-list content should be written.
+ *
+ * <p>This is a short-hand for setting a {@link StringConsumer.FileConsumer} using {@link
+ * #setMainDexListConsumer}. Note that any subsequent call to this method or {@link
+ * #setMainDexListConsumer} will override the previous setting.
+ *
+ * @param mainDexListOutputPath File-system path to write output at.
+ */
public Builder setMainDexListOutputPath(Path mainDexListOutputPath) {
mainDexListConsumer = new StringConsumer.FileConsumer(mainDexListOutputPath);
return self();
}
- public Builder setMainDexListConsumer(StringConsumer consumer) {
- mainDexListConsumer = consumer;
+ /**
+ * Set a consumer for receiving the main-dex-list content.
+ *
+ * <p>Note that any subsequent call to this method or {@link #setMainDexListOutputPath} will
+ * override the previous setting.
+ *
+ * @param mainDexListConsumer Consumer to receive the content once produced.
+ */
+ public Builder setMainDexListConsumer(StringConsumer mainDexListConsumer) {
+ this.mainDexListConsumer = mainDexListConsumer;
return self();
}
@@ -191,15 +206,30 @@
}
/**
- * Set a proguard mapping file resource.
+ * Set an output destination to which proguard-map content should be written.
+ *
+ * <p>This is a short-hand for setting a {@link StringConsumer.FileConsumer} using {@link
+ * #setProguardMapConsumer}. Note that any subsequent call to this method or {@link
+ * #setProguardMapConsumer} will override the previous setting.
+ *
+ * @param proguardMapOutput File-system path to write output at.
*/
- public Builder setProguardMapFile(Path path) {
- guard(() -> getAppBuilder().setProguardMapFile(path));
+ public Builder setProguardMapOutput(Path proguardMapOutput) {
+ assert proguardMapOutput != null;
+ this.proguardMapConsumer = new StringConsumer.FileConsumer(proguardMapOutput);
return self();
}
- public Builder setProguardMapOutput(Path path) {
- this.proguardMapOutput = path;
+ /**
+ * Set a consumer for receiving the proguard-map content.
+ *
+ * <p>Note that any subsequent call to this method or {@link #setProguardMapOutput} will
+ * override the previous setting.
+ *
+ * @param proguardMapConsumer Consumer to receive the content once produced.
+ */
+ public Builder setProguardMapConsumer(StringConsumer proguardMapConsumer) {
+ this.proguardMapConsumer = proguardMapConsumer;
return self();
}
@@ -284,9 +314,6 @@
boolean useDiscardedChecker = discardedChecker.orElse(true);
boolean useMinification = minification.orElse(configuration.isObfuscating());
- StringConsumer proguardMapConsumer =
- proguardMapOutput != null ? new StringConsumer.FileConsumer(proguardMapOutput) : null;
-
assert getProgramConsumer() != null;
R8Command command =
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 9f13ffc..64dc47d 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -62,9 +62,13 @@
}
public DexApplication read() throws IOException, ExecutionException {
+ return read((StringResource) null);
+ }
+
+ public DexApplication read(StringResource proguardMap) throws IOException, ExecutionException {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
- return read(executor);
+ return read(proguardMap, executor);
} finally {
executor.shutdown();
}
@@ -72,6 +76,11 @@
public final DexApplication read(ExecutorService executorService)
throws IOException, ExecutionException {
+ return read(null, executorService);
+ }
+
+ public final DexApplication read(StringResource proguardMap, ExecutorService executorService)
+ throws IOException, ExecutionException {
timing.begin("DexApplication.read");
final LazyLoadedDexApplication.Builder builder = DexApplication.builder(itemFactory, timing);
try {
@@ -83,7 +92,7 @@
// (b) some of the class file resources don't provide information
// about class descriptor.
// TODO: try and preload less classes.
- readProguardMap(builder, executorService, futures);
+ readProguardMap(proguardMap, builder, executorService, futures);
readMainDexList(builder, executorService, futures);
ClassReader classReader = new ClassReader(executorService, futures);
classReader.readSources();
@@ -110,20 +119,25 @@
return computedMinApiLevel;
}
- private void readProguardMap(DexApplication.Builder<?> builder, ExecutorService executorService,
+ private void readProguardMap(
+ StringResource map,
+ DexApplication.Builder<?> builder,
+ ExecutorService executorService,
List<Future<?>> futures) {
// Read the Proguard mapping file in parallel with DexCode and DexProgramClass items.
- StringResource map = inputApp.getProguardMap();
- if (map != null) {
- futures.add(executorService.submit(() -> {
- try {
- String content = map.getString();
- builder.setProguardMap(ClassNameMapper.mapperFromString(content));
- } catch (IOException | ResourceException e) {
- throw new CompilationError("Failure to read proguard map file", e, map.getOrigin());
- }
- }));
+ if (map == null) {
+ return;
}
+ futures.add(
+ executorService.submit(
+ () -> {
+ try {
+ String content = map.getString();
+ builder.setProguardMap(ClassNameMapper.mapperFromString(content));
+ } catch (IOException | ResourceException e) {
+ throw new CompilationError("Failure to read proguard map file", e, map.getOrigin());
+ }
+ }));
}
private void readMainDexList(DexApplication.Builder<?> builder, ExecutorService executorService,
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 3e685a2..34a3e79 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -355,7 +355,7 @@
return filled;
}
- void setFilledForTesting() {
+ public void setFilledForTesting() {
filled = true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DominatorTree.java b/src/main/java/com/android/tools/r8/ir/code/DominatorTree.java
index 511293f..cea2b0b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DominatorTree.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DominatorTree.java
@@ -104,7 +104,12 @@
@Override
public boolean hasNext() {
- return dominatedBy(sorted[current], dominator);
+ boolean found = false;
+ while (current < sorted.length
+ && !(found = dominatedBy(sorted[current], dominator))) {
+ current++;
+ }
+ return found && current < sorted.length;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 5685d22..64c4236 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -166,8 +166,6 @@
}
}
-
-
if (!needed) {
blocksToRemove.add(block);
for (BasicBlock pred : block.getPredecessors()) {
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
index df3801b..71e1516 100644
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
@@ -575,8 +575,8 @@
DominatorTree dom = new DominatorTree(code);
for (BasicBlock current : dom.dominatedBlocks(caseBlock)) {
InstructionIterator it = current.iterator();
- Switch switchInstr;
- if ((switchInstr = (Switch) it.nextUntil(Instruction::isSwitch)) != null) {
+ Switch switchInstr = (Switch) it.nextUntil(Instruction::isSwitch);
+ if (switchInstr != null) {
int nextBlock = code.getHighestBlockNumber() + 1;
IntList liveKeys = new IntArrayList(switchInstr.numberOfKeys());
List<BasicBlock> liveBlocks = new ArrayList<>(switchInstr.numberOfKeys());
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index b279dff..9e6d79c 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -49,7 +49,7 @@
private final ImmutableList<ClassFileResourceProvider> classpathResourceProviders;
private final ImmutableList<ClassFileResourceProvider> libraryResourceProviders;
- private final StringResource proguardMap;
+ private final StringResource proguardMapOutputData;
private final List<StringResource> mainDexListResources;
private final List<String> mainDexClasses;
@@ -59,14 +59,14 @@
ImmutableMap<Resource, String> programResourcesMainDescriptor,
ImmutableList<ClassFileResourceProvider> classpathResourceProviders,
ImmutableList<ClassFileResourceProvider> libraryResourceProviders,
- StringResource proguardMap,
+ StringResource proguardMapOutputData,
List<StringResource> mainDexListResources,
List<String> mainDexClasses) {
this.programResourceProviders = programResourceProviders;
this.programResourcesMainDescriptor = programResourcesMainDescriptor;
this.classpathResourceProviders = classpathResourceProviders;
this.libraryResourceProviders = libraryResourceProviders;
- this.proguardMap = proguardMap;
+ this.proguardMapOutputData = proguardMapOutputData;
this.mainDexListResources = mainDexListResources;
this.mainDexClasses = mainDexClasses;
}
@@ -140,10 +140,13 @@
}
/**
- * Get the input stream of the proguard-map resource if it exists.
+ * Get the proguard-map associated with an output "app" if it exists.
+ *
+ * <p>Note: this should never be used as the input to a compilation. See proguards ApplyMapping
+ * for such use cases.
*/
- public StringResource getProguardMap() {
- return proguardMap;
+ public StringResource getProguardMapOutputData() {
+ return proguardMapOutputData;
}
/**
@@ -229,11 +232,13 @@
private final Map<ProgramResource, String> programResourcesMainDescriptor = new HashMap<>();
private final List<ClassFileResourceProvider> classpathResourceProviders = new ArrayList<>();
private final List<ClassFileResourceProvider> libraryResourceProviders = new ArrayList<>();
- private StringResource proguardMap;
private List<StringResource> mainDexListResources = new ArrayList<>();
private List<String> mainDexListClasses = new ArrayList<>();
private boolean ignoreDexInArchive = false;
+ // Proguard map data is output only data. This should never be used as input to a compilation.
+ private StringResource proguardMapOutputData;
+
// See AndroidApp::builder().
private Builder() {
}
@@ -243,7 +248,6 @@
programResourceProviders.addAll(app.programResourceProviders);
classpathResourceProviders.addAll(app.classpathResourceProviders);
libraryResourceProviders.addAll(app.libraryResourceProviders);
- proguardMap = app.proguardMap;
mainDexListResources = app.mainDexListResources;
mainDexListClasses = app.mainDexClasses;
}
@@ -412,18 +416,13 @@
}
/**
- * Set proguard-map file.
+ * Set proguard-map output data.
+ *
+ * <p>Note: this should not be used as inputs to compilation!
*/
- public Builder setProguardMapFile(Path file) {
- proguardMap = file == null ? null : StringResource.fromFile(file);
- return this;
- }
-
- /**
- * Set proguard-map data.
- */
- public Builder setProguardMapData(String content) {
- proguardMap = content == null ? null : StringResource.fromString(content, Origin.unknown());
+ public Builder setProguardMapOutputData(String content) {
+ proguardMapOutputData =
+ content == null ? null : StringResource.fromString(content, Origin.unknown());
return this;
}
@@ -498,7 +497,7 @@
ImmutableMap.copyOf(programResourcesMainDescriptor),
ImmutableList.copyOf(classpathResourceProviders),
ImmutableList.copyOf(libraryResourceProviders),
- proguardMap,
+ proguardMapOutputData,
mainDexListResources,
mainDexListClasses);
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
index c83b61c..afd97ae 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
@@ -65,7 +65,7 @@
@Override
public void accept(String string, DiagnosticsHandler handler) {
super.accept(string, handler);
- builder.setProguardMapData(string);
+ builder.setProguardMapOutputData(string);
}
};
}
diff --git a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
index cc5f0f9..d5a9274 100644
--- a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.CompilationException;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.errors.CompilationError;
import java.io.IOException;
@@ -31,7 +32,7 @@
}
public interface CompileAction {
- void run() throws IOException, CompilationException, CompilationError;
+ void run() throws IOException, CompilationException, CompilationError, ResourceException;
}
private enum Compiler {
@@ -64,6 +65,11 @@
e);
} catch (CompilationError e) {
throw reporter.fatalError(e);
+ } catch (ResourceException e) {
+ throw reporter.fatalError(
+ e.getCause() instanceof IOException
+ ? new IOExceptionDiagnostic((IOException) e.getCause(), e.getOrigin())
+ : new StringDiagnostic(e.getMessage(), e.getOrigin()));
}
reporter.failIfPendingErrors();
} catch (AbortException e) {
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index a5c1b69..33fab08 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -836,6 +836,8 @@
// Contains an illegal invoke that R8 will fail to compile.
.put("594-invoke-super", TestCondition.match(
TestCondition.R8_COMPILER))
+ .put("974-verify-interface-super", TestCondition.match(
+ TestCondition.R8_COMPILER))
.build();
// Tests that are invalid dex files and on which R8/D8 fails and that is OK.
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index d4e699f..a6ab7e9 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1112,10 +1112,6 @@
return FileVisitResult.CONTINUE;
}
});
- File mapFile = new File(directory.toFile(), DEFAULT_PROGUARD_MAP_FILE);
- if (mapFile.exists()) {
- builder.setProguardMapFile(mapFile.toPath());
- }
return builder;
}
}
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 2ba52d6..182d3b0 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugInfoWhenInliningTest.java
@@ -27,16 +27,18 @@
Path outdir = temp.newFolder().toPath();
Path outjar = outdir.resolve("r8_compiled.jar");
Path proguardMapPath = writeProguardMap ? outdir.resolve("proguard.map") : null;
- ToolHelper.runR8(
+ R8Command.Builder builder =
R8Command.builder()
.addProgramFiles(DEBUGGEE_JAR)
.setMinApiLevel(minSdk)
.addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
.setMode(CompilationMode.RELEASE)
- .setOutput(outjar, OutputMode.DexIndexed)
- .setProguardMapOutput(proguardMapPath)
- .build(),
- options -> options.lineNumberOptimization = lineNumberOptimization);
+ .setOutput(outjar, OutputMode.DexIndexed);
+ if (proguardMapPath != null) {
+ builder.setProguardMapOutput(proguardMapPath);
+ }
+ ToolHelper.runR8(
+ builder.build(), options -> options.lineNumberOptimization = lineNumberOptimization);
DebugTestConfig config = new DexDebugTestConfig(outjar);
config.setProguardMap(proguardMapPath);
return config;
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 1d6d528..5243073 100644
--- a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
@@ -35,15 +35,18 @@
Path outdir = temp.newFolder().toPath();
Path outjar = outdir.resolve("r8_compiled.jar");
Path proguardMapPath = writeProguardMap ? outdir.resolve("proguard.map") : null;
- ToolHelper.runR8(
+ R8Command.Builder builder =
R8Command.builder()
.addProgramFiles(DEBUGGEE_JAR)
.setMinApiLevel(minSdk)
.addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(minSdk)))
.setMode(dontOptimizeByEnablingDebug ? CompilationMode.DEBUG : CompilationMode.RELEASE)
- .setOutput(outjar, OutputMode.DexIndexed)
- .setProguardMapOutput(proguardMapPath)
- .build(),
+ .setOutput(outjar, OutputMode.DexIndexed);
+ if (proguardMapPath != null) {
+ builder.setProguardMapOutput(proguardMapPath);
+ }
+ ToolHelper.runR8(
+ builder.build(),
options -> {
if (!dontOptimizeByEnablingDebug) {
options.lineNumberOptimization = lineNumberOptimization;
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java
index 9101a6e..bff846b 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java
@@ -15,10 +15,7 @@
@Test
public void fixedPoint() throws Exception {
// First compilation.
- AndroidApp app =
- ToolHelper.builderFromProgramDirectory(Paths.get(GMSCORE_V7_DIR))
- .setProguardMapFile(null)
- .build();
+ AndroidApp app = ToolHelper.builderFromProgramDirectory(Paths.get(GMSCORE_V7_DIR)).build();
AndroidApp app1 =
ToolHelper.runR8(
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
index 957ee0c..b350d5a 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.StringResource;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
@@ -19,6 +20,8 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -36,11 +39,19 @@
@Before
public void readGMSCore() throws IOException, ExecutionException {
- app = ToolHelper.builderFromProgramDirectory(Paths.get(APP_DIR)).build();
+ Path directory = Paths.get(APP_DIR);
+ app = ToolHelper.builderFromProgramDirectory(directory).build();
+ Path mapFile = directory.resolve(ToolHelper.DEFAULT_PROGUARD_MAP_FILE);
+ StringResource proguardMap = null;
+ if (Files.exists(mapFile)) {
+ proguardMap = StringResource.fromFile(mapFile);
+ }
ExecutorService executorService = Executors.newSingleThreadExecutor();
Timing timing = new Timing("ReadGMSCore");
- program = new ApplicationReader(app, new InternalOptions(), timing)
- .read(executorService).toDirect();
+ program =
+ new ApplicationReader(app, new InternalOptions(), timing)
+ .read(proguardMap, executorService)
+ .toDirect();
appInfo = new AppInfoWithSubtyping(program);
}
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
new file mode 100644
index 0000000..07e38e5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
@@ -0,0 +1,65 @@
+// Copyright (c) 2017, 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.ir.optimize;
+
+import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.ConstNumber;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.code.Return;
+import com.android.tools.r8.ir.code.Throw;
+import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.code.ValueNumberGenerator;
+import com.android.tools.r8.ir.code.ValueType;
+import com.google.common.collect.ImmutableList;
+import java.util.LinkedList;
+import org.junit.Test;
+
+public class TrivialGotoEliminationTest {
+ @Test
+ public void trivialGotoInEntryBlock() {
+ // Setup silly block structure:
+ //
+ // block0:
+ // goto block2
+ // block1:
+ // v0 = const-number 0
+ // throw v0
+ // block2:
+ // return
+ BasicBlock block2 = new BasicBlock();
+ block2.setNumber(2);
+ BasicBlock block0 = BasicBlock.createGotoBlock(0, block2);
+ block0.setFilledForTesting();
+ block2.getPredecessors().add(block0);
+ Instruction ret = new Return();
+ ret.setPosition(Position.none());
+ block2.add(ret);
+ block2.setFilledForTesting();
+ BasicBlock block1 = new BasicBlock();
+ block1.setNumber(1);
+ Value value = new Value(0, ValueType.INT, null);
+ Instruction number = new ConstNumber(value, 0);
+ number.setPosition(Position.none());
+ block1.add(number);
+ Instruction throwing = new Throw(value);
+ throwing.setPosition(Position.none());
+ block1.add(throwing);
+ block1.setFilledForTesting();
+ LinkedList<BasicBlock> blocks = new LinkedList();
+ blocks.add(block0);
+ blocks.add(block1);
+ blocks.add(block2);
+ // 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);
+ CodeRewriter.collapsTrivialGotos(null, code);
+ assert code.blocks.get(0).isTrivialGoto();
+ assert blocks.contains(block0);
+ assert blocks.contains(block1);
+ assert blocks.contains(block2);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index 6e48cfb..070b6da 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -10,7 +10,9 @@
import static org.junit.Assert.fail;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.R8Command;
+import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
@@ -64,17 +66,28 @@
Path flagForObfuscation =
Paths.get(ToolHelper.EXAMPLES_DIR, "naming044", "keep-rules-005.txt");
Path proguardMap = out.resolve(MAPPING);
- AndroidApp obfuscatedApp = runR8(
+ class ProguardMapConsumer implements StringConsumer {
+ String map;
+
+ @Override
+ public void accept(String string, DiagnosticsHandler handler) {
+ map = string;
+ }
+ }
+ ProguardMapConsumer mapConsumer = new ProguardMapConsumer();
+ runR8(
getCommandForApps(out, flagForObfuscation, NAMING044_JAR)
- .addProguardConfigurationConsumer(c -> {
- c.setPrintMapping(true);
- c.setPrintMappingFile(proguardMap);
- }).build());
+ .setProguardMapConsumer(mapConsumer)
+ .addProguardConfigurationConsumer(
+ c -> {
+ c.setPrintMapping(true);
+ c.setPrintMappingFile(proguardMap);
+ })
+ .build());
// Obviously, dumped map and resource inside the app should be *identical*.
ClassNameMapper mapperFromFile = ClassNameMapper.mapperFromFile(proguardMap);
- ClassNameMapper mapperFromApp =
- ClassNameMapper.mapperFromString(obfuscatedApp.getProguardMap().getString());
+ ClassNameMapper mapperFromApp = ClassNameMapper.mapperFromString(mapConsumer.map);
assertEquals(mapperFromFile, mapperFromApp);
Path instrOut = temp.newFolder("instr").toPath();
diff --git a/src/test/java/com/android/tools/r8/utils/DexInspector.java b/src/test/java/com/android/tools/r8/utils/DexInspector.java
index 2c7c683..56ba5a5 100644
--- a/src/test/java/com/android/tools/r8/utils/DexInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/DexInspector.java
@@ -75,8 +75,6 @@
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -108,7 +106,6 @@
public DexInspector(List<Path> files, String mappingFile)
throws IOException, ExecutionException {
- ExecutorService executor = Executors.newSingleThreadExecutor();
if (mappingFile != null) {
this.mapping = ClassNameMapper.mapperFromFile(Paths.get(mappingFile));
originalToObfuscatedMapping = this.mapping.getObfuscatedToOriginalMapping().inverse();
@@ -120,12 +117,13 @@
InternalOptions options = new InternalOptions();
dexItemFactory = options.itemFactory;
AndroidApp input = AndroidApp.builder().addProgramFiles(files).build();
- application = new ApplicationReader(input, options, timing).read(executor);
- executor.shutdown();
+ application = new ApplicationReader(input, options, timing).read();
}
public DexInspector(AndroidApp app) throws IOException, ExecutionException {
- this(new ApplicationReader(app, new InternalOptions(), new Timing("DexInspector")).read());
+ this(
+ new ApplicationReader(app, new InternalOptions(), new Timing("DexInspector"))
+ .read(app.getProguardMapOutputData()));
}
public DexInspector(DexApplication application) {