Move implementedInterfaces to AppInfoWithClassHierarchy.
Change-Id: I8daf953f9cf5699ca967e9cc14ead23d01824d7e
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 96fee36..6630f9c 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -5,8 +5,11 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
+import com.google.common.collect.Sets;
import java.util.ArrayDeque;
+import java.util.Collections;
import java.util.Deque;
+import java.util.Set;
/* Specific subclass of AppInfo designed to support desugaring in D8. Desugaring requires a
* minimal amount of knowledge in the overall program, provided through classpath. Basic
@@ -89,6 +92,57 @@
return isSubtype(type, other) || isSubtype(other, type);
}
+ /** Collect all interfaces that this type directly or indirectly implements. */
+ public Set<DexType> implementedInterfaces(DexType type) {
+ assert type.isClassType();
+ DexClass clazz = definitionFor(type);
+ if (clazz == null) {
+ return Collections.emptySet();
+ }
+
+ // Fast path for a type below object with no interfaces.
+ if (clazz.superType == dexItemFactory().objectType && clazz.interfaces.isEmpty()) {
+ return clazz.isInterface() ? Collections.singleton(type) : Collections.emptySet();
+ }
+
+ // Slow path traverses the full hierarchy.
+ Set<DexType> interfaces = Sets.newIdentityHashSet();
+ if (clazz.isInterface()) {
+ interfaces.add(type);
+ }
+ Deque<DexType> workList = new ArrayDeque<>();
+ if (clazz.superType != null && clazz.superType != dexItemFactory().objectType) {
+ workList.add(clazz.superType);
+ }
+ Collections.addAll(interfaces, clazz.interfaces.values);
+ Collections.addAll(workList, clazz.interfaces.values);
+ while (!workList.isEmpty()) {
+ DexType item = workList.pollFirst();
+ DexClass definition = definitionFor(item);
+ if (definition == null) {
+ // Collect missing types for future reporting?
+ continue;
+ }
+ if (definition.superType != null && definition.superType != dexItemFactory().objectType) {
+ workList.add(definition.superType);
+ }
+ for (DexType iface : definition.interfaces.values) {
+ if (interfaces.add(iface)) {
+ workList.add(iface);
+ }
+ }
+ }
+ return interfaces;
+ }
+
+ public boolean isExternalizable(DexType type) {
+ return isSubtype(type, dexItemFactory().externalizableType);
+ }
+
+ public boolean isSerializable(DexType type) {
+ return isSubtype(type, dexItemFactory().serializableType);
+ }
+
/**
* Helper method used for emulated interface resolution (not in JVM specifications). The result
* may be abstract.
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index 17e63e6..f04ba61 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -511,47 +511,6 @@
return clazz == null || clazz.hasMissingSuperType(this);
}
- public boolean isExternalizable(DexType type) {
- return implementedInterfaces(type).contains(dexItemFactory().externalizableType);
- }
-
- public boolean isSerializable(DexType type) {
- return implementedInterfaces(type).contains(dexItemFactory().serializableType);
- }
-
- /** Collect all interfaces that this type directly or indirectly implements. */
- public Set<DexType> implementedInterfaces(DexType type) {
- TypeInfo info = getTypeInfo(type);
- if (info.implementedInterfaces != null) {
- return info.implementedInterfaces;
- }
- synchronized (this) {
- if (info.implementedInterfaces == null) {
- Set<DexType> interfaces = Sets.newIdentityHashSet();
- implementedInterfaces(type, interfaces);
- info.implementedInterfaces = interfaces;
- }
- }
- return info.implementedInterfaces;
- }
-
- private void implementedInterfaces(DexType type, Set<DexType> interfaces) {
- DexClass dexClass = definitionFor(type);
- // Loop to traverse the super type hierarchy of the current type.
- while (dexClass != null) {
- if (dexClass.isInterface()) {
- interfaces.add(dexClass.type);
- }
- for (DexType itf : dexClass.interfaces.values) {
- implementedInterfaces(itf, interfaces);
- }
- if (dexClass.superType == null) {
- break;
- }
- dexClass = definitionFor(dexClass.superType);
- }
- }
-
public DexType getSingleSubtype(DexType type) {
TypeInfo info = getTypeInfo(type);
assert info.hierarchyLevel != UNKNOWN_LEVEL;
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 d540b18..321b5c7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -779,11 +779,11 @@
return isResolvable.isTrue();
}
- public boolean isSerializable(AppView<? extends AppInfoWithSubtyping> appView) {
+ public boolean isSerializable(AppView<? extends AppInfoWithClassHierarchy> appView) {
return appView.appInfo().isSerializable(type);
}
- public boolean isExternalizable(AppView<? extends AppInfoWithSubtyping> appView) {
+ public boolean isExternalizable(AppView<? extends AppInfoWithClassHierarchy> appView) {
return appView.appInfo().isExternalizable(type);
}