Replace all usages of GraphLens.mapProgramMethod() by a new LongLivedProgramMethodSetBuilder
Change-Id: Ia71277f3f2c42f8ad9d50076b7dc67d9e27aa108
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLense.java b/src/main/java/com/android/tools/r8/graph/GraphLense.java
index 9d06315..e5de7ff 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLense.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLense.java
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-
import com.android.tools.r8.ir.code.Invoke.Type;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
@@ -163,19 +161,6 @@
return newEncodedMethod;
}
- public ProgramMethod mapProgramMethod(
- ProgramMethod oldMethod, DexDefinitionSupplier definitions) {
- assert oldMethod.getDefinition() != DexEncodedMethod.SENTINEL;
- assert oldMethod.getDefinition() != DexEncodedMethod.ANNOTATION_REFERENCE;
- DexMethod newMethodReference = getRenamedMethodSignature(oldMethod.getReference());
- DexProgramClass newHolder =
- asProgramClassOrNull(definitions.definitionForHolder(newMethodReference));
- assert newHolder != null;
- DexEncodedMethod newMethod = newHolder.lookupMethod(newMethodReference);
- assert newMethod != null;
- return new ProgramMethod(newHolder, newMethod);
- }
-
public abstract DexType lookupType(DexType type);
// This overload can be used when the graph lense is known to be context insensitive.
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 ea88c95..2bfe820 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
@@ -901,7 +901,7 @@
throws ExecutionException {
assert !options.skipIR;
ThreadUtils.processItems(
- outliner.getMethodsSelectedForOutlining(),
+ outliner.buildMethodsSelectedForOutlining(),
method -> {
IRCode code = method.buildIR(appView);
assert code != null;
@@ -1040,9 +1040,11 @@
public void processMethodsConcurrently(ProgramMethodSet methods, ExecutorService executorService)
throws ExecutionException {
- OneTimeMethodProcessor processor = OneTimeMethodProcessor.getInstance(methods);
- processor.forEachWave(
- method -> processMethod(method, delayedOptimizationFeedback, processor), executorService);
+ if (!methods.isEmpty()) {
+ OneTimeMethodProcessor processor = OneTimeMethodProcessor.getInstance(methods);
+ processor.forEachWave(
+ method -> processMethod(method, delayedOptimizationFeedback, processor), executorService);
+ }
}
private String logCode(InternalOptions options, DexEncodedMethod method) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java b/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
index 562a463..7c136f6 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PostMethodProcessor.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.utils.IROrdering;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.ArrayDeque;
import java.util.Collection;
@@ -57,7 +58,8 @@
public static class Builder {
private final Collection<CodeOptimization> defaultCodeOptimizations;
- private final ProgramMethodSet methodsMap = ProgramMethodSet.create();
+ private final LongLivedProgramMethodSetBuilder methodsMap =
+ new LongLivedProgramMethodSetBuilder();
private final Map<DexEncodedMethod, Collection<CodeOptimization>> optimizationsMap =
new IdentityHashMap<>();
@@ -99,17 +101,12 @@
// new signature. The compiler needs to update the set of methods that must be reprocessed
// according to the graph lens.
public void mapDexEncodedMethods(AppView<?> appView) {
- ProgramMethodSet newMethodsMap = ProgramMethodSet.create();
Map<DexEncodedMethod, Collection<CodeOptimization>> newOptimizationsMap =
new IdentityHashMap<>();
- methodsMap.forEach(
- method -> newMethodsMap.add(appView.graphLense().mapProgramMethod(method, appView)));
optimizationsMap.forEach(
(method, optimizations) ->
newOptimizationsMap.put(
appView.graphLense().mapDexEncodedMethod(method, appView), optimizations));
- methodsMap.clear();
- methodsMap.addAll(newMethodsMap);
optimizationsMap.clear();
optimizationsMap.putAll(newOptimizationsMap);
}
@@ -128,7 +125,7 @@
if (definition != null) {
DexProgramClass clazz =
appView.definitionForHolder(definition).asProgramClass();
- set.add(new ProgramMethod(clazz, definition));
+ set.createAndAdd(clazz, definition);
}
});
put(set);
@@ -138,7 +135,8 @@
return null;
}
CallGraph callGraph =
- new PartialCallGraphBuilder(appView, methodsMap).build(executorService, timing);
+ new PartialCallGraphBuilder(appView, methodsMap.build(appView))
+ .build(executorService, timing);
return new PostMethodProcessor(appView, optimizationsMap, callGraph);
}
}
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 3210468..47ee95f 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
@@ -355,7 +355,7 @@
private void addSyntheticMethod(DexProgramClass clazz, DexEncodedMethod method) {
newSyntheticMethods
.computeIfAbsent(clazz, key -> ProgramMethodSet.create())
- .add(new ProgramMethod(clazz, method));
+ .createAndAdd(clazz, method);
}
private void addICCEThrowingMethod(DexMethod method, DexClass clazz) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
index 863e92d..a640fb6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -22,7 +22,6 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
-import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -282,22 +281,21 @@
assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
continue;
}
- DexClass dexClass = appView.definitionFor(clazz.superType);
+ DexClass superclass = appView.definitionFor(clazz.superType);
// Only performs computation if superclass is a library class, but not object to filter out
// the most common case.
- if (dexClass != null
- && dexClass.isLibraryClass()
- && dexClass.type != appView.dexItemFactory().objectType) {
- for (DexType dexType : map.keySet()) {
- if (inherit(dexClass.asLibraryClass(), dexType, emulatedDispatchMethods)) {
- addedMethods.addAll(addInterfacesAndForwardingMethods(clazz, map.get(dexType)));
- }
- }
+ if (superclass != null
+ && superclass.isLibraryClass()
+ && superclass.type != appView.dexItemFactory().objectType) {
+ map.forEach(
+ (type, methods) -> {
+ if (inherit(superclass.asLibraryClass(), type, emulatedDispatchMethods)) {
+ addInterfacesAndForwardingMethods(
+ clazz, methods, method -> addedMethods.createAndAdd(clazz, method));
+ }
+ });
}
}
- if (addedMethods.isEmpty()) {
- return;
- }
converter.processMethodsConcurrently(addedMethods, executorService);
}
@@ -320,14 +318,15 @@
return false;
}
- private List<ProgramMethod> addInterfacesAndForwardingMethods(
- DexProgramClass clazz, List<DexMethod> dexMethods) {
+ private void addInterfacesAndForwardingMethods(
+ DexProgramClass clazz,
+ List<DexMethod> methods,
+ Consumer<DexEncodedMethod> newForwardingMethodsConsumer) {
// DesugaredLibraryRetargeter emulate dispatch: insertion of a marker interface & forwarding
// methods.
// We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
// applies up to 24.
- List<ProgramMethod> newForwardingMethods = new ArrayList<>();
- for (DexMethod dexMethod : dexMethods) {
+ for (DexMethod dexMethod : methods) {
DexType[] newInterfaces =
Arrays.copyOf(clazz.interfaces.values, clazz.interfaces.size() + 1);
newInterfaces[newInterfaces.length - 1] = dispatchInterfaceTypeFor(dexMethod);
@@ -336,10 +335,9 @@
if (dexEncodedMethod == null) {
DexEncodedMethod newMethod = createForwardingMethod(dexMethod, clazz);
clazz.addVirtualMethod(newMethod);
- newForwardingMethods.add(new ProgramMethod(clazz, newMethod));
+ newForwardingMethodsConsumer.accept(newMethod);
}
}
- return newForwardingMethods;
}
private DexEncodedMethod createForwardingMethod(DexMethod target, DexClass clazz) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 1e93aa9..2b9456a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -68,6 +68,7 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
+import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.ArrayList;
import java.util.Collections;
@@ -94,14 +95,14 @@
* <li>Second, {@link Outliner#selectMethodsForOutlining()} is called to retain the lists of
* methods found in the first step that are large enough (see {@link InternalOptions#outline}
* {@link OutlineOptions#threshold}), and the methods to be further analyzed for outlining is
- * returned by {@link Outliner#getMethodsSelectedForOutlining}. Each selected method is then
+ * returned by {@link Outliner#buildMethodsSelectedForOutlining}. Each selected method is then
* converted back to IR and passed to {@link Outliner#identifyOutlineSites(IRCode)}, which
* then stores concrete outlining candidates in {@link Outliner#outlineSites}.
* <li>Third, {@link Outliner#buildOutlinerClass(DexType)} is called to construct the <em>outline
* support class</em> containing a static helper method for each outline candidate that occurs
* frequently enough. Each selected method is then converted to IR, passed to {@link
- * Outliner#applyOutliningCandidate(IRCode)} to perform the outlining, and
- * converted back to the output format (DEX or CF).
+ * Outliner#applyOutliningCandidate(IRCode)} to perform the outlining, and converted back to
+ * the output format (DEX or CF).
* </ul>
*/
public class Outliner {
@@ -109,7 +110,8 @@
/** Result of first step (see {@link Outliner#createOutlineMethodIdentifierGenerator()}. */
private final List<List<ProgramMethod>> candidateMethodLists = new ArrayList<>();
/** Result of second step (see {@link Outliner#selectMethodsForOutlining()}. */
- private final ProgramMethodSet methodsSelectedForOutlining = ProgramMethodSet.create();
+ private final LongLivedProgramMethodSetBuilder methodsSelectedForOutlining =
+ new LongLivedProgramMethodSetBuilder();
/** Result of second step (see {@link Outliner#selectMethodsForOutlining()}. */
private final Map<Outline, List<ProgramMethod>> outlineSites = new HashMap<>();
/** Result of third step (see {@link Outliner#buildOutlinerClass(DexType)}. */
@@ -1311,19 +1313,15 @@
assert outlineSites.isEmpty();
for (List<ProgramMethod> outlineMethods : candidateMethodLists) {
if (outlineMethods.size() >= appView.options().outline.threshold) {
- for (ProgramMethod outlineMethod : outlineMethods) {
- ProgramMethod mappedOutlineMethod =
- appView.graphLense().mapProgramMethod(outlineMethod, appView);
- methodsSelectedForOutlining.add(mappedOutlineMethod);
- }
+ methodsSelectedForOutlining.addAll(outlineMethods);
}
}
candidateMethodLists.clear();
return !methodsSelectedForOutlining.isEmpty();
}
- public ProgramMethodSet getMethodsSelectedForOutlining() {
- return methodsSelectedForOutlining;
+ public ProgramMethodSet buildMethodsSelectedForOutlining() {
+ return methodsSelectedForOutlining.build(appView);
}
public DexProgramClass buildOutlinerClass(DexType type) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 0141c6e..06c2894 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -314,7 +314,6 @@
appView
.appInfo()
.rewrittenWithLens(appView.appInfo().app().asDirect(), enumUnboxingLens));
- classStaticizer.filterCandidates();
// Update optimization info.
feedback.fixupOptimizationInfos(
appView,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 01f1800..2a5e9cd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -52,6 +52,7 @@
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
+import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
@@ -194,7 +195,8 @@
// we mark a method for further processing, and then invalidate the only lambda referenced
// from it. In this case we will reprocess method that does not need patching, but it
// should not be happening very frequently and we ignore possible overhead.
- private final ProgramMethodSet methodsToReprocess = ProgramMethodSet.create();
+ private final LongLivedProgramMethodSetBuilder methodsToReprocess =
+ new LongLivedProgramMethodSetBuilder();
private final AppView<AppInfoWithLiveness> appView;
private final Kotlin kotlin;
@@ -453,11 +455,7 @@
if (methodsToReprocess.isEmpty()) {
return;
}
- ProgramMethodSet methods = ProgramMethodSet.create();
- methodsToReprocess.forEach(
- method -> {
- methods.add(appView.graphLense().mapProgramMethod(method, appView));
- });
+ ProgramMethodSet methods = methodsToReprocess.build(appView);
converter.processMethodsConcurrently(methods, executorService);
assert methods.stream()
.map(DexClassAndMethod::getDefinition)
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 21ed08c..675e8f4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -34,7 +34,8 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
-import com.android.tools.r8.utils.collections.ProgramMethodSet;
+import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
+import com.android.tools.r8.utils.collections.ProgramMethodSetOrBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -68,7 +69,7 @@
final AtomicInteger fieldWrites = new AtomicInteger();
// Number of instances created.
final AtomicInteger instancesCreated = new AtomicInteger();
- final ProgramMethodSet referencedFrom = ProgramMethodSet.create();
+ ProgramMethodSetOrBuilder referencedFrom = new LongLivedProgramMethodSetBuilder();
final AtomicReference<DexEncodedMethod> constructor = new AtomicReference<>();
final AtomicReference<DexEncodedMethod> getter = new AtomicReference<>();
@@ -100,16 +101,6 @@
candidates.remove(candidate.type);
return null;
}
-
- void filterMethods() {
- ProgramMethodSet newReferencedFrom = ProgramMethodSet.create();
- for (ProgramMethod method : referencedFrom) {
- ProgramMethod mapped = appView.graphLense().mapProgramMethod(method, appView);
- newReferencedFrom.add(mapped);
- }
- referencedFrom.clear();
- referencedFrom.addAll(newReferencedFrom);
- }
}
// The map storing all the potential candidates for staticizing.
@@ -298,7 +289,7 @@
}
// Ignore just read instruction.
}
- candidateInfo.referencedFrom.add(method);
+ candidateInfo.referencedFrom.asLongLivedBuilder().add(method);
}
continue;
}
@@ -318,7 +309,7 @@
// Check the field being read: make sure all usages are valid.
CandidateInfo info = processStaticFieldRead(instruction.asStaticGet());
if (info != null) {
- info.referencedFrom.add(method);
+ info.referencedFrom.asLongLivedBuilder().add(method);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -332,7 +323,7 @@
// Check if it is a static singleton getter.
CandidateInfo info = processInvokeStatic(instruction.asInvokeStatic());
if (info != null) {
- info.referencedFrom.add(method);
+ info.referencedFrom.asLongLivedBuilder().add(method);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -668,17 +659,6 @@
return false;
}
- // Methods may have their signature changed in-between the IR processing rounds, leading to
- // duplicates where one version is the outdated version. Remove these.
- // This also ensures no unboxed enum are staticized, if that would be the case, then
- // the candidate would need to be removed from the candidate list.
- public void filterCandidates() {
- for (Map.Entry<DexType, CandidateInfo> entry : candidates.entrySet()) {
- assert !appView.unboxedEnums().containsEnum(entry.getKey());
- entry.getValue().filterMethods();
- }
- }
-
// Perform staticizing candidates:
//
// 1. After filtering candidates based on usage, finalize the list of candidates by
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 4d21056..efcf89f 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
@@ -219,9 +219,12 @@
continue;
}
+ ProgramMethodSet referencedFrom = info.referencedFrom.asLongLivedBuilder().build(appView);
+ info.referencedFrom = referencedFrom;
+
// CHECK: references to field read usages are fixable.
boolean fixableFieldReads = true;
- for (ProgramMethod method : info.referencedFrom) {
+ for (ProgramMethod method : referencedFrom) {
IRCode code = method.buildIR(appView);
assert code != null;
List<Instruction> singletonUsers =
@@ -298,8 +301,9 @@
if (getter != null) {
singletonGetters.put(getter.method, candidate);
}
- assert validMethods(candidate.referencedFrom);
- referencingExtraMethods.addAll(candidate.referencedFrom);
+ ProgramMethodSet referencedFrom = candidate.referencedFrom.asSet();
+ assert validMethods(referencedFrom);
+ referencingExtraMethods.addAll(referencedFrom);
}
removedInstanceMethods.forEach(referencingExtraMethods::remove);
@@ -720,7 +724,7 @@
} else if (!factory().isConstructor(method.method)) {
DexEncodedMethod staticizedMethod = method.toStaticMethodWithoutThis();
newDirectMethods.add(staticizedMethod);
- staticizedMethods.add(new ProgramMethod(candidateClass, staticizedMethod));
+ staticizedMethods.createAndAdd(candidateClass, staticizedMethod);
methodMapping.put(method.method, staticizedMethod.method);
}
}
@@ -806,7 +810,7 @@
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.add(new ProgramMethod(hostClass, newMethod));
+ staticizedMethods.createAndAdd(hostClass, newMethod);
}
DexMethod originalMethod = methodMapping.inverse().get(method.method);
if (originalMethod == null) {
diff --git a/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java b/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java
new file mode 100644
index 0000000..269b24d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/collections/LongLivedProgramMethodSetBuilder.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2020, 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.utils.collections;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.Sets;
+import java.util.Set;
+
+public class LongLivedProgramMethodSetBuilder implements ProgramMethodSetOrBuilder {
+
+ private Set<DexMethod> methods = Sets.newIdentityHashSet();
+
+ public LongLivedProgramMethodSetBuilder() {}
+
+ public void add(ProgramMethod method) {
+ methods.add(method.getReference());
+ }
+
+ public void addAll(Iterable<ProgramMethod> methods) {
+ methods.forEach(this::add);
+ }
+
+ public ProgramMethodSet build(AppView<AppInfoWithLiveness> appView) {
+ ProgramMethodSet result = ProgramMethodSet.create(methods.size());
+ for (DexMethod oldMethod : methods) {
+ DexMethod method = appView.graphLense().getRenamedMethodSignature(oldMethod);
+ DexProgramClass holder = appView.definitionForHolder(method).asProgramClass();
+ result.createAndAdd(holder, holder.lookupMethod(method));
+ }
+ return result;
+ }
+
+ public boolean isEmpty() {
+ return methods.isEmpty();
+ }
+
+ @Override
+ public boolean isLongLivedBuilder() {
+ return true;
+ }
+
+ @Override
+ public LongLivedProgramMethodSetBuilder asLongLivedBuilder() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
index 0ca3738..d288177 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
@@ -17,7 +18,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
-public class ProgramMethodSet implements Iterable<ProgramMethod> {
+public class ProgramMethodSet implements ProgramMethodSetOrBuilder, Iterable<ProgramMethod> {
private static final ProgramMethodSet EMPTY = new ProgramMethodSet(ImmutableMap.of());
@@ -67,6 +68,15 @@
backing.putAll(methods.backing);
}
+ @Override
+ public ProgramMethodSet asSet() {
+ return this;
+ }
+
+ public boolean createAndAdd(DexProgramClass clazz, DexEncodedMethod definition) {
+ return add(new ProgramMethod(clazz, definition));
+ }
+
public boolean contains(DexEncodedMethod method) {
return backing.containsKey(method.getReference());
}
@@ -83,6 +93,11 @@
return backing.isEmpty();
}
+ @Override
+ public Iterator<ProgramMethod> iterator() {
+ return backing.values().iterator();
+ }
+
public boolean remove(DexMethod method) {
ProgramMethod existing = backing.remove(method);
return existing != null;
@@ -106,9 +121,4 @@
forEach(method -> definitions.add(method.getDefinition()));
return definitions;
}
-
- @Override
- public Iterator<ProgramMethod> iterator() {
- return backing.values().iterator();
- }
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSetOrBuilder.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSetOrBuilder.java
new file mode 100644
index 0000000..f7298be
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSetOrBuilder.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, 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.utils.collections;
+
+public interface ProgramMethodSetOrBuilder {
+
+ default boolean isLongLivedBuilder() {
+ return false;
+ }
+
+ default LongLivedProgramMethodSetBuilder asLongLivedBuilder() {
+ return null;
+ }
+
+ default ProgramMethodSet asSet() {
+ return null;
+ }
+}