Merge "Replace clinit static puts with initial values for static fields"
diff --git a/build.gradle b/build.gradle
index e2c21b6..722106c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,11 +6,15 @@
apply plugin: 'java'
apply plugin: 'idea'
-apply plugin: 'jacoco'
apply plugin: 'com.google.protobuf'
apply from: 'copyAdditionalJctfCommonFiles.gradle'
+
+if (project.hasProperty('with_code_coverage')) {
+ apply plugin: 'jacoco'
+}
+
repositories {
maven { url 'https://maven.google.com' }
mavenCentral()
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 2f5fb79..4c8cdd5 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -172,7 +172,6 @@
// Disable global optimizations.
options.skipMinification = true;
- options.allowAccessModification = false;
options.inlineAccessors = false;
options.outline.enabled = false;
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 2937205..64a1a0e 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -215,8 +215,6 @@
internal.useTreeShaking = false;
assert internal.interfaceMethodDesugaring == OffOrAuto.Off;
assert internal.tryWithResourcesDesugaring == OffOrAuto.Off;
- assert internal.allowAccessModification;
- internal.allowAccessModification = false;
assert internal.inlineAccessors;
internal.inlineAccessors = false;
assert internal.removeSwitchMaps;
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 84bcee7..acbbe0a 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -244,7 +244,8 @@
timing.begin("Strip unused code");
try {
Set<DexType> missingClasses = appInfo.getMissingClasses();
- missingClasses = filterMissingClasses(missingClasses, options.dontWarnPatterns);
+ missingClasses = filterMissingClasses(
+ missingClasses, options.proguardConfiguration.getDontWarnPatterns());
if (!missingClasses.isEmpty()) {
System.err.println();
System.err.println("WARNING, some classes are missing:");
@@ -256,11 +257,12 @@
"Shrinking can't be performed because some library classes are missing.");
}
}
- rootSet = new RootSetBuilder(application, appInfo, options.keepRules).run(executorService);
+ rootSet = new RootSetBuilder(application, appInfo, options.proguardConfiguration.getRules())
+ .run(executorService);
Enqueuer enqueuer = new Enqueuer(appInfo);
enqueuer.addExtension(new ProtoLiteExtension(appInfo));
appInfo = enqueuer.traceApplication(rootSet, timing);
- if (options.printSeeds) {
+ if (options.proguardConfiguration.isPrintSeeds()) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bytes);
RootSetBuilder.writeSeeds(appInfo.withLiveness().pinnedItems, out);
@@ -278,7 +280,7 @@
timing.end();
}
- if (options.allowAccessModification) {
+ if (options.proguardConfiguration.isAccessModificationAllowed()) {
ClassAndMemberPublicizer.run(application);
// We can now remove visibility bridges. Note that we do not need to update the
// invoke-targets here, as the existing invokes will simply dispatch to the now
@@ -424,23 +426,23 @@
outputApp.write(command.getOutputPath(), options.outputMode);
}
- if (options.printMapping && !options.skipMinification) {
+ if (options.proguardConfiguration.isPrintMapping() && !options.skipMinification) {
assert outputApp.hasProguardMap();
try (Closer closer = Closer.create()) {
OutputStream mapOut = FileUtils.openPathWithDefault(
closer,
- options.printMappingFile,
+ options.proguardConfiguration.getPrintMappingFile(),
System.out,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
outputApp.writeProguardMap(closer, mapOut);
}
}
- if (options.printSeeds) {
+ if (options.proguardConfiguration.isPrintSeeds()) {
assert outputApp.hasProguardSeeds();
try (Closer closer = Closer.create()) {
OutputStream seedsOut = FileUtils.openPathWithDefault(
closer,
- options.seedsFile,
+ options.proguardConfiguration.getSeedFile(),
System.out,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
outputApp.writeProguardSeeds(closer, seedsOut);
@@ -457,11 +459,11 @@
outputApp.writeMainDexList(closer, mainDexOut);
}
}
- if (options.printUsage && outputApp.hasDeadCode()) {
+ if (options.proguardConfiguration.isPrintUsage() && outputApp.hasDeadCode()) {
try (Closer closer = Closer.create()) {
OutputStream deadCodeOut = FileUtils.openPathWithDefault(
closer,
- options.printUsageFile,
+ options.proguardConfiguration.getPrintUsageFile(),
System.out,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
outputApp.writeDeadCode(closer, deadCodeOut);
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 86844a3..928b28f 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -5,13 +5,13 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.shaking.ProguardConfiguration;
+import com.android.tools.r8.shaking.ProguardConfiguration.Builder;
import com.android.tools.r8.shaking.ProguardConfigurationParser;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.android.tools.r8.utils.OutputMode;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
@@ -21,6 +21,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.function.Consumer;
public class R8Command extends BaseCommand {
@@ -28,6 +29,7 @@
private final List<Path> mainDexRules = new ArrayList<>();
private Path mainDexListOutput = null;
+ private Consumer<ProguardConfiguration.Builder> proguardConfigurationConsumer = null;
private final List<Path> proguardConfigFiles = new ArrayList<>();
private Optional<Boolean> treeShaking = Optional.empty();
private Optional<Boolean> minification = Optional.empty();
@@ -35,10 +37,14 @@
private Builder() {
super(CompilationMode.RELEASE);
+ // TODO(b/62048823): Minifier should not depend on -allowaccessmodification.
+ proguardConfigurationConsumer = builder -> builder.setAllowAccessModification(true);
}
private Builder(AndroidApp app) {
super(app, CompilationMode.RELEASE);
+ // TODO(b/62048823): Minifier should not depend on -allowaccessmodification.
+ proguardConfigurationConsumer = builder -> builder.setAllowAccessModification(true);
}
@Override
@@ -100,6 +106,20 @@
}
/**
+ * Add and/or chain proguard configuration consumer(s) for testing.
+ */
+ public Builder addProguardConfigurationConsumer(Consumer<ProguardConfiguration.Builder> c) {
+ Consumer<ProguardConfiguration.Builder> oldConsumer = proguardConfigurationConsumer;
+ proguardConfigurationConsumer = builder -> {
+ if (oldConsumer != null) {
+ oldConsumer.accept(builder);
+ }
+ c.accept(builder);
+ };
+ return self();
+ }
+
+ /**
* Set a proguard mapping file resource.
*/
public Builder setProguardMapFile(Path path) {
@@ -164,7 +184,11 @@
} catch (ProguardRuleParserException e) {
throw new CompilationException(e.getMessage(), e.getCause());
}
- configuration = parser.getConfig();
+ ProguardConfiguration.Builder configurationBuilder = parser.getConfigurationBuilder();
+ if (proguardConfigurationConsumer != null) {
+ proguardConfigurationConsumer.accept(configurationBuilder);
+ }
+ configuration = configurationBuilder.build();
addProgramFiles(configuration.getInjars());
addLibraryFiles(configuration.getLibraryjars());
}
@@ -364,55 +388,27 @@
@Override
InternalOptions getInternalOptions() {
- InternalOptions internal = new InternalOptions(proguardConfiguration.getDexItemFactory());
+ InternalOptions internal = new InternalOptions(proguardConfiguration);
assert !internal.debug;
internal.debug = getMode() == CompilationMode.DEBUG;
internal.minApiLevel = getMinApiLevel();
assert !internal.skipMinification;
- internal.skipMinification = !useMinification();
+ internal.skipMinification = !useMinification() || !proguardConfiguration.isObfuscating();
assert internal.useTreeShaking;
internal.useTreeShaking = useTreeShaking();
- assert !internal.printUsage;
- internal.printUsage = proguardConfiguration.isPrintUsage();
- internal.printUsageFile = proguardConfiguration.getPrintUsageFile();
assert !internal.ignoreMissingClasses;
internal.ignoreMissingClasses = ignoreMissingClasses;
-
- // TODO(zerny): Consider which other proguard options should be given flags.
- assert internal.packagePrefix.length() == 0;
- internal.packageObfuscationMode = proguardConfiguration.getPackageObfuscationMode();
- internal.packagePrefix = proguardConfiguration.getPackagePrefix();
- assert internal.allowAccessModification;
- internal.allowAccessModification = proguardConfiguration.getAllowAccessModification();
for (String pattern : proguardConfiguration.getAttributesRemovalPatterns()) {
internal.attributeRemoval.applyPattern(pattern);
}
- if (proguardConfiguration.isIgnoreWarnings()) {
- internal.ignoreMissingClasses = true;
- }
- assert internal.seedsFile == null;
- if (proguardConfiguration.getSeedFile() != null) {
- internal.seedsFile = proguardConfiguration.getSeedFile();
- }
+ internal.ignoreMissingClasses |= proguardConfiguration.isIgnoreWarnings();
assert !internal.verbose;
- if (proguardConfiguration.isVerbose()) {
- internal.verbose = true;
- }
- if (!proguardConfiguration.isObfuscating()) {
- internal.skipMinification = true;
- }
- internal.printSeeds |= proguardConfiguration.getPrintSeeds();
- internal.printMapping |= proguardConfiguration.isPrintingMapping();
- internal.printMappingFile = proguardConfiguration.getPrintMappingOutput();
- internal.classObfuscationDictionary = proguardConfiguration.getClassObfuscationDictionary();
- internal.obfuscationDictionary = proguardConfiguration.getObfuscationDictionary();
+ internal.verbose |= proguardConfiguration.isVerbose();
internal.mainDexKeepRules = mainDexKeepRules;
internal.minimalMainDex = internal.debug;
if (mainDexListOutput != null) {
internal.printMainDexListFile = mainDexListOutput;
}
- internal.keepRules = proguardConfiguration.getRules();
- internal.dontWarnPatterns = proguardConfiguration.getDontWarnPatterns();
internal.outputMode = getOutputMode();
if (internal.debug) {
// TODO(zerny): Should we support removeSwitchMaps in debug mode? b/62936642
diff --git a/src/main/java/com/android/tools/r8/code/Const.java b/src/main/java/com/android/tools/r8/code/Const.java
index 301f982..2f63777 100644
--- a/src/main/java/com/android/tools/r8/code/Const.java
+++ b/src/main/java/com/android/tools/r8/code/Const.java
@@ -41,12 +41,12 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 8) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 8) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
- return formatSmaliString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 8) +
+ return formatSmaliString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 8) +
" # " + decodedValue());
}
diff --git a/src/main/java/com/android/tools/r8/code/Const16.java b/src/main/java/com/android/tools/r8/code/Const16.java
index aa00341..baf2ca7 100644
--- a/src/main/java/com/android/tools/r8/code/Const16.java
+++ b/src/main/java/com/android/tools/r8/code/Const16.java
@@ -42,7 +42,7 @@
@Override
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 4) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 4) +
" (" + decodedValue() + ")");
}
diff --git a/src/main/java/com/android/tools/r8/code/Const4.java b/src/main/java/com/android/tools/r8/code/Const4.java
index 26da02a..b907e78 100644
--- a/src/main/java/com/android/tools/r8/code/Const4.java
+++ b/src/main/java/com/android/tools/r8/code/Const4.java
@@ -41,12 +41,12 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + A + ", 0x" + StringUtils.hexString(decodedValue(), 1) +
+ return formatString("v" + A + ", " + StringUtils.hexString(decodedValue(), 1) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
- return formatSmaliString("v" + A + ", 0x" + StringUtils.hexString(decodedValue(), 2) +
+ return formatSmaliString("v" + A + ", " + StringUtils.hexString(decodedValue(), 2) +
" # " + decodedValue());
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstHigh16.java b/src/main/java/com/android/tools/r8/code/ConstHigh16.java
index 3245fa9..d3a4264 100644
--- a/src/main/java/com/android/tools/r8/code/ConstHigh16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstHigh16.java
@@ -41,12 +41,12 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 8) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 8) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
- return formatSmaliString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 8) +
+ return formatSmaliString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 8) +
" # " + decodedValue());
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstWide.java b/src/main/java/com/android/tools/r8/code/ConstWide.java
index 7323f9b..002a377 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWide.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWide.java
@@ -41,12 +41,12 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
- return formatSmaliString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) +
+ return formatSmaliString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) +
"L # " + decodedValue());
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstWide16.java b/src/main/java/com/android/tools/r8/code/ConstWide16.java
index edd93fc..b593491 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWide16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWide16.java
@@ -41,13 +41,13 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
return formatSmaliString(
- "v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) + "L # " + decodedValue());
+ "v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) + "L # " + decodedValue());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/ConstWide32.java b/src/main/java/com/android/tools/r8/code/ConstWide32.java
index 540e840..5c4fc7b 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWide32.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWide32.java
@@ -41,13 +41,13 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
return formatSmaliString(
- "v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) + " # " + decodedValue());
+ "v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) + " # " + decodedValue());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java b/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java
index 864a079..182b39a 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java
@@ -40,12 +40,12 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) +
+ return formatString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) +
" (" + decodedValue() + ")");
}
public String toSmaliString(ClassNameMapper naming) {
- return formatSmaliString("v" + AA + ", 0x" + StringUtils.hexString(decodedValue(), 16) +
+ return formatSmaliString("v" + AA + ", " + StringUtils.hexString(decodedValue(), 16) +
"L # " + decodedValue());
}
diff --git a/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java b/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java
index 1f69d9c..885a8af 100644
--- a/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java
+++ b/src/main/java/com/android/tools/r8/code/FillArrayDataPayload.java
@@ -80,8 +80,7 @@
public String toSmaliString(ClassNameMapper naming) {
StringBuilder builder = new StringBuilder();
builder.append(" ");
- builder.append(".array-data");
- builder.append(" 0x");
+ builder.append(".array-data ");
builder.append(StringUtils.hexString(element_width, 1));
builder.append(" # ");
builder.append(element_width);
@@ -93,7 +92,6 @@
int value = (data[i] >> j * 8) & 0xff;
if (i * 2 + j < size) {
builder.append(" ");
- builder.append("0x");
builder.append(StringUtils.hexString(value, 2));
builder.append(" # ");
builder.append(value);
@@ -109,7 +107,6 @@
value = (Short.toUnsignedLong(data[i]) << (16 * (i % (element_width / 2)))) | value;
if ((((i + 1) * 2) % element_width) == 0) {
builder.append(" ");
- builder.append("0x");
builder.append(StringUtils.hexString(value, element_width * 2));
builder.append(" # ");
builder.append(value);
diff --git a/src/main/java/com/android/tools/r8/code/Format10t.java b/src/main/java/com/android/tools/r8/code/Format10t.java
index e5d2952..8d65d2b 100644
--- a/src/main/java/com/android/tools/r8/code/Format10t.java
+++ b/src/main/java/com/android/tools/r8/code/Format10t.java
@@ -40,8 +40,7 @@
}
public String toString(ClassNameMapper naming) {
- String relative = AA >= 0 ? ("+" + AA) : Integer.toString(AA);
- return formatString(relative + " (" + (getOffset() + AA) + ")");
+ return formatString(formatRelativeOffset(AA));
}
public String toSmaliString(ClassNameMapper naming) {
diff --git a/src/main/java/com/android/tools/r8/code/Format20t.java b/src/main/java/com/android/tools/r8/code/Format20t.java
index b3e3627..75721a3 100644
--- a/src/main/java/com/android/tools/r8/code/Format20t.java
+++ b/src/main/java/com/android/tools/r8/code/Format20t.java
@@ -40,7 +40,7 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("" + AAAA + " (" + (getOffset() + AAAA) + ")");
+ return formatString("" + AAAA + " " + formatRelativeOffset(AAAA));
}
public String toSmaliString(ClassNameMapper naming) {
diff --git a/src/main/java/com/android/tools/r8/code/Format21s.java b/src/main/java/com/android/tools/r8/code/Format21s.java
index db148bd..cc5d6c0 100644
--- a/src/main/java/com/android/tools/r8/code/Format21s.java
+++ b/src/main/java/com/android/tools/r8/code/Format21s.java
@@ -51,7 +51,7 @@
}
public String toSmaliString(ClassNameMapper naming) {
- return formatSmaliString("v" + AA + ", 0x" + StringUtils.hexString(BBBB, 4) + " # " + BBBB);
+ return formatSmaliString("v" + AA + ", " + StringUtils.hexString(BBBB, 4) + " # " + BBBB);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format21t.java b/src/main/java/com/android/tools/r8/code/Format21t.java
index 26f7650..6e91554 100644
--- a/src/main/java/com/android/tools/r8/code/Format21t.java
+++ b/src/main/java/com/android/tools/r8/code/Format21t.java
@@ -62,7 +62,7 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", +" + BBBB + " (" + (getOffset() + BBBB) + ")");
+ return formatString("v" + AA + ", " + formatRelativeOffset(BBBB));
}
public String toSmaliString(ClassNameMapper naming) {
diff --git a/src/main/java/com/android/tools/r8/code/Format22b.java b/src/main/java/com/android/tools/r8/code/Format22b.java
index 8aeae42..1164b03 100644
--- a/src/main/java/com/android/tools/r8/code/Format22b.java
+++ b/src/main/java/com/android/tools/r8/code/Format22b.java
@@ -56,7 +56,7 @@
public String toSmaliString(ClassNameMapper naming) {
return formatSmaliString(
- "v" + AA + ", v" + BB + ", 0x" + StringUtils.hexString(CC, 2) + " # " + CC);
+ "v" + AA + ", v" + BB + ", " + StringUtils.hexString(CC, 2) + " # " + CC);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format22s.java b/src/main/java/com/android/tools/r8/code/Format22s.java
index eef5fa5..85fbeab 100644
--- a/src/main/java/com/android/tools/r8/code/Format22s.java
+++ b/src/main/java/com/android/tools/r8/code/Format22s.java
@@ -56,7 +56,7 @@
public String toSmaliString(ClassNameMapper naming) {
return formatSmaliString(
- "v" + A + ", v" + B + ", 0x" + StringUtils.hexString(CCCC, 4) + " # " + CCCC);
+ "v" + A + ", v" + B + ", " + StringUtils.hexString(CCCC, 4) + " # " + CCCC);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format22t.java b/src/main/java/com/android/tools/r8/code/Format22t.java
index 3ff5190..0a4d664 100644
--- a/src/main/java/com/android/tools/r8/code/Format22t.java
+++ b/src/main/java/com/android/tools/r8/code/Format22t.java
@@ -66,7 +66,7 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + A + ", v" + B + ", +" + CCCC + " (" + (getOffset() + CCCC) + ")");
+ return formatString("v" + A + ", v" + B + ", " + formatRelativeOffset(CCCC));
}
public String toSmaliString(ClassNameMapper naming) {
diff --git a/src/main/java/com/android/tools/r8/code/Format30t.java b/src/main/java/com/android/tools/r8/code/Format30t.java
index 77cb49d..098863c 100644
--- a/src/main/java/com/android/tools/r8/code/Format30t.java
+++ b/src/main/java/com/android/tools/r8/code/Format30t.java
@@ -39,7 +39,7 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("" + AAAAAAAA);
+ return formatString(formatOffset(AAAAAAAA));
}
public String toSmaliString(ClassNameMapper naming) {
diff --git a/src/main/java/com/android/tools/r8/code/Format31t.java b/src/main/java/com/android/tools/r8/code/Format31t.java
index ec41ed4..87106f0 100644
--- a/src/main/java/com/android/tools/r8/code/Format31t.java
+++ b/src/main/java/com/android/tools/r8/code/Format31t.java
@@ -58,7 +58,7 @@
}
public String toString(ClassNameMapper naming) {
- return formatString("v" + AA + ", +" + BBBBBBBB + " (" + (getOffset() + BBBBBBBB) + ")");
+ return formatString("v" + AA + ", " + formatRelativeOffset(BBBBBBBB));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index 6b61845..617642c 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -142,9 +142,18 @@
return 0;
}
+ static String formatOffset(int offset) {
+ return StringUtils.hexString(offset, 2);
+ }
+
+ String formatRelativeOffset(int offset) {
+ String relativeString = offset >= 0 ? ("+" + offset) : Integer.toString(offset);
+ return formatOffset(getOffset() + offset) + " (" + relativeString + ")";
+ }
+
String formatString(String left) {
StringBuilder builder = new StringBuilder();
- StringUtils.appendLeftPadded(builder, Integer.toString(getOffset()), 6);
+ StringUtils.appendLeftPadded(builder, formatOffset(getOffset()), 6);
builder.append(": ");
StringUtils.appendRightPadded(builder, getName(), 20);
builder.append(left == null ? "" : left);
diff --git a/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java b/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
index a3e2d15..5032ab0 100644
--- a/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
+++ b/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
@@ -94,7 +94,6 @@
StringBuilder builder = new StringBuilder();
builder.append(" ");
builder.append(".packed-switch ");
- builder.append("0x");
builder.append(StringUtils.hexString(first_key, 8));
builder.append(" # ");
builder.append(first_key);
diff --git a/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java b/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
index 328e6d2..e0e1280 100644
--- a/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
+++ b/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
@@ -103,7 +103,6 @@
builder.append("\n");
for (int i = 0; i < keys.length; i++) {
builder.append(" ");
- builder.append("0x");
builder.append(StringUtils.hexString(keys[i], 8));
builder.append(" -> :label_");
builder.append(payloadUser.getOffset() + targets[i]);
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 7915df3..8bd13f0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -193,7 +193,7 @@
int instructionNumber = 0;
for (Instruction insn : instructions) {
while (debugInfo != null && debugInfo.address == insn.getOffset()) {
- builder.append(" ").append(debugInfo).append("\n");
+ builder.append(" ").append(debugInfo.toString(false)).append("\n");
debugInfo = debugInfoIterator.hasNext() ? debugInfoIterator.next() : null;
}
StringUtils.appendLeftPadded(builder, Integer.toString(instructionNumber++), 5);
@@ -353,9 +353,9 @@
public String toString() {
return "["
- + startAddress
+ + StringUtils.hexString(startAddress, 2)
+ " .. "
- + (startAddress + instructionCount - 1)
+ + StringUtils.hexString(startAddress + instructionCount - 1, 2)
+ "] -> "
+ handlerIndex;
}
@@ -420,12 +420,12 @@
builder.append(" ");
builder.append(pair.type);
builder.append(" -> ");
- builder.append(pair.addr);
+ builder.append(StringUtils.hexString(pair.addr, 2));
builder.append("\n");
}
if (catchAllAddr != NO_HANDLER) {
builder.append(" default -> ");
- builder.append(catchAllAddr);
+ builder.append(StringUtils.hexString(catchAllAddr, 2));
builder.append("\n");
}
builder.append(" ]");
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
index de7b544..f083794 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
@@ -33,8 +33,15 @@
@Override
public String toString() {
+ return toString(true);
+ }
+
+ public String toString(boolean withPcPrefix) {
StringBuilder builder = new StringBuilder();
- builder.append("pc 0x").append(StringUtils.hexString(address, 2));
+ if (withPcPrefix) {
+ builder.append("pc ");
+ }
+ builder.append(StringUtils.hexString(address, 2));
builder.append(", line ").append(line);
if (sourceFile != null) {
builder.append(", file ").append(sourceFile);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 484354a..8d36ef7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -258,23 +258,15 @@
@Override
public void buildPrelude(IRBuilder builder) {
Map<Integer, MoveType> initializedLocals = new HashMap<>(node.localVariables.size());
+ // Record types for arguments.
+ recordArgumentTypes(initializedLocals);
+ // Add debug information for all locals at the initial label.
if (initialLabel != null) {
state.openLocals(initialLabel);
}
- int argumentRegister = 0;
- if (!isStatic()) {
- Type thisType = Type.getType(clazz.descriptor.toString());
- int register = state.writeLocal(argumentRegister++, thisType);
- builder.addThisArgument(register);
- initializedLocals.put(register, moveType(thisType));
- }
- for (Type type : parameterTypes) {
- MoveType moveType = moveType(type);
- int register = state.writeLocal(argumentRegister, type);
- builder.addNonThisArgument(register, moveType);
- argumentRegister += moveType.requiredRegisters();
- initializedLocals.put(register, moveType);
- }
+ // Build the actual argument instructions now that type and debug information is known
+ // for arguments.
+ buildArgumentInstructions(builder);
if (isSynchronized()) {
generatingMethodSynchronization = true;
Type clazzType = Type.getType(clazz.toDescriptorString());
@@ -297,6 +289,23 @@
for (Object o : node.localVariables) {
LocalVariableNode local = (LocalVariableNode) o;
Type localType = Type.getType(local.desc);
+ int sort = localType.getSort();
+ switch (sort) {
+ case Type.OBJECT:
+ case Type.ARRAY:
+ localType = JarState.NULL_TYPE;
+ break;
+ case Type.DOUBLE:
+ case Type.LONG:
+ case Type.FLOAT:
+ break;
+ case Type.VOID:
+ case Type.METHOD:
+ throw new Unreachable("Invalid local variable type: " + localType);
+ default:
+ localType = Type.INT_TYPE;
+ break;
+ }
int localRegister = state.getLocalRegister(local.index, localType);
MoveType exitingLocalType = initializedLocals.get(localRegister);
assert exitingLocalType == null || exitingLocalType == moveType(localType);
@@ -311,6 +320,36 @@
state.setBuilding();
}
+ private void buildArgumentInstructions(IRBuilder builder) {
+ int argumentRegister = 0;
+ if (!isStatic()) {
+ Type thisType = Type.getType(clazz.descriptor.toString());
+ Slot slot = state.readLocal(argumentRegister++, thisType);
+ builder.addThisArgument(slot.register);
+ }
+ for (Type type : parameterTypes) {
+ MoveType moveType = moveType(type);
+ Slot slot = state.readLocal(argumentRegister, type);
+ builder.addNonThisArgument(slot.register, moveType);
+ argumentRegister += moveType.requiredRegisters();
+ }
+ }
+
+ private void recordArgumentTypes(Map<Integer, MoveType> initializedLocals) {
+ int argumentRegister = 0;
+ if (!isStatic()) {
+ Type thisType = Type.getType(clazz.descriptor.toString());
+ int register = state.writeLocal(argumentRegister++, thisType);
+ initializedLocals.put(register, moveType(thisType));
+ }
+ for (Type type : parameterTypes) {
+ MoveType moveType = moveType(type);
+ int register = state.writeLocal(argumentRegister, type);
+ argumentRegister += moveType.requiredRegisters();
+ initializedLocals.put(register, moveType);
+ }
+ }
+
private void computeBlockEntryJarStates(IRBuilder builder) {
Int2ReferenceSortedMap<BlockInfo> CFG = builder.getCFG();
Queue<JarStateWorklistItem> worklist = new LinkedList<>();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
index 5009d5e..a6b1f2c 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
@@ -87,6 +87,9 @@
if (type == BYTE_OR_BOOL_TYPE) {
type = Type.BYTE_TYPE;
}
+ if (other == BYTE_OR_BOOL_TYPE) {
+ other = Type.BYTE_TYPE;
+ }
int sort = type.getSort();
int otherSort = other.getSort();
if (isReferenceCompatible(type, other)) {
@@ -256,7 +259,7 @@
Collection<LocalVariableNode> nodes = localVariableStartPoints.get(label);
ArrayList<Local> locals = new ArrayList<>(nodes.size());
for (LocalVariableNode node : nodes) {
- locals.add(setLocal(node.index, Type.getType(node.desc), localVariables.get(node)));
+ locals.add(setLocalInfo(node.index, Type.getType(node.desc), localVariables.get(node)));
}
// Sort to ensure deterministic instruction ordering (correctness is unaffected).
locals.sort(Comparator.comparingInt(local -> local.slot.register));
@@ -335,6 +338,18 @@
return local;
}
+ private Local setLocalInfo(int index, Type type, DebugLocalInfo info) {
+ return setLocalInfoForRegister(getLocalRegister(index, type), type, info);
+ }
+
+ private Local setLocalInfoForRegister(int register, Type type, DebugLocalInfo info) {
+ Local existingLocal = getLocalForRegister(register);
+ Local local = new Local(existingLocal.slot, info);
+ locals[register] = local;
+ return local;
+ }
+
+
public int writeLocal(int index, Type type) {
assert nonNullType(type);
Local local = getLocal(index, type);
@@ -344,8 +359,9 @@
}
// We cannot assume consistency for writes because we do not have complete information about the
// scopes of locals. We assume the program to be verified and overwrite if the types mismatch.
- if (local == null || (local.info == null && !typeEquals(local.slot.type, type))) {
- local = setLocal(index, type, null);
+ if (local == null || !typeEquals(local.slot.type, type)) {
+ DebugLocalInfo info = local == null ? null : local.info;
+ local = setLocal(index, type, info);
}
return local.slot.register;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java b/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java
index 27cf89a..9f833f0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/BasicBlockInstructionsEquivalence.java
@@ -5,19 +5,25 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
import com.google.common.base.Equivalence;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
class BasicBlockInstructionsEquivalence extends Equivalence<BasicBlock> {
-
+ private static final int UNKNOW_HASH = -1;
private static final int MAX_HASH_INSTRUCTIONS = 5;
private final RegisterAllocator allocator;
+ private final int[] hashes;
- BasicBlockInstructionsEquivalence(RegisterAllocator allocator) {
+ BasicBlockInstructionsEquivalence(IRCode code, RegisterAllocator allocator) {
this.allocator = allocator;
+ hashes = new int[code.getHighestBlockNumber() + 1];
+ Arrays.fill(hashes, UNKNOW_HASH);
}
private boolean hasIdenticalInstructions(BasicBlock first, BasicBlock second) {
@@ -60,8 +66,23 @@
return hasIdenticalInstructions(a, b);
}
+ void clearComputedHash(BasicBlock basicBlock) {
+ hashes[basicBlock.getNumber()] = UNKNOW_HASH;
+ }
+
@Override
protected int doHash(BasicBlock basicBlock) {
+ int hash = hashes[basicBlock.getNumber()];
+ if (hash != UNKNOW_HASH) {
+ assert hash == computeHash(basicBlock);
+ return hash;
+ }
+ hash = computeHash(basicBlock);
+ hashes[basicBlock.getNumber()] = hash;
+ return hash;
+ }
+
+ private int computeHash(BasicBlock basicBlock) {
List<Instruction> instructions = basicBlock.getInstructions();
int hash = instructions.size();
for (int i = 0; i < instructions.size() && i < MAX_HASH_INSTRUCTIONS; i++) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
index 4ad05cc..a7d6e8d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
@@ -173,7 +173,7 @@
*/
private static void removeIdenticalPredecessorBlocks(IRCode code, RegisterAllocator allocator) {
BasicBlockInstructionsEquivalence equivalence =
- new BasicBlockInstructionsEquivalence(allocator);
+ new BasicBlockInstructionsEquivalence(code, allocator);
// Locate one block at a time that has identical predecessors. Rewrite those predecessors and
// then start over. Restarting when one blocks predecessors have been rewritten simplifies
// the rewriting and reduces the size of the data structures.
@@ -194,6 +194,7 @@
BasicBlock otherPred = block.getPredecessors().get(otherPredIndex);
pred.clearCatchHandlers();
pred.getInstructions().clear();
+ equivalence.clearComputedHash(pred);
for (BasicBlock succ : pred.getSuccessors()) {
succ.removePredecessor(pred);
}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 632aa6f..32342fc 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -20,15 +20,16 @@
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
@@ -42,7 +43,8 @@
private final Map<DexType, DexString> renaming = Maps.newIdentityHashMap();
private final Map<String, ClassNamingState> states = new HashMap<>();
- private final List<String> dictionary;
+ private final ImmutableList<String> packageDictionary;
+ private final ImmutableList<String> classDictionary;
private final boolean keepInnerClassStructure;
private final ClassNamingState topLevelState;
@@ -55,18 +57,17 @@
ClassNameMinifier(
AppInfoWithLiveness appInfo,
RootSet rootSet,
- PackageObfuscationMode packageObfuscationMode,
- String packagePrefix,
- List<String> dictionary,
- boolean keepInnerClassStructure) {
+ InternalOptions options) {
this.appInfo = appInfo;
this.rootSet = rootSet;
- this.packageObfuscationMode = packageObfuscationMode;
- this.dictionary = dictionary;
- this.keepInnerClassStructure = keepInnerClassStructure;
+ this.packageObfuscationMode = options.proguardConfiguration.getPackageObfuscationMode();
+ this.packageDictionary = options.proguardConfiguration.getPackageObfuscationDictionary();
+ this.classDictionary = options.proguardConfiguration.getClassObfuscationDictionary();
+ this.keepInnerClassStructure = options.attributeRemoval.signature;
// Initialize top-level naming state.
- topLevelState = new ClassNamingState(getPackageBinaryNameFromJavaType(packagePrefix));
+ topLevelState = new ClassNamingState(getPackageBinaryNameFromJavaType(
+ options.proguardConfiguration.getPackagePrefix()));
states.computeIfAbsent("", k -> topLevelState);
}
@@ -270,7 +271,8 @@
// L or La/b/ (or La/b/C$)
+ (packageName.isEmpty() ? "" : separator))
.toCharArray();
- this.dictionaryIterator = dictionary.iterator();
+ // TODO(b/36799686): general obfuscation should use packageDictionary when renaming package.
+ this.dictionaryIterator = classDictionary.iterator();
}
public char[] getPackagePrefix() {
diff --git a/src/main/java/com/android/tools/r8/naming/DictionaryReader.java b/src/main/java/com/android/tools/r8/naming/DictionaryReader.java
index 6c1e8e5..146d531 100644
--- a/src/main/java/com/android/tools/r8/naming/DictionaryReader.java
+++ b/src/main/java/com/android/tools/r8/naming/DictionaryReader.java
@@ -52,7 +52,7 @@
}
}
- public static List<String> readAllNames(Path path) {
+ public static ImmutableList<String> readAllNames(Path path) {
if (path != null) {
Builder<String> namesBuilder = new ImmutableList.Builder<String>();
try (DictionaryReader reader = new DictionaryReader(path);) {
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index eec918f..ac65c5c 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -10,9 +10,10 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.ImmutableList;
import java.util.IdentityHashMap;
-import java.util.List;
import java.util.Map;
class FieldNameMinifier {
@@ -20,13 +21,13 @@
private final AppInfoWithSubtyping appInfo;
private final RootSet rootSet;
private final Map<DexField, DexString> renaming = new IdentityHashMap<>();
- private final List<String> dictionary;
+ private final ImmutableList<String> dictionary;
private final Map<DexType, NamingState<DexType>> states = new IdentityHashMap<>();
- FieldNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, List<String> dictionary) {
+ FieldNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, InternalOptions options) {
this.appInfo = appInfo;
this.rootSet = rootSet;
- this.dictionary = dictionary;
+ this.dictionary = options.proguardConfiguration.getObfuscationDictionary();
}
Map<DexField, DexString> computeRenaming(Timing timing) {
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index 86670b8..4fa3809 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import com.android.tools.r8.utils.InternalOptions;
import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
@@ -91,13 +93,12 @@
private final Map<DexType, NamingState<DexProto>> states = new IdentityHashMap<>();
private final NamingState<DexProto> globalState;
private MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();
- private final List<String> dictionary;
+ private final ImmutableList<String> dictionary;
- MethodNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet,
- List<String> dictionary) {
+ MethodNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, InternalOptions options) {
this.appInfo = appInfo;
this.rootSet = rootSet;
- this.dictionary = dictionary;
+ this.dictionary = options.proguardConfiguration.getObfuscationDictionary();
this.globalState = NamingState.createRoot(appInfo.dexItemFactory, dictionary);
}
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index b1a15b6..951790c 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -36,29 +36,21 @@
public NamingLens run(Timing timing) {
assert !options.skipMinification;
- if (!options.allowAccessModification) {
+ // TODO(b/62048823): Minifier should not depend on -allowaccessmodification.
+ if (!options.proguardConfiguration.isAccessModificationAllowed()) {
throw new CompilationError("Minification requires allowaccessmodification.");
}
timing.begin("MinifyClasses");
Map<DexType, DexString> classRenaming =
- new ClassNameMinifier(
- appInfo,
- rootSet,
- options.packageObfuscationMode,
- options.packagePrefix,
- options.classObfuscationDictionary,
- options.attributeRemoval.signature)
- .computeRenaming(timing);
+ new ClassNameMinifier(appInfo, rootSet, options).computeRenaming(timing);
timing.end();
timing.begin("MinifyMethods");
Map<DexMethod, DexString> methodRenaming =
- new MethodNameMinifier(appInfo, rootSet, options.obfuscationDictionary)
- .computeRenaming(timing);
+ new MethodNameMinifier(appInfo, rootSet, options).computeRenaming(timing);
timing.end();
timing.begin("MinifyFields");
Map<DexField, DexString> fieldRenaming =
- new FieldNameMinifier(appInfo, rootSet, options.obfuscationDictionary)
- .computeRenaming(timing);
+ new FieldNameMinifier(appInfo, rootSet, options).computeRenaming(timing);
timing.end();
return new MinifiedRenaming(classRenaming, methodRenaming, fieldRenaming, appInfo);
}
diff --git a/src/main/java/com/android/tools/r8/naming/NamingState.java b/src/main/java/com/android/tools/r8/naming/NamingState.java
index 0474c1a..f42af78 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.HashBiMap;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.util.IdentityHashMap;
import java.util.Iterator;
@@ -15,19 +16,22 @@
import java.util.Map;
import java.util.Set;
-public class NamingState<T extends CanonicalizedDexItem> {
+class NamingState<T extends CanonicalizedDexItem> {
private final NamingState<T> parent;
private final Map<T, InternalState> usedNames = new IdentityHashMap<>();
private final DexItemFactory itemFactory;
- private final List<String> dictionary;
+ private final ImmutableList<String> dictionary;
- public static <T extends CanonicalizedDexItem> NamingState<T> createRoot(
- DexItemFactory itemFactory, List<String> dictionary) {
+ static <T extends CanonicalizedDexItem> NamingState<T> createRoot(
+ DexItemFactory itemFactory, ImmutableList<String> dictionary) {
return new NamingState<>(null, itemFactory, dictionary);
}
- private NamingState(NamingState<T> parent, DexItemFactory itemFactory, List<String> dictionary) {
+ private NamingState(
+ NamingState<T> parent,
+ DexItemFactory itemFactory,
+ ImmutableList<String> dictionary) {
this.parent = parent;
this.itemFactory = itemFactory;
this.dictionary = dictionary;
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 642b459..93c4dbb 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -31,7 +31,7 @@
private boolean printUsage = false;
private Path printUsageFile;
private boolean printMapping;
- private Path printMappingOutput;
+ private Path printMappingFile;
private boolean verbose = false;
private final List<String> attributesRemovalPatterns = new ArrayList<>();
private final Set<ProguardTypeMatcher> dontWarnPatterns = new HashSet<>();
@@ -106,8 +106,8 @@
this.printMapping = printMapping;
}
- public void setPrintMappingOutput(Path file) {
- this.printMappingOutput = file;
+ public void setPrintMappingFile(Path file) {
+ this.printMappingFile = file;
}
public void setVerbose(boolean verbose) {
@@ -130,7 +130,7 @@
this.seedFile = seedFile;
}
- public void setPrintSeed(boolean printSeeds) {
+ public void setPrintSeeds(boolean printSeeds) {
this.printSeeds = printSeeds;
}
@@ -161,7 +161,7 @@
printUsage,
printUsageFile,
printMapping,
- printMappingOutput,
+ printMappingFile,
verbose,
attributesRemovalPatterns,
dontWarnPatterns,
@@ -175,8 +175,8 @@
}
private final DexItemFactory dexItemFactory;
- private final List<Path> injars;
- private final List<Path> libraryjars;
+ private final ImmutableList<Path> injars;
+ private final ImmutableList<Path> libraryjars;
private final PackageObfuscationMode packageObfuscationMode;
private final String packagePrefix;
private final boolean allowAccessModification;
@@ -187,16 +187,16 @@
private final boolean printUsage;
private final Path printUsageFile;
private final boolean printMapping;
- private final Path printMappingOutput;
+ private final Path printMappingFile;
private final boolean verbose;
- private final List<String> attributesRemovalPatterns;
+ private final ImmutableList<String> attributesRemovalPatterns;
private final ImmutableSet<ProguardTypeMatcher> dontWarnPatterns;
protected final ImmutableList<ProguardConfigurationRule> rules;
private final boolean printSeeds;
private final Path seedFile;
- private final List<String> obfuscationDictionary;
- private final List<String> classObfuscationDictionary;
- private final List<String> packageObfuscationDictionary;
+ private final ImmutableList<String> obfuscationDictionary;
+ private final ImmutableList<String> classObfuscationDictionary;
+ private final ImmutableList<String> packageObfuscationDictionary;
private ProguardConfiguration(
DexItemFactory factory,
@@ -212,16 +212,16 @@
boolean printUsage,
Path printUsageFile,
boolean printMapping,
- Path printMappingOutput,
+ Path printMappingFile,
boolean verbose,
List<String> attributesRemovalPatterns,
Set<ProguardTypeMatcher> dontWarnPatterns,
List<ProguardConfigurationRule> rules,
boolean printSeeds,
Path seedFile,
- List<String> obfuscationDictionary,
- List<String> classObfuscationDictionary,
- List<String> packageObfuscationDictionary) {
+ ImmutableList<String> obfuscationDictionary,
+ ImmutableList<String> classObfuscationDictionary,
+ ImmutableList<String> packageObfuscationDictionary) {
this.dexItemFactory = factory;
this.injars = ImmutableList.copyOf(injars);
this.libraryjars = ImmutableList.copyOf(libraryjars);
@@ -235,7 +235,7 @@
this.printUsage = printUsage;
this.printUsageFile = printUsageFile;
this.printMapping = printMapping;
- this.printMappingOutput = printMappingOutput;
+ this.printMappingFile = printMappingFile;
this.verbose = verbose;
this.attributesRemovalPatterns = ImmutableList.copyOf(attributesRemovalPatterns);
this.dontWarnPatterns = ImmutableSet.copyOf(dontWarnPatterns);
@@ -262,11 +262,11 @@
return false;
}
- public List<Path> getInjars() {
+ public ImmutableList<Path> getInjars() {
return injars;
}
- public List<Path> getLibraryjars() {
+ public ImmutableList<Path> getLibraryjars() {
return libraryjars;
}
@@ -278,16 +278,16 @@
return packagePrefix;
}
- public boolean getAllowAccessModification() {
+ public boolean isAccessModificationAllowed() {
return allowAccessModification;
}
- public boolean isPrintingMapping() {
+ public boolean isPrintMapping() {
return printMapping;
}
- public Path getPrintMappingOutput() {
- return printMappingOutput;
+ public Path getPrintMappingFile() {
+ return printMappingFile;
}
public boolean isIgnoreWarnings() {
@@ -318,7 +318,7 @@
return verbose;
}
- public List<String> getAttributesRemovalPatterns() {
+ public ImmutableList<String> getAttributesRemovalPatterns() {
return attributesRemovalPatterns;
}
@@ -330,21 +330,20 @@
return rules;
}
- public List<String> getObfuscationDictionary() {
+ public ImmutableList<String> getObfuscationDictionary() {
return obfuscationDictionary;
}
- public List<String> getPackageObfuscationDictionary() {
- return packageObfuscationDictionary;
- }
-
- public List<String> getClassObfuscationDictionary() {
+ public ImmutableList<String> getClassObfuscationDictionary() {
return classObfuscationDictionary;
}
+ public ImmutableList<String> getPackageObfuscationDictionary() {
+ return packageObfuscationDictionary;
+ }
+
public static ProguardConfiguration defaultConfiguration(DexItemFactory dexItemFactory) {
- ProguardConfiguration config = new DefaultProguardConfiguration(dexItemFactory);
- return config;
+ return new DefaultProguardConfiguration(dexItemFactory);
}
public static class DefaultProguardConfiguration extends ProguardConfiguration {
@@ -372,7 +371,7 @@
null /* seedFile */,
ImmutableList.of() /* obfuscationDictionary */,
ImmutableList.of() /* classObfuscationDictionary */,
- ImmutableList.of() /* packageObfucationDictionary */);
+ ImmutableList.of() /* packageObfuscationDictionary */);
}
@Override
@@ -381,7 +380,7 @@
}
}
- public boolean getPrintSeeds() {
+ public boolean isPrintSeeds() {
return printSeeds;
}
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 0486d52..5b34221 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -76,6 +76,10 @@
configurationBuilder = ProguardConfiguration.builder(dexItemFactory);
}
+ public ProguardConfiguration.Builder getConfigurationBuilder() {
+ return configurationBuilder;
+ }
+
public ProguardConfiguration getConfig() {
return configurationBuilder.build();
}
@@ -214,7 +218,7 @@
configurationBuilder.setPrintMapping(true);
skipWhitespace();
if (isOptionalArgumentGiven()) {
- configurationBuilder.setPrintMappingOutput(parseFileName());
+ configurationBuilder.setPrintMappingFile(parseFileName());
}
} else if (acceptString("assumenosideeffects")) {
ProguardAssumeNoSideEffectRule rule = parseAssumeNoSideEffectsRule();
@@ -233,7 +237,7 @@
} else if (acceptString("libraryjars")) {
configurationBuilder.addLibraryJars(parseClassPath());
} else if (acceptString("printseeds")) {
- configurationBuilder.setPrintSeed(true);
+ configurationBuilder.setPrintSeeds(true);
skipWhitespace();
if (isOptionalArgumentGiven()) {
configurationBuilder.setSeedFile(parseFileName());
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index d8fd6c2..58646a8 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -30,7 +30,8 @@
this.application = application;
this.appInfo = appInfo;
this.options = options;
- this.usagePrinter = options.printUsage ? new UsagePrinter() : UsagePrinter.DONT_PRINT;
+ this.usagePrinter = options.proguardConfiguration.isPrintUsage()
+ ? new UsagePrinter() : UsagePrinter.DONT_PRINT;
}
public DexApplication run() throws IOException {
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 70a2e53..b03721f 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -9,10 +9,9 @@
import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
-import com.android.tools.r8.shaking.ProguardTypeMatcher;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Function;
@@ -20,14 +19,26 @@
public class InternalOptions {
public final DexItemFactory itemFactory;
+ public final ProguardConfiguration proguardConfiguration;
+ // Constructor for testing and/or other utilities.
public InternalOptions() {
itemFactory = new DexItemFactory();
+ proguardConfiguration = ProguardConfiguration.defaultConfiguration(itemFactory);
}
+ // Constructor for D8.
public InternalOptions(DexItemFactory factory) {
assert factory != null;
itemFactory = factory;
+ proguardConfiguration = ProguardConfiguration.defaultConfiguration(itemFactory);
+ }
+
+ // Constructor for R8.
+ public InternalOptions(ProguardConfiguration proguardConfiguration) {
+ assert proguardConfiguration != null;
+ this.proguardConfiguration = proguardConfiguration;
+ itemFactory = proguardConfiguration.getDexItemFactory();
}
public final int NOT_SPECIFIED = -1;
@@ -80,21 +91,12 @@
public OutputMode outputMode = OutputMode.Indexed;
public boolean useTreeShaking = true;
- public boolean printUsage = false;
- public Path printUsageFile = null;
public boolean printCfg = false;
public String printCfgFile;
- public boolean printSeeds;
- public Path seedsFile;
- public boolean printMapping;
- public Path printMappingFile;
public Path printMainDexListFile;
public boolean ignoreMissingClasses = false;
public boolean skipMinification = false;
- public PackageObfuscationMode packageObfuscationMode = PackageObfuscationMode.NONE;
- public String packagePrefix = "";
- public boolean allowAccessModification = true;
public boolean inlineAccessors = true;
public boolean removeSwitchMaps = true;
public boolean disableAssertions = true;
@@ -107,14 +109,8 @@
public boolean singleStepDebug = false;
public final TestingOptions testing = new TestingOptions();
- // TODO(zerny): These stateful dictionaries do not belong here.
- public List<String> classObfuscationDictionary = ImmutableList.of();
- public List<String> obfuscationDictionary = ImmutableList.of();
-
public ImmutableList<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
public boolean minimalMainDex;
- public ImmutableList<ProguardConfigurationRule> keepRules = ImmutableList.of();
- public ImmutableSet<ProguardTypeMatcher> dontWarnPatterns = ImmutableSet.of();
public String warningInvalidParameterAnnotations = null;
@@ -200,8 +196,8 @@
public static class TestingOptions {
- public Function<List<DexEncodedMethod>, List<DexEncodedMethod>> irOrdering
- = Function.identity();
+ public Function<List<DexEncodedMethod>, List<DexEncodedMethod>> irOrdering =
+ Function.identity();
}
public static class AttributeRemovalOptions {
diff --git a/src/main/java/com/android/tools/r8/utils/StringUtils.java b/src/main/java/com/android/tools/r8/utils/StringUtils.java
index 8404703..ea81b10 100644
--- a/src/main/java/com/android/tools/r8/utils/StringUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/StringUtils.java
@@ -158,11 +158,11 @@
assert(0 <= width && width <= 8);
String hex = Integer.toHexString(value);
if (value >= 0) {
- return zeroPrefixString(hex, width);
+ return "0x" + zeroPrefixString(hex, width);
} else {
// Negative ints are always formatted as 8 characters.
assert(hex.length() == 8);
- return hex;
+ return "0x" + hex;
}
}
@@ -170,11 +170,11 @@
assert(0 <= width && width <= 16);
String hex = Long.toHexString(value);
if (value >= 0) {
- return zeroPrefixString(hex, width);
+ return "0x" + zeroPrefixString(hex, width);
} else {
// Negative longs are always formatted as 16 characters.
assert(hex.length() == 16);
- return hex;
+ return "0x" + hex;
}
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 0d0d6f0..7bd18e0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -36,7 +36,6 @@
.addProguardConfigurationFiles(EXAMPLE_KEEP)
.setMinification(false)
.build(), o -> {
- o.allowAccessModification = false;
o.skipClassMerging = false;
});
inspector = new DexInspector(
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 10947a4..0b3726c 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -82,14 +82,11 @@
builder.addProguardConfigurationFiles(Paths.get(pgConf));
}
builder.setMode(mode);
- outputApp = ToolHelper.runR8(builder.build(),
- options -> {
- options.printSeeds = false;
- options.minApiLevel = Constants.ANDROID_L_API;
- if (optionsConsumer != null) {
- optionsConsumer.accept(options);
- }
- });
+ builder.setMinApiLevel(Constants.ANDROID_L_API);
+ builder.addProguardConfigurationConsumer(b -> {
+ b.setPrintSeeds(false);
+ });
+ outputApp = ToolHelper.runR8(builder.build(), optionsConsumer);
} else {
assert compiler == CompilerUnderTest.D8;
outputApp =
diff --git a/src/test/java/com/android/tools/r8/jasmin/DebugLocalTests.java b/src/test/java/com/android/tools/r8/jasmin/DebugLocalTests.java
index 72bbaed..2782c91 100644
--- a/src/test/java/com/android/tools/r8/jasmin/DebugLocalTests.java
+++ b/src/test/java/com/android/tools/r8/jasmin/DebugLocalTests.java
@@ -183,9 +183,9 @@
"MethodStart:",
".line 1",
- "LabelXStart:",
" ldc 0",
" istore 1",
+ "LabelXStart:",
".line 2",
" invokestatic Test/ensureLine()V",
"LabelXEnd:",
diff --git a/src/test/java/com/android/tools/r8/jasmin/Regress64658224.java b/src/test/java/com/android/tools/r8/jasmin/Regress64658224.java
new file mode 100644
index 0000000..8c1df56
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/jasmin/Regress64658224.java
@@ -0,0 +1,50 @@
+// 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.jasmin;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+public class Regress64658224 extends JasminTestBase {
+
+ @Test
+ public void testInvalidTypeInfoFromLocals() throws Exception {
+ JasminBuilder builder = new JasminBuilder();
+ JasminBuilder.ClassBuilder clazz = builder.addClass("Test");
+
+ clazz.addStaticMethod("foo", ImmutableList.of("I"), "V",
+ ".limit stack 2",
+ ".limit locals 2",
+ ".var 1 is x Ljava/lang/Object; from L1 to L2",
+ " aconst_null",
+ " astore 1",
+ "L1:",
+ " iload 0",
+ " ifeq L3",
+ "L2:",
+ " goto L5",
+ "L3:",
+ " aload 1",
+ " iconst_0",
+ " aaload",
+ " pop",
+ "L5:",
+ " return");
+
+ clazz.addMainMethod(
+ ".limit stack 1",
+ ".limit locals 1",
+ " ldc 2",
+ " invokestatic Test/foo(I)V",
+ " return");
+
+ String expected = "";
+ String javaResult = runOnJava(builder, clazz.name);
+ assertEquals(expected, javaResult);
+ String artResult = runOnArtD8(builder, clazz.name);
+ assertEquals(expected, artResult);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 7a81186..8818bbb 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -64,10 +64,9 @@
throws IOException, ProguardRuleParserException, ExecutionException {
ProguardConfiguration configuration =
ToolHelper.loadProguardConfiguration(dexItemFactory, configPaths);
- InternalOptions options = new InternalOptions();
- copyProguardConfigurationToInternalOptions(configuration, options);
+ InternalOptions options = new InternalOptions(configuration);
- if (options.allowAccessModification) {
+ if (options.proguardConfiguration.isAccessModificationAllowed()) {
ClassAndMemberPublicizer.run(program);
}
@@ -78,16 +77,6 @@
return new Minifier(appInfo.withLiveness(), rootSet, options).run(timing);
}
- private void copyProguardConfigurationToInternalOptions(
- ProguardConfiguration config, InternalOptions options) {
- options.packageObfuscationMode = config.getPackageObfuscationMode();
- options.packagePrefix = config.getPackagePrefix();
- options.allowAccessModification = config.getAllowAccessModification();
- options.classObfuscationDictionary = config.getClassObfuscationDictionary();
- options.obfuscationDictionary = config.getObfuscationDictionary();
- options.keepRules = config.getRules();
- }
-
static <T> Collection<Object[]> createTests(List<String> tests, Map<String, T> inspections) {
List<Object[]> testCases = new ArrayList<>();
Set<String> usedInspections = new HashSet<>();
diff --git a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
index 3138f4e..4cb6736 100644
--- a/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/PrintUsageTest.java
@@ -71,13 +71,15 @@
.setOutputPath(out)
.addProgramFiles(Paths.get(programFile))
.addProguardConfigurationFiles(ListUtils.map(keepRulesFiles, Paths::get))
+ .addProguardConfigurationConsumer(builder -> {
+ builder.setPrintUsage(true);
+ builder.setPrintUsageFile(out.resolve(test + PRINT_USAGE_FILE_SUFFIX));
+ })
.addLibraryFiles(Paths.get(ANDROID_JAR))
.build();
ToolHelper.runR8(command, options -> {
// Disable inlining to make this test not depend on inlining decisions.
options.inlineAccessors = false;
- options.printUsage = true;
- options.printUsageFile = out.resolve(test + PRINT_USAGE_FILE_SUFFIX);
});
}
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 6f2a347..28722af 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -384,7 +384,7 @@
ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
parser.parse(Paths.get(SEEDS));
ProguardConfiguration config = parser.getConfig();
- assertTrue(config.getPrintSeeds());
+ assertTrue(config.isPrintSeeds());
assertNull(config.getSeedFile());
}
@@ -393,7 +393,7 @@
ProguardConfigurationParser parser = new ProguardConfigurationParser(new DexItemFactory());
parser.parse(Paths.get(SEEDS_2));
ProguardConfiguration config = parser.getConfig();
- assertTrue(config.getPrintSeeds());
+ assertTrue(config.isPrintSeeds());
assertNotNull(config.getSeedFile());
}
diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
index 99be74a..4c1fc69 100644
--- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java
@@ -130,13 +130,15 @@
.setOutputPath(out)
.addProgramFiles(Paths.get(programFile))
.addProguardConfigurationFiles(ListUtils.map(keepRulesFiles, Paths::get))
+ .addProguardConfigurationConsumer(builder -> {
+ builder.setPrintMapping(true);
+ builder.setPrintMappingFile(out.resolve(AndroidApp.DEFAULT_PROGUARD_MAP_FILE));
+ })
.addLibraryFiles(JAR_LIBRARIES)
.setMinification(minify)
.build();
ToolHelper.runR8(command, options -> {
options.inlineAccessors = inline;
- options.printMapping = true;
- options.printMappingFile = out.resolve(AndroidApp.DEFAULT_PROGUARD_MAP_FILE);
});
}
diff --git a/third_party/framework.tar.gz.sha1 b/third_party/framework.tar.gz.sha1
index 7c11eec..675bb98 100644
--- a/third_party/framework.tar.gz.sha1
+++ b/third_party/framework.tar.gz.sha1
@@ -1 +1 @@
-d36913d75cde7c1293959698c45cf62342c709e0
\ No newline at end of file
+58224fa0baf2e9bd995918db690c35b2200c83a2
\ No newline at end of file
diff --git a/tools/test.py b/tools/test.py
index 8e016c7..ccc36d8 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -58,6 +58,9 @@
result.add_option('--disable_assertions',
help="Disable assertions when running tests.",
default=False, action='store_true')
+ result.add_option('--with_code_coverage',
+ help="Enable code coverage with Jacoco.",
+ default=False, action='store_true')
return result.parse_args()
@@ -72,10 +75,12 @@
def Main():
(options, args) = ParseOptions()
- gradle_args = ['cleanTest', 'test']
if len(args) > 1:
print("test.py takes at most one argument, the pattern for tests to run")
return -1
+
+ gradle_args = []
+ # Set all necessary Gradle properties and options first.
if options.verbose:
gradle_args.append('-Pprint_test_stdout')
if options.no_internal:
@@ -96,9 +101,8 @@
gradle_args.append('-Pjctf_compile_only')
if options.disable_assertions:
gradle_args.append('-Pdisable_assertions')
- if len(args) > 0:
- gradle_args.append('--tests')
- gradle_args.append(args[0])
+ if options.with_code_coverage:
+ gradle_args.append('-Pwith_code_coverage')
if os.name == 'nt':
# temporary hack
gradle_args.append('-Pno_internal')
@@ -108,6 +112,19 @@
gradle_args.append('jctfCommonJar')
gradle_args.append('-x')
gradle_args.append('jctfTestsClasses')
+
+ # Add Gradle tasks
+ gradle_args.append('cleanTest')
+ gradle_args.append('test')
+ if len(args) > 0:
+ # Test filtering. Must always follow the 'test' task.
+ gradle_args.append('--tests')
+ gradle_args.append(args[0])
+ if options.with_code_coverage:
+ # Create Jacoco report after tests.
+ gradle_args.append('jacocoTestReport')
+
+ # Now run tests on selected runtime(s).
vms_to_test = [options.dex_vm] if options.dex_vm != "all" else ALL_ART_VMS
for art_vm in vms_to_test:
return_code = gradle.RunGradle(gradle_args + ['-Pdex_vm=%s' % art_vm],
diff --git a/tools/test_framework.py b/tools/test_framework.py
index a153847..32f0bc7 100755
--- a/tools/test_framework.py
+++ b/tools/test_framework.py
@@ -34,7 +34,7 @@
GOYT_EXE = os.path.join('third_party', 'goyt',
'goyt_164843480')
FRAMEWORK_JAR = os.path.join('third_party', 'framework',
- 'framework_160115954.jar')
+ 'framework_14082017_desugared.jar')
MIN_SDK_VERSION = '24'
def parse_arguments():
@@ -43,7 +43,7 @@
' third_party/framework/framework*.jar.'
' Report Golem-compatible CodeSize and RunTimeRaw values.')
parser.add_argument('--tool',
- choices = ['dx', 'd8', 'd8-release', 'goyt'],
+ choices = ['dx', 'd8', 'd8-release', 'goyt', 'goyt-release'],
required = True,
help = 'Compiler tool to use.')
parser.add_argument('--name',
@@ -65,13 +65,15 @@
with utils.TempDir() as temp_dir:
- if args.tool in ['dx', 'goyt']:
+ if args.tool in ['dx', 'goyt', 'goyt-release']:
tool_args = ['--dex', '--output=' + temp_dir, '--multi-dex',
'--min-sdk-version=' + MIN_SDK_VERSION]
- if args.tool == 'goyt':
+ if args.tool.startswith('goyt'):
tool_file = GOYT_EXE
tool_args = ['--num-threads=8'] + tool_args
+ if args.tool == 'goyt-release':
+ tool_args.append('--no-locals')
elif args.tool == 'dx':
tool_file = DX_JAR
else: