Merge "Implement -alwaysinline directive."
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index a6da2ec..575b09f 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -55,6 +55,7 @@
*/
public final class D8 {
+ private static final String kVersion = "v0.0.1";
private static final int STATUS_ERROR = 1;
private D8() {}
@@ -109,7 +110,7 @@
return;
}
if (command.isPrintVersion()) {
- System.out.println("D8 v0.0.1");
+ System.out.println("D8 " + kVersion);
return;
}
run(command);
@@ -159,7 +160,9 @@
if (options.customizedMarker != null) {
return options.customizedMarker;
}
- return new Marker(Tool.D8);
+ return new Marker(Tool.D8)
+ .put("version", kVersion)
+ .put("min-api", options.minApiLevel);
}
private static CompilationResult runForTesting(
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 4393a3e..620faf8 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -71,6 +71,7 @@
public class R8 {
+ private static final String kVersion = "v0.0.1";
private final Timing timing = new Timing("R8");
private final InternalOptions options;
@@ -84,7 +85,9 @@
if (options.customizedMarker != null) {
return options.customizedMarker;
}
- return new Marker(Tool.R8);
+ return new Marker(Tool.R8)
+ .put("version", kVersion)
+ .put("min-api", options.minApiLevel);
}
public static AndroidApp writeApplication(
@@ -497,7 +500,7 @@
return;
}
if (command.isPrintVersion()) {
- System.out.println("R8 v0.0.1");
+ System.out.println("R8 " + kVersion);
return;
}
run(command);
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index e6ec968..1e2e2c9 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -156,8 +156,7 @@
distributor =
new VirtualFile.PackageMapDistributor(this, packageDistribution, executorService);
} else {
- boolean minimal = options.minimalMainDex && !application.mainDexList.isEmpty();
- distributor = new VirtualFile.FillFilesDistributor(this, minimal);
+ distributor = new VirtualFile.FillFilesDistributor(this, options.minimalMainDex);
}
Map<Integer, VirtualFile> newFiles = distributor.run();
@@ -167,6 +166,7 @@
for (int i = 0; i < newFiles.size(); i++) {
VirtualFile newFile = newFiles.get(i);
assert newFile.getId() == i;
+ assert !newFile.isEmpty();
if (!newFile.isEmpty()) {
dexDataFutures.put(newFile, executorService.submit(() -> writeDexFile(newFile)));
}
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index 9391af9..f06aa45 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -57,9 +57,6 @@
// The fill strategy determine how to distribute classes into dex files.
enum FillStrategy {
- // Only put classes matches by the main dex rules into the first dex file. Distribute remaining
- // classes in additional dex files filling each dex file as much as possible.
- MINIMAL_MAIN_DEX,
// Distribute classes in as few dex files as possible filling each dex file as much as possible.
FILL_MAX,
// Distribute classes keeping some space for future growth. This is mainly useful together with
@@ -114,7 +111,8 @@
if (!next.startsWith(prefix)) {
throw new RuntimeException("Input filenames lack common prefix.");
}
- String numberPart = next.substring(prefix.length(), next.length() - FileUtils.DEX_EXTENSION.length());
+ String numberPart =
+ next.substring(prefix.length(), next.length() - FileUtils.DEX_EXTENSION.length());
if (Integer.parseInt(numberPart) != index++) {
throw new RuntimeException("DEX files are not numbered consecutively.");
}
@@ -233,6 +231,11 @@
for (DexProgramClass clazz : application.classes()) {
VirtualFile file = new VirtualFile(nameToFileMap.size(), writer.namingLens);
nameToFileMap.put(nameToFileMap.size(), file);
+ // Write the marker string to all files in files-per-class mode.
+ // TODO(sgjesse): Get rid of this (currently some tests fails without it).
+ if (writer.markerString != null) {
+ file.transaction.addString(writer.markerString);
+ }
file.addClass(clazz);
file.commitTransaction();
}
@@ -243,16 +246,25 @@
public abstract static class DistributorBase extends Distributor {
protected Set<DexProgramClass> classes;
protected Map<DexProgramClass, String> originalNames;
+ protected final VirtualFile mainDexFile;
DistributorBase(ApplicationWriter writer) {
super(writer);
+ // Create the primary dex file. The distribution will add more if needed.
+ mainDexFile = new VirtualFile(0, writer.namingLens);
+ nameToFileMap.put(0, mainDexFile);
+ if (writer.markerString != null) {
+ mainDexFile.transaction.addString(writer.markerString);
+ mainDexFile.commitTransaction();
+ }
+
classes = Sets.newHashSet(application.classes());
originalNames = computeOriginalNameMapping(classes, application.getProguardMap());
}
protected void fillForMainDexList(Set<DexProgramClass> classes) {
- if (application.mainDexList != null) {
+ if (!application.mainDexList.isEmpty()) {
VirtualFile mainDexFile = nameToFileMap.get(0);
for (DexType type : application.mainDexList) {
DexClass clazz = application.definitionFor(type);
@@ -306,34 +318,38 @@
}
public static class FillFilesDistributor extends DistributorBase {
+ boolean minimalMainDex;
private final FillStrategy fillStrategy;
FillFilesDistributor(ApplicationWriter writer, boolean minimalMainDex) {
super(writer);
- this.fillStrategy = minimalMainDex ? FillStrategy.MINIMAL_MAIN_DEX : FillStrategy.FILL_MAX;
+ this.minimalMainDex = minimalMainDex;
+ this.fillStrategy = FillStrategy.FILL_MAX;
}
public Map<Integer, VirtualFile> run() throws ExecutionException, IOException {
- // Strategy for distributing classes for write out:
- // 1. Place the remaining files based on their packages in sorted order.
-
- // Start with 1 file. The package populator will add more if needed.
- VirtualFile main = new VirtualFile(0, writer.namingLens);
- nameToFileMap.put(0, main);
- if (writer.markerString != null) {
- main.transaction.addString(writer.markerString);
- main.commitTransaction();
- }
-
// First fill required classes into the main dex file.
fillForMainDexList(classes);
+ if (classes.isEmpty()) {
+ // All classes ended up in the main dex file, no more to do.
+ return nameToFileMap;
+ }
+
+ Map<Integer, VirtualFile> filesForDistribution = nameToFileMap;
+ if (minimalMainDex && !mainDexFile.isEmpty()) {
+ assert !nameToFileMap.get(0).isEmpty();
+ // The main dex file is filtered out, so create ensure at least one file for the remaining
+ // classes
+ nameToFileMap.put(1, new VirtualFile(1, writer.namingLens));
+ filesForDistribution = Maps.filterKeys(filesForDistribution, key -> key != 0);
+ }
// Sort the remaining classes based on the original names.
// This with make classes from the same package be adjacent.
classes = sortClassesByPackage(classes, originalNames);
new PackageSplitPopulator(
- nameToFileMap, classes, originalNames, null, application.dexItemFactory,
+ filesForDistribution, classes, originalNames, null, application.dexItemFactory,
fillStrategy, writer.namingLens)
.call();
return nameToFileMap;
@@ -347,13 +363,7 @@
@Override
public Map<Integer, VirtualFile> run() throws ExecutionException, IOException {
- VirtualFile mainDexFile = new VirtualFile(0, writer.namingLens);
- nameToFileMap.put(0, mainDexFile);
- if (writer.markerString != null) {
- mainDexFile.transaction.addString(writer.markerString);
- mainDexFile.commitTransaction();
- }
-
+ // Add all classes to the main dex file.
for (DexProgramClass programClass : classes) {
mainDexFile.addClass(programClass);
}
@@ -381,8 +391,10 @@
// 1. Place all files in the package distribution file in the proposed files (if any).
// 2. Place the remaining files based on their packages in sorted order.
+ assert nameToFileMap.size() == 1;
+ assert nameToFileMap.containsKey(0);
int maxReferencedIndex = packageDistribution.maxReferencedIndex();
- for (int index = 0; index <= maxReferencedIndex; index++) {
+ for (int index = 1; index <= maxReferencedIndex; index++) {
VirtualFile file = new VirtualFile(index, writer.namingLens);
nameToFileMap.put(index, file);
}
@@ -791,14 +803,7 @@
this.namingLens = namingLens;
this.fillStrategy = fillStrategy;
- nextFileId = files.size();
- if (fillStrategy == FillStrategy.MINIMAL_MAIN_DEX) {
- // The main dex file is filtered out, so ensure at least one file for the remaining
- // classes
- files.put(nextFileId, new VirtualFile(nextFileId, namingLens));
- this.files = Maps.filterKeys(files, key -> key != 0);
- nextFileId++;
- }
+ nextFileId = Collections.max(files.keySet()) + 1;
reset();
}
@@ -814,7 +819,6 @@
VirtualFile next() {
VirtualFile next = activeFiles.next();
- assert fillStrategy != FillStrategy.MINIMAL_MAIN_DEX || next.getId() != 0;
return next;
}