Simple cleanup of access to methods and fields in DexClass. Bug: Change-Id: I74e211e5ee13b6a68404ddfbd331ba92caa63d30
diff --git a/src/main/java/com/android/tools/r8/PrintClassList.java b/src/main/java/com/android/tools/r8/PrintClassList.java index 6c49769..bc274a8 100644 --- a/src/main/java/com/android/tools/r8/PrintClassList.java +++ b/src/main/java/com/android/tools/r8/PrintClassList.java
@@ -19,6 +19,7 @@ import com.android.tools.r8.utils.InternalOptions; import com.android.tools.r8.utils.ListUtils; import com.android.tools.r8.utils.Timing; + import java.io.IOException; import java.nio.file.Paths; import java.util.Arrays; @@ -46,39 +47,32 @@ for (DexProgramClass clazz : application.classes()) { System.out.print(maybeDeobfuscateType(map, clazz.type)); System.out.println(); - printMethods(clazz.directMethods(), map); - printMethods(clazz.virtualMethods(), map); - printFields(clazz.staticFields(), map); - printFields(clazz.instanceFields(), map); + clazz.forEachMethod(method -> printMethod(method, map)); + clazz.forEachField(field -> printField(field, map)); } executorService.shutdown(); } - private static void printMethods(DexEncodedMethod[] methods, ClassNameMapper map) { - for (DexEncodedMethod encodedMethod : methods) { - DexMethod method = encodedMethod.method; - - if (map != null) { - System.out.println(map.originalNameOf(method)); - } else { - // Detour via Signature to get the same formatting. - MethodSignature signature = MethodSignature.fromDexMethod(method); - System.out.println(method.holder.toSourceString() + " " + signature); - } + private static void printMethod(DexEncodedMethod encodedMethod, ClassNameMapper map) { + DexMethod method = encodedMethod.method; + if (map != null) { + System.out.println(map.originalNameOf(method)); + } else { + // Detour via Signature to get the same formatting. + MethodSignature signature = MethodSignature.fromDexMethod(method); + System.out.println(method.holder.toSourceString() + " " + signature); } } - private static void printFields(DexEncodedField[] fields, ClassNameMapper map) { - for (DexEncodedField encodedField : fields) { - DexField field = encodedField.field; - if (map != null) { - System.out.println(map.originalNameOf(field)); - } else { - // Detour via Signature to get the same formatting. - FieldSignature signature = new FieldSignature(field.name.toSourceString(), - field.type.toSourceString()); - System.out.println(field.clazz.toSourceString() + " " + signature); - } + private static void printField(DexEncodedField encodedField, ClassNameMapper map) { + DexField field = encodedField.field; + if (map != null) { + System.out.println(map.originalNameOf(field)); + } else { + // Detour via Signature to get the same formatting. + FieldSignature signature = new FieldSignature(field.name.toSourceString(), + field.type.toSourceString()); + System.out.println(field.clazz.toSourceString() + " " + signature); } }
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java index a215ece..b56f712 100644 --- a/src/main/java/com/android/tools/r8/dex/FileWriter.java +++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -5,6 +5,8 @@ import static com.android.tools.r8.utils.LebUtils.sizeAsUleb128; +import com.google.common.collect.Sets; + import com.android.tools.r8.code.Instruction; import com.android.tools.r8.errors.CompilationError; import com.android.tools.r8.graph.AppInfo; @@ -49,11 +51,12 @@ import com.android.tools.r8.naming.NamingLens; import com.android.tools.r8.utils.InternalOptions; import com.android.tools.r8.utils.LebUtils; -import com.google.common.collect.Sets; + import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Reference2IntMap; + import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; @@ -153,17 +156,14 @@ return this; } - private void rewriteCodeWithJumboStrings(IRConverter converter, DexEncodedMethod[] methods) { - for (int i = 0; i < methods.length; i++) { - DexEncodedMethod method = methods[i]; - if (method.getCode() == null) { - continue; - } - DexCode code = method.getCode().asDexCode(); - if (code.highestSortingString != null) { - if (mapping.getOffsetFor(code.highestSortingString) > Constants.MAX_NON_JUMBO_INDEX) { - converter.processJumboStrings(method, mapping.getFirstJumboString()); - } + private void rewriteCodeWithJumboStrings(IRConverter converter, DexEncodedMethod method) { + if (method.getCode() == null) { + return; + } + DexCode code = method.getCode().asDexCode(); + if (code.highestSortingString != null) { + if (mapping.getOffsetFor(code.highestSortingString) > Constants.MAX_NON_JUMBO_INDEX) { + converter.processJumboStrings(method, mapping.getFirstJumboString()); } } } @@ -181,8 +181,7 @@ // At least one method needs a jumbo string. IRConverter converter = new IRConverter(application, appInfo, options, false); for (DexProgramClass clazz : classes) { - rewriteCodeWithJumboStrings(converter, clazz.directMethods()); - rewriteCodeWithJumboStrings(converter, clazz.virtualMethods()); + clazz.forEachMethod(method -> rewriteCodeWithJumboStrings(converter, method)); } return this; } @@ -275,56 +274,53 @@ private void checkInterfaceMethods() { for (DexProgramClass clazz : mapping.getClasses()) { if (clazz.isInterface()) { - checkInterfaceMethods(clazz.directMethods()); - checkInterfaceMethods(clazz.virtualMethods()); + clazz.forEachMethod(this::checkInterfaceMethod); } } } - // Ensures interface methods comply with requirements imposed by Android runtime: + // Ensures interface method comply with requirements imposed by Android runtime: // -- in pre-N Android versions interfaces may only have class // initializer and public abstract methods. // -- starting with N interfaces may also have public or private // static methods, as well as public non-abstract (default) // and private instance methods. - private void checkInterfaceMethods(DexEncodedMethod[] methods) { - for (DexEncodedMethod method : methods) { - if (application.dexItemFactory.isClassConstructor(method.method)) { - continue; // Class constructor is always OK. - } - if (method.accessFlags.isStatic()) { - if (!options.canUseDefaultAndStaticInterfaceMethods()) { - throw new CompilationError("Static interface methods are only supported " - + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): " - + method.method.toSourceString()); - } - - } else { - if (method.accessFlags.isConstructor()) { - throw new CompilationError( - "Interface must not have constructors: " + method.method.toSourceString()); - } - if (!method.accessFlags.isAbstract() && !method.accessFlags.isPrivate() && - !options.canUseDefaultAndStaticInterfaceMethods()) { - throw new CompilationError("Default interface methods are only supported " - + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): " - + method.method.toSourceString()); - } - } - - if (method.accessFlags.isPrivate()) { - if (options.canUsePrivateInterfaceMethods()) { - continue; - } - throw new CompilationError("Private interface methods are only supported " + private void checkInterfaceMethod(DexEncodedMethod method) { + if (application.dexItemFactory.isClassConstructor(method.method)) { + return; // Class constructor is always OK. + } + if (method.accessFlags.isStatic()) { + if (!options.canUseDefaultAndStaticInterfaceMethods()) { + throw new CompilationError("Static interface methods are only supported " + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): " + method.method.toSourceString()); } - if (!method.accessFlags.isPublic()) { - throw new CompilationError("Interface methods must not be " - + "protected or package private: " + method.method.toSourceString()); + } else { + if (method.accessFlags.isConstructor()) { + throw new CompilationError( + "Interface must not have constructors: " + method.method.toSourceString()); } + if (!method.accessFlags.isAbstract() && !method.accessFlags.isPrivate() && + !options.canUseDefaultAndStaticInterfaceMethods()) { + throw new CompilationError("Default interface methods are only supported " + + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): " + + method.method.toSourceString()); + } + } + + if (method.accessFlags.isPrivate()) { + if (options.canUsePrivateInterfaceMethods()) { + return; + } + throw new CompilationError("Private interface methods are only supported " + + "starting with Android N (--min-api " + Constants.ANDROID_N_API + "): " + + method.method.toSourceString()); + } + + if (!method.accessFlags.isPublic()) { + throw new CompilationError("Interface methods must not be " + + "protected or package private: " + method.method.toSourceString()); } } @@ -332,34 +328,30 @@ DexApplication application) { Map<DexCode, String> codeToSignatureMap = new IdentityHashMap<>(); for (DexProgramClass clazz : mapping.getClasses()) { - addSignaturesFromMethods(clazz.directMethods(), codeToSignatureMap, - application.getProguardMap()); - addSignaturesFromMethods(clazz.virtualMethods(), codeToSignatureMap, - application.getProguardMap()); + clazz.forEachMethod(method -> + addSignaturesFromMethod(method, codeToSignatureMap, application.getProguardMap())); } DexCode[] codesArray = codes.toArray(new DexCode[codes.size()]); Arrays.sort(codesArray, Comparator.comparing(codeToSignatureMap::get)); return Arrays.asList(codesArray); } - private static void addSignaturesFromMethods(DexEncodedMethod[] methods, + private static void addSignaturesFromMethod(DexEncodedMethod method, Map<DexCode, String> codeToSignatureMap, ClassNameMapper proguardMap) { - for (DexEncodedMethod method : methods) { - if (method.getCode() == null) { - assert method.accessFlags.isAbstract() || method.accessFlags.isNative(); + if (method.getCode() == null) { + assert method.accessFlags.isAbstract() || method.accessFlags.isNative(); + } else { + Signature signature; + String originalClassName; + if (proguardMap != null) { + signature = proguardMap.originalSignatureOf(method.method); + originalClassName = proguardMap.originalNameOf(method.method.holder); } else { - Signature signature; - String originalClassName; - if (proguardMap != null) { - signature = proguardMap.originalSignatureOf(method.method); - originalClassName = proguardMap.originalNameOf(method.method.holder); - } else { - signature = MethodSignature.fromDexMethod(method.method); - originalClassName = method.method.holder.toSourceString(); - } - codeToSignatureMap.put(method.getCode().asDexCode(), originalClassName + signature); + signature = MethodSignature.fromDexMethod(method.method); + originalClassName = method.method.holder.toSourceString(); } + codeToSignatureMap.put(method.getCode().asDexCode(), originalClassName + signature); } }
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java index a5c8ff8..3619b9c 100644 --- a/src/main/java/com/android/tools/r8/graph/AppInfo.java +++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -42,21 +42,12 @@ Builder<Descriptor, KeyedDexItem> builder = ImmutableMap.builder(); DexClass clazz = app.definitionFor(type); if (clazz != null) { - registerDefinitions(builder, clazz.directMethods()); - registerDefinitions(builder, clazz.virtualMethods()); - registerDefinitions(builder, clazz.instanceFields()); - registerDefinitions(builder, clazz.staticFields()); + clazz.forEachMethod(method -> builder.put(method.getKey(), method)); + clazz.forEachField(field -> builder.put(field.getKey(), field)); } return builder.build(); } - private void registerDefinitions(Builder<Descriptor, KeyedDexItem> builder, - KeyedDexItem<? extends Descriptor>[] items) { - for (KeyedDexItem<? extends Descriptor> item : items) { - builder.put(item.getKey(), item); - } - } - public Iterable<DexProgramClass> classes() { return app.classes(); }
diff --git a/src/main/java/com/android/tools/r8/graph/ClassAndMemberPublicizer.java b/src/main/java/com/android/tools/r8/graph/ClassAndMemberPublicizer.java index 9583e9c..6a6b3d8 100644 --- a/src/main/java/com/android/tools/r8/graph/ClassAndMemberPublicizer.java +++ b/src/main/java/com/android/tools/r8/graph/ClassAndMemberPublicizer.java
@@ -12,8 +12,8 @@ public static DexApplication run(DexApplication application) { for (DexClass clazz : application.classes()) { clazz.accessFlags.promoteToPublic(); - clazz.forEachMethod( method -> method.accessFlags.promoteNonPrivateToPublic()); - clazz.forEachField( field -> field.accessFlags.promoteToPublic()); + clazz.forEachMethod(method -> method.accessFlags.promoteNonPrivateToPublic()); + clazz.forEachField(field -> field.accessFlags.promoteToPublic()); } return application; }
diff --git a/src/main/java/com/android/tools/r8/graph/DexApplication.java b/src/main/java/com/android/tools/r8/graph/DexApplication.java index d84dd8c..e57cd05 100644 --- a/src/main/java/com/android/tools/r8/graph/DexApplication.java +++ b/src/main/java/com/android/tools/r8/graph/DexApplication.java
@@ -193,16 +193,11 @@ */ public void disassemble(Path outputDir, InternalOptions options) { for (DexProgramClass clazz : programClasses.getAllClasses()) { - for (DexEncodedMethod method : clazz.virtualMethods()) { + clazz.forEachMethod(method -> { if (options.methodMatchesFilter(method)) { disassemble(method, getProguardMap(), outputDir); } - } - for (DexEncodedMethod method : clazz.directMethods()) { - if (options.methodMatchesFilter(method)) { - disassemble(method, getProguardMap(), outputDir); - } - } + }); } }
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java index b28f06c..a029a61 100644 --- a/src/main/java/com/android/tools/r8/graph/DexClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -11,6 +11,7 @@ import com.google.common.base.MoreObjects; import java.util.Arrays; +import java.util.Comparator; import java.util.function.Consumer; public abstract class DexClass extends DexItem { @@ -168,10 +169,6 @@ return false; } - public DexClasspathClass asClasspathClass() { - return null; - } - public boolean isLibraryClass() { return false; }
diff --git a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java index 036b8bc..27ab302 100644 --- a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
@@ -41,11 +41,6 @@ } @Override - public DexClasspathClass asClasspathClass() { - return this; - } - - @Override public DexClasspathClass get() { return this; }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java index 9c76d74..8b348a0 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
@@ -186,7 +186,7 @@ private static boolean allMethodsExists(DexApplication application, CallGraph graph) { for (DexProgramClass clazz : application.classes()) { - clazz.forEachMethod( method -> { assert graph.nodes.get(method) != null; }); + clazz.forEachMethod(method -> { assert graph.nodes.get(method) != null; }); } return true; }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java index a345ddf..51aa284 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -6,6 +6,8 @@ import static com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.Flavor.ExcludeDexResources; import static com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.Flavor.IncludeAllResources; +import com.google.common.collect.ImmutableSet; + import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.AppInfo; import com.android.tools.r8.graph.AppInfoWithSubtyping; @@ -38,7 +40,6 @@ import com.android.tools.r8.utils.ThreadUtils; import com.android.tools.r8.utils.Timing; -import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -229,25 +230,19 @@ ExecutorService executor) throws ExecutionException { List<Future<?>> futures = new ArrayList<>(); for (DexProgramClass clazz : classes) { - futures.add(executor.submit(() -> { - convertMethodsToDex(clazz.directMethods()); - convertMethodsToDex(clazz.virtualMethods()); - })); + futures.add(executor.submit(() -> clazz.forEachMethod(this::convertMethodToDex))); } ThreadUtils.awaitFutures(futures); } - private void convertMethodsToDex(DexEncodedMethod[] methods) { - for (int i = 0; i < methods.length; i++) { - DexEncodedMethod method = methods[i]; - if (method.getCode() != null) { - boolean matchesMethodFilter = options.methodMatchesFilter(method); - if (matchesMethodFilter) { - if (method.getCode().isJarCode()) { - rewriteCode(method, ignoreOptimizationFeedback, Outliner::noProcessing); - } - updateHighestSortingStrings(method); + private void convertMethodToDex(DexEncodedMethod method) { + if (method.getCode() != null) { + boolean matchesMethodFilter = options.methodMatchesFilter(method); + if (matchesMethodFilter) { + if (method.getCode().isJarCode()) { + rewriteCode(method, ignoreOptimizationFeedback, Outliner::noProcessing); } + updateHighestSortingStrings(method); } } }
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 d7b17c6..ec7fa46 100644 --- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java +++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -3,6 +3,9 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.naming; +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; @@ -13,8 +16,7 @@ import com.android.tools.r8.shaking.RootSetBuilder.RootSet; import com.android.tools.r8.utils.MethodSignatureEquivalence; import com.android.tools.r8.utils.Timing; -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; @@ -337,19 +339,16 @@ : parent.createChild()); if (holder != null) { boolean keepAll = holder.isLibraryClass() || holder.accessFlags.isAnnotation(); - reserveNamesForMethods(holder.virtualMethods(), keepAll, state); - reserveNamesForMethods(holder.directMethods(), keepAll, state); + holder.forEachMethod(method -> reserveNamesForMethod(method, keepAll, state)); } return state; } - private void reserveNamesForMethods(DexEncodedMethod[] methods, + private void reserveNamesForMethod(DexEncodedMethod method, boolean keepAll, NamingState<DexProto> state) { - for (DexEncodedMethod method : methods) { - if (keepAll || rootSet.noObfuscation.contains(method)) { - state.reserveName(method.method.name, method.method.proto); - globalState.reserveName(method.method.name, method.method.proto); - } + 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/optimize/BridgeMethodAnalysis.java b/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java index f36e8c5..1a28332 100644 --- a/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java +++ b/src/main/java/com/android/tools/r8/optimize/BridgeMethodAnalysis.java
@@ -12,6 +12,7 @@ import com.android.tools.r8.graph.GraphLense; import com.android.tools.r8.logging.Log; import com.android.tools.r8.optimize.InvokeSingleTargetExtractor.InvokeKind; + import java.util.IdentityHashMap; import java.util.Map; @@ -28,35 +29,32 @@ public GraphLense run() { for (DexClass clazz : appInfo.classes()) { - identifyBridgeMethods(clazz.virtualMethods()); - identifyBridgeMethods(clazz.directMethods()); + clazz.forEachMethod(this::identifyBridgeMethod); } return new BridgeLense(lense, bridgeTargetToBridgeMap); } - private void identifyBridgeMethods(DexEncodedMethod[] dexEncodedMethods) { - for (DexEncodedMethod method : dexEncodedMethods) { - if (method.accessFlags.isBridge()) { - InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor(); - method.getCode().registerReachableDefinitions(targetExtractor); - DexMethod target = targetExtractor.getTarget(); - InvokeKind kind = targetExtractor.getKind(); - if (target != null && - target.proto.parameters.values.length == method.method.proto.parameters.values.length) { - assert !method.accessFlags.isPrivate() && !method.accessFlags.isConstructor(); - target = lense.lookupMethod(target, method); - if (kind == InvokeKind.STATIC) { - assert method.accessFlags.isStatic(); - DexEncodedMethod targetMethod = appInfo.lookupStaticTarget(target); - if (targetMethod != null) { - addForwarding(method, targetMethod); - } - } else if (kind == InvokeKind.VIRTUAL) { - // TODO(herhut): Add support for bridges with multiple targets. - DexEncodedMethod targetMethod = appInfo.lookupSingleVirtualTarget(target); - if (targetMethod != null) { - addForwarding(method, targetMethod); - } + private void identifyBridgeMethod(DexEncodedMethod method) { + if (method.accessFlags.isBridge()) { + InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor(); + method.getCode().registerReachableDefinitions(targetExtractor); + DexMethod target = targetExtractor.getTarget(); + InvokeKind kind = targetExtractor.getKind(); + if (target != null && + target.proto.parameters.values.length == method.method.proto.parameters.values.length) { + assert !method.accessFlags.isPrivate() && !method.accessFlags.isConstructor(); + target = lense.lookupMethod(target, method); + if (kind == InvokeKind.STATIC) { + assert method.accessFlags.isStatic(); + DexEncodedMethod targetMethod = appInfo.lookupStaticTarget(target); + if (targetMethod != null) { + addForwarding(method, targetMethod); + } + } else if (kind == InvokeKind.VIRTUAL) { + // TODO(herhut): Add support for bridges with multiple targets. + DexEncodedMethod targetMethod = appInfo.lookupSingleVirtualTarget(target); + if (targetMethod != null) { + addForwarding(method, targetMethod); } } }
diff --git a/src/main/java/com/android/tools/r8/optimize/DebugStripper.java b/src/main/java/com/android/tools/r8/optimize/DebugStripper.java index 3f83606..0eda1e5 100644 --- a/src/main/java/com/android/tools/r8/optimize/DebugStripper.java +++ b/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
@@ -17,8 +17,10 @@ import com.android.tools.r8.naming.MemberNaming.Range; import com.android.tools.r8.naming.MemberNaming.Signature; import com.android.tools.r8.utils.InternalOptions; + import it.unimi.dsi.fastutil.objects.Reference2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + import java.util.List; public class DebugStripper { @@ -162,16 +164,6 @@ processCode(method, naming, nameCounts); } - private void processMethods(DexEncodedMethod[] methods, ClassNaming naming, - Reference2IntMap<DexString> nameCounts) { - if (methods == null) { - return; - } - for (DexEncodedMethod method : methods) { - processMethod(method, naming, nameCounts); - } - } - public void processClass(DexProgramClass clazz) { if (!clazz.hasMethodsOrFields()) { return; @@ -179,20 +171,16 @@ String name = descriptorToName(clazz.type.toDescriptorString()); ClassNaming naming = classNameMapper == null ? null : classNameMapper.getClassNaming(name); Reference2IntMap<DexString> nameCounts = new Reference2IntOpenHashMap<>(); - setIntialNameCounts(nameCounts, clazz.directMethods()); - setIntialNameCounts(nameCounts, clazz.virtualMethods()); - processMethods(clazz.directMethods(), naming, nameCounts); - processMethods(clazz.virtualMethods(), naming, nameCounts); + clazz.forEachMethod(method -> setIntialNameCounts(nameCounts, method)); + clazz.forEachMethod(method -> processMethod(method, naming, nameCounts)); } private void setIntialNameCounts(Reference2IntMap<DexString> nameCounts, - DexEncodedMethod[] methods) { - for (DexEncodedMethod method : methods) { - if (nameCounts.containsKey(method.method.name)) { - nameCounts.put(method.method.name, USED_MORE_THAN_ONCE); - } else { - nameCounts.put(method.method.name, USED_ONCE); - } + DexEncodedMethod method) { + if (nameCounts.containsKey(method.method.name)) { + nameCounts.put(method.method.name, USED_MORE_THAN_ONCE); + } else { + nameCounts.put(method.method.name, USED_ONCE); } } }
diff --git a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java index 6c3e715..31c7f1f 100644 --- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java +++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
@@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.optimize; +import com.google.common.collect.Sets; + import com.android.tools.r8.graph.AppInfoWithSubtyping; import com.android.tools.r8.graph.DexApplication; import com.android.tools.r8.graph.DexClass; @@ -11,7 +13,7 @@ import com.android.tools.r8.graph.DexType; import com.android.tools.r8.logging.Log; import com.android.tools.r8.optimize.InvokeSingleTargetExtractor.InvokeKind; -import com.google.common.collect.Sets; + import java.util.Arrays; import java.util.List; import java.util.Set; @@ -27,27 +29,25 @@ this.application = application; } - private void identifyBridgeMethods(DexEncodedMethod[] dexEncodedMethods) { - for (DexEncodedMethod method : dexEncodedMethods) { - if (method.accessFlags.isBridge()) { - InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor(); - method.getCode().registerReachableDefinitions(targetExtractor); - DexMethod target = targetExtractor.getTarget(); - InvokeKind kind = targetExtractor.getKind(); - if (target != null && - target.proto == method.method.proto) { - assert !method.accessFlags.isPrivate() && !method.accessFlags.isConstructor(); - if (kind == InvokeKind.SUPER) { - // This is a visibility forward, so check for the direct target. - DexEncodedMethod targetMethod - = appInfo.lookupVirtualDefinition(target.getHolder(), target); - if (targetMethod != null && targetMethod.accessFlags.isPublic()) { - if (Log.ENABLED) { - Log.info(getClass(), "Removing visibility forwarding %s -> %s", method.method, - targetMethod.method); - } - unneededVisibilityBridges.add(method); + private void identifyBridgeMethod(DexEncodedMethod method) { + if (method.accessFlags.isBridge()) { + InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor(); + method.getCode().registerReachableDefinitions(targetExtractor); + DexMethod target = targetExtractor.getTarget(); + InvokeKind kind = targetExtractor.getKind(); + if (target != null && + target.proto == method.method.proto) { + assert !method.accessFlags.isPrivate() && !method.accessFlags.isConstructor(); + if (kind == InvokeKind.SUPER) { + // This is a visibility forward, so check for the direct target. + DexEncodedMethod targetMethod + = appInfo.lookupVirtualDefinition(target.getHolder(), target); + if (targetMethod != null && targetMethod.accessFlags.isPublic()) { + if (Log.ENABLED) { + Log.info(getClass(), "Removing visibility forwarding %s -> %s", method.method, + targetMethod.method); } + unneededVisibilityBridges.add(method); } } } @@ -76,8 +76,7 @@ public DexApplication run() { for (DexClass clazz : appInfo.classes()) { - identifyBridgeMethods(clazz.virtualMethods()); - identifyBridgeMethods(clazz.directMethods()); + clazz.forEachMethod(this::identifyBridgeMethod); } if (!unneededVisibilityBridges.isEmpty()) { removeUnneededVisibilityBridges();
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java index 8a7ee43..f6ac140 100644 --- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java +++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -150,8 +150,8 @@ addMainDexType(type); // Super and interfaces are live, no need to add them. traceAnnotationsDirectDendencies(clazz.annotations); - clazz.forEachField( field -> addMainDexType(field.field.type)); - clazz.forEachMethod( method -> { + clazz.forEachField(field -> addMainDexType(field.field.type)); + clazz.forEachMethod(method -> { traceMethodDirectDependencies(method.method); method.registerReachableDefinitions(codeDirectReferenceCollector); });
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java index 8afe151..6ac5694 100644 --- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java +++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -3,6 +3,9 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; +import com.google.common.base.Equivalence.Wrapper; +import com.google.common.collect.Sets; + import com.android.tools.r8.graph.AppInfo; import com.android.tools.r8.graph.DexAnnotation; import com.android.tools.r8.graph.DexAnnotationSet; @@ -21,8 +24,7 @@ import com.android.tools.r8.shaking.ProguardTypeMatcher.MatchSpecificType; import com.android.tools.r8.utils.MethodSignatureEquivalence; import com.android.tools.r8.utils.ThreadUtils; -import com.google.common.base.Equivalence.Wrapper; -import com.google.common.collect.Sets; + import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; @@ -246,8 +248,8 @@ DexType onlyIfClassKept) { Set<Wrapper<DexMethod>> methodsMarked = new HashSet<>(); while (clazz != null) { - markMethods(clazz.directMethods(), memberKeepRules, rule, methodsMarked, onlyIfClassKept); - markMethods(clazz.virtualMethods(), memberKeepRules, rule, methodsMarked, onlyIfClassKept); + clazz.forEachMethod(method -> + markMethod(method, memberKeepRules, rule, methodsMarked, onlyIfClassKept)); clazz = application.definitionFor(clazz.superType); } } @@ -255,8 +257,7 @@ private void markMatchingFields(DexClass clazz, Collection<ProguardMemberRule> memberKeepRules, ProguardConfigurationRule rule, DexType onlyIfClassKept) { - markFields(clazz.staticFields(), memberKeepRules, rule, onlyIfClassKept); - markFields(clazz.instanceFields(), memberKeepRules, rule, onlyIfClassKept); + clazz.forEachField(field -> markField(field, memberKeepRules, rule, onlyIfClassKept)); } public static void writeSeeds(Iterable<DexItem> seeds, PrintStream out) { @@ -371,36 +372,32 @@ return typeCache.computeIfAbsent(type, DexType::toSourceString); } - private void markMethods(DexEncodedMethod[] methods, Collection<ProguardMemberRule> rules, + private void markMethod(DexEncodedMethod method, Collection<ProguardMemberRule> rules, ProguardConfigurationRule context, Set<Wrapper<DexMethod>> methodsMarked, DexType onlyIfClassKept) { - for (DexEncodedMethod method : methods) { - if (methodsMarked.contains(MethodSignatureEquivalence.get().wrap(method.method))) { - continue; - } - for (ProguardMemberRule rule : rules) { - if (rule.matches(method, this)) { - if (Log.ENABLED) { - Log.verbose(getClass(), "Marking method `%s` due to `%s { %s }`.", method, context, - rule); - } - addItemToSets(method, context, rule, onlyIfClassKept); + if (methodsMarked.contains(MethodSignatureEquivalence.get().wrap(method.method))) { + return; + } + for (ProguardMemberRule rule : rules) { + if (rule.matches(method, this)) { + if (Log.ENABLED) { + Log.verbose(getClass(), "Marking method `%s` due to `%s { %s }`.", method, context, + rule); } + addItemToSets(method, context, rule, onlyIfClassKept); } } } - private void markFields(DexEncodedField[] fields, Collection<ProguardMemberRule> rules, + private void markField(DexEncodedField field, Collection<ProguardMemberRule> rules, ProguardConfigurationRule context, DexType onlyIfClassKept) { - for (DexEncodedField field : fields) { - for (ProguardMemberRule rule : rules) { - if (rule.matches(field, this)) { - if (Log.ENABLED) { - Log.verbose(getClass(), "Marking field `%s` due to `%s { %s }`.", field, context, - rule); - } - addItemToSets(field, context, rule, onlyIfClassKept); + for (ProguardMemberRule rule : rules) { + if (rule.matches(field, this)) { + if (Log.ENABLED) { + Log.verbose(getClass(), "Marking field `%s` due to `%s { %s }`.", field, context, + rule); } + addItemToSets(field, context, rule, onlyIfClassKept); } } }