Only parse mapping file once for all resources
Change-Id: I2b8f853ddd67f4aa9a636f4e6e1b08822ff6dce9
diff --git a/src/main/java/com/android/tools/r8/Disassemble.java b/src/main/java/com/android/tools/r8/Disassemble.java
index 8c66ba5..1e1fffb 100644
--- a/src/main/java/com/android/tools/r8/Disassemble.java
+++ b/src/main/java/com/android/tools/r8/Disassemble.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.CommandLineOrigin;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
@@ -28,6 +29,7 @@
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import java.util.function.Consumer;
public class Disassemble {
@@ -245,9 +247,11 @@
throws IOException, ExecutionException {
AndroidApp app = command.getInputApp();
InternalOptions options = command.getInternalOptions();
+ Box<Future<ClassNameMapper>> readMapFuture = new Box<>();
try (OutputWriter outputWriter = getOutputWriter(command)) {
for (ProgramResource computeAllProgramResource : app.computeAllProgramResources()) {
- disassembleResource(command, outputWriter, computeAllProgramResource, options);
+ disassembleResource(
+ command, outputWriter, computeAllProgramResource, readMapFuture, options);
}
} catch (Exception e) {
throw new RuntimeException(e);
@@ -270,6 +274,7 @@
DisassembleCommand command,
OutputWriter outputWriter,
ProgramResource programResource,
+ Box<Future<ClassNameMapper>> readMapFuture,
InternalOptions options)
throws IOException {
ExecutorService executor = ThreadUtils.getExecutorService(options);
@@ -280,7 +285,8 @@
.addProgramResourceProvider(() -> Collections.singletonList(programResource))
.build(),
options,
- Timing.empty())
+ Timing.empty(),
+ readMapFuture)
.read(command.proguardMap, executor);
DexByteCodeWriter writer =
command.useSmali()
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 10acb93..f2d4053 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.graph.ClassKind.LIBRARY;
import static com.android.tools.r8.graph.ClassKind.PROGRAM;
import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException;
+import static com.android.tools.r8.utils.ExceptionUtils.unwrapInterruptedException;
import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.DataResourceProvider;
@@ -38,6 +39,7 @@
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ClassProvider;
import com.android.tools.r8.utils.ClasspathClassCollection;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -55,6 +57,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Queue;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -68,6 +71,7 @@
private final DexItemFactory itemFactory;
private final Timing timing;
private final AndroidApp inputApp;
+ private final Box<Future<ClassNameMapper>> readMap;
private DexApplicationReadFlags flags;
@@ -76,10 +80,19 @@
}
public ApplicationReader(AndroidApp inputApp, InternalOptions options, Timing timing) {
+ this(inputApp, options, timing, new Box<>());
+ }
+
+ public ApplicationReader(
+ AndroidApp inputApp,
+ InternalOptions options,
+ Timing timing,
+ Box<Future<ClassNameMapper>> readMap) {
this.options = options;
itemFactory = options.itemFactory;
this.timing = timing;
this.inputApp = inputApp;
+ this.readMap = readMap;
}
public LazyLoadedDexApplication read() throws IOException {
@@ -136,10 +149,14 @@
// (b) some of the class file resources don't provide information
// about class descriptor.
// TODO: try and preload less classes.
- readProguardMap(proguardMap, builder, executorService, futures);
+ readProguardMap(proguardMap, executorService);
ClassReader classReader = new ClassReader(executorService, futures);
classReader.readSources();
ThreadUtils.awaitFutures(futures);
+ ClassNameMapper mapper = readMap.get().get();
+ if (mapper != null) {
+ builder.setProguardMap(mapper);
+ }
flags = classReader.getDexApplicationReadFlags();
builder.setFlags(flags);
classReader.initializeLazyClassCollection(builder);
@@ -149,6 +166,8 @@
builder.addDataResourceProvider(dataResourceProvider);
}
}
+ } catch (InterruptedException e) {
+ throw unwrapInterruptedException(e);
} catch (ExecutionException e) {
throw unwrapExecutionException(e);
} catch (ResourceException e) {
@@ -265,31 +284,34 @@
+ "'.");
}
- private void readProguardMap(
- StringResource map,
- DexApplication.Builder<?> builder,
- ExecutorService executorService,
- List<Future<?>> futures) {
+ private void readProguardMap(StringResource map, ExecutorService executorService) {
// Read the Proguard mapping file in parallel with DexCode and DexProgramClass items.
- if (map == null) {
- return;
- }
- futures.add(
- executorService.submit(
- () -> {
- try {
- String content = map.getString();
- builder.setProguardMap(
- ClassNameMapper.mapperFromString(
- content,
+ if (!readMap.isSet()) {
+ synchronized (readMap) {
+ if (readMap.isSet()) {
+ return;
+ }
+ if (map == null) {
+ readMap.set(CompletableFuture.completedFuture(null));
+ return;
+ }
+ readMap.set(
+ executorService.submit(
+ () -> {
+ try {
+ return ClassNameMapper.mapperFromString(
+ map.getString(),
options.reporter,
false,
options.testing.enableExperimentalMapFileVersion,
- false));
- } catch (IOException | ResourceException e) {
- throw new CompilationError("Failure to read proguard map file", e, map.getOrigin());
- }
- }));
+ false);
+ } catch (IOException | ResourceException e) {
+ throw new CompilationError(
+ "Failure to read proguard map file", e, map.getOrigin());
+ }
+ }));
+ }
+ }
}
private final class ClassReader {
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 ef5c3ca..8cb08c0 100644
--- a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
@@ -221,6 +221,11 @@
return new RuntimeException(executionException);
}
+ public static RuntimeException unwrapInterruptedException(
+ InterruptedException interruptedException) {
+ return new RuntimeException(interruptedException);
+ }
+
public static void withOriginAttachmentHandler(Origin origin, Runnable action) {
withOriginAndPositionAttachmentHandler(origin, Position.UNKNOWN, action);
}