Change return type of directMethods() and virtualMethods() to Iterable
Bug: 155595879
Change-Id: Iee803b99651be79a9988ccbb250fdccb135791f7
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 bd4c6da..c4040a2 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -51,6 +51,7 @@
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DexVersion;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.LebUtils;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
@@ -633,8 +634,8 @@
}
private void writeEncodedMethods(
- List<DexEncodedMethod> unsortedMethods, boolean isSharedSynthetic) {
- List<DexEncodedMethod> methods = new ArrayList<>(unsortedMethods);
+ Iterable<DexEncodedMethod> unsortedMethods, boolean isSharedSynthetic) {
+ List<DexEncodedMethod> methods = IterableUtils.toNewArrayList(unsortedMethods);
methods.sort((a, b) -> a.method.slowCompareTo(b.method, namingLens));
int currentOffset = 0;
for (DexEncodedMethod method : methods) {
@@ -666,8 +667,8 @@
mixedSectionOffsets.setOffsetFor(clazz, dest.position());
dest.putUleb128(clazz.staticFields().size());
dest.putUleb128(clazz.instanceFields().size());
- dest.putUleb128(clazz.directMethods().size());
- dest.putUleb128(clazz.virtualMethods().size());
+ dest.putUleb128(clazz.getMethodCollection().numberOfDirectMethods());
+ dest.putUleb128(clazz.getMethodCollection().numberOfVirtualMethods());
writeEncodedFields(clazz.staticFields());
writeEncodedFields(clazz.instanceFields());
boolean isSharedSynthetic = clazz.getSynthesizedFrom().size() > 1;
diff --git a/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java b/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java
index c83010d..d24a75b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/DexByteCodeWriter.java
@@ -78,8 +78,7 @@
private boolean anyMethodMatches(DexClass clazz) {
return !options.hasMethodsFilter()
- || clazz.virtualMethods().stream().anyMatch(options::methodMatchesFilter)
- || clazz.directMethods().stream().anyMatch(options::methodMatchesFilter);
+ || clazz.getMethodCollection().hasMethods(options::methodMatchesFilter);
}
private void writeClass(DexProgramClass clazz, PrintStream ps) {
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 5bcb25c..c2cdc32 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -138,7 +138,7 @@
throw new Unreachable();
}
- public List<DexEncodedMethod> directMethods() {
+ public Iterable<DexEncodedMethod> directMethods() {
return methodCollection.directMethods();
}
@@ -158,7 +158,7 @@
methodCollection.setDirectMethods(methods);
}
- public List<DexEncodedMethod> virtualMethods() {
+ public Iterable<DexEncodedMethod> virtualMethods() {
return methodCollection.virtualMethods();
}
@@ -411,6 +411,11 @@
return methodCollection.getMethod(method);
}
+ /** Find method in this class matching {@param method}. */
+ public DexEncodedMethod lookupMethod(Predicate<DexEncodedMethod> predicate) {
+ return methodCollection.getMethod(predicate);
+ }
+
public DexEncodedMethod lookupSignaturePolymorphicMethod(
DexString methodName, DexItemFactory factory) {
if (type != factory.methodHandleType && type != factory.varHandleType) {
@@ -817,7 +822,7 @@
public boolean isValid(InternalOptions options) {
assert verifyNoAbstractMethodsOnNonAbstractClasses(virtualMethods(), options);
- assert !isInterface() || virtualMethods().stream().noneMatch(DexEncodedMethod::isFinal);
+ assert !isInterface() || !getMethodCollection().hasVirtualMethods(DexEncodedMethod::isFinal);
assert verifyCorrectnessOfFieldHolders(fields());
assert verifyNoDuplicateFields();
assert methodCollection.verify();
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollection.java b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
index ac2685a..bad82e1 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -2,13 +2,11 @@
import static com.google.common.base.Predicates.alwaysTrue;
-import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.TraversalContinuation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@@ -50,6 +48,26 @@
// Nothing to do.
}
+ public boolean hasMethods(Predicate<DexEncodedMethod> predicate) {
+ return getMethod(predicate) != null;
+ }
+
+ public boolean hasDirectMethods() {
+ return hasDirectMethods(alwaysTrue());
+ }
+
+ public boolean hasDirectMethods(Predicate<DexEncodedMethod> predicate) {
+ return backing.getDirectMethod(predicate) != null;
+ }
+
+ public boolean hasVirtualMethods() {
+ return hasVirtualMethods(alwaysTrue());
+ }
+
+ public boolean hasVirtualMethods(Predicate<DexEncodedMethod> predicate) {
+ return backing.getVirtualMethod(predicate) != null;
+ }
+
public int numberOfDirectMethods() {
return backing.numberOfDirectMethods();
}
@@ -123,17 +141,11 @@
return sorted;
}
- public List<DexEncodedMethod> directMethods() {
- if (InternalOptions.assertionsEnabled()) {
- return Collections.unmodifiableList(backing.directMethods());
- }
+ public Iterable<DexEncodedMethod> directMethods() {
return backing.directMethods();
}
- public List<DexEncodedMethod> virtualMethods() {
- if (InternalOptions.assertionsEnabled()) {
- return Collections.unmodifiableList(backing.virtualMethods());
- }
+ public Iterable<DexEncodedMethod> virtualMethods() {
return backing.virtualMethods();
}
@@ -141,6 +153,11 @@
return backing.getMethod(method);
}
+ public DexEncodedMethod getMethod(Predicate<DexEncodedMethod> predicate) {
+ DexEncodedMethod result = backing.getDirectMethod(predicate);
+ return result != null ? result : backing.getVirtualMethod(predicate);
+ }
+
public DexEncodedMethod getDirectMethod(DexMethod method) {
return backing.getDirectMethod(method);
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
index 56ab228..2ce0cd8 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.utils.TraversalContinuation;
import java.util.Collection;
-import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -65,9 +64,9 @@
abstract Iterable<DexEncodedMethod> methods();
- abstract List<DexEncodedMethod> directMethods();
+ abstract Iterable<DexEncodedMethod> directMethods();
- abstract List<DexEncodedMethod> virtualMethods();
+ abstract Iterable<DexEncodedMethod> virtualMethods();
// Lookup methods.
diff --git a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
index d34ba36..4ba116d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
@@ -4,14 +4,13 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.base.Equivalence.Wrapper;
import it.unimi.dsi.fastutil.objects.Object2ReferenceLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
@@ -107,27 +106,13 @@
}
@Override
- List<DexEncodedMethod> directMethods() {
- List<DexEncodedMethod> methods = new ArrayList<>(size());
- forEachMethod(
- method -> {
- if (belongsToDirectPool(method)) {
- methods.add(method);
- }
- });
- return methods;
+ Iterable<DexEncodedMethod> directMethods() {
+ return () -> IteratorUtils.filter(methodMap.values().iterator(), this::belongsToDirectPool);
}
@Override
- List<DexEncodedMethod> virtualMethods() {
- List<DexEncodedMethod> methods = new ArrayList<>(size());
- forEachMethod(
- method -> {
- if (belongsToVirtualPool(method)) {
- methods.add(method);
- }
- });
- return methods;
+ Iterable<DexEncodedMethod> virtualMethods() {
+ return () -> IteratorUtils.filter(methodMap.values().iterator(), this::belongsToVirtualPool);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 72f630b..b32ab3b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -28,11 +28,9 @@
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
@@ -234,15 +232,13 @@
assert iface.superType == dexItemFactory.objectType;
// Add non-library default methods as well as those for desugared library classes.
if (!iface.isLibraryClass() || (needsLibraryInfo() && rewriter.isInDesugaredLibrary(iface))) {
- List<DexEncodedMethod> methods = iface.virtualMethods();
- List<Wrapper<DexMethod>> additions = new ArrayList<>(methods.size());
- for (DexEncodedMethod method : methods) {
- if (method.isDefaultMethod()) {
- additions.add(equivalence.wrap(method.method));
- }
+ Set<Wrapper<DexMethod>> additions =
+ new HashSet<>(iface.getMethodCollection().numberOfVirtualMethods());
+ for (DexEncodedMethod method : iface.virtualMethods(DexEncodedMethod::isDefaultMethod)) {
+ additions.add(equivalence.wrap(method.method));
}
if (!additions.isEmpty()) {
- signatures = signatures.merge(MethodSignatures.create(new HashSet<>(additions)));
+ signatures = signatures.merge(MethodSignatures.create(additions));
}
}
return signatures;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 1f6af29..878a5e0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -44,6 +44,7 @@
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
@@ -888,6 +889,10 @@
theInterface.setDirectMethods(renameHolder(theInterface.directMethods(), renamedInterface));
}
+ private DexEncodedMethod[] renameHolder(Iterable<DexEncodedMethod> methods, DexType newName) {
+ return renameHolder(IterableUtils.toNewArrayList(methods), newName);
+ }
+
private DexEncodedMethod[] renameHolder(List<DexEncodedMethod> methods, DexType newName) {
DexEncodedMethod[] newMethods = new DexEncodedMethod[methods.size()];
for (int i = 0; i < newMethods.length; i++) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index f1a499a..a277a71 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -115,7 +115,7 @@
}
// If at least one bridge method was removed then update the table.
- if (remainingMethods.size() < iface.virtualMethods().size()) {
+ if (remainingMethods.size() < iface.getMethodCollection().numberOfVirtualMethods()) {
iface.setVirtualMethods(remainingMethods.toArray(DexEncodedMethod.EMPTY_ARRAY));
}
remainingMethods.clear();
@@ -181,7 +181,7 @@
}
}
}
- if (remainingMethods.size() < iface.directMethods().size()) {
+ if (remainingMethods.size() < iface.getMethodCollection().numberOfDirectMethods()) {
iface.setDirectMethods(remainingMethods.toArray(DexEncodedMethod.EMPTY_ARRAY));
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
index d138d95..7ae1ffa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
@@ -71,7 +71,7 @@
enumUnboxer.reportFailure(clazz.type, Reason.UNEXPECTED_STATIC_FIELD);
return false;
}
- if (!clazz.virtualMethods().isEmpty()) {
+ if (clazz.getMethodCollection().hasVirtualMethods()) {
enumUnboxer.reportFailure(clazz.type, Reason.VIRTUAL_METHOD);
return false;
}
@@ -89,7 +89,7 @@
// public static ** valueOf(java.lang.String);
// }
// In general there will be 4 methods, unless the enum keep rule is not present.
- if (clazz.directMethods().size() > 4) {
+ if (clazz.getMethodCollection().numberOfDirectMethods() > 4) {
enumUnboxer.reportFailure(clazz.type, Reason.UNEXPECTED_DIRECT_METHOD);
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 1e7fb3c..5742de4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -812,28 +812,32 @@
hostClass.setStaticFields(newFields);
// Process static methods.
- List<DexEncodedMethod> extraMethods = candidateClass.directMethods();
- if (!extraMethods.isEmpty()) {
- List<DexEncodedMethod> newMethods = new ArrayList<>(extraMethods.size());
- for (DexEncodedMethod method : extraMethods) {
- DexEncodedMethod newMethod = method.toTypeSubstitutedMethod(
- factory().createMethod(hostType, method.method.proto, method.method.name));
- newMethods.add(newMethod);
- // If the old method from the candidate class has been staticized,
- if (staticizedMethods.remove(method)) {
- // Properly update staticized methods to reprocess, i.e., add the corresponding one that
- // has just been migrated to the host class.
- staticizedMethods.createAndAdd(hostClass, newMethod);
- }
- DexMethod originalMethod = methodMapping.inverse().get(method.method);
- if (originalMethod == null) {
- methodMapping.put(method.method, newMethod.method);
- } else {
- methodMapping.put(originalMethod, newMethod.method);
- }
- }
- hostClass.addDirectMethods(newMethods);
+ if (!candidateClass.getMethodCollection().hasDirectMethods()) {
+ return;
}
+
+ Iterable<DexEncodedMethod> extraMethods = candidateClass.directMethods();
+ List<DexEncodedMethod> newMethods =
+ new ArrayList<>(candidateClass.getMethodCollection().numberOfDirectMethods());
+ for (DexEncodedMethod method : extraMethods) {
+ DexEncodedMethod newMethod =
+ method.toTypeSubstitutedMethod(
+ factory().createMethod(hostType, method.method.proto, method.method.name));
+ newMethods.add(newMethod);
+ // If the old method from the candidate class has been staticized,
+ if (staticizedMethods.remove(method)) {
+ // Properly update staticized methods to reprocess, i.e., add the corresponding one that
+ // has just been migrated to the host class.
+ staticizedMethods.createAndAdd(hostClass, newMethod);
+ }
+ DexMethod originalMethod = methodMapping.inverse().get(method.method);
+ if (originalMethod == null) {
+ methodMapping.put(method.method, newMethod.method);
+ } else {
+ methodMapping.put(originalMethod, newMethod.method);
+ }
+ }
+ hostClass.addDirectMethods(newMethods);
}
private DexField mapCandidateField(DexField field, DexType candidateType, DexType hostType) {
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java b/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
deleted file mode 100644
index 0fdeebc..0000000
--- a/src/main/java/com/android/tools/r8/naming/MinifiedNameMapPrinter.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.naming;
-
-import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.naming.MemberNaming.MethodSignature;
-import com.android.tools.r8.utils.DescriptorUtils;
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-
-public class MinifiedNameMapPrinter {
-
- private static final String NEW_LINE = "\n";
- private final DexApplication application;
- private final NamingLens namingLens;
- private final Set<DexType> seenTypes = Sets.newIdentityHashSet();
-
- public MinifiedNameMapPrinter(DexApplication application, NamingLens namingLens) {
- this.application = application;
- this.namingLens = namingLens;
- }
-
- private <T> T[] sortedCopy(T[] source, Comparator<? super T> comparator) {
- T copy[] = Arrays.copyOf(source, source.length);
- Arrays.sort(copy, comparator);
- return copy;
- }
-
- private <T> List<T> sortedCopy(List<T> source, Comparator<? super T> comparator) {
- List<T> copy = new ArrayList<>(source);
- Collections.sort(copy, comparator);
- return copy;
- }
-
- private void writeClass(DexProgramClass clazz, StringBuilder out) {
- seenTypes.add(clazz.type);
- DexString descriptor = namingLens.lookupDescriptor(clazz.type);
- out.append(DescriptorUtils.descriptorToJavaType(clazz.type.descriptor.toSourceString()));
- out.append(" -> ");
- out.append(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
- out.append(":").append(NEW_LINE);
- writeFields(sortedCopy(
- clazz.instanceFields(), Comparator.comparing(DexEncodedField::toSourceString)), out);
- writeFields(sortedCopy(
- clazz.staticFields(), Comparator.comparing(DexEncodedField::toSourceString)), out);
- writeMethods(sortedCopy(
- clazz.directMethods(), Comparator.comparing(DexEncodedMethod::toSourceString)), out);
- writeMethods(sortedCopy(
- clazz.virtualMethods(), Comparator.comparing(DexEncodedMethod::toSourceString)), out);
- }
-
- private void writeType(DexType type, StringBuilder out) {
- if (type.isClassType() && seenTypes.add(type)) {
- DexString descriptor = namingLens.lookupDescriptor(type);
- out.append(DescriptorUtils.descriptorToJavaType(type.descriptor.toSourceString()));
- out.append(" -> ");
- out.append(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
- out.append(":").append(NEW_LINE);
- }
- }
-
- private void writeFields(List<DexEncodedField> fields, StringBuilder out) {
- for (DexEncodedField encodedField : fields) {
- DexField field = encodedField.field;
- DexString renamed = namingLens.lookupName(field);
- if (renamed != field.name) {
- out.append(" ");
- out.append(field.type.toSourceString());
- out.append(" ");
- out.append(field.name.toSourceString());
- out.append(" -> ");
- out.append(renamed.toSourceString()).append(NEW_LINE);
- }
- }
- }
-
- private void writeMethod(MethodSignature signature, String renamed, StringBuilder out) {
- out.append(" ");
- out.append(signature.toString());
- out.append(" -> ");
- out.append(renamed).append(NEW_LINE);
- }
-
- private void writeMethods(List<DexEncodedMethod> methods, StringBuilder out) {
- for (DexEncodedMethod encodedMethod : methods) {
- DexMethod method = encodedMethod.method;
- DexString renamed = namingLens.lookupName(method);
- if (renamed != method.name) {
- MethodSignature signature = MethodSignature.fromDexMethod(method);
- String renamedSourceString = renamed.toSourceString();
- writeMethod(signature, renamedSourceString, out);
- }
- }
- }
-
- public void write(StringBuilder out) {
- // First write out all classes that have been renamed.
- List<DexProgramClass> classes = new ArrayList<>(application.classes());
- classes.sort(Comparator.comparing(DexProgramClass::toSourceString));
- classes.forEach(clazz -> writeClass(clazz, out));
- // Now write out all types only mentioned in descriptors that have been renamed.
- namingLens.forAllRenamedTypes(type -> writeType(type, out));
- }
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
index 1fcb9e0..b64646d 100644
--- a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.ScopedDexMethodSet.AddMethodIfMoreVisibleResult;
+import com.android.tools.r8.utils.IterableUtils;
import java.util.ArrayList;
import java.util.List;
@@ -42,7 +43,8 @@
DexClass holder = appView.definitionFor(type);
scope = scope.newNestedScope();
if (holder != null && holder.isProgramClass()) {
- DexEncodedMethod[] newVirtualMethods = processMethods(holder.virtualMethods());
+ DexEncodedMethod[] newVirtualMethods =
+ processMethods(IterableUtils.ensureUnmodifiableList(holder.virtualMethods()));
if (newVirtualMethods != null) {
holder.setVirtualMethods(newVirtualMethods);
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 4bb1b2b..584b84b 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -251,8 +251,9 @@
}
assert definition.isInterface();
boolean liveGetter =
- definition.virtualMethods().stream()
- .anyMatch(method -> method.method.name == original.name);
+ definition
+ .getMethodCollection()
+ .hasVirtualMethods(method -> method.method.name == original.name);
return liveGetter ? original : null;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java b/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
index dc69de3..a96194f 100644
--- a/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
@@ -31,6 +31,7 @@
import com.google.common.collect.Streams;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -267,8 +268,7 @@
// TODO(b/141452765): Allow class merging between classes in features.
return MergeGroup.DONT_MERGE;
}
- if (clazz.staticFields().size() + clazz.directMethods().size() + clazz.virtualMethods().size()
- == 0) {
+ if (clazz.staticFields().size() + clazz.getMethodCollection().size() == 0) {
return MergeGroup.DONT_MERGE;
}
if (clazz.instanceFields().size() > 0) {
@@ -278,10 +278,10 @@
.anyMatch(field -> appView.appInfo().isPinned(field.field))) {
return MergeGroup.DONT_MERGE;
}
- if (clazz.directMethods().stream().anyMatch(DexEncodedMethod::isInitializer)) {
+ if (clazz.getMethodCollection().hasDirectMethods(DexEncodedMethod::isInitializer)) {
return MergeGroup.DONT_MERGE;
}
- if (!clazz.virtualMethods().stream().allMatch(DexEncodedMethod::isPrivateMethod)) {
+ if (clazz.getMethodCollection().hasVirtualMethods(method -> !method.isPrivateMethod())) {
return MergeGroup.DONT_MERGE;
}
if (clazz.isInANest()) {
@@ -427,12 +427,12 @@
return false;
}
// Check that all of the members are private or public.
- if (!clazz.directMethods().stream()
- .allMatch(method -> method.accessFlags.isPrivate() || method.accessFlags.isPublic())) {
+ if (clazz
+ .getMethodCollection()
+ .hasDirectMethods(method -> !method.isPrivate() && !method.isPublic())) {
return false;
}
- if (!clazz.staticFields().stream()
- .allMatch(field -> field.accessFlags.isPrivate() || field.accessFlags.isPublic())) {
+ if (!clazz.staticFields().stream().allMatch(field -> field.isPrivate() || field.isPublic())) {
return false;
}
@@ -440,7 +440,7 @@
// virtual methods are private. Therefore, we don't need to consider check if there are any
// package-private or protected instance fields or virtual methods here.
assert clazz.instanceFields().size() == 0;
- assert clazz.virtualMethods().stream().allMatch(method -> method.accessFlags.isPrivate());
+ assert !clazz.getMethodCollection().hasVirtualMethods(method -> !method.isPrivate());
// Check that no methods access package-private or protected members.
IllegalAccessDetector registry = new IllegalAccessDetector(appView, clazz);
@@ -489,20 +489,20 @@
}
private List<DexEncodedMethod> mergeMethods(
- List<DexEncodedMethod> sourceMethods,
- List<DexEncodedMethod> targetMethods,
+ Iterable<DexEncodedMethod> sourceMethods,
+ Iterable<DexEncodedMethod> targetMethods,
DexProgramClass targetClass) {
// Move source methods to result one by one, renaming them if needed.
MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();
- Set<Wrapper<DexMethod>> existingMethods =
- targetMethods.stream()
- .map(targetMethod -> equivalence.wrap(targetMethod.method))
- .collect(Collectors.toSet());
+ Set<Wrapper<DexMethod>> existingMethods = new HashSet<>();
+ for (DexEncodedMethod targetMethod : targetMethods) {
+ existingMethods.add(equivalence.wrap(targetMethod.method));
+ }
Predicate<DexMethod> availableMethodSignatures =
method -> !existingMethods.contains(equivalence.wrap(method));
- List<DexEncodedMethod> newMethods = new ArrayList<>(sourceMethods.size());
+ List<DexEncodedMethod> newMethods = new ArrayList<>();
for (DexEncodedMethod sourceMethod : sourceMethods) {
DexEncodedMethod sourceMethodAfterMove =
renameMethodIfNeeded(sourceMethod, targetClass, availableMethodSignatures);
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index 6f2010c..6560ebc 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -21,6 +21,7 @@
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -254,6 +255,10 @@
return -1;
}
+ private DexEncodedMethod[] reachableMethods(Iterable<DexEncodedMethod> methods, DexClass clazz) {
+ return reachableMethods(IterableUtils.ensureUnmodifiableList(methods), clazz);
+ }
+
private DexEncodedMethod[] reachableMethods(List<DexEncodedMethod> methods, DexClass clazz) {
AppInfoWithLiveness appInfo = appView.appInfo();
InternalOptions options = appView.options();
diff --git a/src/main/java/com/android/tools/r8/utils/IterableUtils.java b/src/main/java/com/android/tools/r8/utils/IterableUtils.java
index ea35dfb..af3208f 100644
--- a/src/main/java/com/android/tools/r8/utils/IterableUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/IterableUtils.java
@@ -4,10 +4,23 @@
package com.android.tools.r8.utils;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.function.Predicate;
public class IterableUtils {
+ public static <T> List<T> ensureUnmodifiableList(Iterable<T> iterable) {
+ List<T> list;
+ if (iterable instanceof List<?>) {
+ list = (List<T>) iterable;
+ } else {
+ list = toNewArrayList(iterable);
+ }
+ return Collections.unmodifiableList(list);
+ }
+
public static <T> int firstIndexMatching(Iterable<T> iterable, Predicate<T> tester) {
int i = 0;
for (T element : iterable) {
@@ -19,7 +32,21 @@
return -1;
}
- public static <T> Iterable<T> filter(Iterable<T> methods, Predicate<T> predicate) {
- return () -> IteratorUtils.filter(methods.iterator(), predicate);
+ public static <T> Iterable<T> filter(Iterable<T> iterable, Predicate<T> predicate) {
+ return () -> IteratorUtils.filter(iterable.iterator(), predicate);
+ }
+
+ public static <T> int size(Iterable<T> iterable) {
+ int result = 0;
+ for (T element : iterable) {
+ result++;
+ }
+ return result;
+ }
+
+ public static <T> List<T> toNewArrayList(Iterable<T> iterable) {
+ List<T> result = new ArrayList<>();
+ iterable.forEach(result::add);
+ return result;
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index d62402b..a785262b 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -540,7 +540,7 @@
private static IdentityHashMap<DexString, List<DexEncodedMethod>> groupMethodsByRenamedName(
GraphLense graphLens, NamingLens namingLens, DexProgramClass clazz) {
IdentityHashMap<DexString, List<DexEncodedMethod>> methodsByRenamedName =
- new IdentityHashMap<>(clazz.directMethods().size() + clazz.virtualMethods().size());
+ new IdentityHashMap<>(clazz.getMethodCollection().size());
for (DexEncodedMethod encodedMethod : clazz.methods()) {
// Add method only if renamed, moved, or contains positions.
DexMethod method = encodedMethod.method;
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
index 3681a77..dd5b43a 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
@@ -90,8 +90,9 @@
}
private static boolean assertEqualClasses(DexProgramClass a, DexProgramClass b) {
- assert a.virtualMethods().size() == b.virtualMethods().size();
- assert a.directMethods().size() == b.directMethods().size();
+ assert a.getMethodCollection().numberOfDirectMethods()
+ == b.getMethodCollection().numberOfDirectMethods();
+ assert a.getMethodCollection().size() == b.getMethodCollection().size();
return true;
}
}
diff --git a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
index fd9259f..2daa0a9 100644
--- a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
+++ b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
@@ -48,7 +48,7 @@
AppView.createForR8(new AppInfoWithClassHierarchy(application), options), null);
converter.optimize();
DexProgramClass clazz = application.classes().iterator().next();
- assertEquals(4, clazz.directMethods().size());
+ assertEquals(4, clazz.getMethodCollection().numberOfDirectMethods());
for (DexEncodedMethod method : clazz.directMethods()) {
if (!method.method.name.toString().equals("main")) {
assertEquals(2, method.getCode().asDexCode().instructions.length);
diff --git a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java
index 9c4a0d6..87310d2 100644
--- a/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java
+++ b/src/test/java/com/android/tools/r8/bridgeremoval/hoisting/NonSuperclassBridgeHoistingTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -55,7 +55,7 @@
private void inspect(CodeInspector inspector) {
ClassSubject aClassSubject = inspector.clazz(A.class);
assertThat(aClassSubject, isPresent());
- assertEquals(0, aClassSubject.getDexProgramClass().virtualMethods().size());
+ assertFalse(aClassSubject.getDexProgramClass().getMethodCollection().hasVirtualMethods());
ClassSubject b1ClassSubject = inspector.clazz(B.class);
assertThat(b1ClassSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
index e0818bb..8d25f23 100644
--- a/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
+++ b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.cf;
+import static com.google.common.base.Predicates.alwaysTrue;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.ClassFileConsumer;
@@ -72,7 +73,7 @@
private int countCatchHandlers(AndroidApp inputApp) throws Exception {
CodeInspector inspector = new CodeInspector(inputApp);
DexProgramClass dexClass = inspector.clazz(TestClass.class).getDexProgramClass();
- Code code = dexClass.virtualMethods().get(0).getCode();
+ Code code = dexClass.lookupVirtualMethod(alwaysTrue()).getCode();
if (code.isCfCode()) {
CfCode cfCode = code.asCfCode();
Set<CfLabel> targets = Sets.newIdentityHashSet();
diff --git a/src/test/java/com/android/tools/r8/cf/NonidenticalCatchHandlerTest.java b/src/test/java/com/android/tools/r8/cf/NonidenticalCatchHandlerTest.java
index fcb172b..a2e6005 100644
--- a/src/test/java/com/android/tools/r8/cf/NonidenticalCatchHandlerTest.java
+++ b/src/test/java/com/android/tools/r8/cf/NonidenticalCatchHandlerTest.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.cf;
+import static com.google.common.base.Predicates.alwaysTrue;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.ClassFileConsumer;
@@ -71,7 +72,7 @@
private int countCatchHandlers(AndroidApp inputApp) throws Exception {
CodeInspector inspector = new CodeInspector(inputApp);
DexProgramClass dexClass = inspector.clazz(TestClass.class).getDexProgramClass();
- Code code = dexClass.virtualMethods().get(0).getCode();
+ Code code = dexClass.lookupVirtualMethod(alwaysTrue()).getCode();
if (code.isCfCode()) {
CfCode cfCode = code.asCfCode();
Set<CfLabel> targets = Sets.newIdentityHashSet();
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
index 83dc73e..14f3ded 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
@@ -103,9 +104,10 @@
assertEquals(
"Missing duplicated forEach",
2,
- myCollection.getDexProgramClass().virtualMethods().stream()
- .filter(m -> m.method.name.toString().equals("forEach"))
- .count());
+ IterableUtils.size(
+ myCollection
+ .getDexProgramClass()
+ .virtualMethods(m -> m.method.name.toString().equals("forEach"))));
}
private void assertWrapperMethodsPresent(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingTest.java
index 0441cbf..2cfe861 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/FailingEnumUnboxingTest.java
@@ -88,7 +88,12 @@
assertTrue(inspector.clazz(EnumInstanceField.class).uniqueFieldWithName("a").isPresent());
assertEquals(
- 5, inspector.clazz(EnumStaticMethod.class).getDexProgramClass().directMethods().size());
+ 5,
+ inspector
+ .clazz(EnumStaticMethod.class)
+ .getDexProgramClass()
+ .getMethodCollection()
+ .numberOfDirectMethods());
assertEquals(1, inspector.clazz(EnumVirtualMethod.class).virtualMethods().size());
}
diff --git a/src/test/java/com/android/tools/r8/invalid/DuplicateDefinitionsTest.java b/src/test/java/com/android/tools/r8/invalid/DuplicateDefinitionsTest.java
index 3c3aee6..90771b4 100644
--- a/src/test/java/com/android/tools/r8/invalid/DuplicateDefinitionsTest.java
+++ b/src/test/java/com/android/tools/r8/invalid/DuplicateDefinitionsTest.java
@@ -59,11 +59,11 @@
assertThat(clazz, isPresent());
// There are two direct methods, but only because one is <init>.
- assertEquals(2, clazz.getDexProgramClass().directMethods().size());
+ assertEquals(2, clazz.getDexProgramClass().getMethodCollection().numberOfDirectMethods());
assertThat(clazz.method("void", "<init>", ImmutableList.of()), isPresent());
// There is only one virtual method.
- assertEquals(1, clazz.getDexProgramClass().virtualMethods().size());
+ assertEquals(1, clazz.getDexProgramClass().getMethodCollection().numberOfVirtualMethods());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTest.java b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTest.java
index 6aac431..2498467 100644
--- a/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/KotlinLambdaMergingTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin.lambda;
+import static com.google.common.base.Predicates.alwaysTrue;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertFalse;
@@ -213,7 +214,9 @@
if (check.match(clazz)) {
// Validate static initializer.
if (check instanceof Group) {
- assertEquals(clazz.directMethods().size(), ((Group) check).singletons == 0 ? 1 : 2);
+ assertEquals(
+ clazz.getMethodCollection().numberOfDirectMethods(),
+ ((Group) check).singletons == 0 ? 1 : 2);
}
list.remove(clazz);
@@ -258,8 +261,8 @@
} else {
assertTrue(isJStyleLambdaOrGroup(clazz));
// Taking the number of any virtual method parameters seems to be good enough.
- assertTrue(clazz.virtualMethods().size() > 0);
- return clazz.virtualMethods().get(0).method.proto.parameters.size();
+ assertTrue(clazz.getMethodCollection().hasVirtualMethods());
+ return clazz.lookupVirtualMethod(alwaysTrue()).method.proto.parameters.size();
}
fail("Failed to get arity for " + clazz.type.descriptor.toString());
throw new AssertionError();
diff --git a/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java b/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
index 7261198..b7017e7 100644
--- a/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/AsterisksTest.java
@@ -100,7 +100,7 @@
assertThat(classSubject, isPresent());
assertThat(classSubject, not(isRenamed()));
DexClass clazz = classSubject.getDexProgramClass();
- assertEquals(3, clazz.virtualMethods().size());
+ assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) {
assertTrue(encodedMethod.method.name.toString().startsWith("foo"));
MethodSubject methodSubject =
@@ -141,7 +141,7 @@
assertThat(classSubject, isPresent());
assertThat(classSubject, not(isRenamed()));
DexClass clazz = classSubject.getDexProgramClass();
- assertEquals(3, clazz.virtualMethods().size());
+ assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) {
assertTrue(encodedMethod.method.name.toString().startsWith("foo"));
MethodSubject methodSubject =
@@ -163,7 +163,7 @@
assertThat(classSubject, isPresent());
assertThat(classSubject, not(isRenamed()));
DexClass clazz = classSubject.getDexProgramClass();
- assertEquals(3, clazz.virtualMethods().size());
+ assertEquals(3, clazz.getMethodCollection().numberOfVirtualMethods());
for (DexEncodedMethod encodedMethod : clazz.virtualMethods()) {
assertTrue(encodedMethod.method.name.toString().startsWith("foo"));
MethodSubject methodSubject =
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java
index 4afc009..df8fdc4 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.shaking;
+import static com.google.common.base.Predicates.alwaysTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -56,8 +57,8 @@
private void verifySingleVirtualMethodMarkedAsOverridingLibraryMethod(
AppInfoWithLiveness appInfo, DexType type) {
DexProgramClass clazz = appInfo.definitionFor(type).asProgramClass();
- assertEquals(1, clazz.virtualMethods().size());
- DexEncodedMethod method = clazz.virtualMethods().get(0);
+ assertEquals(1, clazz.getMethodCollection().numberOfVirtualMethods());
+ DexEncodedMethod method = clazz.lookupVirtualMethod(alwaysTrue());
assertTrue(method.isLibraryMethodOverride().isTrue());
}
diff --git a/src/test/java/com/android/tools/r8/smali/OutlineTest.java b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
index 09c1356..578376e 100644
--- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java
+++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
@@ -865,13 +865,12 @@
CodeInspector inspector = new CodeInspector(processedApplication);
ClassSubject clazz = inspector.clazz(OutlineOptions.CLASS_NAME);
assertTrue(clazz.isPresent());
- assertEquals(3, clazz.getDexProgramClass().directMethods().size());
+ assertEquals(3, clazz.getDexProgramClass().getMethodCollection().numberOfDirectMethods());
// Collect the return types of the putlines for the body of method1 and method2.
List<DexType> r = new ArrayList<>();
- for (int i = 0; i < clazz.getDexProgramClass().directMethods().size(); i++) {
- if (clazz.getDexProgramClass().directMethods().get(i).getCode().asDexCode().instructions[0]
- instanceof InvokeVirtual) {
- r.add(clazz.getDexProgramClass().directMethods().get(i).method.proto.returnType);
+ for (DexEncodedMethod directMethod : clazz.getDexProgramClass().directMethods()) {
+ if (directMethod.getCode().asDexCode().instructions[0] instanceof InvokeVirtual) {
+ r.add(directMethod.method.proto.returnType);
}
}
assert r.size() == 2;
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 1f25605..39f7c44 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -193,7 +193,7 @@
}
static <S, T extends Subject> void forAll(
- List<? extends S> items,
+ Iterable<? extends S> items,
BiFunction<S, FoundClassSubject, ? extends T> constructor,
FoundClassSubject clazz,
Consumer<T> consumer) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index df3f287..207932c 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -101,7 +101,7 @@
: new FoundMethodSubject(codeInspector, encoded, this);
}
- private DexEncodedMethod findMethod(List<DexEncodedMethod> methods, DexMethod dexMethod) {
+ private DexEncodedMethod findMethod(Iterable<DexEncodedMethod> methods, DexMethod dexMethod) {
for (DexEncodedMethod method : methods) {
if (method.method.equals(dexMethod)) {
return method;