Extend abstract base for method collection backings.
Change-Id: Iefd6fe1ef2951717f86026a9075c62e059353f5a
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 773a71a..6c74124 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -148,12 +148,8 @@
return Iterables.filter(directMethods(), predicate::test);
}
- public void appendDirectMethod(DexEncodedMethod method) {
- methodCollection.appendDirectMethod(method);
- }
-
- public void appendDirectMethods(Collection<DexEncodedMethod> methods) {
- methodCollection.appendDirectMethods(methods);
+ public void addDirectMethods(Collection<DexEncodedMethod> methods) {
+ methodCollection.addDirectMethods(methods);
}
public void removeDirectMethod(DexMethod method) {
@@ -172,12 +168,8 @@
return Iterables.filter(virtualMethods(), predicate::test);
}
- public void appendVirtualMethod(DexEncodedMethod method) {
- methodCollection.appendVirtualMethod(method);
- }
-
- public void appendVirtualMethods(Collection<DexEncodedMethod> methods) {
- methodCollection.appendVirtualMethods(methods);
+ public void addVirtualMethods(Collection<DexEncodedMethod> methods) {
+ methodCollection.addVirtualMethods(methods);
}
public void setVirtualMethods(DexEncodedMethod[] methods) {
diff --git a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
index 96059b4..7f87c94 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -30,6 +30,23 @@
return !belongsToDirectPool(method);
}
+ private boolean verifyNoDuplicateMethods() {
+ Set<DexMethod> unique = Sets.newIdentityHashSet();
+ forEachMethod(
+ method -> {
+ boolean changed = unique.add(method.method);
+ assert changed : "Duplicate method `" + method.method.toSourceString() + "`";
+ });
+ return true;
+ }
+
+ @Override
+ boolean verify() {
+ assert verifyNoDuplicateMethods();
+ return true;
+ }
+
+ @Override
int size() {
return directMethods.length + virtualMethods.length;
}
@@ -51,24 +68,19 @@
return TraversalContinuation.CONTINUE;
}
+ @Override
public Iterable<DexEncodedMethod> methods() {
return Iterables.concat(Arrays.asList(directMethods), Arrays.asList(virtualMethods));
}
+ @Override
List<DexEncodedMethod> directMethods() {
assert directMethods != null;
return Arrays.asList(directMethods);
}
- void appendDirectMethod(DexEncodedMethod method) {
- DexEncodedMethod[] newMethods = new DexEncodedMethod[directMethods.length + 1];
- System.arraycopy(directMethods, 0, newMethods, 0, directMethods.length);
- newMethods[directMethods.length] = method;
- directMethods = newMethods;
- assert verifyNoDuplicateMethods();
- }
-
- void appendDirectMethods(Collection<DexEncodedMethod> methods) {
+ @Override
+ void addDirectMethods(Collection<DexEncodedMethod> methods) {
DexEncodedMethod[] newMethods = new DexEncodedMethod[directMethods.length + methods.size()];
System.arraycopy(directMethods, 0, newMethods, 0, directMethods.length);
int i = directMethods.length;
@@ -87,6 +99,7 @@
directMethods = newMethods;
}
+ @Override
void removeDirectMethod(DexMethod method) {
int index = -1;
for (int i = 0; i < directMethods.length; i++) {
@@ -100,25 +113,20 @@
}
}
+ @Override
void setDirectMethods(DexEncodedMethod[] methods) {
directMethods = MoreObjects.firstNonNull(methods, DexEncodedMethod.EMPTY_ARRAY);
assert verifyNoDuplicateMethods();
}
+ @Override
List<DexEncodedMethod> virtualMethods() {
assert virtualMethods != null;
return Arrays.asList(virtualMethods);
}
- void appendVirtualMethod(DexEncodedMethod method) {
- DexEncodedMethod[] newMethods = new DexEncodedMethod[virtualMethods.length + 1];
- System.arraycopy(virtualMethods, 0, newMethods, 0, virtualMethods.length);
- newMethods[virtualMethods.length] = method;
- virtualMethods = newMethods;
- assert verifyNoDuplicateMethods();
- }
-
- void appendVirtualMethods(Collection<DexEncodedMethod> methods) {
+ @Override
+ void addVirtualMethods(Collection<DexEncodedMethod> methods) {
DexEncodedMethod[] newMethods = new DexEncodedMethod[virtualMethods.length + methods.size()];
System.arraycopy(virtualMethods, 0, newMethods, 0, virtualMethods.length);
int i = virtualMethods.length;
@@ -130,11 +138,13 @@
assert verifyNoDuplicateMethods();
}
+ @Override
void setVirtualMethods(DexEncodedMethod[] methods) {
virtualMethods = MoreObjects.firstNonNull(methods, DexEncodedMethod.EMPTY_ARRAY);
assert verifyNoDuplicateMethods();
}
+ @Override
void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
int vLen = virtualMethods.length;
int dLen = directMethods.length;
@@ -161,6 +171,7 @@
setVirtualMethods(newVirtualMethods);
}
+ @Override
DexEncodedMethod getDirectMethod(DexMethod method) {
for (DexEncodedMethod directMethod : directMethods) {
if (method.match(directMethod)) {
@@ -170,10 +181,12 @@
return null;
}
+ @Override
DexEncodedMethod getDirectMethod(Predicate<DexEncodedMethod> predicate) {
return PredicateUtils.findFirst(directMethods, predicate);
}
+ @Override
DexEncodedMethod getVirtualMethod(DexMethod method) {
for (DexEncodedMethod virtualMethod : virtualMethods) {
if (method.match(virtualMethod)) {
@@ -183,51 +196,41 @@
return null;
}
+ @Override
DexEncodedMethod getVirtualMethod(Predicate<DexEncodedMethod> predicate) {
return PredicateUtils.findFirst(virtualMethods, predicate);
}
+ @Override
DexEncodedMethod getMethod(DexMethod method) {
DexEncodedMethod result = getDirectMethod(method);
return result == null ? getVirtualMethod(method) : result;
}
+ @Override
void addMethod(DexEncodedMethod method) {
- if (method.accessFlags.isStatic()
- || method.accessFlags.isPrivate()
- || method.accessFlags.isConstructor()) {
+ if (belongsToDirectPool(method)) {
addDirectMethod(method);
} else {
addVirtualMethod(method);
}
}
+ @Override
void addVirtualMethod(DexEncodedMethod virtualMethod) {
- assert !virtualMethod.accessFlags.isStatic();
- assert !virtualMethod.accessFlags.isPrivate();
- assert !virtualMethod.accessFlags.isConstructor();
+ assert belongsToVirtualPool(virtualMethod);
virtualMethods = Arrays.copyOf(virtualMethods, virtualMethods.length + 1);
virtualMethods[virtualMethods.length - 1] = virtualMethod;
}
- void addDirectMethod(DexEncodedMethod staticMethod) {
- assert staticMethod.accessFlags.isStatic()
- || staticMethod.accessFlags.isPrivate()
- || staticMethod.accessFlags.isConstructor();
+ @Override
+ void addDirectMethod(DexEncodedMethod directMethod) {
+ assert belongsToDirectPool(directMethod);
directMethods = Arrays.copyOf(directMethods, directMethods.length + 1);
- directMethods[directMethods.length - 1] = staticMethod;
+ directMethods[directMethods.length - 1] = directMethod;
}
- boolean verifyNoDuplicateMethods() {
- Set<DexMethod> unique = Sets.newIdentityHashSet();
- forEachMethod(
- method -> {
- boolean changed = unique.add(method.method);
- assert changed : "Duplicate method `" + method.method.toSourceString() + "`";
- });
- return true;
- }
-
+ @Override
public DexEncodedMethod replaceDirectMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < directMethods.length; i++) {
@@ -242,6 +245,7 @@
return null;
}
+ @Override
public DexEncodedMethod replaceDirectMethodWithVirtualMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < directMethods.length; i++) {
@@ -250,18 +254,20 @@
DexEncodedMethod newMethod = replacement.apply(directMethod);
assert belongsToVirtualPool(newMethod);
removeDirectMethod(i);
- appendVirtualMethod(newMethod);
+ addVirtualMethod(newMethod);
return newMethod;
}
}
return null;
}
+ @Override
public void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
replaceDirectMethods(replacement);
replaceVirtualMethods(replacement);
}
+ @Override
public void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < directMethods.length; i++) {
DexEncodedMethod method = directMethods[i];
@@ -274,6 +280,7 @@
}
}
+ @Override
public void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < virtualMethods.length; i++) {
DexEncodedMethod method = virtualMethods[i];
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 7cfc97c..54b212f 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -16,7 +16,7 @@
public class MethodCollection {
private final DexClass holder;
- private final MethodArrayBacking backing = new MethodArrayBacking();
+ private final MethodCollectionBacking backing = new MethodArrayBacking();
private DexEncodedMethod cachedClassInitializer = DexEncodedMethod.SENTINEL;
public MethodCollection(DexClass holder) {
@@ -163,16 +163,10 @@
return backing.replaceDirectMethodWithVirtualMethod(method, replacement);
}
- public void appendDirectMethod(DexEncodedMethod method) {
- assert verifyCorrectnessOfMethodHolder(method);
- resetDirectMethodCaches();
- backing.appendDirectMethod(method);
- }
-
- public void appendDirectMethods(Collection<DexEncodedMethod> methods) {
+ public void addDirectMethods(Collection<DexEncodedMethod> methods) {
assert verifyCorrectnessOfMethodHolders(methods);
resetDirectMethodCaches();
- backing.appendDirectMethods(methods);
+ backing.addDirectMethods(methods);
}
public void removeDirectMethod(DexMethod method) {
@@ -186,16 +180,10 @@
backing.setDirectMethods(methods);
}
- public void appendVirtualMethod(DexEncodedMethod method) {
- assert verifyCorrectnessOfMethodHolder(method);
- resetVirtualMethodCaches();
- backing.appendVirtualMethod(method);
- }
-
- public void appendVirtualMethods(Collection<DexEncodedMethod> methods) {
+ public void addVirtualMethods(Collection<DexEncodedMethod> methods) {
assert verifyCorrectnessOfMethodHolders(methods);
resetVirtualMethodCaches();
- backing.appendVirtualMethods(methods);
+ backing.addVirtualMethods(methods);
}
public void setVirtualMethods(DexEncodedMethod[] methods) {
@@ -223,7 +211,7 @@
method -> {
assert verifyCorrectnessOfMethodHolder(method);
});
- assert backing.verifyNoDuplicateMethods();
+ assert backing.verify();
return true;
}
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 b50adf6..09de861 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
@@ -4,11 +4,25 @@
package com.android.tools.r8.graph;
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;
+import java.util.function.Predicate;
public abstract class MethodCollectionBacking {
+ // Internal consistency.
+
+ abstract boolean verify();
+
+ // Collection methods.
+
+ abstract int size();
+
+ // Traversal methods.
+
abstract TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn);
void forEachMethod(Consumer<DexEncodedMethod> fn) {
@@ -18,4 +32,58 @@
return TraversalContinuation.CONTINUE;
});
}
+
+ abstract Iterable<DexEncodedMethod> methods();
+
+ abstract List<DexEncodedMethod> directMethods();
+
+ abstract List<DexEncodedMethod> virtualMethods();
+
+ // Lookup methods.
+
+ abstract DexEncodedMethod getMethod(DexMethod method);
+
+ abstract DexEncodedMethod getDirectMethod(DexMethod method);
+
+ abstract DexEncodedMethod getDirectMethod(Predicate<DexEncodedMethod> predicate);
+
+ abstract DexEncodedMethod getVirtualMethod(DexMethod method);
+
+ abstract DexEncodedMethod getVirtualMethod(Predicate<DexEncodedMethod> predicate);
+
+ // Amendment methods.
+
+ abstract void addMethod(DexEncodedMethod method);
+
+ abstract void addDirectMethod(DexEncodedMethod method);
+
+ abstract void addVirtualMethod(DexEncodedMethod method);
+
+ abstract void addDirectMethods(Collection<DexEncodedMethod> methods);
+
+ abstract void addVirtualMethods(Collection<DexEncodedMethod> methods);
+
+ // Removal methods.
+
+ abstract void removeDirectMethod(DexMethod method);
+
+ // Replacement/mutation methods.
+
+ abstract void setDirectMethods(DexEncodedMethod[] methods);
+
+ abstract void setVirtualMethods(DexEncodedMethod[] methods);
+
+ abstract void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract DexEncodedMethod replaceDirectMethod(
+ DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract DexEncodedMethod replaceDirectMethodWithVirtualMethod(
+ DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods);
}
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 76e97df..3d16d19 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
@@ -229,7 +229,7 @@
for (DexProgramClass clazz : newSyntheticMethods.keySet()) {
List<DexEncodedMethod> newForwardingMethods = newSyntheticMethods.get(clazz);
if (newForwardingMethods != null) {
- clazz.appendVirtualMethods(newForwardingMethods);
+ clazz.addVirtualMethods(newForwardingMethods);
newForwardingMethods.forEach(newSynthesizedMethodConsumer);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
index efd6f7d..2be1832 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
@@ -99,7 +99,7 @@
method.annotations().keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)));
}
// Add the newly constructed methods to the class.
- clazz.appendVirtualMethods(covariantReturnTypeMethods);
+ clazz.addVirtualMethods(covariantReturnTypeMethods);
}
// Processes all the dalvik.annotation.codegen.CovariantReturnType and dalvik.annotation.codegen.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
index ceed9ef..fb97d0c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
@@ -294,7 +294,7 @@
for (DexClass dexClass : callBackMethods.keySet()) {
List<DexEncodedMethod> dexEncodedMethods =
generateCallbackMethods(callBackMethods.get(dexClass), dexClass);
- dexClass.appendVirtualMethods(dexEncodedMethods);
+ dexClass.addVirtualMethods(dexEncodedMethods);
result.addAll(dexEncodedMethods);
}
return result;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index ec1b05f..87c3424 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -667,14 +667,14 @@
// For all instantiation points for which the compiler creates lambda$
// methods, it creates these methods in the same class/interface.
DexMethod implMethod = descriptor.implHandle.asMethod();
- DexClass implMethodHolder = definitionFor(implMethod.holder);
+ DexProgramClass implMethodHolder = definitionFor(implMethod.holder).asProgramClass();
return allowMethodModification
? modifyLambdaImplementationMethod(implMethod, implMethodHolder)
: createSyntheticAccessor(implMethod, implMethodHolder);
}
private DexEncodedMethod modifyLambdaImplementationMethod(
- DexMethod implMethod, DexClass implMethodHolder) {
+ DexMethod implMethod, DexProgramClass implMethodHolder) {
return implMethodHolder
.getMethodCollection()
.replaceDirectMethodWithVirtualMethod(
@@ -701,7 +701,7 @@
}
private DexEncodedMethod createSyntheticAccessor(
- DexMethod implMethod, DexClass implMethodHolder) {
+ DexMethod implMethod, DexProgramClass implMethodHolder) {
MethodAccessFlags accessorFlags =
MethodAccessFlags.fromSharedAccessFlags(
Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC, false);
@@ -725,7 +725,7 @@
registry -> registry.registerInvokeDirect(implMethod)),
true);
- implMethodHolder.appendVirtualMethod(accessorEncodedMethod);
+ implMethodHolder.addVirtualMethod(accessorEncodedMethod);
return accessorEncodedMethod;
}
}
@@ -761,7 +761,7 @@
// We may arrive here concurrently so we need must update the methods of the class atomically.
synchronized (accessorClass) {
- accessorClass.appendDirectMethod(accessorEncodedMethod);
+ accessorClass.addDirectMethod(accessorEncodedMethod);
}
return accessorEncodedMethod;
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 e0ca9093..9c8b4d5 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
@@ -724,7 +724,7 @@
methodMapping.put(originalMethod, newMethod.method);
}
}
- hostClass.appendDirectMethods(newMethods);
+ hostClass.addDirectMethods(newMethods);
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 1dd374d..bebaf56 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2534,7 +2534,7 @@
DexProgramClass holder = bridge.getHolder();
DexEncodedMethod method = bridge.getMethod();
appView.appInfo().invalidateTypeCacheFor(holder.type);
- holder.appendVirtualMethod(method);
+ holder.addVirtualMethod(method);
targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
liveMethods.add(holder, method, graphReporter.fakeReportShouldNotBeUsed());
pinnedItems.add(method.method);
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 b89678e..5031d82 100644
--- a/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
@@ -471,9 +471,9 @@
numberOfMergedClasses++;
// Move members from source to target.
- targetClass.appendDirectMethods(
+ targetClass.addDirectMethods(
mergeMethods(sourceClass.directMethods(), targetClass.directMethods(), targetClass));
- targetClass.appendVirtualMethods(
+ targetClass.addVirtualMethods(
mergeMethods(sourceClass.virtualMethods(), targetClass.virtualMethods(), targetClass));
targetClass.setStaticFields(
mergeFields(sourceClass.staticFields(), targetClass.staticFields(), targetClass));
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index ef0ce63..fde562c 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1085,8 +1085,8 @@
? DexTypeList.empty()
: new DexTypeList(interfaces.toArray(DexType.EMPTY_ARRAY));
// Step 2: replace fields and methods.
- target.appendDirectMethods(directMethods.values());
- target.appendVirtualMethods(virtualMethods.values());
+ target.addDirectMethods(directMethods.values());
+ target.addVirtualMethods(virtualMethods.values());
target.setInstanceFields(mergedInstanceFields);
target.setStaticFields(mergedStaticFields);
target.forEachField(feedback::markFieldCannotBeKept);