Merge "Delete field nextUnusedRegisterNumber"
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 5f27356..b5ec328 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -673,6 +673,13 @@
internal.outline.enabled = false;
}
+ // Setup a configuration consumer.
+ if (proguardConfiguration.isPrintConfiguration()) {
+ internal.configurationConsumer = proguardConfiguration.getPrintConfigurationFile() != null
+ ? new StringConsumer.FileConsumer(proguardConfiguration.getPrintConfigurationFile())
+ : new StringConsumer.StreamConsumer(StandardOutOrigin.instance(), System.out);
+ }
+
// Setup a usage information consumer.
if (proguardConfiguration.isPrintUsage()) {
internal.usageInformationConsumer = proguardConfiguration.getPrintUsageFile() != null
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index eb6718d..3639d9e 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "v1.2.7-dev";
+ public static final String LABEL = "v1.2.8-dev";
private Version() {
}
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 b413bfe..30664a2 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -260,6 +260,11 @@
String deadCode,
ProguardMapSupplier proguardMapSupplier,
String proguardSeedsData) {
+ if (options.configurationConsumer != null) {
+ ExceptionUtils.withConsumeResourceHandler(
+ options.reporter, options.configurationConsumer,
+ options.proguardConfiguration.getParsedConfiguration());
+ }
if (options.usageInformationConsumer != null && deadCode != null) {
ExceptionUtils.withConsumeResourceHandler(
options.reporter, options.usageInformationConsumer, deadCode);
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 2613aae..4adcf5a 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
@@ -13,6 +13,7 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.Deque;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
@@ -252,25 +253,44 @@
* no sorting.
*/
public ImmutableList<BasicBlock> topologicallySortedBlocks() {
- Set<BasicBlock> visitedBlock = new HashSet<>();
- ImmutableList.Builder<BasicBlock> builder = ImmutableList.builder();
- BasicBlock entryBlock = blocks.getFirst();
- depthFirstSorting(visitedBlock, entryBlock, builder);
- ImmutableList<BasicBlock> ordered = builder.build().reverse();
+ ImmutableList<BasicBlock> ordered = depthFirstSorting();
return options.testing.placeExceptionalBlocksLast
? reorderExceptionalBlocksLastForTesting(ordered)
: ordered;
}
- private void depthFirstSorting(Set<BasicBlock> visitedBlock, BasicBlock block,
- ImmutableList.Builder<BasicBlock> builder) {
- if (!visitedBlock.contains(block)) {
- visitedBlock.add(block);
- for (BasicBlock succ : block.getSuccessors()) {
- depthFirstSorting(visitedBlock, succ, builder);
+ private ImmutableList<BasicBlock> depthFirstSorting() {
+ // Stack marker to denote when all successors of a block have been processed.
+ class BlockMarker {
+ final BasicBlock block;
+ public BlockMarker(BasicBlock block) {
+ this.block = block;
}
- builder.add(block);
}
+ ArrayList<BasicBlock> reverseOrdered = new ArrayList<>(blocks.size());
+ Set<BasicBlock> visitedBlocks = new HashSet<>(blocks.size());
+ Deque<Object> worklist = new ArrayDeque<>(blocks.size());
+ worklist.addLast(blocks.getFirst());
+ while (!worklist.isEmpty()) {
+ Object item = worklist.removeLast();
+ if (item instanceof BlockMarker) {
+ reverseOrdered.add(((BlockMarker) item).block);
+ continue;
+ }
+ BasicBlock block = (BasicBlock) item;
+ if (!visitedBlocks.contains(block)) {
+ visitedBlocks.add(block);
+ worklist.addLast(new BlockMarker(block));
+ for (int i = block.getSuccessors().size() - 1; i >= 0; i--) {
+ worklist.addLast(block.getSuccessors().get(i));
+ }
+ }
+ }
+ ImmutableList.Builder<BasicBlock> builder = ImmutableList.builder();
+ for (int i = reverseOrdered.size() - 1; i >= 0; i--) {
+ builder.add(reverseOrdered.get(i));
+ }
+ return builder.build();
}
// Reorder the blocks forcing all exceptional blocks to be at the end.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java b/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java
index dd7767a..55037e0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MoveEliminator.java
@@ -20,14 +20,16 @@
public boolean shouldBeEliminated(Instruction instruction) {
if (instruction.isMove()) {
Move move = instruction.asMove();
- int moveSrcRegister = allocator.getRegisterForValue(move.src(), move.getNumber());
+ int moveSrcRegister =
+ allocator.getArgumentOrAllocateRegisterForValue(move.src(), move.getNumber());
int moveDstRegister = allocator.getRegisterForValue(move.dest(), move.getNumber());
if (moveSrcRegister == moveDstRegister) {
return true;
}
for (Move activeMove : activeMoves) {
int activeMoveSrcRegister =
- allocator.getRegisterForValue(activeMove.src(), activeMove.getNumber());
+ allocator.getArgumentOrAllocateRegisterForValue(
+ activeMove.src(), activeMove.getNumber());
int activeMoveDstRegister =
allocator.getRegisterForValue(activeMove.dest(), activeMove.getNumber());
if (activeMoveSrcRegister == moveSrcRegister && activeMoveDstRegister == moveDstRegister) {
@@ -47,19 +49,21 @@
if (instruction.outValue() != null && instruction.outValue().needsRegister()) {
Value defined = instruction.outValue();
int definedRegister = allocator.getRegisterForValue(defined, instruction.getNumber());
- activeMoves.removeIf((m) -> {
- int moveSrcRegister = allocator.getRegisterForValue(m.src(), m.getNumber());
- int moveDstRegister = allocator.getRegisterForValue(m.dest(), m.getNumber());
- for (int i = 0; i < defined.requiredRegisters(); i++) {
- for (int j = 0; j < m.outValue().requiredRegisters(); j++) {
- if (definedRegister + i == moveDstRegister + j
- || definedRegister + i == moveSrcRegister + j) {
- return true;
+ activeMoves.removeIf(
+ (m) -> {
+ int moveSrcRegister =
+ allocator.getArgumentOrAllocateRegisterForValue(m.src(), m.getNumber());
+ int moveDstRegister = allocator.getRegisterForValue(m.dest(), m.getNumber());
+ for (int i = 0; i < defined.requiredRegisters(); i++) {
+ for (int j = 0; j < m.outValue().requiredRegisters(); j++) {
+ if (definedRegister + i == moveDstRegister + j
+ || definedRegister + i == moveSrcRegister + j) {
+ return true;
+ }
+ }
}
- }
- }
- return false;
- });
+ return false;
+ });
}
if (instruction.isMove()) {
activeMoves.add(instruction.asMove());
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index b01a29a..89f9352 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -1666,13 +1666,10 @@
usePositions.set(getMoveExceptionRegister(), 0);
}
- // Treat active linked argument intervals as pinned. They cannot be given another register
- // at their uses.
- blockLinkedRegisters(active, unhandledInterval, registerConstraint, usePositions,
- blockedPositions);
-
- // Treat inactive linked argument intervals as pinned. They cannot be given another register
- // at their uses.
+ // Treat active and inactive linked argument intervals as pinned. They cannot be given another
+ // register at their uses.
+ blockLinkedRegisters(
+ active, unhandledInterval, registerConstraint, usePositions, blockedPositions);
blockLinkedRegisters(inactive, unhandledInterval, registerConstraint, usePositions,
blockedPositions);
@@ -1708,7 +1705,7 @@
}
int largestUsePosition = getLargestPosition(usePositions, candidate, needsRegisterPair);
- int blockedPosition = getBlockedPosition(blockedPositions, candidate, needsRegisterPair);
+ int blockedPosition = getLargestPosition(blockedPositions, candidate, needsRegisterPair);
if (largestUsePosition < unhandledInterval.getFirstUse()) {
// All active and inactive intervals are used before current. Therefore, it is best to spill
@@ -1731,26 +1728,13 @@
}
}
- private int getLargestPosition(RegisterPositions usePositions, int register,
- boolean needsRegisterPair) {
- int largestUsePosition = usePositions.get(register);
-
+ private int getLargestPosition(
+ RegisterPositions positions, int register, boolean needsRegisterPair) {
+ int position = positions.get(register);
if (needsRegisterPair) {
- largestUsePosition = Math.min(largestUsePosition, usePositions.get(register + 1));
+ return Math.min(position, positions.get(register + 1));
}
-
- return largestUsePosition;
- }
-
- private int getBlockedPosition(RegisterPositions blockedPositions, int register,
- boolean needsRegisterPair) {
- int blockedPosition = blockedPositions.get(register);
-
- if (needsRegisterPair) {
- blockedPosition = Math.min(blockedPosition, blockedPositions.get(register + 1));
- }
-
- return blockedPosition;
+ return position;
}
private void assignRegisterAndSpill(
@@ -2189,7 +2173,22 @@
if (options.isGeneratingDex()) {
int inConstraint = instruction.maxInValueRegister();
LiveIntervals useIntervals = use.getLiveIntervals();
- useIntervals.addUse(new LiveIntervalsUse(instruction.getNumber(), inConstraint));
+ // Arguments are always kept in their original, incoming register. For every
+ // unconstrained use of an argument we therefore use its incoming register.
+ // As a result, we do not need to record that the argument is being used at the
+ // current instruction.
+ //
+ // For ranged invoke instructions that use a subset of the arguments in the current
+ // order, registering a use for the arguments at the invoke can cause us to run out of
+ // registers. That is because all arguments are forced back into a chosen register at
+ // all uses. Therefore, if we register a use of an argument where we can actually use
+ // it in the argument register, the register allocator would use two registers for the
+ // argument but in reality only use one.
+ boolean isUnconstrainedArgumentUse =
+ use.isArgument() && inConstraint == Constants.U16BIT_MAX;
+ if (!isUnconstrainedArgumentUse) {
+ useIntervals.addUse(new LiveIntervalsUse(instruction.getNumber(), inConstraint));
+ }
}
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index c4a4478..48ea17d 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -20,6 +20,7 @@
public static class Builder {
+ private final List<String> parsedConfiguration = new ArrayList<>();
private final List<FilteredClassPath> injars = new ArrayList<>();
private final List<FilteredClassPath> libraryjars = new ArrayList<>();
private final Reporter reporter;
@@ -30,6 +31,8 @@
private boolean optimizing = true;
private boolean obfuscating = true;
private boolean shrinking = true;
+ private boolean printConfiguration;
+ private Path printConfigurationFile;
private boolean printUsage;
private Path printUsageFile;
private boolean printMapping;
@@ -51,6 +54,10 @@
private Origin keepParameterNamesOptionOrigin;
private Position keepParameterNamesOptionPosition;
private final ProguardClassFilter.Builder adaptClassStrings = ProguardClassFilter.builder();
+ private final ProguardPathFilter.Builder adaptResourceFilenames = ProguardPathFilter.builder();
+ private final ProguardPathFilter.Builder adaptResourceFilecontents =
+ ProguardPathFilter.builder();
+ private final ProguardPathFilter.Builder keepDirectories = ProguardPathFilter.builder();
private boolean forceProguardCompatibility = false;
private boolean overloadAggressively;
@@ -59,6 +66,10 @@
this.reporter = reporter;
}
+ public void addParsedConfiguration(String source) {
+ parsedConfiguration.add(source);
+ }
+
public void addInjars(List<FilteredClassPath> injars) {
this.injars.addAll(injars);
}
@@ -113,6 +124,15 @@
shrinking = false;
}
+ public void setPrintConfiguration(boolean printConfiguration) {
+ this.printConfiguration = printConfiguration;
+ }
+
+ public void setPrintConfigurationFile(Path file) {
+ assert printConfiguration;
+ this.printConfigurationFile = file;
+ }
+
public void setPrintUsage(boolean printUsage) {
this.printUsage = printUsage;
}
@@ -206,6 +226,18 @@
adaptClassStrings.addPattern(pattern);
}
+ public void addAdaptResourceFilenames(ProguardPathList pattern) {
+ adaptResourceFilenames.addPattern(pattern);
+ }
+
+ public void addAdaptResourceFilecontents(ProguardPathList pattern) {
+ adaptResourceFilecontents.addPattern(pattern);
+ }
+
+ public void addKeepDirectories(ProguardPathList pattern) {
+ keepDirectories.addPattern(pattern);
+ }
+
public void setForceProguardCompatibility(boolean forceProguardCompatibility) {
this.forceProguardCompatibility = forceProguardCompatibility;
}
@@ -217,6 +249,7 @@
public ProguardConfiguration buildRaw() {
ProguardConfiguration configuration = new ProguardConfiguration(
+ String.join(System.lineSeparator(), parsedConfiguration),
dexItemFactory,
injars,
libraryjars,
@@ -227,6 +260,8 @@
optimizing,
obfuscating,
shrinking,
+ printConfiguration,
+ printConfigurationFile,
printUsage,
printUsageFile,
printMapping,
@@ -245,7 +280,10 @@
DictionaryReader.readAllNames(packageObfuscationDictionary, reporter),
useUniqueClassMemberNames,
keepParameterNames,
- adaptClassStrings.build());
+ adaptClassStrings.build(),
+ adaptResourceFilenames.build(),
+ adaptResourceFilecontents.build(),
+ keepDirectories.build());
reporter.failIfPendingErrors();
@@ -279,6 +317,7 @@
}
}
+ private final String parsedConfiguration;
private final DexItemFactory dexItemFactory;
private final ImmutableList<FilteredClassPath> injars;
private final ImmutableList<FilteredClassPath> libraryjars;
@@ -289,6 +328,8 @@
private final boolean optimizing;
private final boolean obfuscating;
private final boolean shrinking;
+ private final boolean printConfiguration;
+ private final Path printConfigurationFile;
private final boolean printUsage;
private final Path printUsageFile;
private final boolean printMapping;
@@ -308,8 +349,12 @@
private final boolean useUniqueClassMemberNames;
private final boolean keepParameterNames;
private final ProguardClassFilter adaptClassStrings;
+ private final ProguardPathFilter adaptResourceFilenames;
+ private final ProguardPathFilter adaptResourceFilecontents;
+ private final ProguardPathFilter keepDirectories;
private ProguardConfiguration(
+ String parsedConfiguration,
DexItemFactory factory,
List<FilteredClassPath> injars,
List<FilteredClassPath> libraryjars,
@@ -320,6 +365,8 @@
boolean optimizing,
boolean obfuscating,
boolean shrinking,
+ boolean printConfiguration,
+ Path printConfigurationFile,
boolean printUsage,
Path printUsageFile,
boolean printMapping,
@@ -338,7 +385,11 @@
ImmutableList<String> packageObfuscationDictionary,
boolean useUniqueClassMemberNames,
boolean keepParameterNames,
- ProguardClassFilter adaptClassStrings) {
+ ProguardClassFilter adaptClassStrings,
+ ProguardPathFilter adaptResourceFilenames,
+ ProguardPathFilter adaptResourceFilecontents,
+ ProguardPathFilter keepDirectories) {
+ this.parsedConfiguration = parsedConfiguration;
this.dexItemFactory = factory;
this.injars = ImmutableList.copyOf(injars);
this.libraryjars = ImmutableList.copyOf(libraryjars);
@@ -349,6 +400,8 @@
this.optimizing = optimizing;
this.obfuscating = obfuscating;
this.shrinking = shrinking;
+ this.printConfiguration = printConfiguration;
+ this.printConfigurationFile = printConfigurationFile;
this.printUsage = printUsage;
this.printUsageFile = printUsageFile;
this.printMapping = printMapping;
@@ -368,6 +421,9 @@
this.useUniqueClassMemberNames = useUniqueClassMemberNames;
this.keepParameterNames = keepParameterNames;
this.adaptClassStrings = adaptClassStrings;
+ this.adaptResourceFilenames = adaptResourceFilenames;
+ this.adaptResourceFilecontents = adaptResourceFilecontents;
+ this.keepDirectories = keepDirectories;
}
/**
@@ -378,6 +434,10 @@
return new Builder(dexItemFactory, reporter);
}
+ public String getParsedConfiguration() {
+ return parsedConfiguration;
+ }
+
public DexItemFactory getDexItemFactory() {
return dexItemFactory;
}
@@ -434,6 +494,14 @@
return shrinking;
}
+ public boolean isPrintConfiguration() {
+ return printConfiguration;
+ }
+
+ public Path getPrintConfigurationFile() {
+ return printConfigurationFile;
+ }
+
public boolean isPrintUsage() {
return printUsage;
}
@@ -490,6 +558,18 @@
return adaptClassStrings;
}
+ public ProguardPathFilter getAdaptResourceFilenames() {
+ return adaptResourceFilenames;
+ }
+
+ public ProguardPathFilter getAdaptResourceFilecontents() {
+ return adaptResourceFilecontents;
+ }
+
+ public ProguardPathFilter getKeepDirectories() {
+ return keepDirectories;
+ }
+
public static ProguardConfiguration defaultConfiguration(DexItemFactory dexItemFactory,
Reporter reporter) {
return builder(dexItemFactory, reporter).build();
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index c1af9f4..dd7bb60 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -50,7 +50,6 @@
"target");
private static final List<String> IGNORED_OPTIONAL_SINGLE_ARG_OPTIONS = ImmutableList.of(
- "keepdirectories",
"runtype",
"laststageoutput");
@@ -70,11 +69,9 @@
"whyarenotsimple");
private static final List<String> WARNED_SINGLE_ARG_OPTIONS = ImmutableList.of(
- "printconfiguration",
// TODO -outjars (http://b/37137994) and -adaptresourcefilecontents (http://b/37139570)
// should be reported as errors, not just as warnings!
- "outjars",
- "adaptresourcefilecontents");
+ "outjars");
private static final List<String> WARNED_FLAG_OPTIONS = ImmutableList.of(
// TODO(b/73707846): add support -addconfigurationdebugging
@@ -165,6 +162,7 @@
private final String name;
private final String contents;
private int position = 0;
+ private int positionAfterInclude = 0;
private int line = 1;
private int lineStartPosition = 0;
private Path baseDirectory;
@@ -181,6 +179,9 @@
do {
skipWhitespace();
} while (parseOption());
+ // Collect the parsed configuration.
+ configurationBuilder.addParsedConfiguration(
+ contents.substring(positionAfterInclude, contents.length()));
}
private boolean parseOption()
@@ -214,6 +215,13 @@
} else if (acceptString("checkdiscard")) {
ProguardCheckDiscardRule rule = parseCheckDiscardRule();
configurationBuilder.addRule(rule);
+ } else if (acceptString("keepdirectories")) {
+ skipWhitespace();
+ if (isOptionalArgumentGiven()) {
+ configurationBuilder.addKeepDirectories(parsePathFilter());
+ } else {
+ configurationBuilder.addKeepDirectories(ProguardPathList.emptyList());
+ }
} else if (acceptString("keep")) {
ProguardKeepRule rule = parseKeepRule();
configurationBuilder.addRule(rule);
@@ -283,6 +291,12 @@
configurationBuilder.setOverloadAggressively(true);
} else if (acceptString("allowaccessmodification")) {
configurationBuilder.setAllowAccessModification(true);
+ } else if (acceptString("printconfiguration")) {
+ configurationBuilder.setPrintConfiguration(true);
+ skipWhitespace();
+ if (isOptionalArgumentGiven()) {
+ configurationBuilder.setPrintConfigurationFile(parseFileName());
+ }
} else if (acceptString("printmapping")) {
configurationBuilder.setPrintMapping(true);
skipWhitespace();
@@ -298,8 +312,12 @@
ProguardAssumeValuesRule rule = parseAssumeValuesRule();
configurationBuilder.addRule(rule);
} else if (acceptString("include")) {
+ // Collect the parsed configuration until the include.
+ configurationBuilder.addParsedConfiguration(
+ contents.substring(positionAfterInclude, position - ("include".length() + 1)));
skipWhitespace();
parseInclude();
+ positionAfterInclude = position;
} else if (acceptString("basedirectory")) {
skipWhitespace();
baseDirectory = parseFileName();
@@ -332,6 +350,20 @@
configurationBuilder.addAdaptClassStringsPattern(
ProguardClassNameList.singletonList(ProguardTypeMatcher.defaultAllMatcher()));
}
+ } else if (acceptString("adaptresourcefilenames")) {
+ skipWhitespace();
+ if (isOptionalArgumentGiven()) {
+ configurationBuilder.addAdaptResourceFilenames(parsePathFilter());
+ } else {
+ configurationBuilder.addAdaptResourceFilenames(ProguardPathList.emptyList());
+ }
+ } else if (acceptString("adaptresourcefilecontents")) {
+ skipWhitespace();
+ if (isOptionalArgumentGiven()) {
+ configurationBuilder.addAdaptResourceFilecontents(parsePathFilter());
+ } else {
+ configurationBuilder.addAdaptResourceFilecontents(ProguardPathList.emptyList());
+ }
} else if (acceptString("identifiernamestring")) {
configurationBuilder.addRule(parseIdentifierNameStringRule());
} else if (acceptString("if")) {
@@ -1279,6 +1311,34 @@
return name;
}
+ private boolean pathFilterMatcher(Integer character) {
+ return character != ',' && !Character.isWhitespace(character);
+ }
+
+ private ProguardPathList parsePathFilter() throws ProguardRuleParserException {
+ ProguardPathList.Builder builder = ProguardPathList.builder();
+ skipWhitespace();
+ boolean negated = acceptChar('!');
+ String fileFilter = acceptString(this::pathFilterMatcher);
+ if (fileFilter == null) {
+ throw parseError("Path filter expected");
+ }
+ builder.addFileName(negated, fileFilter);
+ skipWhitespace();
+ while (acceptChar(',')) {
+ skipWhitespace();
+ negated = acceptChar('!');
+ skipWhitespace();
+ fileFilter = acceptString(this::pathFilterMatcher);
+ if (fileFilter == null) {
+ throw parseError("Path filter expected");
+ }
+ builder.addFileName(negated, fileFilter);
+ skipWhitespace();
+ }
+ return builder.build();
+ }
+
private String snippetForPosition() {
// TODO(ager): really should deal with \r as well to get column right.
String[] lines = contents.split("\n", -1); // -1 to get trailing empty lines represented.
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardPathFilter.java b/src/main/java/com/android/tools/r8/shaking/ProguardPathFilter.java
new file mode 100644
index 0000000..cb2e117
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardPathFilter.java
@@ -0,0 +1,48 @@
+// 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.shaking;
+
+import com.google.common.collect.ImmutableList;
+
+public class ProguardPathFilter {
+ private final ImmutableList<ProguardPathList> patterns;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private final ImmutableList.Builder<ProguardPathList> patterns = ImmutableList.builder();
+
+ private Builder() {
+ }
+
+ public Builder addPattern(ProguardPathList pattern) {
+ patterns.add(pattern);
+ return this;
+ }
+
+ ProguardPathFilter build() {
+ return new ProguardPathFilter(patterns.build());
+ }
+ }
+
+ private ProguardPathFilter(ImmutableList<ProguardPathList> patterns) {
+ if (patterns.isEmpty()) {
+ this.patterns = ImmutableList.of(ProguardPathList.emptyList());
+ } else {
+ this.patterns = patterns;
+ }
+ }
+
+ public boolean matches(String path) {
+ for (ProguardPathList pattern : patterns) {
+ if (pattern.matches(path)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardPathList.java b/src/main/java/com/android/tools/r8/shaking/ProguardPathList.java
new file mode 100644
index 0000000..6766128
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardPathList.java
@@ -0,0 +1,128 @@
+// 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.shaking;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public abstract class ProguardPathList {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static ProguardPathList emptyList() {
+ return new EmptyPathList();
+ }
+
+ abstract boolean matches(String path);
+
+ public static class Builder {
+
+ private final ImmutableList.Builder<FileNameMatcher> matchers = ImmutableList.builder();
+
+ private Builder() {
+ }
+
+ public Builder addFileName(boolean isNegated, String path) {
+ matchers.add(new FileNameMatcher(isNegated, path));
+ return this;
+ }
+
+ ProguardPathList build() {
+ List<FileNameMatcher> matchers = this.matchers.build();
+ if (matchers. size() > 0) {
+ return new PathList(matchers);
+ } else {
+ return emptyList();
+ }
+ }
+ }
+
+ private static class FileNameMatcher {
+ public final boolean negated;
+ public final String pattern;
+
+ FileNameMatcher(boolean negated, String pattern) {
+ this.negated = negated;
+ this.pattern = pattern;
+ }
+
+ private boolean match(String path) {
+ return matchImpl(pattern, 0, path, 0);
+ }
+
+ private boolean matchImpl(String pattern, int patternIndex, String path, int pathIndex) {
+ for (int i = patternIndex; i < pattern.length(); i++) {
+ char patternChar = pattern.charAt(i);
+ switch (patternChar) {
+ case '*':
+ boolean includeSeparators = pattern.length() > (i + 1) && pattern.charAt(i + 1) == '*';
+ int nextPatternIndex = i + (includeSeparators ? 2 : 1);
+ // Fast cases for the common case where a pattern ends with '**' or '*'.
+ if (nextPatternIndex == pattern.length()) {
+ return includeSeparators || !containsSeparatorsStartingAt(path, pathIndex);
+ }
+ // Match the rest of the pattern against the (non-empty) rest of the class name.
+ for (int nextPathIndex = pathIndex; nextPathIndex < path.length(); nextPathIndex++) {
+ if (!includeSeparators && path.charAt(nextPathIndex) == '/') {
+ return matchImpl(pattern, nextPatternIndex, path, nextPathIndex);
+ }
+ if (matchImpl(pattern, nextPatternIndex, path, nextPathIndex)) {
+ return true;
+ }
+ }
+ break;
+ case '?':
+ if (pathIndex == path.length() || path.charAt(pathIndex++) == '/') {
+ return false;
+ }
+ break;
+ default:
+ if (pathIndex == path.length() || patternChar != path.charAt(pathIndex++)) {
+ return false;
+ }
+ break;
+ }
+ }
+ return pathIndex == path.length();
+ }
+
+ private boolean containsSeparatorsStartingAt(String path, int pathIndex) {
+ return path.indexOf('/', pathIndex) != -1;
+ }
+
+ }
+
+ private static class PathList extends ProguardPathList {
+ private final List<FileNameMatcher> matchers;
+
+ private PathList(List<FileNameMatcher> matchers) {
+ this.matchers = matchers;
+ }
+
+ @Override
+ boolean matches(String path) {
+ for (FileNameMatcher matcher : matchers) {
+ if (matcher.match(path)) {
+ // If we match a negation, abort as non-match. If we match a positive, return true.
+ return !matcher.negated;
+ }
+ }
+ return false;
+ }
+ }
+
+ private static class EmptyPathList extends ProguardPathList {
+
+ private EmptyPathList() {
+ }
+
+ @Override
+ boolean matches(String path) {
+ return true;
+ }
+ }
+}
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 42775d2..04c5f72 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -251,6 +251,10 @@
// If non-null, it must be and is passed to the consumer.
public StringConsumer usageInformationConsumer = null;
+ // If null, no configuration information needs to be printed.
+ // If non-null, configuration must be passed to the consumer.
+ public StringConsumer configurationConsumer = null;
+
public Path proguardCompatibilityRulesOutput = null;
public void warningMissingEnclosingMember(DexType clazz, Origin origin, int version) {
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index 5d7bec0..a89cbd4 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -373,6 +373,17 @@
}
@Test
+ public void printsConfigurationOnStdout() throws Throwable {
+ Path proguardPrintConfigurationConfiguration =
+ temp.newFile("printconfiguration.txt").toPath().toAbsolutePath();
+ FileUtils.writeTextFile(
+ proguardPrintConfigurationConfiguration, ImmutableList.of("-printconfiguration"));
+ ProcessResult result = runR8OnShaking1(proguardPrintConfigurationConfiguration);
+ assertEquals("R8 run failed: " + result.stderr, 0, result.exitCode);
+ assertTrue(result.stdout.contains("-printconfiguration"));
+ }
+
+ @Test
public void printsPrintSeedsOnStdout() throws Throwable {
Path proguardPrintSeedsConfiguration = temp.newFile("printseeds.txt").toPath().toAbsolutePath();
FileUtils.writeTextFile(proguardPrintSeedsConfiguration, ImmutableList.of("-printseeds"));
@@ -402,6 +413,21 @@
assertTrue(result.stdout.contains("shaking1.Unused"));
}
+ @Test
+ public void printsPrintSeedsAndPrintUsageAndPrintConfigurationOnStdout() throws Throwable {
+ Path proguardPrintSeedsConfiguration =
+ temp.newFile("printseedsandprintusageandprintconfiguration.txt").toPath().toAbsolutePath();
+ FileUtils.writeTextFile(proguardPrintSeedsConfiguration,
+ ImmutableList.of("-printseeds", "-printusage", "-printconfiguration"));
+ ProcessResult result = runR8OnShaking1(proguardPrintSeedsConfiguration);
+ assertEquals("R8 run failed: " + result.stderr, 0, result.exitCode);
+ assertTrue(result.stdout.contains("void main(java.lang.String[])"));
+ assertTrue(result.stdout.contains("shaking1.Unused"));
+ assertTrue(result.stdout.contains("-printseeds"));
+ assertTrue(result.stdout.contains("-printusage"));
+ assertTrue(result.stdout.contains("-printconfiguration"));
+ }
+
private R8Command parse(String... args) throws CompilationFailedException {
return R8Command.parse(args, EmbeddedOrigin.INSTANCE).build();
}
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java b/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
index 440f4f3..28a6fa3 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
@@ -16,7 +16,6 @@
import org.junit.Test;
public class B77240639 extends TestBase {
- @Ignore("b/77240639")
@Test
public void test() throws Exception {
AndroidApp app = compileWithD8(readClasses(TestClass.class));
diff --git a/src/test/java/com/android/tools/r8/shaking/PrintConfigurationTest.java b/src/test/java/com/android/tools/r8/shaking/PrintConfigurationTest.java
new file mode 100644
index 0000000..7621522
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/PrintConfigurationTest.java
@@ -0,0 +1,56 @@
+// 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.shaking;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.FileUtils;
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import org.junit.Test;
+
+class PrintConfigurationTestClass {
+
+ public static void main(String[] args) {
+
+ }
+}
+
+public class PrintConfigurationTest extends TestBase {
+ @Test
+ public void testSingleCOnfiguration() throws Exception {
+ Class mainClass = PrintConfigurationTestClass.class;
+ String proguardConfig = keepMainProguardConfiguration(mainClass);
+ Path printConfigurationFile = temp.newFile().toPath();
+ proguardConfig += "\n-printconfiguration " + printConfigurationFile.toString();
+ compileWithR8(ImmutableList.of(mainClass), proguardConfig);
+ assertEquals(proguardConfig, FileUtils.readTextFile(printConfigurationFile, Charsets.UTF_8));
+ }
+
+ @Test
+ public void testIncludeFile() throws Exception {
+ Class mainClass = PrintConfigurationTestClass.class;
+ String includeProguardConfig = keepMainProguardConfiguration(mainClass);
+ Path includeFile = temp.newFile().toPath();
+ FileUtils.writeTextFile(includeFile, includeProguardConfig);
+ Path printConfigurationFile = temp.newFile().toPath();
+ String proguardConfig = String.join(System.lineSeparator(), ImmutableList.of(
+ "-include " + includeFile.toString(),
+ "-printconfiguration " + printConfigurationFile.toString()
+ ));
+
+ String expected = String.join(System.lineSeparator(), ImmutableList.of(
+ "", // The -include line turns into an empty line.
+ includeProguardConfig,
+ "", // Writing to the file adds an ending line separator
+ "", // An empty line is emitted between two parts
+ "-printconfiguration " + printConfigurationFile.toString()
+ ));
+ compileWithR8(ImmutableList.of(mainClass), proguardConfig);
+ assertEquals(expected, FileUtils.readTextFile(printConfigurationFile, Charsets.UTF_8));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 5dc4ec6..9e9f80e 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -26,6 +26,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.position.TextRange;
@@ -157,11 +158,13 @@
private Reporter reporter;
private KeepingDiagnosticHandler handler;
+ private ProguardConfigurationParser parser;
@Before
- public void setup() {
+ public void reset() {
handler = new KeepingDiagnosticHandler();
reporter = new Reporter(handler);
+ parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
}
@Test
@@ -944,6 +947,32 @@
}
@Test
+ public void parse_printconfiguration_noArguments() throws Exception {
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(createConfigurationForTesting(ImmutableList.of(
+ "-printconfiguration"
+ )));
+ verifyParserEndsCleanly();
+ ProguardConfiguration config = parser.getConfig();
+ assertTrue(config.isPrintConfiguration());
+ assertNull(config.getPrintConfigurationFile());
+ }
+
+ @Test
+ public void parse_printconfiguration_argument() throws Exception {
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(createConfigurationForTesting(ImmutableList.of(
+ "-printconfiguration file_name"
+ )));
+ verifyParserEndsCleanly();
+ ProguardConfiguration config = parser.getConfig();
+ assertTrue(config.isPrintConfiguration());
+ assertEquals("." + File.separator + "file_name", config.getPrintConfigurationFile().toString());
+ }
+
+ @Test
public void parsePrintUsage() throws Exception {
ProguardConfigurationParser parser =
new ProguardConfigurationParser(new DexItemFactory(), reporter);
@@ -1149,6 +1178,146 @@
}
}
+ private void checkFileFilterMatchAnything(ProguardPathFilter filter) {
+ assertTrue(filter.matches("x"));
+ assertTrue(filter.matches("x/y"));
+ assertTrue(filter.matches("x/y/x"));
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_noArguments1() {
+ ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
+ "-adaptresourcefilenames",
+ "-adaptresourcefilecontents",
+ "-keepdirectories"
+ ));
+ checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
+ checkFileFilterMatchAnything(config.getAdaptResourceFilecontents());
+ checkFileFilterMatchAnything(config.getKeepDirectories());
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_noArguments2() {
+ ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
+ "-keepdirectories",
+ "-adaptresourcefilenames",
+ "-adaptresourcefilecontents"
+ ));
+ checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
+ checkFileFilterMatchAnything(config.getAdaptResourceFilecontents());
+ checkFileFilterMatchAnything(config.getKeepDirectories());
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_noArguments3() {
+ ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
+ "-adaptresourcefilecontents",
+ "-keepdirectories",
+ "-adaptresourcefilenames"
+ ));
+ checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
+ checkFileFilterMatchAnything(config.getAdaptResourceFilecontents());
+ checkFileFilterMatchAnything(config.getKeepDirectories());
+ }
+
+ private String FILE_FILTER_SINGLE = "xxx/*";
+
+ private void checkFileFilterSingle(ProguardPathFilter filter) {
+ assertTrue(filter.matches("xxx/x"));
+ assertTrue(filter.matches("xxx/"));
+ assertFalse(filter.matches("xxx/yyy/z"));
+ assertFalse(filter.matches("xxx"));
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_singleArgument() {
+ ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
+ "-adaptresourcefilenames " + FILE_FILTER_SINGLE,
+ "-adaptresourcefilecontents " + FILE_FILTER_SINGLE,
+ "-keepdirectories " + FILE_FILTER_SINGLE
+ ));
+ checkFileFilterSingle(config.getAdaptResourceFilenames());
+ checkFileFilterSingle(config.getAdaptResourceFilecontents());
+ checkFileFilterSingle(config.getKeepDirectories());
+ }
+
+ private String FILE_FILTER_MULTIPLE =
+ "xxx/*, !**.gif ,images/** , com/myapp/**/*.xml,com/mylib/*/*.xml";
+
+ private void checkFileFilterMultiple(ProguardPathFilter filter) {
+ assertTrue(filter.matches("xxx/x"));
+ assertTrue(filter.matches("xxx/x.gif"));
+ assertTrue(filter.matches("images/x.jpg"));
+ assertTrue(filter.matches("images/xxx/x.jpg"));
+ assertTrue(filter.matches("com/myapp/package1/x.xml"));
+ assertTrue(filter.matches("com/myapp/package1/package2/x.xml"));
+ assertTrue(filter.matches("com/mylib/package1/x.xml"));
+ assertFalse(filter.matches("x.gif"));
+ assertFalse(filter.matches("images/x.gif"));
+ assertFalse(filter.matches("images/xxx/y.gif"));
+ assertFalse(filter.matches("images/xxx/yyy/z.gif"));
+ assertFalse(filter.matches("com/myapp/package1/x.jpg"));
+ assertFalse(filter.matches("com/myapp/package1/package2/x.jpg"));
+ assertFalse(filter.matches("com/mylib/package1/package2/x.xml"));
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_multipleArgument() {
+ ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
+ "-adaptresourcefilenames " + FILE_FILTER_MULTIPLE,
+ "-adaptresourcefilecontents " + FILE_FILTER_MULTIPLE,
+ "-keepdirectories " + FILE_FILTER_MULTIPLE
+ ));
+ checkFileFilterMultiple(config.getAdaptResourceFilenames());
+ checkFileFilterMultiple(config.getAdaptResourceFilecontents());
+ checkFileFilterMultiple(config.getKeepDirectories());
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_leadingComma() {
+ List<String> options = ImmutableList.of(
+ "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
+ for (String option : options) {
+ try {
+ reset();
+ parser.parse(createConfigurationForTesting(ImmutableList.of(option + " ,")));
+ fail("Expect to fail due to the lack of path filter.");
+ } catch (AbortException e) {
+ checkDiagnostic(handler.errors, null, 1, option.length() + 2, "Path filter expected");
+ }
+ }
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_emptyListElement() {
+ List<String> options = ImmutableList.of(
+ "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
+ for (String option : options) {
+ try {
+ reset();
+ parser.parse(createConfigurationForTesting(ImmutableList.of(option + " xxx,,yyy")));
+ fail("Expect to fail due to the lack of path filter.");
+ } catch (AbortException e) {
+ checkDiagnostic(handler.errors, null, 1, option.length() + 6, "Path filter expected");
+ }
+ }
+ }
+
+ @Test
+ public void parse_adaptresourcexxx_keepdirectories_trailingComma() {
+ List<String> options = ImmutableList.of(
+ "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
+ for (String option : options) {
+ try {
+ reset();
+ parser.parse(createConfigurationForTesting(ImmutableList.of(option + " xxx,")));
+ fail("Expect to fail due to the lack of path filter.");
+ } catch (AbortException e) {
+ checkDiagnostic(handler.errors, null, 1, option.length() + 6, "Path filter expected");
+ }
+ }
+ }
+
@Test
public void parse_if() throws Exception {
Path proguardConfig = writeTextToTempFile(
@@ -1433,6 +1602,12 @@
verifyWithProguard(proguardConfig);
}
+ private ProguardConfiguration parseAndVerifyParserEndsCleanly(List<String> config) {
+ parser.parse(createConfigurationForTesting(config));
+ verifyParserEndsCleanly();
+ return parser.getConfig();
+ }
+
private void verifyParserEndsCleanly() {
assertEquals(0, handler.infos.size());
assertEquals(0, handler.warnings.size());
@@ -1443,7 +1618,11 @@
int columnStart, String... messageParts) {
assertEquals(1, diagnostics.size());
Diagnostic diagnostic = diagnostics.get(0);
- assertEquals(path, ((PathOrigin) diagnostic.getOrigin()).getPath());
+ if (path != null) {
+ assertEquals(path, ((PathOrigin) diagnostic.getOrigin()).getPath());
+ } else {
+ assertSame(Origin.unknown(), diagnostic.getOrigin());
+ }
TextPosition position;
if (diagnostic.getPosition() instanceof TextRange) {
position = ((TextRange) diagnostic.getPosition()).getStart();
diff --git a/tools/test_gradle_benchmarks.py b/tools/test_gradle_benchmarks.py
index 6720c4a..189b9da 100755
--- a/tools/test_gradle_benchmarks.py
+++ b/tools/test_gradle_benchmarks.py
@@ -3,7 +3,6 @@
# 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.
-
from __future__ import print_function
import argparse
import os
@@ -12,7 +11,6 @@
import gradle
from enum import Enum
-
BENCHMARKS_ROOT_DIR = os.path.join(utils.REPO_ROOT, 'third_party', 'benchmarks')
def parse_arguments():
@@ -24,9 +22,10 @@
choices=['dx', 'd8'],
required=True,
help='Compiler tool to use.')
+ parser.add_argument('--benchmark',
+ help='Which benchmark to run, default all')
return parser.parse_args()
-
class Benchmark:
class Tools(Enum):
D8 = 1
@@ -88,7 +87,6 @@
def EnsurePresence(self):
EnsurePresence(self.rootDirPath, self.displayName)
-
def EnsurePresence(dir, displayName):
if not os.path.exists(dir) or os.path.getmtime(dir + '.tar.gz')\
< os.path.getmtime(dir + '.tar.gz.sha1'):
@@ -111,7 +109,6 @@
return any(namePattern in taskname for namePattern in acceptedGradleTasks)
-
def PrintBuildTimeForGolem(benchmark, stdOut):
for line in stdOut.splitlines():
if 'BENCH' in line and benchmark.moduleName in line:
@@ -138,7 +135,6 @@
print('{}(RunTimeRaw): {} ms'
.format(benchmark.displayName + '-' + taskName, commaSplit[2]))
-
def Main():
args = parse_arguments()
@@ -191,10 +187,16 @@
]
- EnsurePresence(os.path.join('third_party', 'benchmarks', 'android-sdk'), 'android SDK')
- EnsurePresence(os.path.join('third_party', 'gradle-plugin'), 'Android Gradle plugin')
-
- for benchmark in buildTimeBenchmarks:
+ EnsurePresence(os.path.join('third_party', 'benchmarks', 'android-sdk'),
+ 'android SDK')
+ EnsurePresence(os.path.join('third_party', 'gradle-plugin'),
+ 'Android Gradle plugin')
+ toRun = buildTimeBenchmarks
+ if args.benchmark:
+ toRun = [b for b in toRun if b.displayName == args.benchmark]
+ if len(toRun) != 1:
+ raise AssertionError("Unknown benchmark: " + args.benchmark)
+ for benchmark in toRun:
benchmark.EnsurePresence()
benchmark.Clean()
stdOut = benchmark.Build(tool, desugarMode)