Merge "Add com.numix.calculator to run_on_as_app.py"
diff --git a/build.gradle b/build.gradle
index 6afc31a..d9fd85d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -471,6 +471,8 @@
// Javac often runs out of stack space when compiling the tests.
// Increase the stack size for the javac process.
options.forkOptions.jvmArgs << "-Xss4m"
+ // Test compilation is sometimes hitting the default limit at 1g, increase it.
+ options.forkOptions.jvmArgs << "-Xmx2g"
// Set the bootclass path so compilation is consistent with 1.8 target compatibility.
options.forkOptions.jvmArgs << "-Xbootclasspath/a:third_party/openjdk/openjdk-rt-1.8/rt.jar"
}
@@ -1508,7 +1510,7 @@
if (project.hasProperty('r8lib') || project.hasProperty('r8lib_no_deps')) {
def out = new StringBuffer()
def err = new StringBuffer()
- def command = "tools/retrace.py"
+ def command = "python tools/retrace.py"
def header = "RETRACED STACKTRACE";
if (System.getenv('BUILDBOT_BUILDERNAME') != null
&& !System.getenv('BUILDBOT_BUILDERNAME').endsWith("_release")) {
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 5131b19..6705f0a 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -85,6 +85,7 @@
builders {
name: "archive"
+ priority: 25
mixins: "linux"
execution_timeout_secs: 1800 # 1/2h
recipe {
@@ -93,6 +94,7 @@
}
builders {
name: "archive_release"
+ priority: 25
mixins: "linux"
execution_timeout_secs: 1800 # 1/2h
recipe {
diff --git a/infra/config/global/luci-notify.cfg b/infra/config/global/luci-notify.cfg
new file mode 100644
index 0000000..b8d8a32
--- /dev/null
+++ b/infra/config/global/luci-notify.cfg
@@ -0,0 +1,161 @@
+# Defines email notifications for builders.
+# See schema at
+# https://chromium.googlesource.com/infra/luci/luci-go/+/master/luci_notify/api/config/notify.proto
+#
+
+notifiers {
+ name: "r8-failures"
+ notifications {
+ on_change: false
+ on_success: false
+ on_failure: false
+ on_new_failure: true
+ email {
+ # Temporary, to ensure that it works.
+ recipients: "ricow@google.com"
+ }
+ # This means send to all people on the blamelist!
+ notify_blamelist {}
+ }
+ builders {
+ name: "archive"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "archive_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-4.0.4"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-4.0.4_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-4.4.4"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-4.4.4_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-5.1.1"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-5.1.1_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-6.0.1"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-6.0.1_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-7.0.0"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-android-7.0.0_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-jctf"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux-jctf_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "d8-linux_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-4.0.4"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-4.0.4_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-4.4.4"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-4.4.4_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-5.1.1"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-5.1.1_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-6.0.1"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-6.0.1_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-7.0.0"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-android-7.0.0_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-internal"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-internal_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-jctf"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "linux-jctf_release"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "r8cf-linux-jctf"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "windows"
+ bucket: "luci.r8.ci"
+ }
+ builders {
+ name: "windows_release"
+ bucket: "luci.r8.ci"
+ }
+}
+
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index 2b67476..4de5097 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -74,6 +74,9 @@
job {
id: "archive"
acl_sets: "default"
+ triggering_policy: {
+ max_concurrent_invocations: 3
+ }
buildbucket {
server: "cr-buildbucket.appspot.com"
bucket: "luci.r8.ci"
@@ -403,6 +406,9 @@
job {
id: "windows"
+ triggering_policy: {
+ max_concurrent_invocations: 3
+ }
acl_sets: "default"
buildbucket {
server: "cr-buildbucket.appspot.com"
@@ -414,6 +420,9 @@
job {
id: "windows_release"
acl_sets: "default"
+ triggering_policy: {
+ max_concurrent_invocations: 3
+ }
buildbucket {
server: "cr-buildbucket.appspot.com"
bucket: "luci.r8.ci"
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index f6454f9..ad6c7d2 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -215,7 +215,9 @@
int computedMinApiLevel = options.minApiLevel;
for (ProgramResource input : dexSources) {
DexReader dexReader = new DexReader(input);
- computedMinApiLevel = validateOrComputeMinApiLevel(computedMinApiLevel, dexReader);
+ if (options.passthroughDexCode) {
+ computedMinApiLevel = validateOrComputeMinApiLevel(computedMinApiLevel, dexReader);
+ }
dexParsers.add(new DexParser(dexReader, classKind, itemFactory, options.reporter));
}
options.minApiLevel = computedMinApiLevel;
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index d7426fc..92c07d1 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
@@ -25,8 +24,6 @@
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
-import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@@ -44,7 +41,9 @@
private final AppView<AppInfoWithLiveness> appView;
private final AppInfoWithLiveness appInfo;
- private final Reporter reporter;
+ private final ClassNamingStrategy classNamingStrategy;
+ private final PackageNamingStrategy packageNamingStrategy;
+ private final Iterable<? extends DexClass> classes;
private final PackageObfuscationMode packageObfuscationMode;
private final boolean isAccessModificationAllowed;
private final Set<String> noObfuscationPrefixes = Sets.newHashSet();
@@ -62,11 +61,18 @@
private final Namespace topLevelState;
- ClassNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+ ClassNameMinifier(
+ AppView<AppInfoWithLiveness> appView,
+ RootSet rootSet,
+ ClassNamingStrategy classNamingStrategy,
+ PackageNamingStrategy packageNamingStrategy,
+ Iterable<? extends DexClass> classes) {
this.appView = appView;
this.appInfo = appView.appInfo();
+ this.classNamingStrategy = classNamingStrategy;
+ this.packageNamingStrategy = packageNamingStrategy;
+ this.classes = classes;
InternalOptions options = appView.options();
- this.reporter = options.reporter;
this.packageObfuscationMode = options.getProguardConfiguration().getPackageObfuscationMode();
this.isAccessModificationAllowed =
options.getProguardConfiguration().isAccessModificationAllowed();
@@ -99,8 +105,6 @@
}
ClassRenaming computeRenaming(Timing timing) {
- // Use deterministic class order to make sure renaming is deterministic.
- Iterable<DexProgramClass> classes = appInfo.classesWithDeterministicOrder();
// Collect names we have to keep.
timing.begin("reserve");
for (DexClass clazz : classes) {
@@ -175,7 +179,7 @@
// return type. As we don't need the class, we can rename it to anything as long as it is
// unique.
assert appInfo.definitionFor(type) == null;
- renaming.put(type, topLevelState.nextTypeName());
+ renaming.put(type, topLevelState.nextTypeName(type));
}
}
@@ -250,7 +254,7 @@
if (state == null) {
state = getStateForClass(type);
}
- return state.nextTypeName();
+ return state.nextTypeName(type);
}
private Namespace getStateForClass(DexType type) {
@@ -344,12 +348,10 @@
}
}
- private class Namespace {
+ protected class Namespace {
private final String packageName;
private final char[] packagePrefix;
- private int typeCounter = 1;
- private int packageCounter = 1;
private final Iterator<String> packageDictionaryIterator;
private final Iterator<String> classDictionaryIterator;
@@ -376,37 +378,37 @@
return packageName;
}
- private String nextSuggestedNameForClass() {
+ private DexString nextSuggestedNameForClass(DexType type) {
StringBuilder nextName = new StringBuilder();
- if (classDictionaryIterator.hasNext()) {
+ if (!classNamingStrategy.bypassDictionary() && classDictionaryIterator.hasNext()) {
nextName.append(packagePrefix).append(classDictionaryIterator.next()).append(';');
- return nextName.toString();
+ return appInfo.dexItemFactory.createString(nextName.toString());
} else {
- return StringUtils.numberToIdentifier(packagePrefix, typeCounter++, true);
+ return classNamingStrategy.next(this, type, packagePrefix);
}
}
- DexString nextTypeName() {
+ DexString nextTypeName(DexType type) {
DexString candidate;
do {
- candidate = appInfo.dexItemFactory.createString(nextSuggestedNameForClass());
+ candidate = nextSuggestedNameForClass(type);
} while (usedTypeNames.contains(candidate));
usedTypeNames.add(candidate);
return candidate;
}
private String nextSuggestedNameForSubpackage() {
- StringBuilder nextName = new StringBuilder();
// Note that the differences between this method and the other variant for class renaming are
// 1) this one uses the different dictionary and counter,
// 2) this one does not append ';' at the end, and
// 3) this one removes 'L' at the beginning to make the return value a binary form.
- if (packageDictionaryIterator.hasNext()) {
+ if (!packageNamingStrategy.bypassDictionary() && packageDictionaryIterator.hasNext()) {
+ StringBuilder nextName = new StringBuilder();
nextName.append(packagePrefix).append(packageDictionaryIterator.next());
+ return nextName.toString().substring(1);
} else {
- nextName.append(StringUtils.numberToIdentifier(packagePrefix, packageCounter++, false));
+ return packageNamingStrategy.next(this, packagePrefix);
}
- return nextName.toString().substring(1);
}
String nextPackagePrefix() {
@@ -419,6 +421,20 @@
}
}
+ protected interface ClassNamingStrategy {
+
+ DexString next(Namespace namespace, DexType type, char[] packagePrefix);
+
+ boolean bypassDictionary();
+ }
+
+ protected interface PackageNamingStrategy {
+
+ String next(Namespace namespace, char[] packagePrefix);
+
+ boolean bypassDictionary();
+ }
+
/**
* Compute parent package prefix from the given package prefix.
*
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index e2127dd..e419d5a 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -19,8 +19,9 @@
class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
- FieldNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
- super(appView, rootSet);
+ FieldNameMinifier(
+ AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+ super(appView, rootSet, strategy);
}
@Override
@@ -106,7 +107,8 @@
private void renameField(DexEncodedField encodedField, NamingState<DexType, ?> state) {
DexField field = encodedField.field;
if (!state.isReserved(field.name, field.type)) {
- renaming.put(field, state.assignNewNameFor(field.name, field.type, useUniqueMemberNames));
+ renaming.put(
+ field, state.assignNewNameFor(field, field.name, field.type, useUniqueMemberNames));
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java
index b643be3..6c46119 100644
--- a/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/InterfaceMethodNameMinifier.java
@@ -234,7 +234,8 @@
sourceMethods.addAll(sourceMethodsMap.get(k));
for (NamingState<DexProto, ?> namingState : globalStateMap.get(k)) {
collectedStates.add(
- new MethodNamingState(namingState, unifiedMethod.name, unifiedMethod.proto));
+ new MethodNamingState(
+ namingState, unifiedMethod, unifiedMethod.name, unifiedMethod.proto));
}
}
@@ -249,7 +250,7 @@
}
MethodNamingState originState =
- new MethodNamingState(originStates.get(key), method.name, method.proto);
+ new MethodNamingState(originStates.get(key), method, method.name, method.proto);
assignNameForInterfaceMethodInAllStates(collectedStates, sourceMethods, originState);
}
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 53957e4..d60de88 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -5,8 +5,10 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CachedHashValueDexItem;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.naming.NamingState.InternalState;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions;
@@ -36,7 +38,8 @@
// which is useful for debugging.
private final BiMap<DexType, NamingState<StateType, ?>> states = HashBiMap.create();
- MemberNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+ MemberNameMinifier(
+ AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
this.appView = appView;
this.appInfo = appView.appInfo();
this.rootSet = rootSet;
@@ -45,8 +48,9 @@
this.useUniqueMemberNames = options.getProguardConfiguration().isUseUniqueClassMemberNames();
this.overloadAggressively =
options.getProguardConfiguration().isOverloadAggressivelyWithoutUseUniqueClassMemberNames();
- this.globalState = NamingState.createRoot(
- appInfo.dexItemFactory, dictionary, getKeyTransform(), useUniqueMemberNames);
+ this.globalState =
+ NamingState.createRoot(
+ appInfo.dexItemFactory, dictionary, getKeyTransform(), strategy, useUniqueMemberNames);
}
abstract Function<StateType, ?> getKeyTransform();
@@ -88,4 +92,10 @@
return useUniqueMemberNames;
}
}
+
+ interface MemberNamingStrategy {
+ DexString next(DexReference source, InternalState internalState);
+
+ boolean bypassDictionary();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index 2cd8712..e97910f 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -91,9 +91,12 @@
private final Equivalence<DexMethod> equivalence;
private final FrontierState frontierState = new FrontierState();
+ private final MemberNamingStrategy strategy;
- MethodNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
- super(appView, rootSet);
+ MethodNameMinifier(
+ AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+ super(appView, rootSet, strategy);
+ this.strategy = strategy;
equivalence =
overloadAggressively
? MethodSignatureEquivalence.get()
@@ -188,7 +191,8 @@
DexString renamedName =
renamingAtThisLevel.computeIfAbsent(
equivalence.wrap(method),
- key -> state.assignNewNameFor(method.name, method.proto, useUniqueMemberNames));
+ key ->
+ state.assignNewNameFor(method, method.name, method.proto, useUniqueMemberNames));
renaming.put(method, renamedName);
}
}
@@ -233,6 +237,7 @@
appInfo.dexItemFactory,
dictionary,
getKeyTransform(),
+ strategy,
useUniqueMemberNames)
: parent.createChild());
@@ -276,8 +281,11 @@
private final NamingState<DexProto, ?> parent;
private final DexString name;
private final DexProto proto;
+ private final DexMethod method;
- MethodNamingState(NamingState<DexProto, ?> parent, DexString name, DexProto proto) {
+ MethodNamingState(
+ NamingState<DexProto, ?> parent, DexMethod method, DexString name, DexProto proto) {
+ this.method = method;
assert parent != null;
this.parent = parent;
this.name = name;
@@ -285,11 +293,7 @@
}
DexString assignNewName() {
- return parent.assignNewNameFor(name, proto, false);
- }
-
- void reserveName() {
- parent.reserveName(name, proto);
+ return parent.assignNewNameFor(method, name, proto, false);
}
boolean isReserved() {
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
new file mode 100644
index 0000000..f72efe1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
@@ -0,0 +1,186 @@
+// Copyright (c) 2019, 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.naming;
+
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.DexCallSite;
+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.DexItem;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
+import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
+import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
+import com.android.tools.r8.optimize.MemberRebindingAnalysis;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.ImmutableMap;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+class MinifiedRenaming extends NamingLens {
+
+ private final AppInfo appInfo;
+ private final Map<String, String> packageRenaming;
+ private final Map<DexItem, DexString> renaming = new IdentityHashMap<>();
+
+ MinifiedRenaming(
+ ClassRenaming classRenaming,
+ MethodRenaming methodRenaming,
+ FieldRenaming fieldRenaming,
+ AppInfo appInfo) {
+ this.appInfo = appInfo;
+ this.packageRenaming = classRenaming.packageRenaming;
+ renaming.putAll(classRenaming.classRenaming);
+ renaming.putAll(methodRenaming.renaming);
+ renaming.putAll(methodRenaming.callSiteRenaming);
+ renaming.putAll(fieldRenaming.renaming);
+ }
+
+ @Override
+ public String lookupPackageName(String packageName) {
+ return packageRenaming.getOrDefault(packageName, packageName);
+ }
+
+ @Override
+ public DexString lookupDescriptor(DexType type) {
+ return renaming.getOrDefault(type, type.descriptor);
+ }
+
+ @Override
+ public DexString lookupInnerName(InnerClassAttribute attribute, InternalOptions options) {
+ if (attribute.getInnerName() == null) {
+ return null;
+ }
+ // The Java reflection library assumes that that inner-class names are separated by a $ and
+ // thus we allow the mapping of an inner name to rely on that too. If the dollar is not
+ // present after pulling off the original inner-name, then we revert to using the simple name
+ // of the inner class as its name.
+ DexType innerType = attribute.getInner();
+ String inner = DescriptorUtils.descriptorToInternalName(innerType.descriptor.toString());
+ String innerName = attribute.getInnerName().toString();
+ int lengthOfPrefix = inner.length() - innerName.length();
+ if (lengthOfPrefix < 0
+ || inner.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR, lengthOfPrefix - 1) < 0
+ || !inner.endsWith(innerName)) {
+ return lookupSimpleName(innerType, options.itemFactory);
+ }
+
+ // At this point we assume the input was of the form: <OuterType>$<index><InnerName>
+ // Find the mapped type and if it remains the same return that, otherwise split at $.
+ String innerTypeMapped =
+ DescriptorUtils.descriptorToInternalName(lookupDescriptor(innerType).toString());
+ if (inner.equals(innerTypeMapped)) {
+ return attribute.getInnerName();
+ }
+ int index = innerTypeMapped.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR);
+ if (index < 0) {
+ // TODO(b/120639028): Replace this by "assert false" and remove the testing option.
+ // Hitting means we have converted a proper Outer$Inner relationship to an invalid one.
+ assert !options.testing.allowFailureOnInnerClassErrors
+ : "Outer$Inner class was remapped without keeping the dollar separator";
+ return lookupSimpleName(innerType, options.itemFactory);
+ }
+ return options.itemFactory.createString(innerTypeMapped.substring(index + 1));
+ }
+
+ @Override
+ public DexString lookupName(DexMethod method) {
+ return renaming.getOrDefault(method, method.name);
+ }
+
+ @Override
+ public DexString lookupMethodName(DexCallSite callSite) {
+ return renaming.getOrDefault(callSite, callSite.methodName);
+ }
+
+ @Override
+ public DexString lookupName(DexField field) {
+ return renaming.getOrDefault(field, field.name);
+ }
+
+ @Override
+ void forAllRenamedTypes(Consumer<DexType> consumer) {
+ DexReference.filterDexType(DexReference.filterDexReference(renaming.keySet().stream()))
+ .forEach(consumer);
+ }
+
+ @Override
+ <T extends DexItem> Map<String, T> getRenamedItems(
+ Class<T> clazz, Predicate<T> predicate, Function<T, String> namer) {
+ return renaming.keySet().stream()
+ .filter(item -> (clazz.isInstance(item) && predicate.test(clazz.cast(item))))
+ .map(clazz::cast)
+ .collect(ImmutableMap.toImmutableMap(namer, i -> i));
+ }
+
+ /**
+ * Checks whether the target is precise enough to be translated,
+ *
+ * <p>We only track the renaming of actual definitions, Thus, if we encounter a method id that
+ * does not directly point at a definition, we won't find the actual renaming. To avoid
+ * dispatching on every lookup, we assume that the tree has been fully dispatched by {@link
+ * MemberRebindingAnalysis}.
+ *
+ * <p>Library methods are excluded from this check, as those are never renamed.
+ */
+ @Override
+ public boolean checkTargetCanBeTranslated(DexMethod item) {
+ if (item.holder.isArrayType()) {
+ // Array methods are never renamed, so do not bother to check.
+ return true;
+ }
+ DexClass holder = appInfo.definitionFor(item.holder);
+ if (holder == null || holder.isLibraryClass()) {
+ return true;
+ }
+ // We don't know which invoke type this method is used for, so checks that it has been
+ // rebound either way.
+ DexEncodedMethod staticTarget = appInfo.lookupStaticTarget(item);
+ DexEncodedMethod directTarget = appInfo.lookupDirectTarget(item);
+ DexEncodedMethod virtualTarget = appInfo.lookupVirtualTarget(item.holder, item);
+ DexClass staticTargetHolder =
+ staticTarget != null ? appInfo.definitionFor(staticTarget.method.getHolder()) : null;
+ DexClass directTargetHolder =
+ directTarget != null ? appInfo.definitionFor(directTarget.method.getHolder()) : null;
+ DexClass virtualTargetHolder =
+ virtualTarget != null ? appInfo.definitionFor(virtualTarget.method.getHolder()) : null;
+ return (directTarget == null && staticTarget == null && virtualTarget == null)
+ || (virtualTarget != null && virtualTarget.method == item)
+ || (directTarget != null && directTarget.method == item)
+ || (staticTarget != null && staticTarget.method == item)
+ || (directTargetHolder != null && directTargetHolder.isLibraryClass())
+ || (virtualTargetHolder != null && virtualTargetHolder.isLibraryClass())
+ || (staticTargetHolder != null && staticTargetHolder.isLibraryClass());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ renaming.forEach(
+ (item, str) -> {
+ if (item instanceof DexType) {
+ builder.append("[c] ");
+ } else if (item instanceof DexMethod) {
+ builder.append("[m] ");
+ } else if (item instanceof DexField) {
+ builder.append("[f] ");
+ }
+ builder.append(item.toSourceString());
+ builder.append(" -> ");
+ builder.append(str.toSourceString());
+ builder.append('\n');
+ });
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index be4fd39..9aa8502 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -3,34 +3,28 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
-import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
-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.DexItem;
-import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.naming.ClassNameMinifier.ClassNamingStrategy;
import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
+import com.android.tools.r8.naming.ClassNameMinifier.Namespace;
+import com.android.tools.r8.naming.ClassNameMinifier.PackageNamingStrategy;
import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
+import com.android.tools.r8.naming.MemberNameMinifier.MemberNamingStrategy;
import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
-import com.android.tools.r8.optimize.MemberRebindingAnalysis;
+import com.android.tools.r8.naming.NamingState.InternalState;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.ImmutableMap;
-import java.util.IdentityHashMap;
-import java.util.Map;
+import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
import java.util.Set;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
public class Minifier {
@@ -54,7 +48,14 @@
public NamingLens run(Timing timing) {
assert options.enableMinification;
timing.begin("MinifyClasses");
- ClassNameMinifier classNameMinifier = new ClassNameMinifier(appView, rootSet);
+ ClassNameMinifier classNameMinifier =
+ new ClassNameMinifier(
+ appView,
+ rootSet,
+ new MinificationClassNamingStrategy(appInfo.dexItemFactory),
+ new MinificationPackageNamingStrategy(),
+ // Use deterministic class order to make sure renaming is deterministic.
+ appInfo.classesWithDeterministicOrder());
ClassRenaming classRenaming = classNameMinifier.computeRenaming(timing);
timing.end();
@@ -62,16 +63,19 @@
classRenaming, MethodRenaming.empty(), FieldRenaming.empty(), appInfo)
.verifyNoCollisions(appInfo.classes(), appInfo.dexItemFactory);
+ MemberNamingStrategy minifyMembers = new MinifierMemberNamingStrategy(appView.dexItemFactory());
timing.begin("MinifyMethods");
MethodRenaming methodRenaming =
- new MethodNameMinifier(appView, rootSet).computeRenaming(desugaredCallSites, timing);
+ new MethodNameMinifier(appView, rootSet, minifyMembers)
+ .computeRenaming(desugaredCallSites, timing);
timing.end();
assert new MinifiedRenaming(classRenaming, methodRenaming, FieldRenaming.empty(), appInfo)
.verifyNoCollisions(appInfo.classes(), appInfo.dexItemFactory);
timing.begin("MinifyFields");
- FieldRenaming fieldRenaming = new FieldNameMinifier(appView, rootSet).computeRenaming(timing);
+ FieldRenaming fieldRenaming =
+ new FieldNameMinifier(appView, rootSet, minifyMembers).computeRenaming(timing);
timing.end();
NamingLens lens = new MinifiedRenaming(classRenaming, methodRenaming, fieldRenaming, appInfo);
@@ -84,159 +88,73 @@
return lens;
}
- private static class MinifiedRenaming extends NamingLens {
+ static class MinificationClassNamingStrategy implements ClassNamingStrategy {
- private final AppInfo appInfo;
- private final Map<String, String> packageRenaming;
- private final Map<DexItem, DexString> renaming = new IdentityHashMap<>();
+ private final DexItemFactory factory;
+ private final Object2IntMap<Namespace> namespaceCounters = new Object2IntLinkedOpenHashMap<>();
- private MinifiedRenaming(
- ClassRenaming classRenaming,
- MethodRenaming methodRenaming,
- FieldRenaming fieldRenaming,
- AppInfo appInfo) {
- this.appInfo = appInfo;
- this.packageRenaming = classRenaming.packageRenaming;
- renaming.putAll(classRenaming.classRenaming);
- renaming.putAll(methodRenaming.renaming);
- renaming.putAll(methodRenaming.callSiteRenaming);
- renaming.putAll(fieldRenaming.renaming);
+ MinificationClassNamingStrategy(DexItemFactory factory) {
+ this.factory = factory;
+ namespaceCounters.defaultReturnValue(1);
}
@Override
- public String lookupPackageName(String packageName) {
- return packageRenaming.getOrDefault(packageName, packageName);
+ public DexString next(Namespace namespace, DexType type, char[] packagePrefix) {
+ int counter = namespaceCounters.put(namespace, namespaceCounters.getInt(namespace) + 1);
+ DexString string =
+ factory.createString(StringUtils.numberToIdentifier(packagePrefix, counter, true));
+ return string;
}
@Override
- public DexString lookupDescriptor(DexType type) {
- return renaming.getOrDefault(type, type.descriptor);
+ public boolean bypassDictionary() {
+ return false;
+ }
+ }
+
+ static class MinificationPackageNamingStrategy implements PackageNamingStrategy {
+
+ private final Object2IntMap<Namespace> namespaceCounters = new Object2IntLinkedOpenHashMap<>();
+
+ public MinificationPackageNamingStrategy() {
+ namespaceCounters.defaultReturnValue(1);
}
@Override
- public DexString lookupInnerName(InnerClassAttribute attribute, InternalOptions options) {
- if (attribute.getInnerName() == null) {
- return null;
- }
- // The Java reflection library assumes that that inner-class names are separated by a $ and
- // thus we allow the mapping of an inner name to rely on that too. If the dollar is not
- // present after pulling off the original inner-name, then we revert to using the simple name
- // of the inner class as its name.
- DexType innerType = attribute.getInner();
- String inner = DescriptorUtils.descriptorToInternalName(innerType.descriptor.toString());
- String innerName = attribute.getInnerName().toString();
- int lengthOfPrefix = inner.length() - innerName.length();
- if (lengthOfPrefix < 0
- || inner.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR, lengthOfPrefix - 1) < 0
- || !inner.endsWith(innerName)) {
- return lookupSimpleName(innerType, options.itemFactory);
- }
-
- // At this point we assume the input was of the form: <OuterType>$<index><InnerName>
- // Find the mapped type and if it remains the same return that, otherwise split at $.
- String innerTypeMapped =
- DescriptorUtils.descriptorToInternalName(lookupDescriptor(innerType).toString());
- if (inner.equals(innerTypeMapped)) {
- return attribute.getInnerName();
- }
- int index = innerTypeMapped.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR);
- if (index < 0) {
- // TODO(b/120639028): Replace this by "assert false" and remove the testing option.
- // Hitting means we have converted a proper Outer$Inner relationship to an invalid one.
- assert !options.testing.allowFailureOnInnerClassErrors
- : "Outer$Inner class was remapped without keeping the dollar separator";
- return lookupSimpleName(innerType, options.itemFactory);
- }
- return options.itemFactory.createString(innerTypeMapped.substring(index + 1));
+ public String next(Namespace namespace, char[] packagePrefix) {
+ // Note that the differences between this method and the other variant for class renaming are
+ // 1) this one uses the different dictionary and counter,
+ // 2) this one does not append ';' at the end, and
+ // 3) this one removes 'L' at the beginning to make the return value a binary form.
+ int counter = namespaceCounters.put(namespace, namespaceCounters.getInt(namespace) + 1);
+ return StringUtils.numberToIdentifier(packagePrefix, counter, false).substring(1);
}
@Override
- public DexString lookupName(DexMethod method) {
- return renaming.getOrDefault(method, method.name);
+ public boolean bypassDictionary() {
+ return false;
+ }
+ }
+
+ static class MinifierMemberNamingStrategy implements MemberNamingStrategy {
+
+ char[] EMPTY_CHAR_ARRAY = new char[0];
+
+ private final DexItemFactory factory;
+
+ public MinifierMemberNamingStrategy(DexItemFactory factory) {
+ this.factory = factory;
}
@Override
- public DexString lookupMethodName(DexCallSite callSite) {
- return renaming.getOrDefault(callSite, callSite.methodName);
+ public DexString next(DexReference dexReference, InternalState internalState) {
+ int counter = internalState.incrementAndGet();
+ return factory.createString(StringUtils.numberToIdentifier(EMPTY_CHAR_ARRAY, counter, false));
}
@Override
- public DexString lookupName(DexField field) {
- return renaming.getOrDefault(field, field.name);
- }
-
- @Override
- void forAllRenamedTypes(Consumer<DexType> consumer) {
- DexReference.filterDexType(DexReference.filterDexReference(renaming.keySet().stream()))
- .forEach(consumer);
- }
-
- @Override
- <T extends DexItem> Map<String, T> getRenamedItems(
- Class<T> clazz, Predicate<T> predicate, Function<T, String> namer) {
- return renaming.keySet().stream()
- .filter(item -> (clazz.isInstance(item) && predicate.test(clazz.cast(item))))
- .map(clazz::cast)
- .collect(ImmutableMap.toImmutableMap(namer, i -> i));
- }
-
- /**
- * Checks whether the target is precise enough to be translated,
- * <p>
- * We only track the renaming of actual definitions, Thus, if we encounter a method id that
- * does not directly point at a definition, we won't find the actual renaming. To avoid
- * dispatching on every lookup, we assume that the tree has been fully dispatched by
- * {@link MemberRebindingAnalysis}.
- * <p>
- * Library methods are excluded from this check, as those are never renamed.
- */
- @Override
- public boolean checkTargetCanBeTranslated(DexMethod item) {
- if (item.holder.isArrayType()) {
- // Array methods are never renamed, so do not bother to check.
- return true;
- }
- DexClass holder = appInfo.definitionFor(item.holder);
- if (holder == null || holder.isLibraryClass()) {
- return true;
- }
- // We don't know which invoke type this method is used for, so checks that it has been
- // rebound either way.
- DexEncodedMethod staticTarget = appInfo.lookupStaticTarget(item);
- DexEncodedMethod directTarget = appInfo.lookupDirectTarget(item);
- DexEncodedMethod virtualTarget = appInfo.lookupVirtualTarget(item.holder, item);
- DexClass staticTargetHolder =
- staticTarget != null ? appInfo.definitionFor(staticTarget.method.getHolder()) : null;
- DexClass directTargetHolder =
- directTarget != null ? appInfo.definitionFor(directTarget.method.getHolder()) : null;
- DexClass virtualTargetHolder =
- virtualTarget != null ? appInfo.definitionFor(virtualTarget.method.getHolder()) : null;
- return (directTarget == null && staticTarget == null && virtualTarget == null)
- || (virtualTarget != null && virtualTarget.method == item)
- || (directTarget != null && directTarget.method == item)
- || (staticTarget != null && staticTarget.method == item)
- || (directTargetHolder != null && directTargetHolder.isLibraryClass())
- || (virtualTargetHolder != null && virtualTargetHolder.isLibraryClass())
- || (staticTargetHolder != null && staticTargetHolder.isLibraryClass());
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- renaming.forEach((item, str) -> {
- if (item instanceof DexType) {
- builder.append("[c] ");
- } else if (item instanceof DexMethod) {
- builder.append("[m] ");
- } else if (item instanceof DexField) {
- builder.append("[f] ");
- }
- builder.append(item.toSourceString());
- builder.append(" -> ");
- builder.append(str.toSourceString());
- builder.append('\n');
- });
- return builder.toString();
+ public boolean bypassDictionary() {
+ return false;
}
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/NamingState.java b/src/main/java/com/android/tools/r8/naming/NamingState.java
index d414b3b..a3352ad 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -5,8 +5,9 @@
import com.android.tools.r8.graph.CachedHashValueDexItem;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.naming.MemberNameMinifier.MemberNamingStrategy;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@@ -27,14 +28,17 @@
private final DexItemFactory itemFactory;
private final List<String> dictionary;
private final Function<ProtoType, KeyType> keyTransform;
+ private final MemberNamingStrategy strategy;
private final boolean useUniqueMemberNames;
static <S, T extends CachedHashValueDexItem> NamingState<T, S> createRoot(
DexItemFactory itemFactory,
List<String> dictionary,
Function<T, S> keyTransform,
+ MemberNamingStrategy strategy,
boolean useUniqueMemberNames) {
- return new NamingState<>(null, itemFactory, dictionary, keyTransform, useUniqueMemberNames);
+ return new NamingState<>(
+ null, itemFactory, dictionary, keyTransform, strategy, useUniqueMemberNames);
}
private NamingState(
@@ -42,16 +46,19 @@
DexItemFactory itemFactory,
List<String> dictionary,
Function<ProtoType, KeyType> keyTransform,
+ MemberNamingStrategy strategy,
boolean useUniqueMemberNames) {
this.parent = parent;
this.itemFactory = itemFactory;
this.dictionary = dictionary;
this.keyTransform = keyTransform;
+ this.strategy = strategy;
this.useUniqueMemberNames = useUniqueMemberNames;
}
public NamingState<ProtoType, KeyType> createChild() {
- return new NamingState<>(this, itemFactory, dictionary, keyTransform, useUniqueMemberNames);
+ return new NamingState<>(
+ this, itemFactory, dictionary, keyTransform, strategy, useUniqueMemberNames);
}
private InternalState findInternalStateFor(KeyType key) {
@@ -85,12 +92,13 @@
return state.getAssignedNameFor(name, key);
}
- public DexString assignNewNameFor(DexString original, ProtoType proto, boolean markAsUsed) {
+ public DexString assignNewNameFor(
+ DexReference source, DexString original, ProtoType proto, boolean markAsUsed) {
KeyType key = keyTransform.apply(proto);
DexString result = getAssignedNameFor(original, key);
if (result == null) {
InternalState state = getOrCreateInternalStateFor(key);
- result = state.getNameFor(original, key, markAsUsed);
+ result = state.getNameFor(source, original, key, markAsUsed);
}
return result;
}
@@ -146,7 +154,6 @@
class InternalState {
private static final int INITIAL_NAME_COUNT = 1;
- private final char[] EMPTY_CHAR_ARRAY = new char[0];
protected final DexItemFactory itemFactory;
private final InternalState parentInternalState;
@@ -193,6 +200,10 @@
reservedNames.add(name);
}
+ public int incrementAndGet() {
+ return nameCount++;
+ }
+
DexString getAssignedNameFor(DexString original, KeyType proto) {
DexString result = null;
if (renamings != null) {
@@ -215,13 +226,14 @@
return result;
}
- DexString getNameFor(DexString original, KeyType proto, boolean markAsUsed) {
+ DexString getNameFor(
+ DexReference source, DexString original, KeyType proto, boolean markAsUsed) {
DexString name = getAssignedNameFor(original, proto);
if (name != null) {
return name;
}
do {
- name = itemFactory.createString(nextSuggestedName());
+ name = nextSuggestedName(source);
} while (!isAvailable(name));
if (markAsUsed) {
addRenaming(original, proto, name);
@@ -236,11 +248,11 @@
renamings.put(original, proto, newName);
}
- String nextSuggestedName() {
- if (dictionaryIterator.hasNext()) {
- return dictionaryIterator.next();
+ DexString nextSuggestedName(DexReference source) {
+ if (!strategy.bypassDictionary() && dictionaryIterator.hasNext()) {
+ return itemFactory.createString(dictionaryIterator.next());
} else {
- return StringUtils.numberToIdentifier(EMPTY_CHAR_ARRAY, nameCount++, false);
+ return strategy.next(source, this);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java
index 139000e..698cf50 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java
@@ -7,6 +7,8 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -39,13 +41,18 @@
String expectedOutput = StringUtils.lines("I.m()", "JImpl.m()");
byte[] dex = buildProgramDexFileData();
- AndroidApp app =
- AndroidApp.builder().addDexProgramData(buildProgramDexFileData(), Origin.unknown()).build();
- assertEquals(expectedOutput, runOnArt(app, "TestClass"));
+ if (ToolHelper.getDexVm().getVersion().isNewerThan(Version.V6_0_1)) {
+ AndroidApp app =
+ AndroidApp.builder()
+ .addDexProgramData(buildProgramDexFileData(), Origin.unknown())
+ .build();
+ assertEquals(expectedOutput, runOnArt(app, "TestClass"));
+ }
testForR8(Backend.DEX)
.addProgramDexFileData(dex)
.addKeepMainRule("TestClass")
+ .setMinApi(AndroidApiLevel.M)
.run("TestClass")
.assertSuccessWithOutput(expectedOutput);
}
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java
index b99cbdc..3e3fd4e 100644
--- a/src/test/java/com/android/tools/r8/utils/Smali.java
+++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -105,6 +105,7 @@
SingleFileConsumer consumer = new SingleFileConsumer();
AndroidApp app = AndroidApp.builder().addDexProgramData(data, Origin.unknown()).build();
InternalOptions options = new InternalOptions();
+ options.minApiLevel = apiLevel;
options.programConsumer = consumer;
ExecutorService executor = ThreadUtils.getExecutorService(1);
try {
diff --git a/tools/archive.py b/tools/archive.py
index 5c0c231..687844a 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -8,6 +8,7 @@
import jdk
import optparse
import os
+import resource
import shutil
import subprocess
import sys
@@ -90,16 +91,21 @@
def GetMavenUrl(is_master):
return GetVersionDestination('http://storage.googleapis.com/', '', is_master)
+def PrintResourceInfo():
+ (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
+ print('INFO: Open files soft limit: %s' % soft)
+ print('INFO: Open files hard limit: %s' % hard)
+
def Main():
(options, args) = ParseOptions()
- # TODO(126871526): Fix the is_bot check.
- # if not utils.is_bot() and not options.dry_run:
- # raise Exception('You are not a bot, don\'t archive builds')
+ if not utils.is_bot() and not options.dry_run:
+ raise Exception('You are not a bot, don\'t archive builds')
if utils.is_old_bot():
print("Archiving is disabled on old bots.")
return
+ PrintResourceInfo()
# Create maven release which uses a build that exclude dependencies.
create_maven_release.main(["--out", utils.LIBS])