aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Herhut <herhut@google.com>2017-10-27 09:33:15 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-10-27 09:33:15 +0000
commit2bfb29a43eba84ad3345b17f33960dc72bb97564 (patch)
tree8f458f0b8d4aeec207a76e33d4e41f068369d7c6
parent7cec45be0c6c08de76fb9c7f6d0cdab41f703197 (diff)
parentf17b35072cc9b061008e6d12312d356e41a36368 (diff)
downloadr8-2bfb29a43eba84ad3345b17f33960dc72bb97564.tar.gz
Merge "Implement support for not overloading aggressively, making that the default."
-rw-r--r--src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java23
-rw-r--r--src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java17
-rw-r--r--src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java81
-rw-r--r--src/main/java/com/android/tools/r8/naming/NamingState.java50
-rw-r--r--src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java16
-rw-r--r--src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java3
-rw-r--r--src/test/examples/uniquemembernames/BaseCls.java8
-rw-r--r--src/test/examples/uniquemembernames/ClsA.java4
-rw-r--r--src/test/examples/uniquemembernames/ClsB.java6
-rw-r--r--src/test/examples/uniquemembernames/Shaking.java2
-rw-r--r--src/test/examples/uniquemembernames/keep-rules-1.txt4
-rw-r--r--src/test/examples/uniquemembernames/keep-rules-2.txt4
-rw-r--r--src/test/java/com/android/tools/r8/naming/UseUniqueMemberNameTest.java6
13 files changed, 139 insertions, 85 deletions
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 7cbdf9b74..a4f49122e 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -9,10 +9,12 @@ import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import java.util.Map;
+import java.util.function.Function;
class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
@@ -20,6 +22,17 @@ class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
super(appInfo, rootSet, options);
}
+ @Override
+ Function<DexType, ?> getKeyTransform(ProguardConfiguration config) {
+ if (config.isOverloadAggressively()) {
+ // Use the type as the key, hence reuse names per type.
+ return a -> a;
+ } else {
+ // Always use the same key, hence do not reuse names per type.
+ return a -> Void.class;
+ }
+ }
+
Map<DexField, DexString> computeRenaming(Timing timing) {
// Reserve names in all classes first. We do this in subtyping order so we do not
// shadow a reserved field in subclasses. While there is no concept of virtual field
@@ -41,19 +54,19 @@ class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
return renaming;
}
- private void reserveNamesInSubtypes(DexType type, NamingState<DexType> state) {
+ private void reserveNamesInSubtypes(DexType type, NamingState<DexType, ?> state) {
DexClass holder = appInfo.definitionFor(type);
if (holder == null) {
return;
}
- NamingState<DexType> newState = computeStateIfAbsent(type, t -> state.createChild());
+ NamingState<DexType, ?> newState = computeStateIfAbsent(type, t -> state.createChild());
holder.forEachField(field -> reserveFieldName(field, newState, holder.isLibraryClass()));
type.forAllExtendsSubtypes(subtype -> reserveNamesInSubtypes(subtype, newState));
}
private void reserveFieldName(
DexEncodedField encodedField,
- NamingState<DexType> state,
+ NamingState<DexType, ?> state,
boolean isLibrary) {
if (isLibrary || rootSet.noObfuscation.contains(encodedField)) {
DexField field = encodedField.field;
@@ -66,13 +79,13 @@ class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
if (clazz == null) {
return;
}
- NamingState<DexType> state = getState(clazz.type);
+ NamingState<DexType, ?> state = getState(clazz.type);
assert state != null;
clazz.forEachField(field -> renameField(field, state));
type.forAllExtendsSubtypes(this::renameFieldsInSubtypes);
}
- private void renameField(DexEncodedField encodedField, NamingState<DexType> state) {
+ 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, false));
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 37cdb34de..4a288bec3 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -7,6 +7,7 @@ import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.CachedHashValueDexItem;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
@@ -21,25 +22,27 @@ abstract class MemberNameMinifier<MemberType, StateType extends CachedHashValueD
protected final ImmutableList<String> dictionary;
protected final Map<MemberType, DexString> renaming = new IdentityHashMap<>();
- protected final Map<DexType, NamingState<StateType>> states = new IdentityHashMap<>();
- protected final NamingState<StateType> globalState;
+ protected final Map<DexType, NamingState<StateType, ?>> states = new IdentityHashMap<>();
+ protected final NamingState<StateType, ?> globalState;
protected final boolean useUniqueMemberNames;
MemberNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, InternalOptions options) {
this.appInfo = appInfo;
this.rootSet = rootSet;
this.dictionary = options.proguardConfiguration.getObfuscationDictionary();
-
- this.globalState = NamingState.createRoot(appInfo.dexItemFactory, dictionary);
+ this.globalState = NamingState.createRoot(appInfo.dexItemFactory, dictionary,
+ getKeyTransform(options.proguardConfiguration));
this.useUniqueMemberNames = options.proguardConfiguration.isUseUniqueClassMemberNames();
}
- protected NamingState<StateType> computeStateIfAbsent(
- DexType type, Function<DexType, NamingState<StateType>> f) {
+ abstract Function<StateType, ?> getKeyTransform(ProguardConfiguration config);
+
+ protected NamingState<StateType, ?> computeStateIfAbsent(
+ DexType type, Function<DexType, NamingState<StateType, ?>> f) {
return useUniqueMemberNames ? globalState : states.computeIfAbsent(type, f);
}
- protected NamingState<StateType> getState(DexType type) {
+ protected NamingState<StateType, ?> getState(DexType type) {
return useUniqueMemberNames ? globalState : states.get(type);
}
}
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 a6499842a..7b939ae20 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -3,10 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
-import com.android.tools.r8.utils.InternalOptions;
-import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.Sets;
-
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -14,10 +10,15 @@ import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.MethodJavaSignatureEquivalence;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.Timing;
-
+import com.google.common.base.Equivalence;
+import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -25,6 +26,7 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
/**
* A pass to rename methods using common, short names.
@@ -87,10 +89,26 @@ import java.util.Set;
*/
class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
- private MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();
+ private final Equivalence<DexMethod> equivalence;
+ private final ProguardConfiguration config;
MethodNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, InternalOptions options) {
super(appInfo, rootSet, options);
+ this.config = options.proguardConfiguration;
+ equivalence = config.isOverloadAggressively()
+ ? MethodSignatureEquivalence.get()
+ : MethodJavaSignatureEquivalence.get();
+ }
+
+ @Override
+ Function<DexProto, ?> getKeyTransform(ProguardConfiguration config) {
+ if (config.isOverloadAggressively()) {
+ // Use the full proto as key, hence reuse names based on full signature.
+ return a -> a;
+ } else {
+ // Only use the parameters as key, hence do not reuse names on return type.
+ return proto -> proto.parameters;
+ }
}
Map<DexMethod, DexString> computeRenaming(Timing timing) {
@@ -128,7 +146,7 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
private void assignNamesToClassesMethods(DexType type, boolean doPrivates) {
DexClass holder = appInfo.definitionFor(type);
if (holder != null && !holder.isLibraryClass()) {
- NamingState<DexProto> state =
+ NamingState<DexProto, ?> state =
computeStateIfAbsent(type, k -> getState(holder.superType).createChild());
holder.forEachMethod(method -> assignNameToMethod(method, state, doPrivates));
}
@@ -136,7 +154,7 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
}
private void assignNameToMethod(
- DexEncodedMethod encodedMethod, NamingState<DexProto> state, boolean doPrivates) {
+ DexEncodedMethod encodedMethod, NamingState<DexProto, ?> state, boolean doPrivates) {
if (encodedMethod.accessFlags.isPrivate() != doPrivates) {
return;
}
@@ -147,19 +165,19 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
}
}
- private Set<NamingState<DexProto>> getReachableStates(DexType type,
+ private Set<NamingState<DexProto, ?>> getReachableStates(DexType type,
Map<DexType, DexType> frontierMap) {
Set<DexType> interfaces = Sets.newIdentityHashSet();
interfaces.add(type);
collectSuperInterfaces(type, interfaces);
collectSubInterfaces(type, interfaces);
- Set<NamingState<DexProto>> reachableStates = new HashSet<>();
+ Set<NamingState<DexProto, ?>> reachableStates = new HashSet<>();
for (DexType iface : interfaces) {
// Add the interface itself
reachableStates.add(getState(iface));
// And the frontiers that correspond to the classes that implement the interface.
iface.forAllImplementsSubtypes(t -> {
- NamingState<DexProto> state = getState(frontierMap.get(t));
+ NamingState<DexProto, ?> state = getState(frontierMap.get(t));
assert state != null;
reachableStates.add(state);
});
@@ -173,16 +191,16 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
// reserve the names for later method naming.
timing.begin("Compute map");
// A map from DexMethods to all the states linked to interfaces they appear in.
- Map<Wrapper<DexMethod>, Set<NamingState<DexProto>>> globalStateMap = new HashMap<>();
+ Map<Wrapper<DexMethod>, Set<NamingState<DexProto, ?>>> globalStateMap = new HashMap<>();
// A map from DexMethods to all the definitions seen. Needed as the Wrapper equalizes them all.
Map<Wrapper<DexMethod>, Set<DexMethod>> sourceMethodsMap = new HashMap<>();
// A map from DexMethods to the first interface state it was seen in. Used to pick good names.
- Map<Wrapper<DexMethod>, NamingState<DexProto>> originStates = new HashMap<>();
+ Map<Wrapper<DexMethod>, NamingState<DexProto, ?>> originStates = new HashMap<>();
DexType.forAllInterfaces(appInfo.dexItemFactory, iface -> {
assert iface.isInterface();
DexClass clazz = appInfo.definitionFor(iface);
if (clazz != null) {
- Set<NamingState<DexProto>> collectedStates = getReachableStates(iface, frontierMap);
+ Set<NamingState<DexProto, ?>> collectedStates = getReachableStates(iface, frontierMap);
clazz.forEachMethod(method -> addStatesToGlobalMapForMethod(
method, collectedStates, globalStateMap, sourceMethodsMap, originStates, iface));
}
@@ -228,12 +246,12 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
}
private void addStatesToGlobalMapForMethod(
- DexEncodedMethod method, Set<NamingState<DexProto>> collectedStates,
- Map<Wrapper<DexMethod>, Set<NamingState<DexProto>>> globalStateMap,
+ DexEncodedMethod method, Set<NamingState<DexProto, ?>> collectedStates,
+ Map<Wrapper<DexMethod>, Set<NamingState<DexProto, ?>>> globalStateMap,
Map<Wrapper<DexMethod>, Set<DexMethod>> sourceMethodsMap,
- Map<Wrapper<DexMethod>, NamingState<DexProto>> originStates, DexType originInterface) {
+ Map<Wrapper<DexMethod>, NamingState<DexProto, ?>> originStates, DexType originInterface) {
Wrapper<DexMethod> key = equivalence.wrap(method.method);
- Set<NamingState<DexProto>> stateSet =
+ Set<NamingState<DexProto, ?>> stateSet =
globalStateMap.computeIfAbsent(key, k -> new HashSet<>());
stateSet.addAll(collectedStates);
sourceMethodsMap.computeIfAbsent(key, k -> new HashSet<>()).add(method.method);
@@ -242,12 +260,12 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
private void assignNameForInterfaceMethodInAllStates(
DexMethod method,
- Set<NamingState<DexProto>> collectedStates,
+ Set<NamingState<DexProto, ?>> collectedStates,
Set<DexMethod> sourceMethods,
- NamingState<DexProto> originState) {
+ NamingState<DexProto, ?> originState) {
boolean isReserved = false;
if (globalState.isReserved(method.name, method.proto)) {
- for (NamingState<DexProto> state : collectedStates) {
+ for (NamingState<DexProto, ?> state : collectedStates) {
if (state.isReserved(method.name, method.proto)) {
isReserved = true;
break;
@@ -255,7 +273,7 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
}
if (isReserved) {
// This method's name is reserved in at least on naming state, so reserve it everywhere.
- for (NamingState<DexProto> state : collectedStates) {
+ for (NamingState<DexProto, ?> state : collectedStates) {
state.reserveName(method.name, method.proto);
}
return;
@@ -267,14 +285,14 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
DexString candidate = null;
do {
candidate = originState.assignNewNameFor(method.name, method.proto, false);
- for (NamingState<DexProto> state : collectedStates) {
+ for (NamingState<DexProto, ?> state : collectedStates) {
if (!state.isAvailable(method.name, method.proto, candidate)) {
candidate = null;
break;
}
}
} while (candidate == null);
- for (NamingState<DexProto> state : collectedStates) {
+ for (NamingState<DexProto, ?> state : collectedStates) {
state.addRenaming(method.name, method.proto, candidate);
}
// Rename all methods in interfaces that gave rise to this renaming.
@@ -284,11 +302,11 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
}
private void reserveNamesInClasses(DexType type, DexType libraryFrontier,
- NamingState<DexProto> parent,
+ NamingState<DexProto, ?> parent,
Map<DexType, DexType> frontierMap) {
assert !type.isInterface();
DexClass holder = appInfo.definitionFor(type);
- NamingState<DexProto> state = allocateNamingStateAndReserve(holder, type, libraryFrontier,
+ NamingState<DexProto, ?> state = allocateNamingStateAndReserve(holder, type, libraryFrontier,
parent, frontierMap);
// If this is a library class (or effectively a library class as it is missing) move the
// frontier forward.
@@ -307,16 +325,17 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
allocateNamingStateAndReserve(holder, type, type, null, frontierMap);
}
- private NamingState<DexProto> allocateNamingStateAndReserve(DexClass holder, DexType type,
+ private NamingState<DexProto, ?> allocateNamingStateAndReserve(DexClass holder, DexType type,
DexType libraryFrontier,
- NamingState<DexProto> parent,
+ NamingState<DexProto, ?> parent,
Map<DexType, DexType> frontierMap) {
frontierMap.put(type, libraryFrontier);
- NamingState<DexProto> state =
+ NamingState<DexProto, ?> state =
computeStateIfAbsent(
libraryFrontier,
ignore -> parent == null
- ? NamingState.createRoot(appInfo.dexItemFactory, dictionary)
+ ? NamingState
+ .createRoot(appInfo.dexItemFactory, dictionary, getKeyTransform(config))
: parent.createChild());
if (holder != null) {
boolean keepAll = holder.isLibraryClass() || holder.accessFlags.isAnnotation();
@@ -326,7 +345,7 @@ class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
}
private void reserveNamesForMethod(DexEncodedMethod method,
- boolean keepAll, NamingState<DexProto> state) {
+ boolean keepAll, NamingState<DexProto, ?> state) {
if (keepAll || rootSet.noObfuscation.contains(method)) {
state.reserveName(method.method.name, method.method.proto);
globalState.reserveName(method.method.name, method.method.proto);
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 2011530eb..874d506d9 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -10,48 +10,54 @@ import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
-import java.util.IdentityHashMap;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
-class NamingState<T extends CachedHashValueDexItem> {
+class NamingState<ProtoType extends CachedHashValueDexItem, KeyType> {
- private final NamingState<T> parent;
- private final Map<T, InternalState> usedNames = new IdentityHashMap<>();
+ private final NamingState<ProtoType, KeyType> parent;
+ private final Map<KeyType, InternalState> usedNames = new HashMap<>();
private final DexItemFactory itemFactory;
private final ImmutableList<String> dictionary;
+ private final Function<ProtoType, KeyType> keyTransform;
- static <T extends CachedHashValueDexItem> NamingState<T> createRoot(
- DexItemFactory itemFactory, ImmutableList<String> dictionary) {
- return new NamingState<>(null, itemFactory, dictionary);
+ static <S, T extends CachedHashValueDexItem> NamingState<T, S> createRoot(
+ DexItemFactory itemFactory, ImmutableList<String> dictionary, Function<T, S> keyTransform) {
+ return new NamingState<>(null, itemFactory, dictionary, keyTransform);
}
private NamingState(
- NamingState<T> parent,
+ NamingState<ProtoType, KeyType> parent,
DexItemFactory itemFactory,
- ImmutableList<String> dictionary) {
+ ImmutableList<String> dictionary,
+ Function<ProtoType, KeyType> keyTransform) {
this.parent = parent;
this.itemFactory = itemFactory;
this.dictionary = dictionary;
+ this.keyTransform = keyTransform;
}
- public NamingState<T> createChild() {
- return new NamingState<>(this, itemFactory, dictionary);
+ public NamingState<ProtoType, KeyType> createChild() {
+ return new NamingState<>(this, itemFactory, dictionary, keyTransform);
}
- private InternalState findInternalStateFor(T proto) {
- InternalState result = usedNames.get(proto);
+ private InternalState findInternalStateFor(ProtoType proto) {
+ KeyType key = keyTransform.apply(proto);
+ InternalState result = usedNames.get(key);
if (result == null && parent != null) {
result = parent.findInternalStateFor(proto);
}
return result;
}
- private InternalState getOrCreateInternalStateFor(T proto) {
+ private InternalState getOrCreateInternalStateFor(ProtoType proto) {
// TODO(herhut): Maybe allocate these sparsely and search via state chain.
- InternalState result = usedNames.get(proto);
+ KeyType key = keyTransform.apply(proto);
+ InternalState result = usedNames.get(key);
if (result == null) {
if (parent != null) {
InternalState parentState = parent.getOrCreateInternalStateFor(proto);
@@ -59,12 +65,12 @@ class NamingState<T extends CachedHashValueDexItem> {
} else {
result = new InternalState(itemFactory, null, dictionary);
}
- usedNames.put(proto, result);
+ usedNames.put(key, result);
}
return result;
}
- public DexString getAssignedNameFor(DexString name, T proto) {
+ public DexString getAssignedNameFor(DexString name, ProtoType proto) {
InternalState state = findInternalStateFor(proto);
if (state == null) {
return null;
@@ -72,7 +78,7 @@ class NamingState<T extends CachedHashValueDexItem> {
return state.getAssignedNameFor(name);
}
- public DexString assignNewNameFor(DexString original, T proto, boolean markAsUsed) {
+ public DexString assignNewNameFor(DexString original, ProtoType proto, boolean markAsUsed) {
DexString result = getAssignedNameFor(original, proto);
if (result == null) {
InternalState state = getOrCreateInternalStateFor(proto);
@@ -81,12 +87,12 @@ class NamingState<T extends CachedHashValueDexItem> {
return result;
}
- public void reserveName(DexString name, T proto) {
+ public void reserveName(DexString name, ProtoType proto) {
InternalState state = getOrCreateInternalStateFor(proto);
state.reserveName(name);
}
- public boolean isReserved(DexString name, T proto) {
+ public boolean isReserved(DexString name, ProtoType proto) {
InternalState state = findInternalStateFor(proto);
if (state == null) {
return false;
@@ -94,7 +100,7 @@ class NamingState<T extends CachedHashValueDexItem> {
return state.isReserved(name);
}
- public boolean isAvailable(DexString original, T proto, DexString candidate) {
+ public boolean isAvailable(DexString original, ProtoType proto, DexString candidate) {
InternalState state = findInternalStateFor(proto);
if (state == null) {
return true;
@@ -103,7 +109,7 @@ class NamingState<T extends CachedHashValueDexItem> {
return state.isAvailable(candidate);
}
- public void addRenaming(DexString original, T proto, DexString newName) {
+ public void addRenaming(DexString original, ProtoType proto, DexString newName) {
InternalState state = getOrCreateInternalStateFor(proto);
state.addRenaming(original, newName);
}
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 b3cfcb2aa..bdf77489e 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -45,6 +45,7 @@ public class ProguardConfiguration {
private boolean keepParameterNames;
private ProguardClassFilter.Builder adaptClassStrings = ProguardClassFilter.builder();
private boolean forceProguardCompatibility = false;
+ private boolean overloadAggressively;
private Builder(DexItemFactory dexItemFactory) {
this.dexItemFactory = dexItemFactory;
@@ -211,10 +212,13 @@ public class ProguardConfiguration {
this.forceProguardCompatibility = forceProguardCompatibility;
}
+ public void setOverloadAggressively(boolean overloadAggressively) {
+ this.overloadAggressively = overloadAggressively;
+ }
+
public ProguardConfiguration build() throws CompilationException {
ProguardKeepAttributes keepAttributes;
-
if (forceProguardCompatibility
&& !isObfuscating()
&& keepAttributePatterns.size() == 0) {
@@ -246,6 +250,7 @@ public class ProguardConfiguration {
rules,
printSeeds,
seedFile,
+ overloadAggressively,
DictionaryReader.readAllNames(obfuscationDictionary),
DictionaryReader.readAllNames(classObfuscationDictionary),
DictionaryReader.readAllNames(packageObfuscationDictionary),
@@ -277,6 +282,7 @@ public class ProguardConfiguration {
protected final ImmutableList<ProguardConfigurationRule> rules;
private final boolean printSeeds;
private final Path seedFile;
+ private final boolean overloadAggressively;
private final ImmutableList<String> obfuscationDictionary;
private final ImmutableList<String> classObfuscationDictionary;
private final ImmutableList<String> packageObfuscationDictionary;
@@ -307,6 +313,7 @@ public class ProguardConfiguration {
List<ProguardConfigurationRule> rules,
boolean printSeeds,
Path seedFile,
+ boolean overloadAggressively,
ImmutableList<String> obfuscationDictionary,
ImmutableList<String> classObfuscationDictionary,
ImmutableList<String> packageObfuscationDictionary,
@@ -335,6 +342,7 @@ public class ProguardConfiguration {
this.rules = ImmutableList.copyOf(rules);
this.printSeeds = printSeeds;
this.seedFile = seedFile;
+ this.overloadAggressively = overloadAggressively;
this.obfuscationDictionary = obfuscationDictionary;
this.classObfuscationDictionary = classObfuscationDictionary;
this.packageObfuscationDictionary = packageObfuscationDictionary;
@@ -443,6 +451,10 @@ public class ProguardConfiguration {
return rules;
}
+ public boolean isOverloadAggressively() {
+ return overloadAggressively;
+ }
+
public ImmutableList<String> getObfuscationDictionary() {
return obfuscationDictionary;
}
@@ -470,7 +482,7 @@ public class ProguardConfiguration {
public static ProguardConfiguration defaultConfiguration(DexItemFactory dexItemFactory) {
try {
return builderInitializedWithDefaults(dexItemFactory).build();
- } catch(CompilationException e) {
+ } catch (CompilationException e) {
// Building a builder initialized with defaults will not throw CompilationException because
// DictionaryReader is called with empty lists.
throw new RuntimeException();
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 71e7a734c..3f64afdaf 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -51,7 +51,6 @@ public class ProguardConfigurationParser {
"filterlibraryjarswithorginalprogramjars",
"dontskipnonpubliclibraryclasses",
"dontskipnonpubliclibraryclassmembers",
- "overloadaggressively",
"invokebasemethod");
private static final List<String> IGNORED_CLASS_DESCRIPTOR_OPTIONS = ImmutableList
.of("isclassnamestring",
@@ -245,6 +244,8 @@ public class ProguardConfigurationParser {
configurationBuilder.setFlattenPackagePrefix("");
}
}
+ } else if (acceptString("overloadaggressively")) {
+ configurationBuilder.setOverloadAggressively(true);
} else if (acceptString("allowaccessmodification")) {
configurationBuilder.setAllowAccessModification(true);
} else if (acceptString("printmapping")) {
diff --git a/src/test/examples/uniquemembernames/BaseCls.java b/src/test/examples/uniquemembernames/BaseCls.java
index 9843c7b48..2ee24fee1 100644
--- a/src/test/examples/uniquemembernames/BaseCls.java
+++ b/src/test/examples/uniquemembernames/BaseCls.java
@@ -5,17 +5,17 @@ package uniquemembernames;
public abstract class BaseCls {
- protected int a;
+ protected int c;
protected double f2;
- protected abstract int a();
+ protected abstract int c();
protected int foo() {
- return a * (int) f2;
+ return c * (int) f2;
}
protected double bar() {
- return a * f2;
+ return c * f2;
}
}
diff --git a/src/test/examples/uniquemembernames/ClsA.java b/src/test/examples/uniquemembernames/ClsA.java
index 430a255cc..563a070c4 100644
--- a/src/test/examples/uniquemembernames/ClsA.java
+++ b/src/test/examples/uniquemembernames/ClsA.java
@@ -6,8 +6,8 @@ package uniquemembernames;
public class ClsA extends BaseCls {
@Override
- protected int a() {
- return foo() + a;
+ protected int c() {
+ return foo() + c;
}
@Override
diff --git a/src/test/examples/uniquemembernames/ClsB.java b/src/test/examples/uniquemembernames/ClsB.java
index 2659d5a0c..f9d4ecd4d 100644
--- a/src/test/examples/uniquemembernames/ClsB.java
+++ b/src/test/examples/uniquemembernames/ClsB.java
@@ -6,13 +6,13 @@ package uniquemembernames;
public class ClsB extends BaseCls {
@Override
- protected int a() {
- return foo() - a;
+ protected int c() {
+ return foo() - c;
}
@Override
protected double bar() {
- return f2 != 0 ? a / f2 : Double.MAX_VALUE;
+ return f2 != 0 ? c / f2 : Double.MAX_VALUE;
}
}
diff --git a/src/test/examples/uniquemembernames/Shaking.java b/src/test/examples/uniquemembernames/Shaking.java
index ce7ed5dc6..a1b90bae6 100644
--- a/src/test/examples/uniquemembernames/Shaking.java
+++ b/src/test/examples/uniquemembernames/Shaking.java
@@ -11,7 +11,7 @@ public class Shaking {
public static void main(String[] args) {
List<BaseCls> bases = Arrays.asList(new ClsA(), new ClsB());
for (BaseCls base : bases) {
- base.a();
+ base.c();
base.foo();
base.bar();
}
diff --git a/src/test/examples/uniquemembernames/keep-rules-1.txt b/src/test/examples/uniquemembernames/keep-rules-1.txt
index 2acd66a93..40057e457 100644
--- a/src/test/examples/uniquemembernames/keep-rules-1.txt
+++ b/src/test/examples/uniquemembernames/keep-rules-1.txt
@@ -7,8 +7,8 @@
# Keep test fields/methods for deterministic naming
-keepclassmembers public class **.BaseCls {
- *** a;
- *** a(...);
+ *** c;
+ *** c(...);
}
-keepclassmembers public class **.AnotherCls {
diff --git a/src/test/examples/uniquemembernames/keep-rules-2.txt b/src/test/examples/uniquemembernames/keep-rules-2.txt
index 3f1bdadcc..b5c5dcf76 100644
--- a/src/test/examples/uniquemembernames/keep-rules-2.txt
+++ b/src/test/examples/uniquemembernames/keep-rules-2.txt
@@ -7,8 +7,8 @@
# Keep test fields/methods for deterministic naming
-keepclassmembers public class **.BaseCls {
- *** a;
- *** a(...);
+ *** c;
+ *** c(...);
}
-keepclassmembers public class **.AnotherCls {
diff --git a/src/test/java/com/android/tools/r8/naming/UseUniqueMemberNameTest.java b/src/test/java/com/android/tools/r8/naming/UseUniqueMemberNameTest.java
index 309475694..498f4dfec 100644
--- a/src/test/java/com/android/tools/r8/naming/UseUniqueMemberNameTest.java
+++ b/src/test/java/com/android/tools/r8/naming/UseUniqueMemberNameTest.java
@@ -103,9 +103,9 @@ public class UseUniqueMemberNameTest extends NamingTestBase {
// With -useuniquemembernames, foo() with the same signature should be renamed to the same name.
assertEquals(foo_renamed, another_foo_renamed);
- // But, those cannot be renamed to a and b, as those are _globally_ reserved.
- assertNotEquals("a", foo_renamed);
- assertNotEquals("a", another_foo_renamed);
+ // But, those cannot be renamed to c and b, as those are _globally_ reserved.
+ assertNotEquals("c", foo_renamed);
+ assertNotEquals("c", another_foo_renamed);
assertNotEquals("b", foo_renamed);
assertNotEquals("b", another_foo_renamed);