[KeepAnno] Support edges with field preconditions
Edges with field (or class) preconditions are currently soft-pinned as
done for legacy rules. Follow-up work should remove the restriction by
tracking changes via the lens or "original positions" as done for
methods.
Bug: b/323816623
Change-Id: I1729a413299cdf05d8a17c1233b810bb5be58293
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 23fcee7..7138f53 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1688,11 +1688,11 @@
}
}
- void markEffectivelyLiveOriginalReference(DexMethod method) {
- // TODO(b/325014359): It might be reasonable to reduce this map size by tracking which methods
+ void markEffectivelyLiveOriginalReference(DexReference reference) {
+ // TODO(b/325014359): It might be reasonable to reduce this map size by tracking which items
// actually are used in preconditions.
- if (effectivelyLiveOriginalReferences.add(method)) {
- effectivelyLiveOriginalReferences.add(method.getHolderType());
+ if (effectivelyLiveOriginalReferences.add(reference) && reference.isDexMember()) {
+ effectivelyLiveOriginalReferences.add(reference.getContextType());
}
}
@@ -3274,6 +3274,13 @@
}
}
+ private void addEffectivelyLiveOriginalField(ProgramField field) {
+ if (!options.testing.isKeepAnnotationsEnabled()) {
+ return;
+ }
+ markEffectivelyLiveOriginalReference(field.getReference());
+ }
+
private void markFieldAsLive(ProgramField field, ProgramMethod context) {
markFieldAsLive(field, context, KeepReason.fieldReferencedIn(context));
}
@@ -3286,6 +3293,7 @@
// Already live.
return;
}
+ addEffectivelyLiveOriginalField(field);
// Mark the field as targeted.
if (field.getAccessFlags().isStatic()) {
@@ -3327,13 +3335,12 @@
graphReporter.registerField(field.getDefinition(), reason);
return;
}
-
+ addEffectivelyLiveOriginalField(field);
traceFieldDefinition(field);
analyses.forEach(analysis -> analysis.notifyMarkFieldAsReachable(field, worklist));
}
- @SuppressWarnings("UnusedVariable")
private void traceFieldDefinition(ProgramField field) {
markTypeAsLive(field.getHolder(), field);
markTypeAsLive(field.getType(), field);
diff --git a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
index 13b1b4f..82c28fb 100644
--- a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
@@ -107,6 +107,19 @@
minimumKeepInfoCollection.getOrCreateMinimumKeepInfoFor(item.getReference());
updateWithConstraints(item, joiner, result.constraints.get(i), result.edge);
});
+ // TODO(b/323816623): Encode originals instead of soft-pinning class/field preconditions.
+ for (ProgramDefinition precondition : result.preconditions) {
+ if (precondition.isClass() || precondition.isField()) {
+ minimumKeepInfoCollection
+ .getOrCreateMinimumKeepInfoFor(precondition.getReference())
+ .disallowOptimization();
+ if (precondition.isField()) {
+ minimumKeepInfoCollection
+ .getOrCreateMinimumKeepInfoFor(precondition.getContextType())
+ .disallowOptimization();
+ }
+ }
+ }
return minimumKeepInfoCollection;
}
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionFieldAnnotationTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionFieldAnnotationTest.java
index 92f2515..15f96ab 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionFieldAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsesReflectionFieldAnnotationTest.java
@@ -35,6 +35,7 @@
@Test
public void test() throws Exception {
testForKeepAnno(parameters)
+ .enableNativeInterpretation()
.addProgramClasses(getInputClasses())
.addKeepMainRule(TestClass.class)
.setExcludedOuterClass(getClass())