Merge "Properly dedup synthetic $r8$twr$utility classes."
diff --git a/build.gradle b/build.gradle
index e49bbb5..f42501a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,7 +20,6 @@
junitVersion = '4.12'
kotlinVersion = '1.2.30'
kotlinExtMetadataJVMVersion = '0.0.3'
- protobufVersion = '3.0.0'
smaliVersion = '2.2b4'
}
@@ -65,7 +64,6 @@
}
}
dependencies {
- classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.23.0'
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
@@ -83,7 +81,6 @@
apply plugin: 'java'
apply plugin: 'idea'
-apply plugin: 'com.google.protobuf'
apply plugin: 'com.cookpad.android.licensetools'
apply plugin: 'net.ltgt.errorprone-base'
apply plugin: "net.ltgt.apt"
@@ -151,12 +148,7 @@
}
examples {
java {
- srcDirs = ['src/test/examples', 'build/generated/source/proto/examples/javalite/' ]
- }
- proto {
- srcDirs = [
- 'src/test/examples',
- ]
+ srcDirs = ['src/test/examples']
}
output.resourcesDir = 'build/classes/examples'
}
@@ -252,9 +244,7 @@
examplesAndroidPCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion
// Import Guava for @Nullable annotation
examplesCompile "com.google.guava:guava:$guavaVersion"
- examplesCompile "com.google.protobuf:protobuf-lite:$protobufVersion"
examplesCompileOnly "com.google.auto.value:auto-value:$autoValueVersion"
- examplesRuntime "com.google.protobuf:protobuf-lite:$protobufVersion"
supportLibs "com.android.support:support-v4:$androidSupportVersion"
supportLibs "junit:junit:$junitVersion"
supportLibs "com.android.support.test.espresso:espresso-core:$espressoVersion"
@@ -271,29 +261,6 @@
licensesYaml = file('LIBRARY-LICENSE')
}
-protobuf {
- protoc {
- // Download from repositories
- artifact = "com.google.protobuf:protoc:$protobufVersion"
- }
- plugins {
- javalite {
- artifact = "com.google.protobuf:protoc-gen-javalite:$protobufVersion"
- }
- }
- generateProtoTasks {
- all().each { task ->
- task.builtins {
- // Disable the java code generator, as we want javalite only.
- remove java
- }
- task.plugins {
- javalite {}
- }
- }
- }
-}
-
def osString = OperatingSystem.current().isLinux() ? "linux" :
OperatingSystem.current().isMacOsX() ? "mac" : "windows"
@@ -759,7 +726,6 @@
task buildExampleJars {
dependsOn downloadProguard
def examplesDir = file("src/test/examples")
- def protoSourceDir = file("build/generated/source/proto/examples/javalite")
def proguardScript
if (OperatingSystem.current().isWindows()) {
proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.bat"
@@ -782,9 +748,8 @@
}
task "compile_examples"(type: JavaCompile) {
- dependsOn "generateExamplesProto"
dependsOn "copy_examples_resources"
- source examplesDir, protoSourceDir
+ source examplesDir
include "**/*.java"
destinationDir = file("build/test/examples/classes")
classpath = sourceSets.examples.compileClasspath
@@ -792,8 +757,8 @@
targetCompatibility = JavaVersion.VERSION_1_7
options.compilerArgs = ["-g:source,lines", "-Xlint:none"]
}
- task "compile_examples_debuginfo_all"(type: JavaCompile, dependsOn: "generateExamplesProto") {
- source examplesDir, protoSourceDir
+ task "compile_examples_debuginfo_all"(type: JavaCompile) {
+ source examplesDir
include "**/*.java"
destinationDir = file("build/test/examples/classes_debuginfo_all")
classpath = sourceSets.examples.compileClasspath
@@ -801,8 +766,8 @@
targetCompatibility = JavaVersion.VERSION_1_7
options.compilerArgs = ["-g", "-Xlint:none"]
}
- task "compile_examples_debuginfo_none"(type: JavaCompile, dependsOn: "generateExamplesProto") {
- source examplesDir, protoSourceDir
+ task "compile_examples_debuginfo_none"(type: JavaCompile) {
+ source examplesDir
include "**/*.java"
destinationDir = file("build/test/examples/classes_debuginfo_none")
classpath = sourceSets.examples.compileClasspath
@@ -819,13 +784,6 @@
dependsOn "jar_example_${name}_debuginfo_none"
dependsOn "extractExamplesRuntime"
def runtimeDependencies = copySpec { }
- if (!fileTree(dir: dir, include: '**/*.proto').empty) {
- // If we have any proto use, we have to include those classes and the runtime.
- runtimeDependencies = copySpec {
- from "$buildDir/runtime/examples/"
- include "com/google/protobuf/**/*.class"
- }
- }
// The "throwing" test verifies debugging/stack info on the post-proguarded output.
def proguardConfigPath = "${dir}/proguard.cfg"
if (new File(proguardConfigPath).exists()) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index b1622ba..6de196e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -46,7 +46,6 @@
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.shaking.TreePruner;
import com.android.tools.r8.shaking.VerticalClassMerger;
-import com.android.tools.r8.shaking.protolite.ProtoLiteExtension;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.CfgPrinter;
@@ -289,18 +288,14 @@
options.proguardConfiguration.getRules(),
options)
.run(executorService);
- ProtoLiteExtension protoLiteExtension =
- options.forceProguardCompatibility
- ? null
- : new ProtoLiteExtension(appView.getAppInfo());
+
Enqueuer enqueuer =
new Enqueuer(
appView.getAppInfo(),
appView.getGraphLense(),
options,
options.forceProguardCompatibility,
- compatibility,
- protoLiteExtension);
+ compatibility);
appView.setAppInfo(enqueuer.traceApplication(rootSet, executorService, timing));
if (options.proguardConfiguration.isPrintSeeds()) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index ca4652c..fb67255 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -58,7 +58,6 @@
import com.android.tools.r8.kotlin.KotlinInfo;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.naming.IdentifierNameStringMarker;
-import com.android.tools.r8.shaking.protolite.ProtoLitePruner;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -109,7 +108,6 @@
private final LensCodeRewriter lensCodeRewriter;
private final NonNullTracker nonNullTracker;
private final Inliner inliner;
- private final ProtoLitePruner protoLiteRewriter;
private final IdentifierNameStringMarker identifierNameStringMarker;
private final Devirtualizer devirtualizer;
private final CovariantReturnTypeAnnotationTransformer covariantReturnTypeAnnotationTransformer;
@@ -165,9 +163,6 @@
new MemberValuePropagation(appInfo.withLiveness()) : null;
this.lensCodeRewriter = new LensCodeRewriter(graphLense, appInfo.withSubtyping());
if (appInfo.hasLiveness()) {
- // When disabling the pruner here, also disable the ProtoLiteExtension in R8.java.
- this.protoLiteRewriter =
- options.forceProguardCompatibility ? null : new ProtoLitePruner(appInfo.withLiveness());
if (!appInfo.withLiveness().identifierNameStrings.isEmpty() && options.enableMinification) {
this.identifierNameStringMarker =
new IdentifierNameStringMarker(appInfo.withLiveness(), options);
@@ -177,7 +172,6 @@
this.devirtualizer =
options.enableDevirtualization ? new Devirtualizer(appInfo.withLiveness()) : null;
} else {
- this.protoLiteRewriter = null;
this.identifierNameStringMarker = null;
this.devirtualizer = null;
}
@@ -187,7 +181,6 @@
this.outliner = null;
this.memberValuePropagation = null;
this.lensCodeRewriter = null;
- this.protoLiteRewriter = null;
this.identifierNameStringMarker = null;
this.devirtualizer = null;
}
@@ -743,9 +736,6 @@
}
if (!method.isProcessed()) {
- if (protoLiteRewriter != null && protoLiteRewriter.appliesTo(method)) {
- protoLiteRewriter.rewriteProtoLiteSpecialMethod(code, method);
- }
if (lensCodeRewriter != null) {
lensCodeRewriter.rewrite(code, method);
} else {
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 4c2479d..e03890c 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -31,7 +31,8 @@
this.rootSet = rootSet;
this.dictionary = options.proguardConfiguration.getObfuscationDictionary();
this.useUniqueMemberNames = options.proguardConfiguration.isUseUniqueClassMemberNames();
- this.overloadAggressively = options.proguardConfiguration.isOverloadAggressively();
+ this.overloadAggressively =
+ options.proguardConfiguration.isOverloadAggressivelyWithoutUseUniqueClassMemberNames();
this.globalState = NamingState.createRoot(
appInfo.dexItemFactory, dictionary, getKeyTransform(), useUniqueMemberNames);
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 97456ec..13308e5 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -44,7 +44,6 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.RootSetBuilder.ConsequentRootSet;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.shaking.protolite.ProtoLiteExtension;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.Timing;
@@ -116,8 +115,6 @@
Maps.newIdentityHashMap();
private final Set<DexCallSite> callSites = Sets.newIdentityHashSet();
- private final ProtoLiteExtension protoLiteExtension;
- private final Set<DexField> protoLiteFields = Sets.newIdentityHashSet();
private final Set<DexReference> identifierNameStrings = Sets.newIdentityHashSet();
/**
@@ -228,7 +225,7 @@
GraphLense graphLense,
InternalOptions options,
boolean forceProguardCompatibility) {
- this(appInfo, graphLense, options, forceProguardCompatibility, null, null);
+ this(appInfo, graphLense, options, forceProguardCompatibility, null);
}
public Enqueuer(
@@ -236,13 +233,11 @@
GraphLense graphLense,
InternalOptions options,
boolean forceProguardCompatibility,
- ProguardConfiguration.Builder compatibility,
- ProtoLiteExtension protoLiteExtension) {
+ ProguardConfiguration.Builder compatibility) {
this.appInfo = appInfo;
this.graphLense = graphLense;
this.compatibility = compatibility;
this.options = options;
- this.protoLiteExtension = protoLiteExtension;
this.forceProguardCompatibility = forceProguardCompatibility;
}
@@ -1378,11 +1373,7 @@
markParameterAndReturnTypesAsLive(method);
processAnnotations(method.annotations.annotations);
method.parameterAnnotationsList.forEachAnnotation(this::processAnnotation);
- if (protoLiteExtension != null && protoLiteExtension.appliesTo(method)) {
- protoLiteExtension.processMethod(method, new UseRegistry(method), protoLiteFields);
- } else {
- method.registerCodeReferences(new UseRegistry(method));
- }
+ method.registerCodeReferences(new UseRegistry(method));
// Add all dependent members to the workqueue.
enqueueRootItems(rootSet.getDependentItems(method));
}
@@ -1711,11 +1702,6 @@
*/
public final Object2BooleanMap<DexReference> identifierNameStrings;
/**
- * Set of fields that have been identified as proto-lite fields by the
- * {@link ProtoLiteExtension}.
- */
- final Set<DexField> protoLiteFields;
- /**
* A set of types that have been removed by the {@link TreePruner}.
*/
final Set<DexType> prunedTypes;
@@ -1770,7 +1756,6 @@
this.neverInline = enqueuer.rootSet.neverInline;
this.identifierNameStrings = joinIdentifierNameStrings(
enqueuer.rootSet.identifierNameStrings, enqueuer.identifierNameStrings);
- this.protoLiteFields = enqueuer.protoLiteFields;
this.prunedTypes = Collections.emptySet();
this.switchMaps = Collections.emptyMap();
this.ordinalsMaps = Collections.emptyMap();
@@ -1808,7 +1793,6 @@
this.staticInvokes = previous.staticInvokes;
this.callSites = previous.callSites;
this.brokenSuperInvokes = previous.brokenSuperInvokes;
- this.protoLiteFields = previous.protoLiteFields;
this.alwaysInline = previous.alwaysInline;
this.forceInline = previous.forceInline;
this.neverInline = previous.neverInline;
@@ -1872,7 +1856,6 @@
.collect(Collectors.toList()));
this.switchMaps = previous.switchMaps;
this.ordinalsMaps = rewriteKeys(previous.ordinalsMaps, lense::lookupType);
- this.protoLiteFields = previous.protoLiteFields;
// Sanity check sets after rewriting.
assert Sets.intersection(instanceFieldReads.keySet(), staticFieldReads.keySet()).isEmpty();
assert Sets.intersection(instanceFieldWrites.keySet(), staticFieldWrites.keySet()).isEmpty();
@@ -1905,7 +1888,6 @@
this.staticInvokes = previous.staticInvokes;
this.callSites = previous.callSites;
this.brokenSuperInvokes = previous.brokenSuperInvokes;
- this.protoLiteFields = previous.protoLiteFields;
this.alwaysInline = previous.alwaysInline;
this.forceInline = previous.forceInline;
this.neverInline = previous.neverInline;
@@ -2027,10 +2009,6 @@
return pinnedItems.contains(reference);
}
- public boolean isProtoLiteField(DexField field) {
- return protoLiteFields.contains(field);
- }
-
public Iterable<DexReference> getPinnedItems() {
return pinnedItems;
}
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 599d444..bbb255c 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -208,6 +208,10 @@
return useUniqueClassMemberNames;
}
+ boolean isOverloadAggressively() {
+ return overloadAggressively;
+ }
+
public void setKeepParameterNames(boolean keepParameterNames, Origin optionOrigin,
Position optionPosition) {
assert optionOrigin != null || !keepParameterNames;
@@ -552,8 +556,8 @@
return rules;
}
- public boolean isOverloadAggressively() {
- return overloadAggressively;
+ public boolean isOverloadAggressivelyWithoutUseUniqueClassMemberNames() {
+ return overloadAggressively && !useUniqueClassMemberNames;
}
public ImmutableList<String> getObfuscationDictionary() {
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 75e91b1..a410a65 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -127,6 +127,13 @@
configurationBuilder.getKeepParameterNamesOptionOrigin(),
configurationBuilder.getKeepParameterNamesOptionPosition()));
}
+ if (configurationBuilder.isOverloadAggressively()
+ && configurationBuilder.isUseUniqueClassMemberNames()) {
+ reporter.warning(
+ new StringDiagnostic(
+ "The -overloadaggressively flag has no effect if -useuniqueclassmembernames"
+ + " is also specified."));
+ }
}
/**
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteBase.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteBase.java
deleted file mode 100644
index c2264f2..0000000
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteBase.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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.shaking.protolite;
-
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-
-/**
- * Contains common definitions used by the {@link ProtoLiteExtension} for tree shaking and the
- * corresponding {@link ProtoLitePruner} code rewriting.
- */
-abstract class ProtoLiteBase {
-
- static final int GETTER_NAME_PREFIX_LENGTH = 3;
- static final int COUNT_POSTFIX_LENGTH = 5;
-
- final AppInfoWithSubtyping appInfo;
-
- final DexType messageType;
- final DexString dynamicMethodName;
- final DexString writeToMethodName;
- final DexString getSerializedSizeMethodName;
- final DexString constructorMethodName;
- final DexString setterNamePrefix;
- final DexString getterNamePrefix;
- final DexString bitFieldPrefix;
- final DexString underscore;
-
- ProtoLiteBase(AppInfoWithSubtyping appInfo) {
- this.appInfo = appInfo;
- DexItemFactory factory = appInfo.dexItemFactory;
- this.messageType = factory.createType("Lcom/google/protobuf/GeneratedMessageLite;");
- this.dynamicMethodName = factory.createString("dynamicMethod");
- this.writeToMethodName = factory.createString("writeTo");
- this.getSerializedSizeMethodName = factory.createString("getSerializedSize");
- this.constructorMethodName = factory.constructorMethodName;
- this.setterNamePrefix = factory.createString("set");
- this.getterNamePrefix = factory.createString("get");
- this.bitFieldPrefix = factory.createString("bitField");
- this.underscore = factory.createString("_");
- assert getterNamePrefix.size == GETTER_NAME_PREFIX_LENGTH;
- }
-
- /**
- * Returns true of the given method is a setter on a message class that does need processing
- * by this phase of proto lite shaking.
- * <p>
- * False positives are ok.
- */
- abstract boolean isSetterThatNeedsProcessing(DexEncodedMethod method);
-
- DexField getterToField(DexMethod getter) {
- return getterToField(getter, 0);
- }
-
- DexField getterToField(DexMethod getter, int postfixLength) {
- String getterName = getter.name.toString();
- assert getterName.length() > GETTER_NAME_PREFIX_LENGTH + postfixLength;
- String fieldName = Character.toLowerCase(getterName.charAt(GETTER_NAME_PREFIX_LENGTH))
- + getterName.substring(GETTER_NAME_PREFIX_LENGTH + 1, getterName.length() - postfixLength)
- + "_";
- DexItemFactory factory = appInfo.dexItemFactory;
- return factory
- .createField(getter.holder, getter.proto.returnType, factory.createString(fieldName));
- }
-
- boolean hasSingleIntArgument(DexMethod method) {
- return method.getArity() == 1
- && method.proto.parameters.values[0] == appInfo.dexItemFactory.intType;
- }
-
- public boolean appliesTo(DexEncodedMethod method) {
- if (!method.method.holder.isSubtypeOf(messageType, appInfo)) {
- return false;
- }
- DexClass clazz = appInfo.definitionFor(method.method.holder);
- // We only care for the actual leaf classes that implement a specific proto.
- if (!clazz.accessFlags.isFinal()) {
- return false;
- }
- DexString methodName = method.method.name;
- // We could be even more precise here and check for the signature. However, there is only
- // one of each method generated.
- return methodName == dynamicMethodName
- || methodName == writeToMethodName
- || methodName == getSerializedSizeMethodName
- || methodName == constructorMethodName
- || isSetterThatNeedsProcessing(method);
- }
-
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
deleted file mode 100644
index c4dee58..0000000
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLiteExtension.java
+++ /dev/null
@@ -1,198 +0,0 @@
-// 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.shaking.protolite;
-
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.DelegatingUseRegistry;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.utils.MethodJavaSignatureEquivalence;
-import com.google.common.base.Equivalence;
-import com.google.common.base.Equivalence.Wrapper;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Extends the tree shaker with special treatment for ProtoLite generated classes.
- * <p>
- * The goal is to remove unused fields from proto classes. To achieve this, we filter the
- * dependency processing of certain methods of ProtoLite classes. Read/write references to
- * fields or corresponding getters are ignored. If the fields or getters are not used otherwise
- * in the program, they will be pruned even though they are referenced from the processed
- * ProtoLite class.
- * <p>
- * The companion code rewriter in {@link ProtoLitePruner} then fixes up the code and removes
- * references to these dead fields and getters in a semantics preserving way. For proto2, the
- * fields are turned into unknown fields and hence are preserved over the wire. For proto3, the
- * fields are removed and, as with unknown fields in proto3, their data is lost on retransmission.
- * <p>
- * We have to process the following three methods specially:
- * <dl>
- * <dt>dynamicMethod</dt>
- * <dd>implements most proto operations, like merging, comparing, etc</dd>
- * <dt>writeTo</dt>
- * <dd>performs the actual write operations</dd>
- * <dt>getSerializedSize</dt>
- * <dd>implements computing the serialized size of a proto, very similar to writeTo</dd>
- * </dl>
- * As they access all fields of a proto, regardless of whether they are used, we have to mask
- * their accesses to ensure actually dead fields are not made live.
- * <p>
- * We also have to treat setters specially. While their code does not need to be rewritten, we
- * need to ensure that the fields they write are actually kept and marked as live. We achieve
- * this by also marking them read.
- */
-public class ProtoLiteExtension extends ProtoLiteBase {
-
- private final Equivalence<DexMethod> equivalence = MethodJavaSignatureEquivalence.get();
- /**
- * Set of all methods directly defined on the GeneratedMessageLite class. Used to filter
- * getters from other methods that begin with get.
- */
- private final Set<Wrapper<DexMethod>> methodsOnMessageType;
-
- private final DexString caseGetterSuffix;
- private final DexString caseFieldSuffix;
-
- public ProtoLiteExtension(AppInfoWithSubtyping appInfo) {
- super(appInfo);
- DexItemFactory factory = appInfo.dexItemFactory;
- this.methodsOnMessageType = computeMethodsOnMessageType();
- this.caseGetterSuffix = factory.createString("Case");
- this.caseFieldSuffix = factory.createString("Case_");
- }
-
- private Set<Wrapper<DexMethod>> computeMethodsOnMessageType() {
- DexClass messageClass = appInfo.definitionFor(messageType);
- if (messageClass == null) {
- return Collections.emptySet();
- }
- Set<Wrapper<DexMethod>> superMethods = new HashSet<>();
- messageClass.forEachMethod(method -> superMethods.add(equivalence.wrap(method.method)));
- return superMethods;
- }
-
- @Override
- boolean isSetterThatNeedsProcessing(DexEncodedMethod method) {
- return method.accessFlags.isPrivate()
- && method.method.name.beginsWith(setterNamePrefix)
- && !methodsOnMessageType.contains(equivalence.wrap(method.method));
- }
-
- private boolean isGetter(DexMethod method, DexType instanceType) {
- return method.holder == instanceType
- && (method.proto.parameters.isEmpty() || hasSingleIntArgument(method))
- && method.name.beginsWith(getterNamePrefix)
- && !method.name.endsWith(caseGetterSuffix)
- && !methodsOnMessageType.contains(equivalence.wrap(method));
- }
-
- private boolean isProtoField(DexField field, DexType instanceType) {
- if (field.getHolder() != instanceType) {
- return false;
- }
- // All instance fields that end with _ are proto fields. For proto2, there are also the
- // bitField<n>_ fields that are used to store presence information. We process those normally.
- // Likewise, the XXXCase_ fields for oneOfs.
- DexString name = field.name;
- return name.endsWith(underscore)
- && !name.beginsWith(bitFieldPrefix)
- && !name.endsWith(caseFieldSuffix);
- }
-
- public void processMethod(DexEncodedMethod method, UseRegistry registry,
- Set<DexField> protoLiteFields) {
- assert protoLiteFields != null;
- if (isSetterThatNeedsProcessing(method)) {
- // If a field is accessed by a live setter, the field is live as it has to be written to the
- // serialized stream for this proto. As we mask all reads in the writing code and normally
- // remove fields that are only written but never read, we have to mark fields used in setters
- // as read and written.
- method.registerCodeReferences(
- new FieldWriteImpliesReadUseRegistry(registry, method.method.holder));
- } else {
- // Filter all getters and field accesses in these methods. We do not want fields to become
- // live just due to being referenced in a special method. The pruning phase will remove
- // all references to dead fields in the code later.
- method.registerCodeReferences(new FilteringUseRegistry(registry, method.method.holder,
- protoLiteFields));
- }
- }
-
- private class FieldWriteImpliesReadUseRegistry extends DelegatingUseRegistry {
-
- private final DexType instanceType;
-
- FieldWriteImpliesReadUseRegistry(UseRegistry delegate,
- DexType instanceType) {
- super(delegate);
- this.instanceType = instanceType;
- }
-
- @Override
- public boolean registerInstanceFieldWrite(DexField field) {
- if (isProtoField(field, instanceType)) {
- super.registerInstanceFieldRead(field);
- }
- return super.registerInstanceFieldWrite(field);
- }
- }
-
- private class FilteringUseRegistry extends DelegatingUseRegistry {
-
- private final DexType instanceType;
- private final Set<DexField> registerField;
-
- private FilteringUseRegistry(UseRegistry delegate,
- DexType instanceType, Set<DexField> registerField) {
- super(delegate);
- this.instanceType = instanceType;
- this.registerField = registerField;
- }
-
- @Override
- public boolean registerInstanceFieldWrite(DexField field) {
- if (isProtoField(field, instanceType)) {
- registerField.add(field);
- return false;
- }
- return super.registerInstanceFieldWrite(field);
- }
-
- @Override
- public boolean registerInstanceFieldRead(DexField field) {
- if (isProtoField(field, instanceType)) {
- registerField.add(field);
- return false;
- }
- return super.registerInstanceFieldRead(field);
- }
-
- @Override
- public boolean registerInvokeVirtual(DexMethod method) {
- if (isGetter(method, instanceType)) {
- // Try whether this is a getXXX method.
- DexField field = getterToField(method);
- if (isProtoField(field, instanceType)) {
- registerField.add(field);
- return false;
- }
- // Try whether this is a getXXXCount method.
- field = getterToField(method, COUNT_POSTFIX_LENGTH);
- if (isProtoField(field, instanceType)) {
- registerField.add(field);
- return false;
- }
- }
- return super.registerInvokeVirtual(method);
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
deleted file mode 100644
index c37102c..0000000
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
+++ /dev/null
@@ -1,735 +0,0 @@
-// 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.shaking.protolite;
-
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.code.BasicBlock;
-import com.android.tools.r8.ir.code.DominatorTree;
-import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.InstanceGet;
-import com.android.tools.r8.ir.code.InstancePut;
-import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeInterface;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.MemberType;
-import com.android.tools.r8.ir.code.Switch;
-import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.ir.optimize.SwitchUtils;
-import com.android.tools.r8.ir.optimize.SwitchUtils.EnumSwitchInfo;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import it.unimi.dsi.fastutil.ints.IntArrayList;
-import it.unimi.dsi.fastutil.ints.IntList;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.BiPredicate;
-
-/**
- * Implements the second phase of proto lite tree shaking.
- * <p>
- * In the pruner pass, we remove all references to the now dead fields from the methods that
- * were treated specially during tree shaking using the {@link ProtoLiteExtension}.
- * <p>
- * For proto2 code, we aim to keep presence information for fields alive and move the values of
- * dead fields to the unknown fields storage. For proto3, as it has no concept of passing on
- * unknown fields, dead fields are completely removed. In particular, reading a proto and writing
- * it again might loose data.
- */
-public class ProtoLitePruner extends ProtoLiteBase {
-
- private final DexType visitorType;
-
- private final DexType methodEnumType;
- private final DexType codedOutputStreamType;
- private final DexType protobufListType;
- private final DexType listType;
-
- private final DexString visitTag;
- private final DexString mergeTag;
- private final DexString isInitializedTag;
- private final DexString makeImmutabkeTag;
- private final DexString computeMethodPrefix;
- private final DexString writeMethodPrefix;
- private final DexString isInitializedMethodName;
-
- private final DexString makeImmutableMethodName;
- private final DexString sizeMethodName;
- private final DexMethod sizeMethod;
-
- public ProtoLitePruner(AppInfoWithLiveness appInfo) {
- super(appInfo);
- DexItemFactory factory = appInfo.dexItemFactory;
- this.visitorType = factory.createType("Lcom/google/protobuf/GeneratedMessageLite$Visitor;");
- this.methodEnumType = factory
- .createType("Lcom/google/protobuf/GeneratedMessageLite$MethodToInvoke;");
- this.codedOutputStreamType = factory.createType("Lcom/google/protobuf/CodedOutputStream;");
- this.protobufListType = factory.createType("Lcom/google/protobuf/Internal$ProtobufList;");
- this.listType = factory.createType("Ljava/util/List;");
- this.visitTag = factory.createString("VISIT");
- this.mergeTag = factory.createString("MERGE_FROM_STREAM");
- this.isInitializedTag = factory.createString("IS_INITIALIZED");
- this.makeImmutabkeTag = factory.createString("MAKE_IMMUTABLE");
- this.computeMethodPrefix = factory.createString("compute");
- this.writeMethodPrefix = factory.createString("write");
- this.sizeMethodName = factory.createString("size");
- this.isInitializedMethodName = factory.createString("isInitialized");
- this.makeImmutableMethodName = factory.createString("makeImmutable");
- this.sizeMethod = factory.createMethod(listType,
- factory.createProto(factory.intType), sizeMethodName);
- }
-
- private boolean isPresenceField(DexField field, DexType instanceType) {
- if (field.getHolder() != instanceType) {
- return false;
- }
- // Proto2 uses fields named bitField<n>_ fields to store presence information.
- String fieldName = field.name.toString();
- return fieldName.endsWith("_")
- && fieldName.startsWith("bitField");
- }
-
- @Override
- boolean isSetterThatNeedsProcessing(DexEncodedMethod method) {
- // The pruner does not need to process setters, so this method always returns false.
- return false;
- }
-
- private boolean isGetter(DexMethod method) {
- return isGetterHelper(method, 0);
- }
-
- private boolean isCountGetter(DexMethod method) {
- return isGetterHelper(method, COUNT_POSTFIX_LENGTH);
- }
-
- private boolean isGetterHelper(DexMethod method, int postFixLength) {
- if (!method.name.beginsWith(getterNamePrefix)
- || !(method.proto.parameters.isEmpty() || hasSingleIntArgument(method))
- || (method.holder == messageType)
- || !method.holder.isSubtypeOf(messageType, appInfo)
- || method.name.size <= GETTER_NAME_PREFIX_LENGTH + postFixLength) {
- return false;
- }
- DexField correspondingField = getterToField(method, postFixLength);
- return isProtoField(correspondingField);
- }
-
- private boolean isDefinedAsNull(Value value) {
- return value.definition != null && value.isZero();
- }
-
- private boolean isComputeSizeMethod(DexMethod invokedMethod) {
- return invokedMethod.holder == codedOutputStreamType
- && invokedMethod.name.beginsWith(computeMethodPrefix);
- }
-
- private boolean isWriteMethod(DexMethod invokedMethod) {
- return invokedMethod.holder == codedOutputStreamType
- && invokedMethod.name.beginsWith(writeMethodPrefix);
- }
-
- private boolean isProtoField(DexField field) {
- return appInfo.withLiveness().isProtoLiteField(field);
- }
-
- public void rewriteProtoLiteSpecialMethod(IRCode code, DexEncodedMethod method) {
- DexString methodName = method.method.name;
- if (methodName == dynamicMethodName) {
- rewriteDynamicMethod(code, method);
- } else if ((methodName == writeToMethodName) || (methodName == getSerializedSizeMethodName)) {
- rewriteSizeOrWriteMethod(code);
- } else if (methodName == constructorMethodName) {
- rewriteConstructor(code);
- } else {
- throw new Unreachable();
- }
- }
-
- /**
- * For protos with repeated fields, the constructor may contain field initialization code like
- *
- * <pre>
- * private Repeated() {
- * repeated_ = com.google.protobuf.GeneratedMessageLite.emptyProtobufList();
- * other_ = emptyBooleanList();
- * sub_ = emptyProtobufList();
- * }
- * </pre>
- *
- * which this rewriting removes.
- */
- private void rewriteConstructor(IRCode code) {
- boolean wasRewritten;
- do {
- wasRewritten = false;
- InstructionIterator it = code.instructionIterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
- if (insn.isInstancePut() && isDeadProtoField(insn.asInstancePut().getField())) {
- // Remove initializations of dead fields.
- it.remove();
- wasRewritten = true;
- } else if (insn.isInvokeStatic()) {
- // Remove now unneeded constructor calls.
- InvokeStatic invokeStatic = insn.asInvokeStatic();
- DexMethod invokedMethod = invokeStatic.getInvokedMethod();
- if ((!invokeStatic.outValue().isUsed())
- && invokedMethod.proto.returnType.isSubtypeOf(protobufListType, appInfo)) {
- it.remove();
- }
- }
- }
- } while (wasRewritten);
- }
-
-
- /**
- * The writeTo and getSerializedSize methods of a generated proto access all fields. We have to
- * remove the accesses to dead fields. The actual code of these methods varies to quite some
- * degree depending on the types of the fields. For example
- *
- * <pre>
- * public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
- * if (((bitField0_ & 0x00000001) == 0x00000001)) {
- * output.writeInt32(1, id_);
- * }
- * if (((bitField0_ & 0x00000002) == 0x00000002)) {
- * output.writeMessage(2, getInner());
- * }
- * for (int i = 0; i < repeated_.size(); i++) {
- * output.writeString(3, repeated_.get(i));
- * }
- * for (int i = 0; i < other_.size(); i++) {
- * output.writeBool(4, other_.getBoolean(i));
- * }
- * for (int i = 0; i < sub_.size(); i++) {
- * output.writeMessage(5, sub_.get(i));
- * }
- * unknownFields.writeTo(output);
- * }
- * </pre>
- *
- * We look for direct field accesses (id_, repeated_, etc. above) and getters (getInner) and
- * rewrite those to null/0. We also rewrite all uses of the results, like the size() and
- * write methods above.
- */
- private void rewriteSizeOrWriteMethod(IRCode code) {
- boolean wasRewritten;
- do {
- wasRewritten = false;
- InstructionIterator it = code.instructionIterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
- if (insn.isInstanceGet()) {
- DexField field = insn.asInstanceGet().getField();
- if (isDeadProtoField(field)) {
- // Rewrite deads field access to corresponding 0.
- it.replaceCurrentInstruction(code.createConstNull(insn.asInstanceGet()));
- wasRewritten = true;
- }
- } else if (insn.isInvokeMethodWithReceiver()) {
- InvokeMethodWithReceiver invokeMethod = insn.asInvokeMethodWithReceiver();
- DexMethod invokedMethod = invokeMethod.getInvokedMethod();
- if (isDeadProtoGetter(invokedMethod)) {
- // Rewrite dead getters.
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- wasRewritten = true;
- } else if (invokedMethod.name == sizeMethodName
- && invokedMethod.holder.isSubtypeOf(listType, appInfo)) {
- Value receiver = invokeMethod.getReceiver();
- if (isDefinedAsNull(receiver)) {
- // Rewrite size() methods with null receiver.
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- }
- } else if (invokedMethod.name == getterNamePrefix
- && invokedMethod.holder.isSubtypeOf(listType, appInfo)) {
- Value receiver = invokeMethod.getReceiver();
- if (isDefinedAsNull(receiver)) {
- // Rewrite get(x) methods with null receiver.
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- wasRewritten = true;
- }
- } else if (isWriteMethod(invokedMethod)) {
- Value lastArg = Iterables.getLast(invokeMethod.inValues());
- if (isDefinedAsNull(lastArg)) {
- it.remove();
- }
- }
- } else if (insn.isInvokeMethod()) {
- InvokeMethod invokeMethod = insn.asInvokeMethod();
- DexMethod invokedMethod = invokeMethod.getInvokedMethod();
- if (isComputeSizeMethod(invokedMethod)) {
- Value lastArg = Iterables.getLast(invokeMethod.inValues());
- if (isDefinedAsNull(lastArg)) {
- // This is a computeSize method on a constant null. The field was dead.
- assert (invokeMethod.outValue() != null);
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- wasRewritten = true;
- }
- }
- }
- }
- } while (wasRewritten);
- }
-
- /**
- * The dyanmicMethod code is actually a collection of various methods contained in one.
- * It uses a switch statement over an enum to identify which actual operation is performed.
- * We need to rewrite all cases that might access dead fields. These are
- * <dl>
- * <dt>IS_INITIALIZED</dt>
- * <dd>See {@link #rewriteIsInitializedCase}.</dd>
- * <dt>MAKE_IMMUTABLE</dt>
- * <dd>See {@link #rewriteMakeImmutableCase}.</dd>
- * <dt>VISIT</dt>
- * <dd>See {@link #rewriteVisitCase}.</dd>
- * <dt>MERGE_FROM_STREAM</dt>
- * <dd>See {@link #rewriteMergeCase}.</dd>
- * </dl>
- */
- private void rewriteDynamicMethod(IRCode code, DexEncodedMethod method) {
- // This method contains a switch and we are interested in some of the cases only.
- InstructionIterator iterator = code.instructionIterator();
- Instruction matchingInstr = iterator.nextUntil(Instruction::isSwitch);
- if (matchingInstr == null) {
- throw new CompilationError("dynamicMethod in protoLite without switch.");
- }
- Switch switchInstr = matchingInstr.asSwitch();
- EnumSwitchInfo info = SwitchUtils.analyzeSwitchOverEnum(switchInstr, appInfo.withLiveness());
- if (info == null || info.enumClass != methodEnumType) {
- throw new CompilationError("Malformed switch in dynamicMethod of proto lite.");
- }
- BasicBlock initializedCase = null;
- BasicBlock visitCase = null;
- BasicBlock mergeCase = null;
- BasicBlock makeImmutableCase = null;
- for (int keyIdx = 0; keyIdx < switchInstr.numberOfKeys(); keyIdx++) {
- int key = switchInstr.getKey(keyIdx);
- DexField label = info.indexMap.get(key);
- assert label != null;
- if (label.name == visitTag) {
- assert visitCase == null;
- visitCase = switchInstr.targetBlock(keyIdx);
- } else if (label.name == mergeTag) {
- assert mergeCase == null;
- mergeCase = switchInstr.targetBlock(keyIdx);
- } else if (label.name == isInitializedTag) {
- assert initializedCase == null;
- initializedCase = switchInstr.targetBlock(keyIdx);
- } else if (label.name == makeImmutabkeTag) {
- assert makeImmutableCase == null;
- makeImmutableCase = switchInstr.targetBlock(keyIdx);
- }
- }
- DexType instanceType = method.method.getHolder();
- rewriteIsInitializedCase(initializedCase, instanceType, code);
- assert code.isConsistentSSA();
- rewriteMakeImmutableCase(makeImmutableCase, code);
- assert code.isConsistentSSA();
- rewriteVisitCase(visitCase, code);
- assert code.isConsistentSSA();
- rewriteMergeCase(mergeCase, instanceType, code);
- // Rewriting of the merge case changes branching structure and adds more blocks that target
- // the fallthrough label. This can introduce critical edges. Therefore, we split critical
- // edges to maintain our edge-split form.
- code.splitCriticalEdges();
- assert code.isConsistentSSA();
- }
-
- /**
- * In the presence of repeated fields, the MAKE_IMMUTABLE case will contain code of the form
- *
- * <pre>
- * case MAKE_IMMUTABLE: {
- * repeated_.makeImmutable();
- * other_.makeImmutable();
- * sub_.makeImmutable();
- * return null;
- * }
- * </pre>
- *
- * For dead fields, we remove the field access and the call to makeImmutable.
- */
- private void rewriteMakeImmutableCase(BasicBlock switchCase, IRCode code) {
- DominatorTree dom = new DominatorTree(code);
- boolean wasRewritten;
- do {
- wasRewritten = false;
- for (BasicBlock current : dom.dominatedBlocks(switchCase)) {
- InstructionIterator it = current.iterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
- if (insn.isInstanceGet() && isDeadProtoField(insn.asInstanceGet().getField())) {
- it.replaceCurrentInstruction(code.createConstNull(insn));
- wasRewritten = true;
- } else if (insn.isInvokeMethodWithReceiver()) {
- InvokeMethodWithReceiver invokeMethod = insn.asInvokeMethodWithReceiver();
- DexMethod invokedMethod = invokeMethod.getInvokedMethod();
- if (isDeadProtoGetter(invokedMethod)) {
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- wasRewritten = true;
- } else if (invokedMethod.name == makeImmutableMethodName
- && invokedMethod.getHolder().isSubtypeOf(protobufListType, appInfo)) {
- Value receiver = invokeMethod.getReceiver();
- if (isDefinedAsNull(receiver)) {
- it.remove();
- }
- }
- }
- }
- }
- } while (wasRewritten);
- }
-
- /**
- * The IS_INITIALIZED case also has a high degree of variability depending on the type of fields.
- * Common code looks as follows
- *
- * <pre>
- * case IS_INITIALIZED: {
- * byte isInitialized = memoizedIsInitialized;
- * if (isInitialized == 1) return DEFAULT_INSTANCE;
- * if (isInitialized == 0) return null;
- *
- * boolean shouldMemoize = ((Boolean) arg0).booleanValue();
- * if (!hasId()) {
- * if (shouldMemoize) {
- * memoizedIsInitialized = 0;
- * }
- * return null;
- * }
- * for (int i = 0; i < getSubCount(); i++) {
- * if (!getSub(i).isInitialized()) {
- * if (shouldMemoize) {
- * memoizedIsInitialized = 0;
- * }
- * return null;
- * }
- * }
- * if (shouldMemoize) memoizedIsInitialized = 1;
- * return DEFAULT_INSTANCE;
- * }
- * </pre>
- *
- * We remove all the accesses of dead fields and getters. We also replace secondary invokes
- * (like getSubCount or isInitialized) with conservative default values (e.g. 0, true).
- * <p>
- * We also rewrite getXXXCount methods on live fields, as accesses to those methods was filtered
- * during tree shaking. In place of those methods, we inline their definition.
- */
- private void rewriteIsInitializedCase(BasicBlock switchCase, DexType instanceType,
- IRCode code) {
- DominatorTree dom = new DominatorTree(code);
- boolean wasRewritten;
- do {
- wasRewritten = false;
- for (BasicBlock current : dom.dominatedBlocks(switchCase)) {
- InstructionIterator it = current.iterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
- if (insn.isInvokeMethodWithReceiver()) {
- InvokeMethodWithReceiver invokeMethod = insn.asInvokeMethodWithReceiver();
- DexMethod invokedMethod = invokeMethod.getInvokedMethod();
- if (isDeadProtoGetter(invokedMethod)) {
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- wasRewritten = true;
- } else if (invokedMethod.name == isInitializedMethodName
- && invokedMethod.getHolder().isSubtypeOf(messageType, appInfo)) {
- Value receiver = invokeMethod.getReceiver();
- if (isDefinedAsNull(receiver)) {
- // We cannot compute initialization state for nested messages and repeated
- // messages that have been removed or moved to unknown fields. Just return
- // true.
- it.replaceCurrentInstruction(code.createTrue());
- wasRewritten = true;
- }
- } else if (isCountGetter(invokedMethod)) {
- // We have to rewrite these as a precaution, as they might be dead due to
- // tree shaking ignoring them.
- DexField field = getterToField(invokedMethod, 5);
- if (appInfo.withLiveness().liveFields.contains(field)) {
- // Effectively inline the code that is normally inside these methods.
- Value thisReference = invokeMethod.getReceiver();
- Value newResult = code.createValue(ValueType.INT);
- invokeMethod.outValue().replaceUsers(newResult);
- Value theList = code.createValue(ValueType.OBJECT);
- it.replaceCurrentInstruction(
- new InstanceGet(MemberType.OBJECT, theList, thisReference, field));
- it.add(new InvokeInterface(sizeMethod, newResult, Collections.emptyList()));
- } else {
- // The field is dead, so its count is always 0.
- it.replaceCurrentInstruction(code.createConstNull(invokeMethod));
- }
- }
- }
- }
- }
- } while (wasRewritten);
- }
-
- private InstancePut findProtoFieldWrite(BasicBlock block, DexType instanceType,
- BiPredicate<DexField, DexType> filter, DominatorTree dom) {
- for (BasicBlock current : dom.dominatedBlocks(block)) {
- InstructionIterator insns = current.iterator();
- InstancePut instancePut = (InstancePut) insns.nextUntil(Instruction::isInstancePut);
- if (instancePut != null && filter.test(instancePut.getField(), instanceType)) {
- return instancePut;
- }
- }
- return null;
- }
-
- /**
- * For the merge case, we typically see code that contains a switch over the field tags. The inner
- * switch has the form
- *
- * <pre>
- * switch (tag) {
- * case 0:
- * done = true;
- * break;
- * default: {
- * if (!parseUnknownField(tag, input)) {
- * done = true;
- * }
- * break;
- * }
- * case 8: {
- * bitField0_ |= 0x00000001;
- * id_ = input.readInt32();
- * break;
- * }
- * case 18: {
- * nestedproto2.GeneratedNestedProto.NestedOne.Builder subBuilder = null;
- * if (((bitField0_ & 0x00000002) == 0x00000002)) {
- * subBuilder = inner_.toBuilder();
- * }
- * inner_ = input.readMessage(nestedproto2.GeneratedNestedProto.NestedOne.parser(),
- * extensionRegistry);
- * if (subBuilder != null) {
- * subBuilder.mergeFrom(inner_);
- * inner_ = subBuilder.buildPartial();
- * }
- * bitField0_ |= 0x00000002;
- * break;
- * }
- * case 24: {
- * if (!other_.isModifiable()) {
- * other_ =
- * com.google.protobuf.GeneratedMessageLite.mutableCopy(other_);
- * }
- * other_.addBoolean(input.readBool());
- * break;
- * }
- * case 26: {
- * int length = input.readRawVarint32();
- * int limit = input.pushLimit(length);
- * if (!other_.isModifiable() && input.getBytesUntilLimit() > 0) {
- * final int currentSize = other_.size();
- * other_ = other_.mutableCopyWithCapacity(
- * currentSize + (length/1));
- * }
- * while (input.getBytesUntilLimit() > 0) {
- * other_.addBoolean(input.readBool());
- * }
- * input.popLimit(limit);
- * break;
- * }
- * }
- * </pre>
- *
- * The general approach here is to identify the field that is processed by a case and, if
- * the field is dead, remove the entire case.
- * <p>
- * We slightly complicate the rewriting by also checking whether the block computes a
- * presence bitfield (bitField0_ above). If so, we move that computation to a new block that
- * continues to the default case. This ensures that presence is recorded correctly, yet the
- * field is moved to the unknownFields collection, if such exists.
- */
- private void rewriteMergeCase(BasicBlock caseBlock, DexType instanceType,
- IRCode code) {
- // We are looking for a switch statement over the input tag. Just traverse all blocks until
- // we find it.
- List<BasicBlock> deadBlocks = new ArrayList<>();
- DominatorTree dom = new DominatorTree(code);
- for (BasicBlock current : dom.dominatedBlocks(caseBlock)) {
- InstructionIterator it = current.iterator();
- Switch switchInstr = (Switch) it.nextUntil(Instruction::isSwitch);
- if (switchInstr != null) {
- int nextBlock = code.getHighestBlockNumber() + 1;
- IntList liveKeys = new IntArrayList(switchInstr.numberOfKeys());
- List<BasicBlock> liveBlocks = new ArrayList<>(switchInstr.numberOfKeys());
- boolean needsCleanup = false;
- // Filter out all the cases that contain writes to dead fields.
- for (int keyIdx = 0; keyIdx < switchInstr.numberOfKeys(); keyIdx++) {
- BasicBlock targetBlock = switchInstr.targetBlock(keyIdx);
- InstancePut instancePut =
- findProtoFieldWrite(targetBlock, instanceType, (field, holder) -> isProtoField(field),
- dom);
- if (instancePut == null
- || appInfo.withLiveness().liveFields.contains(instancePut.getField())) {
- // This is a live case. Keep it.
- liveKeys.add(switchInstr.getKey(keyIdx));
- liveBlocks.add(targetBlock);
- } else {
- // We cannot just remove this entire switch case if there is some computation here
- // for whether the field is present. We check this by searching for a write to
- // the bitField<xxx>_ fields. If such write exists, we move the corresponding
- // instructions to the first block in the switch.
- //TODO(herhut): Only do this if the written field has a live hasMethod.
- InstancePut bitFieldUpdate = findProtoFieldWrite(targetBlock, instanceType,
- this::isPresenceField, dom);
- if (bitFieldUpdate != null) {
- BasicBlock newBlock = BasicBlock.createGotoBlock(nextBlock++);
- newBlock.link(switchInstr.fallthroughBlock());
- // Copy over the computation of the field;
- moveInstructionTo(newBlock.listIterator(), bitFieldUpdate, dom, targetBlock);
- switchInstr.getBlock().link(newBlock);
- liveKeys.add(switchInstr.getKey(keyIdx));
- liveBlocks.add(newBlock);
- code.blocks.add(newBlock);
- }
- needsCleanup = true;
- }
- }
- if (needsCleanup) {
- DominatorTree updatedTree = new DominatorTree(code);
- BasicBlock fallThrough = switchInstr.fallthroughBlock();
- List<BasicBlock> successors = ImmutableList.copyOf(current.getNormalSuccessors());
- for (BasicBlock successor : successors) {
- if (successor != fallThrough && !liveBlocks.contains(successor)) {
- deadBlocks.addAll(current.unlink(successor, updatedTree));
- }
- }
- int[] blockIndices = new int[liveBlocks.size()];
- for (int i = 0; i < liveBlocks.size(); i++) {
- blockIndices[i] = current.getSuccessors().indexOf(liveBlocks.get(i));
- }
- Switch newSwitch = new Switch(switchInstr.inValues().get(0), liveKeys.toIntArray(),
- blockIndices, current.getSuccessors().indexOf(fallThrough));
- it.replaceCurrentInstruction(newSwitch);
- }
- break;
- }
- }
- code.removeBlocks(deadBlocks);
- }
-
- //TODO(herhut): This should really be a copy with a value substitution map.
- private void moveInstructionTo(InstructionListIterator iterator, Instruction insn,
- DominatorTree dom,
- BasicBlock dominator) {
- for (Value value : insn.inValues()) {
- Instruction input = value.definition;
- // We do not support phis.
- assert input != null;
- if (dom.dominatedBy(input.getBlock(), dominator)) {
- // And no shared instructions.
- assert input.outValue().numberOfUsers() == 1;
- moveInstructionTo(iterator, input, dom, dominator);
- }
- }
- insn.getBlock().removeInstruction(insn);
- iterator.add(insn);
- }
-
- private boolean isDeadProtoField(DexField field) {
- return isProtoField(field) && !appInfo.withLiveness().liveFields.contains(field);
- }
-
- private boolean isDeadProtoGetter(DexMethod method) {
- return isGetter(method) && isDeadProtoField(getterToField(method));
- }
-
- private boolean isVisitOfDeadField(Instruction instruction) {
- if (!instruction.isInvokeMethod()) {
- return false;
- }
- InvokeMethod invokeMethod = instruction.asInvokeMethod();
- if (invokeMethod.getInvokedMethod().getHolder() == visitorType
- && invokeMethod.getInvokedMethod().getArity() >= 2) {
- Instruction secondArg = invokeMethod.inValues().get(2).definition;
- return secondArg.isConstNumber();
- }
- return false;
- }
-
- /**
- * The visit case has typically the form
- *
- * <pre>
- * case VISIT: {
- * Visitor visitor = (Visitor) arg0;
- * repeatedproto.GeneratedRepeatedProto.Repeated other =
- * (repeatedproto.GeneratedRepeatedProto.Repeated) arg1;
- * id_ = visitor.visitInt(
- * hasId(), id_,
- * other.hasId(), other.id_);
- * repeated_= visitor.visitList(repeated_, other.repeated_);
- * inner_ = visitor.visitMessage(inner_, other.inner_);
- * if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor.INSTANCE) {
- * bitField0_ |= other.bitField0_;
- * }
- * return this;
- * }
- * </pre>
- *
- * We remove all writes and reads to dead fields and correspondign secondary instructions, like
- * the visitXXX methods.
- * <p>
- * Note that the invoked hasMethods are benign, as the only access the bitFieldXXX_ fields, which
- * we currently do not remove. Inlining will likely remove the methods.
- */
- private void rewriteVisitCase(BasicBlock switchCase, IRCode code) {
- DominatorTree dom = new DominatorTree(code);
- boolean wasRewritten;
- do {
- wasRewritten = false;
- for (BasicBlock target : dom.dominatedBlocks(switchCase)) {
- InstructionIterator it = target.iterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
- if (insn.isInstanceGet()) {
- InstanceGet instanceGet = insn.asInstanceGet();
- if (isDeadProtoField(instanceGet.getField())) {
- it.replaceCurrentInstruction(code.createConstNull(instanceGet));
- wasRewritten = true;
- }
- } else if (insn.isInstancePut()) {
- if (isDeadProtoField(insn.asInstancePut().getField())) {
- it.remove();
- }
- } else if (isVisitOfDeadField(insn)) {
- it.replaceCurrentInstruction(code.createConstNull(insn));
- } else if (insn.isCheckCast()) {
- // The call to visitXXX is a generic method invoke, so it will be followed by a check
- // cast to fix up the type. As the result is no longer needed once we are done, we can
- // remove the cast. This removes a potential last reference to an inner message class.
- // TODO(herhut): We should have a generic dead cast removal.
- Value inValue = insn.inValues().get(0);
- if (isDefinedAsNull(inValue)) {
- insn.outValue().replaceUsers(inValue);
- it.remove();
- }
- }
-
- }
- }
- } while (wasRewritten);
- }
-}
diff --git a/src/test/examples/enumproto/Enumproto.java b/src/test/examples/enumproto/Enumproto.java
deleted file mode 100644
index 9176378..0000000
--- a/src/test/examples/enumproto/Enumproto.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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 enumproto;
-
-
-import enumproto.GeneratedEnumProto.Enum;
-import enumproto.three.GeneratedEnumProto.EnumThree;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public class Enumproto {
-
- private static final byte[] WITH_ALL_FIELDS = new byte[]{6, 8, 42, 16, 2, 24, 3};
- private static final byte[] WITH_DEFAULT_FOR_ENUM = new byte[]{2, 8, 42};
-
-
- public static void main(String... args) throws IOException {
- readProtoAndPrintDaEnum(WITH_ALL_FIELDS);
- readProtoAndPrintDaEnum(WITH_DEFAULT_FOR_ENUM);
- readProtoThreeAndPrintDaEnum(WITH_ALL_FIELDS);
- readProtoThreeAndPrintDaEnum(WITH_DEFAULT_FOR_ENUM);
- roundTrip(WITH_ALL_FIELDS);
- roundTrip(WITH_DEFAULT_FOR_ENUM);
- roundTripThree(WITH_ALL_FIELDS);
- roundTripThree(WITH_DEFAULT_FOR_ENUM);
- }
-
- private static void readProtoAndPrintDaEnum(byte[] bytes) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(bytes);
- Enum.Builder builder = Enum.newBuilder();
- builder.mergeDelimitedFrom(input);
- Enum buffer = builder.build();
- System.out.println(buffer.getEnum());
- }
-
- private static void readProtoThreeAndPrintDaEnum(byte[] bytes) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(bytes);
- EnumThree.Builder builder = EnumThree.newBuilder();
- builder.mergeDelimitedFrom(input);
- EnumThree buffer = builder.build();
- System.out.println(buffer.getEnum());
- }
-
- private static void roundTrip(byte[] bytes) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(bytes);
- Enum.Builder builder = Enum.newBuilder();
- builder.mergeDelimitedFrom(input);
- Enum buffer = builder.build();
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- buffer.writeDelimitedTo(output);
- readProtoAndPrintDaEnum(output.toByteArray());
- }
-
- private static void roundTripThree(byte[] bytes) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(bytes);
- EnumThree.Builder builder = EnumThree.newBuilder();
- builder.mergeDelimitedFrom(input);
- EnumThree buffer = builder.build();
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- buffer.writeDelimitedTo(output);
- readProtoThreeAndPrintDaEnum(output.toByteArray());
- }
-
-}
diff --git a/src/test/examples/enumproto/enum.proto b/src/test/examples/enumproto/enum.proto
deleted file mode 100644
index 0fa5695..0000000
--- a/src/test/examples/enumproto/enum.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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.
-syntax = "proto2";
-package enumproto;
-
-option java_outer_classname = "GeneratedEnumProto";
-
-message Enum {
- required int32 id = 1;
- enum DaEnum {
- UNKOWN = 0;
- KNOWN = 1;
- BELIEF = 2;
- }
- optional DaEnum enum = 2;
- enum OtherEnum {
- BLACK = 0;
- RED = 1;
- GREEN = 2;
- OKALALALA = 3;
- }
- optional OtherEnum other = 3;
-}
-
diff --git a/src/test/examples/enumproto/enum_three.proto b/src/test/examples/enumproto/enum_three.proto
deleted file mode 100644
index a2731fb..0000000
--- a/src/test/examples/enumproto/enum_three.proto
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto3";
-package enumproto.three;
-
-option java_outer_classname = "GeneratedEnumProto";
-
-message EnumThree {
- int32 id = 1;
- enum DaEnum {
- UNKOWN = 0;
- KNOWN = 1;
- BELIEF = 2;
- }
- DaEnum enum = 2;
- enum OtherEnum {
- BLACK = 0;
- RED = 1;
- GREEN = 2;
- OKALALALA = 3;
- }
- OtherEnum other = 3;
-}
-
diff --git a/src/test/examples/enumproto/keep-rules.txt b/src/test/examples/enumproto/keep-rules.txt
deleted file mode 100644
index 088f88f..0000000
--- a/src/test/examples/enumproto/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class enumproto.Enumproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/nestedproto1/Nestedproto.java b/src/test/examples/nestedproto1/Nestedproto.java
deleted file mode 100644
index fe1a535..0000000
--- a/src/test/examples/nestedproto1/Nestedproto.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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 nestedproto1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import nestedproto1.GeneratedNestedProto.Outer;
-
-public class Nestedproto {
-
- private static final byte[] NESTED_MESSAGE_WITH_BOTH = new byte[] {25, 8, 42, 18, 12, 8, 1, 18, 8,
- 105, 110, 110, 101, 114, 79, 110, 101, 26, 7, 8, 2, 21, 0, 0, -10, 66};
-
- private static final byte[] NESTED_MESSAGE_WITH_ONE = new byte[]{16, 8, 42, 18, 12, 8, 1, 18, 8,
- 105,
- 110, 110, 101, 114, 79, 110, 101};
-
- public static void main(String... args) throws IOException {
- testWith(NESTED_MESSAGE_WITH_BOTH);
- testWith(NESTED_MESSAGE_WITH_ONE);
- }
-
- public static void testWith(byte[] data) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(data);
- Outer.Builder builder = Outer.newBuilder();
- builder.mergeDelimitedFrom(input);
- Outer outer = builder.build();
- System.out.println(outer.getInner().getOther());
- }
-}
diff --git a/src/test/examples/nestedproto1/keep-rules.txt b/src/test/examples/nestedproto1/keep-rules.txt
deleted file mode 100644
index 1c47672..0000000
--- a/src/test/examples/nestedproto1/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class nestedproto1.Nestedproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/nestedproto1/nested.proto b/src/test/examples/nestedproto1/nested.proto
deleted file mode 100644
index 0d05749..0000000
--- a/src/test/examples/nestedproto1/nested.proto
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package nestedproto1;
-
-option java_outer_classname = "GeneratedNestedProto";
-
-message NestedOne {
- required int32 id = 1;
- optional string other = 2;
-}
-
-message NestedTwo {
- required int32 id = 1;
- optional float other = 2;
-}
-
-message Outer {
- required int32 id = 1;
- required NestedOne inner = 2;
- optional NestedTwo inner2 = 3;
-}
-
diff --git a/src/test/examples/nestedproto2/Nestedproto.java b/src/test/examples/nestedproto2/Nestedproto.java
deleted file mode 100644
index 59217de..0000000
--- a/src/test/examples/nestedproto2/Nestedproto.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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 nestedproto2;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import nestedproto2.GeneratedNestedProto.Outer;
-
-public class Nestedproto {
-
- private static final byte[] NESTED_MESSAGE_WITH_BOTH = new byte[]{25, 8, 42, 18, 12, 8, 1, 18, 8,
- 105, 110, 110, 101, 114, 79, 110, 101, 26, 7, 8, 2, 21, 0, 0, -10, 66};
-
- private static final byte[] NESTED_MESSAGE_WITH_ONE = new byte[]{16, 8, 42, 18, 12, 8, 1, 18, 8,
- 105,
- 110, 110, 101, 114, 79, 110, 101};
-
- // Test that all fields remain when roundtripping with removed fields.
- public static void main(String... args) throws IOException {
- testWith(NESTED_MESSAGE_WITH_BOTH);
- testWith(NESTED_MESSAGE_WITH_ONE);
- }
-
- private static void testWith(byte[] data) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(data);
- Outer.Builder builder = Outer.newBuilder();
- builder.mergeDelimitedFrom(input);
- builder.setId(1982);
- Outer outer = builder.build();
- outer.writeTo(System.out);
- }
-}
diff --git a/src/test/examples/nestedproto2/keep-rules.txt b/src/test/examples/nestedproto2/keep-rules.txt
deleted file mode 100644
index 87c9218..0000000
--- a/src/test/examples/nestedproto2/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class nestedproto2.Nestedproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/nestedproto2/nested.proto b/src/test/examples/nestedproto2/nested.proto
deleted file mode 100644
index ac56f40..0000000
--- a/src/test/examples/nestedproto2/nested.proto
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package nestedproto2;
-
-option java_outer_classname = "GeneratedNestedProto";
-
-message NestedOne {
- required int32 id = 1;
- optional string other = 2;
-}
-
-message NestedTwo {
- required int32 id = 1;
- optional float other = 2;
-}
-
-message Outer {
- required int32 id = 1;
- required NestedOne inner = 2;
- optional NestedTwo inner2 = 3;
-}
-
diff --git a/src/test/examples/oneofproto/Oneofproto.java b/src/test/examples/oneofproto/Oneofproto.java
deleted file mode 100644
index 261705f..0000000
--- a/src/test/examples/oneofproto/Oneofproto.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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 oneofproto;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import oneofproto.GeneratedOneOfProto.Oneof;
-
-public class Oneofproto {
-
- private static final byte[] WITH_BOOL_FIELD = new byte[]{4, 8, 42, 24, 1};
- private static final byte[] WITH_FLOAT_FIELD = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
- private static final byte[] WITH_STRING_FIELD = new byte[]{9, 8, 42, 34, 5, 104, 101, 108, 108,
- 111};
- private static final byte[] WITH_NO_FIELD = new byte[]{2, 8, 42};
-
-
- public static void main(String... args) throws IOException {
- roundTrip(WITH_BOOL_FIELD);
- roundTrip(WITH_FLOAT_FIELD);
- roundTrip(WITH_STRING_FIELD);
- roundTrip(WITH_NO_FIELD);
- }
-
- private static void roundTrip(byte[] data) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(data);
- Oneof.Builder builder = Oneof.newBuilder();
- builder.mergeDelimitedFrom(input);
- Oneof oneof = builder.build();
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- oneof.writeDelimitedTo(output);
- System.out.println(Arrays.toString(output.toByteArray()));
- }
-
-}
diff --git a/src/test/examples/oneofproto/keep-rules.txt b/src/test/examples/oneofproto/keep-rules.txt
deleted file mode 100644
index 70f00f1..0000000
--- a/src/test/examples/oneofproto/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class oneofproto.Oneofproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/oneofproto/oneof.proto b/src/test/examples/oneofproto/oneof.proto
deleted file mode 100644
index c5a67a1..0000000
--- a/src/test/examples/oneofproto/oneof.proto
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package oneofproto;
-
-option java_outer_classname = "GeneratedOneOfProto";
-
-message Oneof {
- required int32 id = 1;
- oneof otherfields {
- float floatField = 2;
- bool boolField = 3;
- string stringField = 4;
- }
-}
-
diff --git a/src/test/examples/protowithexts/withexts.proto b/src/test/examples/protowithexts/withexts.proto
deleted file mode 100644
index d384173..0000000
--- a/src/test/examples/protowithexts/withexts.proto
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package protowithexts;
-
-option java_outer_classname = "GeneratedProtoWithExts";
-
-message Simple {
- required int32 id = 1;
-
- optional int32 other = 2;
-
- extensions 10 to 19;
-}
-
-extend Simple {
- optional string extra = 10;
-}
diff --git a/src/test/examples/repeatedproto/Repeatedproto.java b/src/test/examples/repeatedproto/Repeatedproto.java
deleted file mode 100644
index 280070d..0000000
--- a/src/test/examples/repeatedproto/Repeatedproto.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 repeatedproto;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import repeatedproto.GeneratedRepeatedProto.Repeated;
-
-public class Repeatedproto {
-
- private static final byte[] WITH_ALL_FIELDS = new byte[]{29, 8, 123, 18, 3, 111, 110, 101, 18, 3,
- 116, 119, 111, 18, 5, 116, 104, 114, 101, 101, 24, 1, 34, 2, 8, 42, 34, 2, 8, 42};
-
- public static void main(String... args) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(WITH_ALL_FIELDS);
- Repeated.Builder builder = Repeated.newBuilder();
- builder.mergeDelimitedFrom(input);
- Repeated repeated = builder.build();
- System.out.println(repeated.getRepeatedList());
- }
-}
diff --git a/src/test/examples/repeatedproto/keep-rules.txt b/src/test/examples/repeatedproto/keep-rules.txt
deleted file mode 100644
index 3d02352..0000000
--- a/src/test/examples/repeatedproto/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class repeatedproto.Repeatedproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/repeatedproto/repeated.proto b/src/test/examples/repeatedproto/repeated.proto
deleted file mode 100644
index 7414e6f..0000000
--- a/src/test/examples/repeatedproto/repeated.proto
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package repeatedproto;
-
-option java_outer_classname = "GeneratedRepeatedProto";
-
-message Repeated {
- required int32 id = 1;
- repeated string repeated = 2;
- repeated bool other = 3;
-
- message Sub {
- required int32 value = 1;
- }
-
- repeated Sub sub = 4;
-}
-
diff --git a/src/test/examples/repeatedproto/repeated_three.proto b/src/test/examples/repeatedproto/repeated_three.proto
deleted file mode 100644
index 7da7881..0000000
--- a/src/test/examples/repeatedproto/repeated_three.proto
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto3";
-package repeatedproto.three;
-
-option java_outer_classname = "GeneratedRepeatedProto";
-
-
-message RepeatedThree {
- int32 id = 1;
- repeated string repeated = 2;
- repeated bool other = 3;
-}
-
diff --git a/src/test/examples/simpleproto1/Simpleproto.java b/src/test/examples/simpleproto1/Simpleproto.java
deleted file mode 100644
index d07ce8d..0000000
--- a/src/test/examples/simpleproto1/Simpleproto.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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 simpleproto1;
-
-import com.google.protobuf.UninitializedMessageException;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import simpleproto1.GeneratedSimpleProto.Simple;
-
-public class Simpleproto {
-
- private static final byte[] WITH_REQUIRED_FIELDS = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
- private static final byte[] WITH_MISSING_FIELD = new byte[]{2, 8, 42};
-
-
- public static void main(String... args) throws IOException {
- readProtoWithAllReqFields();
- partialBuildFails();
- partialReadFails();
- }
-
- private static void partialBuildFails() {
- Simple.Builder builder = Simple.newBuilder();
- builder.setId(32);
- try {
- builder.build();
- } catch (UninitializedMessageException e) {
- System.out.println("got exception");
- }
- }
-
- private static void partialReadFails() throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(WITH_MISSING_FIELD);
- Simple.Builder builder = Simple.newBuilder();
- builder.mergeDelimitedFrom(input);
- try {
- builder.build();
- } catch (UninitializedMessageException e) {
- System.out.println("got exception");
- }
- }
-
- private static void readProtoWithAllReqFields() throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(WITH_REQUIRED_FIELDS);
- Simple.Builder builder = Simple.newBuilder();
- builder.mergeDelimitedFrom(input);
- Simple simple = builder.build();
- ByteArrayOutputStream output = new ByteArrayOutputStream(WITH_REQUIRED_FIELDS.length);
- simple.writeDelimitedTo(output);
- System.out.println(Arrays.toString(output.toByteArray()));
- System.out.println(Arrays.equals(WITH_REQUIRED_FIELDS, output.toByteArray()));
- }
-}
diff --git a/src/test/examples/simpleproto1/keep-rules.txt b/src/test/examples/simpleproto1/keep-rules.txt
deleted file mode 100644
index 3c3c33f..0000000
--- a/src/test/examples/simpleproto1/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class simpleproto1.Simpleproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/simpleproto1/simple.proto b/src/test/examples/simpleproto1/simple.proto
deleted file mode 100644
index f4e1be4..0000000
--- a/src/test/examples/simpleproto1/simple.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package simpleproto1;
-
-option java_outer_classname = "GeneratedSimpleProto";
-
-message Simple {
- required int32 id = 1;
- required float unusedRequired = 2;
- optional bool other = 3;
-}
-
diff --git a/src/test/examples/simpleproto2/Simpleproto.java b/src/test/examples/simpleproto2/Simpleproto.java
deleted file mode 100644
index f333d72..0000000
--- a/src/test/examples/simpleproto2/Simpleproto.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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 simpleproto2;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import simpleproto2.GeneratedSimpleProto.Simple;
-
-/**
- * A class that only uses a has method but otherwise ignores the value of a field.
- */
-public class Simpleproto {
-
- private static final byte[] WITHOUT_HASME_FIELD = new byte[]{2, 8, 42};
- private static final byte[] WITH_HASME_FIELD = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
-
- public static void main(String... args) throws IOException {
- testHasWorks(WITHOUT_HASME_FIELD, false);
- testHasWorks(WITH_HASME_FIELD, true);
- }
-
- private static void testHasWorks(byte[] msg, boolean expected) throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(msg);
- Simple.Builder builder = Simple.newBuilder();
- builder.mergeDelimitedFrom(input);
- Simple simple = builder.build();
- System.out.println("Expected " + expected + " and got " + simple.hasHasMe());
- }
-}
diff --git a/src/test/examples/simpleproto2/keep-rules.txt b/src/test/examples/simpleproto2/keep-rules.txt
deleted file mode 100644
index 8f9c93e..0000000
--- a/src/test/examples/simpleproto2/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class simpleproto2.Simpleproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/simpleproto2/simple.proto b/src/test/examples/simpleproto2/simple.proto
deleted file mode 100644
index b9173e9..0000000
--- a/src/test/examples/simpleproto2/simple.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto2";
-package simpleproto2;
-
-option java_outer_classname = "GeneratedSimpleProto";
-
-message Simple {
- required int32 id = 1;
- optional float hasMe = 2;
- optional int32 other = 3;
-}
-
diff --git a/src/test/examples/simpleproto3/Simpleproto.java b/src/test/examples/simpleproto3/Simpleproto.java
deleted file mode 100644
index 2cdbae8..0000000
--- a/src/test/examples/simpleproto3/Simpleproto.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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 simpleproto3;
-
-import com.google.protobuf.UninitializedMessageException;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import simpleproto3.GeneratedSimpleProto.Simple;
-
-public class Simpleproto {
-
- private static final byte[] WITH_REQUIRED_FIELDS = new byte[]{7, 8, 42, 21, 0, 0, -10, 66};
- private static final byte[] WITH_MISSING_FIELD = new byte[]{2, 8, 42};
-
-
- public static void main(String... args) throws IOException {
- readProtoWithAllReqFields();
- partialBuildFails();
- partialReadFails();
- }
-
- private static void partialBuildFails() {
- Simple.Builder builder = Simple.newBuilder();
- builder.setId(32);
- try {
- builder.build();
- } catch (UninitializedMessageException e) {
- System.out.println("got exception");
- }
- }
-
- private static void partialReadFails() throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(WITH_MISSING_FIELD);
- Simple.Builder builder = Simple.newBuilder();
- builder.mergeDelimitedFrom(input);
- try {
- builder.build();
- } catch (UninitializedMessageException e) {
- System.out.println("got exception");
- }
- }
-
- private static void readProtoWithAllReqFields() throws IOException {
- ByteArrayInputStream input = new ByteArrayInputStream(WITH_REQUIRED_FIELDS);
- Simple.Builder builder = Simple.newBuilder();
- builder.mergeDelimitedFrom(input);
- Simple simple = builder.build();
- ByteArrayOutputStream output = new ByteArrayOutputStream(WITH_REQUIRED_FIELDS.length);
- simple.writeDelimitedTo(output);
- System.out.println(isContained(WITH_REQUIRED_FIELDS, output.toByteArray()));
- }
-
- // After shaking, the serialized proto will no longer contain fields that are not referenced.
- private static boolean isContained(byte[] fullBytes, byte[] reducedBytes) {
- int j = 1;
- for (int i = 1; i < fullBytes.length && j < reducedBytes.length; i++) {
- if (fullBytes[i] == reducedBytes[j]) {
- j++;
- }
- }
- return j == reducedBytes.length;
- }
-}
diff --git a/src/test/examples/simpleproto3/keep-rules.txt b/src/test/examples/simpleproto3/keep-rules.txt
deleted file mode 100644
index 186e9f8..0000000
--- a/src/test/examples/simpleproto3/keep-rules.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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.
-
-# Keep the application entry point. Get rid of everything that is not
-# reachable from there.
--keep public class simpleproto3.Simpleproto {
- public static void main(...);
-}
-
-# allow access modification to enable minification
--allowaccessmodification
diff --git a/src/test/examples/simpleproto3/simple.proto b/src/test/examples/simpleproto3/simple.proto
deleted file mode 100644
index 87512d1..0000000
--- a/src/test/examples/simpleproto3/simple.proto
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2016, 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.
-syntax = "proto3";
-package simpleproto3;
-
-option java_outer_classname = "GeneratedSimpleProto";
-
-message Simple {
- int32 id = 1;
- float unusedRequired = 2;
- bool other = 3;
-}
-
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index b28ddd7..48e7d1a 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -641,6 +641,13 @@
return ToolHelper.runJava(out, mainAndArgs.toArray(new String[0]));
}
+ protected ProcessResult runOnJavaRawNoVerify(AndroidApp app, String mainClass, List<String> args)
+ throws IOException {
+ Path out = File.createTempFile("junit", ".zip", temp.getRoot()).toPath();
+ app.writeToZip(out, OutputMode.ClassFile);
+ return ToolHelper.runJavaNoVerify(out, mainClass, args.toArray(new String[0]));
+ }
+
private String extractClassName(byte[] ccc) {
class ClassNameExtractor extends ClassVisitor {
private String className;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java
index f894322..e505499 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/CheckCastRemovalTest.java
@@ -50,7 +50,8 @@
List<String> pgConfigs = ImmutableList.of(
"-keep class " + CLASS_NAME + " { *; }",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, o -> o.enableClassInlining = false);
+ AndroidApp app =
+ compileWithR8(builder, pgConfigs, o -> o.enableClassInlining = false, Backend.DEX);
DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
assertNotNull(method);
@@ -89,7 +90,8 @@
"-keep class B { *; }",
"-keep class C { *; }",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, opts -> opts.enableClassInlining = false);
+ AndroidApp app =
+ compileWithR8(builder, pgConfigs, opts -> opts.enableClassInlining = false, Backend.DEX);
DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
assertNotNull(method);
@@ -129,7 +131,7 @@
"-keep class C { *; }",
"-dontoptimize",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, Backend.DEX);
DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
assertNotNull(method);
@@ -168,7 +170,7 @@
List<String> pgConfigs = ImmutableList.of(
"-keep class " + CLASS_NAME + " { *; }",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, Backend.DEX);
DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
assertNotNull(method);
@@ -205,7 +207,7 @@
List<String> pgConfigs = ImmutableList.of(
"-keep class " + CLASS_NAME + " { *; }",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, Backend.DEX);
DexEncodedMethod method = getMethod(app, CLASS_NAME, main);
assertNotNull(method);
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
index c75ea7d..6500ca7 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
@@ -106,11 +106,12 @@
protected AndroidApp compileWithR8(
JasminBuilder builder,
List<String> proguardConfigs,
- Consumer<InternalOptions> optionsConsumer)
+ Consumer<InternalOptions> optionsConsumer,
+ Backend backend)
throws Exception {
R8Command command =
- ToolHelper.prepareR8CommandBuilder(builder.build())
- .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
+ ToolHelper.prepareR8CommandBuilder(builder.build(), emptyConsumer(backend))
+ .addLibraryFiles(runtimeJar(backend))
.addProguardConfiguration(proguardConfigs, Origin.unknown())
.build();
return ToolHelper.runR8(command, optionsConsumer);
diff --git a/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java b/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
index efead2d..61274ee 100644
--- a/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
+++ b/src/test/java/com/android/tools/r8/naming/overloadaggressively/ValidNameConflictTest.java
@@ -9,23 +9,42 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.jasmin.JasminTestBase;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
-@RunWith(VmTestRunner.class)
+@RunWith(Parameterized.class)
public class ValidNameConflictTest extends JasminTestBase {
+ private static final String REPEATED_NAME = "hopeTheresNoSuchNameInRuntimeLibraries";
+
+ private final Backend backend;
+
+ @Parameterized.Parameters(name = "Backend: {0}")
+ public static Collection<Backend> data() {
+ return Arrays.asList(Backend.values());
+ }
+
+ public ValidNameConflictTest(Backend backend) {
+ this.backend = backend;
+ }
+
private final String CLASS_NAME = "Example";
private final String SUPER_CLASS = "Super";
private final String ANOTHER_CLASS = "Test";
@@ -64,8 +83,8 @@
private JasminBuilder buildFieldNameConflictClassFile() {
JasminBuilder builder = new JasminBuilder();
ClassBuilder classBuilder = builder.addClass(CLASS_NAME);
- classBuilder.addStaticField("same", "Ljava/lang/Object;", null);
- classBuilder.addStaticField("same", "Ljava/lang/String;", "\"" + MSG + "\"");
+ classBuilder.addStaticField(REPEATED_NAME, "Ljava/lang/Object;", null);
+ classBuilder.addStaticField(REPEATED_NAME, "Ljava/lang/String;", "\"" + MSG + "\"");
classBuilder.addMainMethod(
buildCodeForVisitingDeclaredMembers(
ImmutableList.of(
@@ -79,6 +98,15 @@
return builder;
}
+ private ProcessResult runRaw(AndroidApp app, String main) throws IOException {
+ if (backend == Backend.DEX) {
+ return runOnArtRaw(app, main);
+ } else {
+ assert backend == Backend.CF;
+ return runOnJavaRawNoVerify(app, main, Collections.emptyList());
+ }
+ }
+
@Test
public void remainFieldNameConflict_keepRules() throws Exception {
JasminBuilder builder = buildFieldNameConflictClassFile();
@@ -92,22 +120,22 @@
+ "}\n"
+ "-printmapping\n",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
assertTrue(clazz.isPresent());
- FieldSubject f1 = clazz.field("java.lang.String", "same");
+ FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
assertTrue(f1.isPresent());
assertFalse(f1.isRenamed());
- FieldSubject f2 = clazz.field("java.lang.Object", "same");
+ FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
assertTrue(f2.isPresent());
assertFalse(f2.isRenamed());
assertEquals(f1.getFinalName(), f2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -120,22 +148,22 @@
keepMainProguardConfiguration(CLASS_NAME),
"-useuniqueclassmembernames",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
assertTrue(clazz.isPresent());
- FieldSubject f1 = clazz.field("java.lang.String", "same");
+ FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
assertTrue(f1.isPresent());
assertTrue(f1.isRenamed());
- FieldSubject f2 = clazz.field("java.lang.Object", "same");
+ FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
assertTrue(f2.isPresent());
assertTrue(f2.isRenamed());
assertEquals(f1.getFinalName(), f2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -150,22 +178,22 @@
"-useuniqueclassmembernames",
"-overloadaggressively", // no-op
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
assertTrue(clazz.isPresent());
- FieldSubject f1 = clazz.field("java.lang.String", "same");
+ FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
assertTrue(f1.isPresent());
assertTrue(f1.isRenamed());
- FieldSubject f2 = clazz.field("java.lang.Object", "same");
+ FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
assertTrue(f2.isPresent());
assertTrue(f2.isRenamed());
assertEquals(f1.getFinalName(), f2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -177,22 +205,22 @@
List<String> pgConfigs = ImmutableList.of(
keepMainProguardConfiguration(CLASS_NAME),
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
assertTrue(clazz.isPresent());
- FieldSubject f1 = clazz.field("java.lang.String", "same");
+ FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
assertTrue(f1.isPresent());
assertTrue(f1.isRenamed());
- FieldSubject f2 = clazz.field("java.lang.Object", "same");
+ FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
assertTrue(f2.isPresent());
assertTrue(f2.isRenamed());
assertNotEquals(f1.getFinalName(), f2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -205,33 +233,31 @@
keepMainProguardConfiguration(CLASS_NAME),
"-overloadaggressively",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(CLASS_NAME);
assertTrue(clazz.isPresent());
- FieldSubject f1 = clazz.field("java.lang.String", "same");
+ FieldSubject f1 = clazz.field("java.lang.String", REPEATED_NAME);
assertTrue(f1.isPresent());
assertTrue(f1.isRenamed());
- FieldSubject f2 = clazz.field("java.lang.Object", "same");
+ FieldSubject f2 = clazz.field("java.lang.Object", REPEATED_NAME);
assertTrue(f2.isPresent());
assertTrue(f2.isRenamed());
assertEquals(f1.getFinalName(), f2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
private JasminBuilder buildMethodNameConflictClassFile() {
JasminBuilder builder = new JasminBuilder();
ClassBuilder classBuilder = builder.addClass(ANOTHER_CLASS);
- classBuilder.addStaticMethod("same", ImmutableList.of(), "Ljava/lang/Object;",
- "aconst_null",
- "areturn");
- classBuilder.addStaticMethod("same", ImmutableList.of(), "Ljava/lang/String;",
- "ldc \"" + MSG + "\"",
- "areturn");
+ classBuilder.addStaticMethod(
+ REPEATED_NAME, ImmutableList.of(), "Ljava/lang/Object;", "aconst_null", "areturn");
+ classBuilder.addStaticMethod(
+ REPEATED_NAME, ImmutableList.of(), "Ljava/lang/String;", "ldc \"" + MSG + "\"", "areturn");
classBuilder = builder.addClass(CLASS_NAME);
classBuilder.addMainMethod(
buildCodeForVisitingDeclaredMembers(
@@ -261,22 +287,22 @@
+ "}\n",
keepMainProguardConfiguration(CLASS_NAME),
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(clazz.isPresent());
- MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertFalse(m1.isRenamed());
- MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertFalse(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -289,22 +315,22 @@
keepMainProguardConfiguration(CLASS_NAME),
"-useuniqueclassmembernames",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(clazz.isPresent());
- MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -319,22 +345,22 @@
"-useuniqueclassmembernames",
"-overloadaggressively", // no-op
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(clazz.isPresent());
- MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -346,22 +372,24 @@
List<String> pgConfigs = ImmutableList.of(
keepMainProguardConfiguration(CLASS_NAME),
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(clazz.isPresent());
- MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertNotEquals(m1.getFinalName(), m2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(
+ new HashSet<String>(StringUtils.splitLines(javaOutput.stdout)),
+ new HashSet<String>(StringUtils.splitLines(output.stdout)));
}
@Test
@@ -374,41 +402,45 @@
keepMainProguardConfiguration(CLASS_NAME),
"-overloadaggressively",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject clazz = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(clazz.isPresent());
- MethodSubject m1 = clazz.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = clazz.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = clazz.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = clazz.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
private JasminBuilder buildMethodNameConflictInHierarchy() {
JasminBuilder builder = new JasminBuilder();
ClassBuilder classBuilder = builder.addClass(SUPER_CLASS);
- classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/Object;",
- "aconst_null",
- "areturn");
- classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/String;",
- "ldc \"" + MSG + "\"",
- "areturn");
+ classBuilder.addVirtualMethod(
+ REPEATED_NAME, ImmutableList.of(), "Ljava/lang/Object;", "aconst_null", "areturn");
+ classBuilder.addVirtualMethod(
+ REPEATED_NAME, ImmutableList.of(), "Ljava/lang/String;", "ldc \"" + MSG + "\"", "areturn");
classBuilder = builder.addClass(ANOTHER_CLASS, SUPER_CLASS);
- classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/Object;",
+ classBuilder.addVirtualMethod(
+ REPEATED_NAME,
+ ImmutableList.of(),
+ "Ljava/lang/Object;",
"aload_0",
- "invokespecial " + SUPER_CLASS + "/same()Ljava/lang/Object;",
+ "invokespecial " + SUPER_CLASS + "/" + REPEATED_NAME + "()Ljava/lang/Object;",
"areturn");
- classBuilder.addVirtualMethod("same", ImmutableList.of(), "Ljava/lang/String;",
+ classBuilder.addVirtualMethod(
+ REPEATED_NAME,
+ ImmutableList.of(),
+ "Ljava/lang/String;",
"aload_0",
- "invokespecial " + SUPER_CLASS + "/same()Ljava/lang/String;",
+ "invokespecial " + SUPER_CLASS + "/" + REPEATED_NAME + "()Ljava/lang/String;",
"areturn");
classBuilder = builder.addClass(CLASS_NAME);
classBuilder.addMainMethod(
@@ -443,25 +475,25 @@
+ "}\n",
keepMainProguardConfiguration(CLASS_NAME),
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
assertTrue(sup.isPresent());
- MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertFalse(m1.isRenamed());
- MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertFalse(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(sub.isPresent());
- MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(subM1.isPresent());
assertFalse(subM1.isRenamed());
- MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(subM2.isPresent());
assertFalse(subM2.isRenamed());
assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -470,9 +502,9 @@
assertEquals(m1.getFinalName(), subM1.getFinalName());
assertEquals(m2.getFinalName(), subM2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -485,25 +517,25 @@
keepMainProguardConfiguration(CLASS_NAME),
"-useuniqueclassmembernames",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
assertTrue(sup.isPresent());
- MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(sub.isPresent());
- MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(subM1.isPresent());
assertTrue(subM1.isRenamed());
- MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(subM2.isPresent());
assertTrue(subM2.isRenamed());
assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -512,9 +544,9 @@
assertEquals(m1.getFinalName(), subM1.getFinalName());
assertEquals(m2.getFinalName(), subM2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -529,25 +561,25 @@
"-useuniqueclassmembernames",
"-overloadaggressively", // no-op
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
assertTrue(sup.isPresent());
- MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(sub.isPresent());
- MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(subM1.isPresent());
assertTrue(subM1.isRenamed());
- MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(subM2.isPresent());
assertTrue(subM2.isRenamed());
assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -556,9 +588,9 @@
assertEquals(m1.getFinalName(), subM1.getFinalName());
assertEquals(m2.getFinalName(), subM2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
@Test
@@ -570,25 +602,25 @@
List<String> pgConfigs = ImmutableList.of(
keepMainProguardConfiguration(CLASS_NAME),
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
assertTrue(sup.isPresent());
- MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertNotEquals(m1.getFinalName(), m2.getFinalName());
ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(sub.isPresent());
- MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(subM1.isPresent());
assertTrue(subM1.isRenamed());
- MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(subM2.isPresent());
assertTrue(subM2.isRenamed());
assertNotEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -597,9 +629,11 @@
assertEquals(m1.getFinalName(), subM1.getFinalName());
assertEquals(m2.getFinalName(), subM2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(
+ new HashSet<String>(StringUtils.splitLines(javaOutput.stdout)),
+ new HashSet<String>(StringUtils.splitLines(output.stdout)));
}
@Test
@@ -612,26 +646,26 @@
keepMainProguardConfiguration(CLASS_NAME),
"-overloadaggressively",
"-dontshrink");
- AndroidApp app = compileWithR8(builder, pgConfigs, null);
+ AndroidApp app = compileWithR8(builder, pgConfigs, null, backend);
CodeInspector codeInspector = new CodeInspector(app);
ClassSubject sup = codeInspector.clazz(SUPER_CLASS);
assertTrue(sup.isPresent());
- MethodSubject m1 = sup.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject m1 = sup.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(m1.isPresent());
assertTrue(m1.isRenamed());
- MethodSubject m2 = sup.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject m2 = sup.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(m2.isPresent());
assertTrue(m2.isRenamed());
assertEquals(m1.getFinalName(), m2.getFinalName());
ClassSubject sub = codeInspector.clazz(ANOTHER_CLASS);
assertTrue(sub.isPresent());
- MethodSubject subM1 = sub.method("java.lang.String", "same", ImmutableList.of());
+ MethodSubject subM1 = sub.method("java.lang.String", REPEATED_NAME, ImmutableList.of());
assertTrue(subM1.isPresent());
assertTrue(subM1.isRenamed());
- MethodSubject subM2 = sub.method("java.lang.Object", "same", ImmutableList.of());
+ MethodSubject subM2 = sub.method("java.lang.Object", REPEATED_NAME, ImmutableList.of());
assertTrue(subM2.isPresent());
assertTrue(subM2.isRenamed());
assertEquals(subM1.getFinalName(), subM2.getFinalName());
@@ -640,8 +674,8 @@
assertEquals(m1.getFinalName(), subM1.getFinalName());
assertEquals(m2.getFinalName(), subM2.getFinalName());
- ProcessResult artOutput = runOnArtRaw(app, CLASS_NAME);
- assertEquals(0, artOutput.exitCode);
- assertEquals(javaOutput.stdout, artOutput.stdout);
+ ProcessResult output = runRaw(app, CLASS_NAME);
+ assertEquals(0, output.exitCode);
+ assertEquals(javaOutput.stdout, output.stdout);
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingEnumprotoTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingEnumprotoTest.java
deleted file mode 100644
index 7f211db..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingEnumprotoTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingEnumprotoTest extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingEnumprotoTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/enumproto", "enumproto.Enumproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingEnumprotoTest::enumprotoUnusedFieldsAreGone,
- null,
- null,
- ImmutableList.of("src/test/examples/enumproto/keep-rules.txt"));
- }
-
- private static void enumprotoUnusedFieldsAreGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("enumproto.GeneratedEnumProto$Enum");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertFalse(protoClass.field("int", "id_").isPresent());
- Assert.assertTrue(protoClass.field("int", "enum_").isPresent());
- Assert.assertFalse(protoClass.field("int", "other_").isPresent());
- ClassSubject protoThreeClass = inspector.clazz("enumproto.three.GeneratedEnumProto$EnumThree");
- Assert.assertTrue(protoThreeClass.isPresent());
- Assert.assertFalse(protoThreeClass.field("int", "id_").isPresent());
- Assert.assertTrue(protoThreeClass.field("int", "enum_").isPresent());
- Assert.assertFalse(protoThreeClass.field("int", "other_").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto1Test.java
deleted file mode 100644
index 16b5f59..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto1Test.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingNestedproto1Test extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingNestedproto1Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/nestedproto1", "nestedproto1.Nestedproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingNestedproto1Test::nestedproto1UnusedFieldsAreGone,
- null,
- null,
- ImmutableList.of("src/test/examples/nestedproto1/keep-rules.txt"));
- }
-
- private static void nestedproto1UnusedFieldsAreGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("nestedproto1.GeneratedNestedProto$Outer");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertFalse(protoClass.field("int", "id_").isPresent());
- Assert.assertTrue(
- protoClass.field("nestedproto1.GeneratedNestedProto$NestedOne", "inner_").isPresent());
- Assert.assertFalse(
- protoClass.field("nestedproto1.GeneratedNestedProto$NestedTwo", "inner2_").isPresent());
- ClassSubject nestedOne = inspector.clazz("nestedproto1.GeneratedNestedProto$NestedOne");
- Assert.assertTrue(nestedOne.isPresent());
- Assert.assertTrue(nestedOne.field("java.lang.String", "other_").isPresent());
- Assert.assertFalse(nestedOne.field("int", "id_").isPresent());
- Assert.assertFalse(inspector.clazz("nestedproto1.GeneratedNestedProto$NestedTwo").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto2Test.java
deleted file mode 100644
index a679810..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingNestedproto2Test.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingNestedproto2Test extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingNestedproto2Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/nestedproto2", "nestedproto2.Nestedproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingNestedproto2Test::nestedproto2UnusedFieldsAreGone,
- null,
- null,
- ImmutableList.of("src/test/examples/nestedproto2/keep-rules.txt"));
- }
-
- private static void nestedproto2UnusedFieldsAreGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("nestedproto2.GeneratedNestedProto$Outer");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertTrue(protoClass.field("int", "id_").isPresent());
- Assert.assertFalse(
- protoClass.field("nestedproto2.GeneratedNestedProto$NestedOne", "inner_").isPresent());
- Assert.assertFalse(
- protoClass.field("nestedproto2.GeneratedNestedProto$NestedTwo", "inner2_").isPresent());
- Assert.assertFalse(inspector.clazz("nestedproto2.GeneratedNestedProto$NestedOne").isPresent());
- Assert.assertFalse(inspector.clazz("nestedproto2.GeneratedNestedProto$NestedTwo").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingOneofprotoTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingOneofprotoTest.java
deleted file mode 100644
index e38258c..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingOneofprotoTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingOneofprotoTest extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingOneofprotoTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/oneofproto", "oneofproto.Oneofproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingOneofprotoTest::oneofprotoUnusedFieldsAreGone,
- null,
- null,
- ImmutableList.of("src/test/examples/oneofproto/keep-rules.txt"));
- }
-
- private static void oneofprotoUnusedFieldsAreGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("oneofproto.GeneratedOneOfProto$Oneof");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertFalse(protoClass.field("int", "id_").isPresent());
- Assert.assertFalse(protoClass.field("Object", "otherfields_").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingRepeatedprotoTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingRepeatedprotoTest.java
deleted file mode 100644
index 923cf34..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingRepeatedprotoTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingRepeatedprotoTest extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingRepeatedprotoTest(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/repeatedproto", "repeatedproto.Repeatedproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingRepeatedprotoTest::repeatedUnusedFieldsAreGone,
- null,
- null,
- ImmutableList.of("src/test/examples/repeatedproto/keep-rules.txt"));
- }
-
- private static void repeatedUnusedFieldsAreGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("repeatedproto.GeneratedRepeatedProto$Repeated");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertFalse(protoClass.field("int", "id_").isPresent());
- Assert.assertTrue(
- protoClass.field("com.google.protobuf.Internal$ProtobufList", "repeated_").isPresent());
- Assert.assertFalse(
- protoClass.field("com.google.protobuf.Internal$ProtobufList", "sub_").isPresent());
- Assert.assertFalse(
- protoClass.field("com.google.protobuf.Internal$BooleanList", "other_").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto1Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto1Test.java
deleted file mode 100644
index 64e3839..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto1Test.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingSimpleproto1Test extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingSimpleproto1Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/simpleproto1", "simpleproto1.Simpleproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingSimpleproto1Test::simpleproto1UnusedFieldIsGone,
- null,
- null,
- ImmutableList.of("src/test/examples/simpleproto1/keep-rules.txt"));
- }
-
- private static void simpleproto1UnusedFieldIsGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("simpleproto1.GeneratedSimpleProto$Simple");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertFalse(protoClass.field("boolean", "other_").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto2Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto2Test.java
deleted file mode 100644
index 5304dae..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto2Test.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingSimpleproto2Test extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingSimpleproto2Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/simpleproto2", "simpleproto2.Simpleproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(
- TreeShakingSimpleproto2Test::simpleproto2UnusedFieldsAreGone,
- null,
- null,
- ImmutableList.of("src/test/examples/simpleproto2/keep-rules.txt"));
- }
-
- private static void simpleproto2UnusedFieldsAreGone(CodeInspector inspector) {
- ClassSubject protoClass = inspector.clazz("simpleproto2.GeneratedSimpleProto$Simple");
- Assert.assertTrue(protoClass.isPresent());
- Assert.assertFalse(protoClass.field("int", "id_").isPresent());
- Assert.assertFalse(protoClass.field("float", "hasMe_").isPresent());
- Assert.assertFalse(protoClass.field("int", "other_").isPresent());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto3Test.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto3Test.java
deleted file mode 100644
index 896517a..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingSimpleproto3Test.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.examples;
-
-import com.android.tools.r8.TestBase.MinifyMode;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingSimpleproto3Test extends TreeShakingTest {
-
- @Parameters(name = "mode:{0}-{1} minify:{2}")
- public static Collection<Object[]> data() {
- List<Object[]> parameters = new ArrayList<>();
- for (MinifyMode minify : MinifyMode.values()) {
- parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
- parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
- parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
- }
- return parameters;
- }
-
- public TreeShakingSimpleproto3Test(Frontend frontend, Backend backend, MinifyMode minify) {
- super("examples/simpleproto3", "simpleproto3.Simpleproto", frontend, backend, minify);
- }
-
- @Test
- public void test() throws Exception {
- runTest(null, null, null, ImmutableList.of("src/test/examples/simpleproto3/keep-rules.txt"));
- }
-}
diff --git a/tools/golem.py b/tools/golem.py
index cda9875..c4c554a 100755
--- a/tools/golem.py
+++ b/tools/golem.py
@@ -22,7 +22,7 @@
]
# Path to our internally updated third party
-THIRD_PARTY_SOURCE = "/usr/local/google/home/golem/src/r8/third_party"
+THIRD_PARTY_SOURCE = "/usr/local/google/home/golem/r8/third_party"
def link_third_party():
assert os.path.exists('third_party')
diff --git a/tools/run_kotlin_benchmarks.py b/tools/run_kotlin_benchmarks.py
index c3f5b94..166c3e9 100755
--- a/tools/run_kotlin_benchmarks.py
+++ b/tools/run_kotlin_benchmarks.py
@@ -87,25 +87,25 @@
(options, args) = parse_options()
if options.golem:
golem.link_third_party()
- temp = '/tmp/output'
- dex_path = os.path.join(temp, "classes.jar")
- proguard_conf = os.path.join(temp, 'proguard.conf')
- with open(proguard_conf, 'w') as f:
- f.write(PROGUARD_CONF)
- benchmark_jar = get_jar_for_benchmark(options.benchmark)
- r8_args = [
- '--lib', utils.get_android_jar(26), # Only works with api 26
- '--output', dex_path,
- '--pg-conf', proguard_conf,
- '--min-api', str(options.api),
- benchmark_jar
- ]
- toolhelper.run('r8', r8_args, build=not options.golem)
- if options.use_device:
- result = run_art_device(dex_path)
- else:
- result = run_art(dex_path)
- print('Kotlin_{}(RunTimeRaw): {} ms'.format(options.benchmark, result))
+ with utils.TempDir() as temp:
+ dex_path = os.path.join(temp, "classes.jar")
+ proguard_conf = os.path.join(temp, 'proguard.conf')
+ with open(proguard_conf, 'w') as f:
+ f.write(PROGUARD_CONF)
+ benchmark_jar = get_jar_for_benchmark(options.benchmark)
+ r8_args = [
+ '--lib', utils.get_android_jar(26), # Only works with api 26
+ '--output', dex_path,
+ '--pg-conf', proguard_conf,
+ '--min-api', str(options.api),
+ benchmark_jar
+ ]
+ toolhelper.run('r8', r8_args, build=not options.golem)
+ if options.use_device:
+ result = run_art_device(dex_path)
+ else:
+ result = run_art(dex_path)
+ print('Kotlin_{}(RunTimeRaw): {} ms'.format(options.benchmark, result))
if __name__ == '__main__':
sys.exit(Main())