Workaround assertion error due to profile rules not in app
Change-Id: I5afed4fcbafb8378003b2073a74c5034fd9f0a56
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
index e132aed..6f4fb22 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
@@ -17,7 +17,7 @@
import java.util.Collection;
import java.util.List;
-public abstract class ArtProfileCollection {
+public abstract class ArtProfileCollection implements Iterable<ArtProfile> {
public static ArtProfileCollection createInitialArtProfileCollection(
AppInfo appInfo, InternalOptions options) {
diff --git a/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java
index ab478b8..42ab16d 100644
--- a/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/EmptyArtProfileCollection.java
@@ -8,7 +8,9 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.Timing;
+import java.util.Iterator;
public class EmptyArtProfileCollection extends ArtProfileCollection {
@@ -31,6 +33,11 @@
}
@Override
+ public Iterator<ArtProfile> iterator() {
+ return IteratorUtils.empty();
+ }
+
+ @Override
public NonEmptyArtProfileCollection asNonEmpty() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
index a4b8450..c98371b 100644
--- a/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
@@ -17,8 +17,7 @@
import java.util.List;
import java.util.function.Function;
-public class NonEmptyArtProfileCollection extends ArtProfileCollection
- implements Iterable<ArtProfile> {
+public class NonEmptyArtProfileCollection extends ArtProfileCollection {
private final List<ArtProfile> artProfiles;
diff --git a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
index 6730a23..00aae47 100644
--- a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
@@ -44,6 +44,10 @@
return counter.get();
}
+ public static <T> Iterator<T> empty() {
+ return IterableUtils.<T>empty().iterator();
+ }
+
public static <T, S extends T> Iterator<S> filter(
Iterator<? extends T> iterator, Predicate<T> predicate) {
return new Iterator<S>() {
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
index 45f4ca8..cb482b9 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.classmerging.SyntheticArgumentClass;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -20,10 +20,12 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.optimize.argumentpropagation.utils.ProgramClassesBidirectedGraph;
+import com.android.tools.r8.profile.art.ArtProfile;
import com.android.tools.r8.profile.art.ArtProfileCompletenessChecker;
import com.android.tools.r8.profile.rewriting.ProfileCollectionAdditions;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.KeepInfoCollection;
+import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ThreadUtils;
@@ -93,44 +95,65 @@
// TODO(b/192821424): Can be removed if handled.
extractPinnedClasses(appView.appInfo().getFailedMethodResolutionTargets(), pinnedClasses);
+ // The ART profiles may contain method rules that do not exist in the app. These method may
+ // refer to classes that will be vertically merged into their unique subtype, but the vertical
+ // class merger lens will not contain any mappings for the missing methods in the ART profiles.
+ // Therefore, trying to perform a lens lookup on these methods will fail.
+ for (ArtProfile artProfile : appView.getArtProfileCollection()) {
+ artProfile.forEachRule(
+ ConsumerUtils.emptyThrowingConsumer(),
+ methodRule -> {
+ DexMethod method = methodRule.getMethod();
+ if (method.getHolderType().isArrayType()) {
+ return;
+ }
+ DexClass holder =
+ appView.appInfo().definitionForWithoutExistenceAssert(method.getHolderType());
+ if (method.lookupOnClass(holder) == null) {
+ extractPinnedClasses(methodRule.getMethod(), pinnedClasses);
+ }
+ });
+ }
+
return pinnedClasses;
}
private <T extends DexReference> void extractPinnedClasses(
Iterable<T> items, Set<DexProgramClass> pinnedClasses) {
for (DexReference item : items) {
- if (item.isDexType()) {
- markTypeAsPinned(item.asDexType(), pinnedClasses);
- } else if (item.isDexField()) {
- // Pin the holder and the type of the field.
- DexField field = item.asDexField();
- markTypeAsPinned(field.getHolderType(), pinnedClasses);
- markTypeAsPinned(field.getType(), pinnedClasses);
- } else {
- assert item.isDexMethod();
- // Pin the holder, the return type and the parameter types of the method. If we were to
- // merge any of these types into their sub classes, then we would implicitly change the
- // signature of this method.
- DexMethod method = item.asDexMethod();
- markTypeAsPinned(method.getHolderType(), pinnedClasses);
- markTypeAsPinned(method.getReturnType(), pinnedClasses);
- for (DexType parameterType : method.getParameters()) {
- markTypeAsPinned(parameterType, pinnedClasses);
- }
- }
+ extractPinnedClasses(item, pinnedClasses);
}
}
+ private void extractPinnedClasses(DexReference reference, Set<DexProgramClass> pinnedClasses) {
+ markTypeAsPinned(reference.getContextType(), pinnedClasses);
+ reference.accept(
+ ConsumerUtils.emptyConsumer(),
+ field -> {
+ // Pin the type of the field.
+ markTypeAsPinned(field.getType(), pinnedClasses);
+ },
+ method -> {
+ // Pin the return type and the parameter types of the method. If we were to merge any of
+ // these types into their sub classes, then we would implicitly change the signature of
+ // this method.
+ for (DexType type : method.getReferencedTypes()) {
+ markTypeAsPinned(type, pinnedClasses);
+ }
+ });
+ }
+
private void markTypeAsPinned(DexType type, Set<DexProgramClass> pinnedClasses) {
DexType baseType = type.toBaseType(dexItemFactory);
- if (!baseType.isClassType() || appView.appInfo().isPinnedWithDefinitionLookup(baseType)) {
- // We check for the case where the type is pinned according to appInfo.isPinned,
- // so we only need to add it here if it is not the case.
+ if (!baseType.isClassType()) {
return;
}
- DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(baseType));
- if (clazz != null) {
+ DexProgramClass clazz =
+ asProgramClassOrNull(appView.appInfo().definitionForWithoutExistenceAssert(baseType));
+ if (clazz != null && !appView.getKeepInfo(clazz).isPinned(options)) {
+ // We check for the case where the type is pinned according to its keep info, so we only need
+ // to add it here if it is not the case.
markClassAsPinned(clazz, pinnedClasses);
}
}