Move deferred annotation processing to the fixed point
This is required to ensure that conditional edges with annotation
constraints are applied to the final keep info. This is a prerequisite
for more precise native interpretation of keep annotations.
Bug: b/323816623
Change-Id: I52977cd698b9b58630ae8486277682e5255dcc19
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 0b345b0..25a690e 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -442,6 +442,9 @@
*/
private final Set<DexMethod> recordFieldValuesReferences = Sets.newIdentityHashSet();
+ /** Set of annotations that are live (needed for deferred (re)processing). */
+ private final Set<DexType> liveAnnotations = Sets.newIdentityHashSet();
+
/**
* A map from annotation classes to annotations that need to be processed should the classes ever
* become live.
@@ -2327,11 +2330,8 @@
processAnnotations(clazz);
- // If this type has deferred annotations, we have to process those now, too.
if (clazz.isAnnotation()) {
- processDeferredAnnotations(clazz, deferredAnnotations, AnnotatedKind::from);
- processDeferredAnnotations(
- clazz, deferredParameterAnnotations, annotatedItem -> AnnotatedKind.PARAMETER);
+ liveAnnotations.add(clazz.getType());
}
compatEnqueueHolderIfDependentNonStaticMember(
@@ -2341,20 +2341,21 @@
}
private void processDeferredAnnotations(
- DexProgramClass clazz,
Map<DexType, Map<DexAnnotation, List<ProgramDefinition>>> deferredAnnotations,
Function<ProgramDefinition, AnnotatedKind> kindProvider) {
- Map<DexAnnotation, List<ProgramDefinition>> annotations =
- deferredAnnotations.remove(clazz.getType());
- if (annotations != null) {
- assert annotations.keySet().stream()
- .allMatch(annotation -> clazz.getType().isIdenticalTo(annotation.getAnnotationType()));
- annotations.forEach(
- (annotation, annotatedItems) ->
- annotatedItems.forEach(
- annotatedItem ->
- processAnnotation(
- annotatedItem, annotation, kindProvider.apply(annotatedItem))));
+ for (DexType annotationType : liveAnnotations) {
+ Map<DexAnnotation, List<ProgramDefinition>> annotations =
+ deferredAnnotations.remove(annotationType);
+ if (annotations != null) {
+ assert annotations.keySet().stream()
+ .allMatch(annotation -> annotationType.isIdenticalTo(annotation.getAnnotationType()));
+ annotations.forEach(
+ (annotation, annotatedItems) ->
+ annotatedItems.forEach(
+ annotatedItem ->
+ processAnnotation(
+ annotatedItem, annotation, kindProvider.apply(annotatedItem))));
+ }
}
}
@@ -4732,6 +4733,11 @@
}
}
+ // Process all deferred annotations.
+ processDeferredAnnotations(deferredAnnotations, AnnotatedKind::from);
+ processDeferredAnnotations(
+ deferredParameterAnnotations, annotatedItem -> AnnotatedKind.PARAMETER);
+
// Continue fix-point processing while there are additional work items to ensure items that
// are passed to Java reflections are traced.
if (!pendingReflectiveUses.isEmpty()) {