diff options
author | Stephan Herhut <herhut@google.com> | 2017-10-27 09:33:15 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-10-27 09:33:15 +0000 |
commit | 2bfb29a43eba84ad3345b17f33960dc72bb97564 (patch) | |
tree | 8f458f0b8d4aeec207a76e33d4e41f068369d7c6 | |
parent | 7cec45be0c6c08de76fb9c7f6d0cdab41f703197 (diff) | |
parent | f17b35072cc9b061008e6d12312d356e41a36368 (diff) | |
download | r8-2bfb29a43eba84ad3345b17f33960dc72bb97564.tar.gz |
Merge "Implement support for not overloading aggressively, making that the default."
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); |