Generalize traversal continuation to have a break value.
Change-Id: I3a5d8abd255147a6c68d8eb2c13f849687e17015
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java
index ed6767a..977a836 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java
@@ -30,28 +30,28 @@
public abstract int getMemberCount();
- public TraversalContinuation visitFields(
- BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation> visitor) {
+ public TraversalContinuation<?> visitFields(
+ BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?>> visitor) {
return visitFields(visitor, classReference, 1);
}
- public TraversalContinuation visitMethods(
- BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation> visitor) {
+ public TraversalContinuation<?> visitMethods(
+ BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?>> visitor) {
return visitMethods(visitor, classReference, 1);
}
- protected abstract TraversalContinuation visitFields(
- BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation> visitor,
+ protected abstract TraversalContinuation<?> visitFields(
+ BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
ClassReference holder,
int minApiClass);
- protected abstract TraversalContinuation visitMethods(
- BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation> visitor,
+ protected abstract TraversalContinuation<?> visitMethods(
+ BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
ClassReference holder,
int minApiClass);
- protected TraversalContinuation visitField(
- BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation> visitor,
+ protected TraversalContinuation<?> visitField(
+ BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
ClassReference holder,
int minApiClass,
int minApiField,
@@ -62,8 +62,8 @@
getAndroidApiLevel(Integer.max(minApiClass, minApiField)));
}
- protected TraversalContinuation visitMethod(
- BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation> visitor,
+ protected TraversalContinuation<?> visitMethod(
+ BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
ClassReference holder,
int minApiClass,
int minApiMethod,
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index f32be7e..4ecd71c 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.graph;
-import static com.android.tools.r8.utils.TraversalContinuation.BREAK;
-import static com.android.tools.r8.utils.TraversalContinuation.CONTINUE;
+import static com.android.tools.r8.utils.TraversalContinuation.doBreak;
+import static com.android.tools.r8.utils.TraversalContinuation.doContinue;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.MethodResolutionResult.ArrayCloneMethodResult;
@@ -21,7 +21,6 @@
import com.android.tools.r8.shaking.MissingClasses;
import com.android.tools.r8.synthesis.CommittedItems;
import com.android.tools.r8.synthesis.SyntheticItems;
-import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.TraversalContinuation;
@@ -159,19 +158,19 @@
}
/** Primitive traversal over all (non-interface) superclasses of a given type. */
- public TraversalContinuation traverseSuperClasses(
- DexClass clazz, TriFunction<DexType, DexClass, DexClass, TraversalContinuation> fn) {
+ public <T> TraversalContinuation<T> traverseSuperClasses(
+ DexClass clazz, TriFunction<DexType, DexClass, DexClass, TraversalContinuation<T>> fn) {
DexClass currentClass = clazz;
while (currentClass != null && currentClass.getSuperType() != null) {
DexClass superclass = definitionFor(currentClass.getSuperType());
- TraversalContinuation stepResult =
+ TraversalContinuation<T> stepResult =
fn.apply(currentClass.getSuperType(), superclass, currentClass);
if (stepResult.shouldBreak()) {
return stepResult;
}
currentClass = superclass;
}
- return CONTINUE;
+ return doContinue();
}
/**
@@ -181,8 +180,8 @@
* given type is *not* visited. The function indicates if traversal should continue or break. The
* result of the traversal is BREAK iff the function returned BREAK.
*/
- public TraversalContinuation traverseSuperTypes(
- final DexClass clazz, TriFunction<DexType, DexClass, Boolean, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseSuperTypes(
+ final DexClass clazz, TriFunction<DexType, DexClass, Boolean, TraversalContinuation<?>> fn) {
// We do an initial zero-allocation pass over the class super chain as it does not require a
// worklist/seen-set. Only if the traversal is not aborted and there actually are interfaces,
// do we continue traversal over the interface types. This is assuming that the second pass
@@ -195,7 +194,7 @@
if (currentClass.superType == null) {
break;
}
- TraversalContinuation stepResult = fn.apply(currentClass.superType, currentClass, false);
+ TraversalContinuation<?> stepResult = fn.apply(currentClass.superType, currentClass, false);
if (stepResult.shouldBreak()) {
return stepResult;
}
@@ -203,7 +202,7 @@
}
}
if (interfaceCount == 0) {
- return CONTINUE;
+ return doContinue();
}
// Interfaces exist, create a worklist and seen set to ensure single visits.
Set<DexType> seen = Sets.newIdentityHashSet();
@@ -214,7 +213,7 @@
while (currentClass != null) {
for (DexType iface : currentClass.interfaces.values) {
if (seen.add(iface)) {
- TraversalContinuation stepResult = fn.apply(iface, currentClass, true);
+ TraversalContinuation<?> stepResult = fn.apply(iface, currentClass, true);
if (stepResult.shouldBreak()) {
return stepResult;
}
@@ -234,7 +233,7 @@
if (definition != null) {
for (DexType iface : definition.interfaces.values) {
if (seen.add(iface)) {
- TraversalContinuation stepResult = fn.apply(iface, definition, true);
+ TraversalContinuation<?> stepResult = fn.apply(iface, definition, true);
if (stepResult.shouldBreak()) {
return stepResult;
}
@@ -243,7 +242,7 @@
}
}
}
- return CONTINUE;
+ return doContinue();
}
/**
@@ -256,7 +255,7 @@
clazz,
(superType, subclass, isInterface) -> {
fn.accept(superType, subclass, isInterface);
- return CONTINUE;
+ return doContinue();
});
}
@@ -292,7 +291,8 @@
}
// TODO(b/123506120): Report missing types when the predicate is inconclusive.
return traverseSuperTypes(
- clazz, (superType, subclass, isInterface) -> superType == supertype ? BREAK : CONTINUE)
+ clazz,
+ (superType, subclass, isInterface) -> superType == supertype ? doBreak() : doContinue())
.shouldBreak();
}
@@ -327,23 +327,22 @@
if (superclass.getType() == dexItemFactory().objectType) {
return true;
}
- BooleanBox result = new BooleanBox();
- traverseSuperClasses(
- subclass,
- (currentType, currentClass, immediateSubclass) -> {
- if (currentType == superclass.getType()) {
- result.set();
- return BREAK;
- }
- if (currentClass == null) {
- return BREAK;
- }
- if (superclass.isProgramClass() && !currentClass.isProgramClass()) {
- return BREAK;
- }
- return CONTINUE;
- });
- return result.isTrue();
+ TraversalContinuation<Boolean> result =
+ traverseSuperClasses(
+ subclass,
+ (currentType, currentClass, immediateSubclass) -> {
+ if (currentType == superclass.getType()) {
+ return doBreak(true);
+ }
+ if (currentClass == null) {
+ return doBreak(false);
+ }
+ if (superclass.isProgramClass() && !currentClass.isProgramClass()) {
+ return doBreak(false);
+ }
+ return doContinue();
+ });
+ return result.isBreak() && result.asBreak().getValue();
}
public boolean inSameHierarchy(DexType type, DexType other) {
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 31e7030..a0535bc 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -356,13 +356,14 @@
staticFields(predicate).forEach(consumer);
}
- public TraversalContinuation traverseFields(Function<DexEncodedField, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseFields(
+ Function<DexEncodedField, TraversalContinuation<?>> fn) {
for (DexEncodedField field : fields()) {
if (fn.apply(field).shouldBreak()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
public List<DexEncodedField> staticFields() {
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 3077717..e0d4545 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -327,38 +327,38 @@
return null;
}
- public TraversalContinuation traverseProgramMembers(
- Function<ProgramMember<?, ?>, TraversalContinuation> fn) {
- TraversalContinuation continuation = traverseProgramFields(fn);
+ public TraversalContinuation<?> traverseProgramMembers(
+ Function<ProgramMember<?, ?>, TraversalContinuation<?>> fn) {
+ TraversalContinuation<?> continuation = traverseProgramFields(fn);
if (continuation.shouldContinue()) {
return traverseProgramMethods(fn);
}
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
- public TraversalContinuation traverseProgramFields(
- Function<? super ProgramField, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseProgramFields(
+ Function<? super ProgramField, TraversalContinuation<?>> fn) {
return traverseFields(field -> fn.apply(new ProgramField(this, field)));
}
- public TraversalContinuation traverseProgramMethods(
- Function<? super ProgramMethod, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseProgramMethods(
+ Function<? super ProgramMethod, TraversalContinuation<?>> fn) {
return getMethodCollection().traverse(method -> fn.apply(new ProgramMethod(this, method)));
}
- public TraversalContinuation traverseProgramInstanceInitializers(
- Function<ProgramMethod, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseProgramInstanceInitializers(
+ Function<ProgramMethod, TraversalContinuation<?>> fn) {
return traverseProgramMethods(fn, DexEncodedMethod::isInstanceInitializer);
}
- public TraversalContinuation traverseProgramMethods(
- Function<ProgramMethod, TraversalContinuation> fn, Predicate<DexEncodedMethod> predicate) {
+ public TraversalContinuation<?> traverseProgramMethods(
+ Function<ProgramMethod, TraversalContinuation<?>> fn, Predicate<DexEncodedMethod> predicate) {
return getMethodCollection()
.traverse(
method ->
predicate.test(method)
? fn.apply(new ProgramMethod(this, method))
- : TraversalContinuation.CONTINUE);
+ : TraversalContinuation.doContinue());
}
public Kind getOriginKind() {
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 545645e..d848b49 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -56,20 +56,20 @@
}
@Override
- TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn) {
+ TraversalContinuation<?> traverse(Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
for (DexEncodedMethod method : directMethods) {
- TraversalContinuation stepResult = fn.apply(method);
+ TraversalContinuation<?> stepResult = fn.apply(method);
if (stepResult.shouldBreak()) {
return stepResult;
}
}
for (DexEncodedMethod method : virtualMethods) {
- TraversalContinuation stepResult = fn.apply(method);
+ TraversalContinuation<?> stepResult = fn.apply(method);
if (stepResult.shouldBreak()) {
return stepResult;
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
@Override
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 4a403c4..45b0902 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -90,7 +90,8 @@
return backing.size();
}
- public TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverse(
+ Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
return backing.traverse(fn);
}
@@ -340,8 +341,8 @@
return traverse(
method ->
method.hasAnyAnnotations()
- ? TraversalContinuation.BREAK
- : TraversalContinuation.CONTINUE)
+ ? TraversalContinuation.doBreak()
+ : TraversalContinuation.doContinue())
.shouldBreak();
}
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 90fbf1f..0d91ae4 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
@@ -36,7 +36,8 @@
// Traversal methods.
- abstract TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn);
+ abstract TraversalContinuation<?> traverse(
+ Function<DexEncodedMethod, TraversalContinuation<?>> fn);
void forEachMethod(Consumer<DexEncodedMethod> fn) {
forEachMethod(fn, alwaysTrue());
@@ -48,7 +49,7 @@
if (predicate.test(method)) {
fn.accept(method);
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
index 66be012..f7717d0 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
@@ -85,9 +85,10 @@
}
@Override
- public TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverse(
+ Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
assert assertReadEntry();
- TraversalContinuation result = super.traverse(fn);
+ TraversalContinuation<?> result = super.traverse(fn);
assert assertReadExit();
return result;
}
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 d42f6eb..1437ac1 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
@@ -88,14 +88,14 @@
}
@Override
- TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn) {
+ TraversalContinuation<?> traverse(Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
for (Entry<DexMethodSignature, DexEncodedMethod> entry : methodMap.entrySet()) {
- TraversalContinuation result = fn.apply(entry.getValue());
+ TraversalContinuation<?> result = fn.apply(entry.getValue());
if (result.shouldBreak()) {
return result;
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
@Override
@@ -128,9 +128,9 @@
method -> {
if (predicate.test(method)) {
found.set(method);
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
return found.get();
}
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
index bcad963..f1a3bda 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
@@ -174,19 +174,19 @@
type,
clazz -> {
onClass.accept(clazz);
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
},
lambda -> {
onLambda.accept(lambda);
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
},
appInfo);
}
- public TraversalContinuation traverseInstantiatedSubtypes(
+ public TraversalContinuation<?> traverseInstantiatedSubtypes(
DexType type,
- Function<DexProgramClass, TraversalContinuation> onClass,
- Function<LambdaDescriptor, TraversalContinuation> onLambda,
+ Function<DexProgramClass, TraversalContinuation<?>> onClass,
+ Function<LambdaDescriptor, TraversalContinuation<?>> onLambda,
AppInfo appInfo) {
WorkList<DexClass> worklist = WorkList.newIdentityWorkList();
if (type == appInfo.dexItemFactory().objectType) {
@@ -208,7 +208,7 @@
for (LambdaDescriptor lambda :
instantiatedLambdas.getOrDefault(type, Collections.emptyList())) {
if (onLambda.apply(lambda).shouldBreak()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
} else {
@@ -223,7 +223,7 @@
if (isInstantiatedDirectly(programClass)
|| isInterfaceWithUnknownSubtypeHierarchy(programClass)) {
if (onClass.apply(programClass).shouldBreak()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
}
@@ -231,11 +231,11 @@
for (LambdaDescriptor lambda :
instantiatedLambdas.getOrDefault(clazz.type, Collections.emptyList())) {
if (onLambda.apply(lambda).shouldBreak()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
public Set<DexType> getInstantiatedLambdaInterfaces() {
diff --git a/src/main/java/com/android/tools/r8/graph/UseRegistry.java b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
index 1ce97e6..919d940 100644
--- a/src/main/java/com/android/tools/r8/graph/UseRegistry.java
+++ b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
@@ -15,7 +15,7 @@
private final AppView<?> appView;
private final T context;
- private TraversalContinuation continuation = TraversalContinuation.CONTINUE;
+ private TraversalContinuation<?> continuation = TraversalContinuation.doContinue();
public enum MethodHandleUse {
ARGUMENT_TO_LAMBDA_METAFACTORY,
@@ -37,7 +37,7 @@
public void doBreak() {
assert continuation.shouldContinue();
- continuation = TraversalContinuation.BREAK;
+ continuation = TraversalContinuation.doBreak();
}
public GraphLens getCodeLens() {
@@ -54,7 +54,7 @@
return context.asMethod();
}
- public TraversalContinuation getTraversalContinuation() {
+ public TraversalContinuation<?> getTraversalContinuation() {
return continuation;
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 70d534e..c0cb840 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -326,7 +326,7 @@
(superType, subclass, isInterface) -> {
assert superType != interfaceClass.getType()
: "Interface " + interfaceClass.getTypeName() + " inherits from itself";
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
}
return true;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
index e8eb14e..79d2a51 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
@@ -208,9 +208,9 @@
(supertype, superclass, immediateSubclass) -> {
if (superclass != null && superclass.isProgramClass()) {
superclasses.add(superclass.asProgramClass());
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
});
// Run the tracer from the class initializers of the superclasses.
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
index 9336e2b..1573dde 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
@@ -65,16 +65,16 @@
// Check that all accesses from [clazz] to classes or members from the current package of
// [clazz] will continue to work. This is guaranteed if the methods of [clazz] do not access
// any private or protected classes or members from the current package of [clazz].
- TraversalContinuation result =
+ TraversalContinuation<?> result =
clazz.traverseProgramMethods(
method -> {
boolean foundIllegalAccess =
method.registerCodeReferencesWithResult(
new IllegalAccessDetector(appView, method));
if (foundIllegalAccess) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
return result.shouldBreak();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java
index ddbe46b..572b153 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java
@@ -7,8 +7,8 @@
import static com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query.DIRECTLY;
import static com.android.tools.r8.ir.optimize.SimpleDominatingEffectAnalysis.InstructionEffect.NO_EFFECT;
import static com.android.tools.r8.ir.optimize.SimpleDominatingEffectAnalysis.InstructionEffect.OTHER_EFFECT;
-import static com.android.tools.r8.utils.TraversalContinuation.BREAK;
-import static com.android.tools.r8.utils.TraversalContinuation.CONTINUE;
+import static com.android.tools.r8.utils.TraversalContinuation.doBreak;
+import static com.android.tools.r8.utils.TraversalContinuation.doContinue;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ProgramMethod;
@@ -249,7 +249,7 @@
new StatefulDepthFirstSearchWorkList<BasicBlock, ResultStateWithPartialBlocks>() {
@Override
- protected TraversalContinuation process(
+ protected TraversalContinuation<?> process(
DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks> node,
Function<BasicBlock, DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks>>
childNodeConsumer) {
@@ -257,7 +257,7 @@
for (Instruction instruction : node.getNode().getInstructions()) {
if (visitedInstructions.getAndIncrement() > analysis.maxNumberOfInstructions()) {
builder.fail();
- return BREAK;
+ return doBreak();
}
effect = analysis.analyze(instruction);
if (!effect.isNoEffect()) {
@@ -276,16 +276,16 @@
// If we see a block where the children have not been processed we cannot guarantee
// all paths having the effect since - ex. we could have a non-terminating loop.
builder.fail();
- return BREAK;
+ return doBreak();
}
}
}
node.setState(new ResultStateWithPartialBlocks(effect.toResultState(), ImmutableList.of()));
- return CONTINUE;
+ return doContinue();
}
@Override
- protected TraversalContinuation joiner(
+ protected TraversalContinuation<?> joiner(
DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks> node,
List<DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks>> childNodes) {
ResultStateWithPartialBlocks resultState = node.getState();
@@ -300,7 +300,7 @@
builder.setResult(resultState.state);
builder.setFailingBlocksForPartialResults(resultState.failingBlocks);
}
- return CONTINUE;
+ return doContinue();
}
}.run(code.entryBlock());
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index 339f93d..618e1f5 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -180,7 +180,7 @@
reservedNamingState.add(reservationState);
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index d601873..7081da1 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1126,9 +1126,9 @@
.traverseProgramMembers(
member -> {
if (keepInfo.getInfo(member).isRepackagingAllowed(member, options())) {
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
})
.shouldContinue();
}
@@ -1574,20 +1574,20 @@
type,
clazz -> {
if (objectAllocationInfoCollection.isInterfaceWithUnknownSubtypeHierarchy(clazz)) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
} else {
SingleResolutionResult resolution =
resolveMethodOn(clazz, dexItemFactory().objectMembers.finalize)
.asSingleResolution();
if (resolution != null && resolution.getResolvedHolder().isProgramClass()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
},
lambda -> {
// Lambda classes do not have finalizers.
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
},
this)
.shouldBreak();
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
index 8ffaa8e..ffc2149 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
@@ -114,18 +114,18 @@
});
}
- public abstract TraversalContinuation traverseTypeMatchers(
- Function<ProguardTypeMatcher, TraversalContinuation> fn);
+ public abstract TraversalContinuation<?> traverseTypeMatchers(
+ Function<ProguardTypeMatcher, TraversalContinuation<?>> fn);
- public final TraversalContinuation traverseTypeMatchers(
- Function<ProguardTypeMatcher, TraversalContinuation> fn,
+ public final TraversalContinuation<?> traverseTypeMatchers(
+ Function<ProguardTypeMatcher, TraversalContinuation<?>> fn,
Predicate<ProguardTypeMatcher> predicate) {
return traverseTypeMatchers(
matcher -> {
if (predicate.test(matcher)) {
return fn.apply(matcher);
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
}
@@ -168,9 +168,9 @@
}
@Override
- public TraversalContinuation traverseTypeMatchers(
- Function<ProguardTypeMatcher, TraversalContinuation> fn) {
- return TraversalContinuation.CONTINUE;
+ public TraversalContinuation<?> traverseTypeMatchers(
+ Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
+ return TraversalContinuation.doContinue();
}
}
@@ -236,8 +236,8 @@
}
@Override
- public TraversalContinuation traverseTypeMatchers(
- Function<ProguardTypeMatcher, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseTypeMatchers(
+ Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
return fn.apply(className);
}
}
@@ -320,14 +320,14 @@
}
@Override
- public TraversalContinuation traverseTypeMatchers(
- Function<ProguardTypeMatcher, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseTypeMatchers(
+ Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
for (ProguardTypeMatcher matcher : classNames) {
if (fn.apply(matcher).shouldBreak()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
}
@@ -416,14 +416,14 @@
}
@Override
- public TraversalContinuation traverseTypeMatchers(
- Function<ProguardTypeMatcher, TraversalContinuation> fn) {
+ public TraversalContinuation<?> traverseTypeMatchers(
+ Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
for (ProguardTypeMatcher matcher : classNames.keySet()) {
if (fn.apply(matcher).shouldBreak()) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
}
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index 95ec8c3..524fe08 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -1403,7 +1403,7 @@
dependentMinimumKeepInfo.getUnconditionalMinimumKeepInfoOrDefault(
MinimumKeepInfoCollection.empty());
for (DexProgramClass clazz : classesWithCheckDiscardedMembers) {
- TraversalContinuation continueIfAllMembersMarkedAsCheckDiscarded =
+ TraversalContinuation<?> continueIfAllMembersMarkedAsCheckDiscarded =
clazz.traverseProgramMembers(
member ->
TraversalContinuation.continueIf(
diff --git a/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java b/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java
index df9803a..33b7d4e 100644
--- a/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java
+++ b/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java
@@ -38,9 +38,9 @@
(superType, subclass, ignore) -> {
if (seen.add(superType)) {
cache.remove(superType);
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
} else {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
}),
lambda -> {
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 14a84d5..6cc5f84 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -417,7 +417,7 @@
// If there is a constructor in the target, make sure that all source constructors can be
// inlined.
if (!Iterables.isEmpty(targetClass.programInstanceInitializers())) {
- TraversalContinuation result =
+ TraversalContinuation<?> result =
sourceClass.traverseProgramInstanceInitializers(
method -> {
AbortReason reason = disallowInlining(method, targetClass);
@@ -426,9 +426,9 @@
if (Log.ENABLED) {
reason.printLogMessageForClass(sourceClass);
}
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
if (result.shouldBreak()) {
return false;
@@ -454,7 +454,7 @@
// If there is an invoke-special to a default interface method and we are not merging into an
// interface, then abort, since invoke-special to a virtual class method requires desugaring.
if (sourceClass.isInterface() && !targetClass.isInterface()) {
- TraversalContinuation result =
+ TraversalContinuation<?> result =
sourceClass.traverseProgramMethods(
method -> {
boolean foundInvokeSpecialToDefaultLibraryMethod =
@@ -586,16 +586,16 @@
// Check that all accesses from [source] to classes or members from the current package of
// [source] will continue to work. This is guaranteed if the methods of [source] do not access
// any private or protected classes or members from the current package of [source].
- TraversalContinuation result =
+ TraversalContinuation<?> result =
source.traverseProgramMethods(
method -> {
boolean foundIllegalAccess =
method.registerCodeReferencesWithResult(
new IllegalAccessDetector(appView, method));
if (foundIllegalAccess) {
- return TraversalContinuation.BREAK;
+ return TraversalContinuation.doBreak();
}
- return TraversalContinuation.CONTINUE;
+ return TraversalContinuation.doContinue();
});
return result.shouldBreak();
}
diff --git a/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java b/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java
index c82f332..6b5df9b 100644
--- a/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java
+++ b/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java
@@ -107,10 +107,10 @@
abstract T createDfsNode(N node);
/** The initial processing of a node during forward search */
- abstract TraversalContinuation internalOnVisit(T node);
+ abstract TraversalContinuation<?> internalOnVisit(T node);
/** The joining of state during backtracking of the algorithm. */
- abstract TraversalContinuation internalOnJoin(T node);
+ abstract TraversalContinuation<?> internalOnJoin(T node);
final T internalEnqueueNode(N value) {
T dfsNode = createDfsNode(value);
@@ -121,13 +121,13 @@
}
@SafeVarargs
- public final TraversalContinuation run(N... roots) {
+ public final TraversalContinuation<?> run(N... roots) {
return run(Arrays.asList(roots));
}
- public final TraversalContinuation run(Collection<N> roots) {
+ public final TraversalContinuation<?> run(Collection<N> roots) {
roots.forEach(this::internalEnqueueNode);
- TraversalContinuation continuation = TraversalContinuation.CONTINUE;
+ TraversalContinuation<?> continuation = TraversalContinuation.doContinue();
while (!workList.isEmpty()) {
T node = workList.removeLast();
if (node.isFinished()) {
@@ -161,7 +161,7 @@
* before but not finished there is a cycle.
* @return A value describing if the DFS algorithm should continue to run.
*/
- protected abstract TraversalContinuation process(
+ protected abstract TraversalContinuation<?> process(
DFSNode<N> node, Function<N, DFSNode<N>> childNodeConsumer);
@Override
@@ -170,13 +170,13 @@
}
@Override
- TraversalContinuation internalOnVisit(DFSNodeImpl<N> node) {
+ TraversalContinuation<?> internalOnVisit(DFSNodeImpl<N> node) {
return process(node, this::internalEnqueueNode);
}
@Override
- protected TraversalContinuation internalOnJoin(DFSNodeImpl<N> node) {
- return TraversalContinuation.CONTINUE;
+ protected TraversalContinuation<?> internalOnJoin(DFSNodeImpl<N> node) {
+ return TraversalContinuation.doContinue();
}
}
@@ -195,7 +195,7 @@
* before but not finished there is a cycle.
* @return A value describing if the DFS algorithm should continue to run.
*/
- protected abstract TraversalContinuation process(
+ protected abstract TraversalContinuation<?> process(
DFSNodeWithState<N, S> node, Function<N, DFSNodeWithState<N, S>> childNodeConsumer);
/**
@@ -205,7 +205,7 @@
* @param childStates The already computed child states.
* @return A value describing if the DFS algorithm should continue to run.
*/
- protected abstract TraversalContinuation joiner(
+ protected abstract TraversalContinuation<?> joiner(
DFSNodeWithState<N, S> node, List<DFSNodeWithState<N, S>> childStates);
@Override
@@ -214,7 +214,7 @@
}
@Override
- TraversalContinuation internalOnVisit(DFSNodeWithStateImpl<N, S> node) {
+ TraversalContinuation<?> internalOnVisit(DFSNodeWithStateImpl<N, S> node) {
List<DFSNodeWithState<N, S>> childStates = new ArrayList<>();
List<DFSNodeWithState<N, S>> removedChildStates = childStateMap.put(node, childStates);
assert removedChildStates == null;
@@ -228,7 +228,7 @@
}
@Override
- protected TraversalContinuation internalOnJoin(DFSNodeWithStateImpl<N, S> node) {
+ protected TraversalContinuation<?> internalOnJoin(DFSNodeWithStateImpl<N, S> node) {
return joiner(
node,
childStateMap.computeIfAbsent(
diff --git a/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
index 0e9d873..5bd242f 100644
--- a/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
+++ b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
@@ -3,25 +3,87 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
+import com.android.tools.r8.errors.Unreachable;
+
/** Two value continuation value to indicate the continuation of a loop/traversal. */
/* This class is used for building up api class member traversals. */
-public enum TraversalContinuation {
- CONTINUE,
- BREAK;
+public abstract class TraversalContinuation<T> {
- public static TraversalContinuation breakIf(boolean condition) {
+ public boolean isBreak() {
+ return !isContinue();
+ }
+
+ public boolean isContinue() {
+ return false;
+ }
+
+ public Break<T> asBreak() {
+ return null;
+ }
+
+ public static final class Continue<T> extends TraversalContinuation<T> {
+ private static final TraversalContinuation<?> CONTINUE = new Continue<Object>();
+
+ private Continue() {}
+
+ @Override
+ public boolean isContinue() {
+ return true;
+ }
+ }
+
+ public static class Break<T> extends TraversalContinuation<T> {
+ private static final TraversalContinuation<?> BREAK_NO_VALUE =
+ new Break<Object>(null) {
+ @Override
+ public Object getValue() {
+ return new Unreachable(
+ "Invalid attempt at getting a value from a no-value break state.");
+ }
+ };
+
+ private final T value;
+
+ private Break(T value) {
+ this.value = value;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ @Override
+ public Break<T> asBreak() {
+ return this;
+ }
+ }
+
+ public static TraversalContinuation<?> breakIf(boolean condition) {
return continueIf(!condition);
}
- public static TraversalContinuation continueIf(boolean condition) {
- return condition ? CONTINUE : BREAK;
+ public static TraversalContinuation<?> continueIf(boolean condition) {
+ return condition ? doContinue() : doBreak();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> TraversalContinuation<T> doContinue() {
+ return (TraversalContinuation<T>) Continue.CONTINUE;
+ }
+
+ public static TraversalContinuation<?> doBreak() {
+ return Break.BREAK_NO_VALUE;
+ }
+
+ public static <T> TraversalContinuation<T> doBreak(T value) {
+ return new Break<>(value);
}
public final boolean shouldBreak() {
- return this == BREAK;
+ return isBreak();
}
public final boolean shouldContinue() {
- return this == CONTINUE;
+ return isContinue();
}
}