Split annotation keep info in parameters, types and normal annotations
Change-Id: Id43f028fca0afbaa081d9549b020a6d18e83d1aa
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 1cfa7f2..75397e5 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -131,14 +131,21 @@
}
if (kind.isParameter()) {
- if (!options.isKeepRuntimeVisibleParameterAnnotationsEnabled()) {
+ KeepMethodInfo methodInfo = keepInfo.asMethodInfo();
+ if (methodInfo == null || !options.isKeepRuntimeVisibleParameterAnnotationsEnabled()) {
return false;
}
- } else if (!annotation.isTypeAnnotation()
- && !options.isKeepRuntimeVisibleAnnotationsEnabled()) {
- return false;
- } else if (annotation.isTypeAnnotation()
- && !options.isKeepRuntimeVisibleTypeAnnotationsEnabled()) {
+ return !methodInfo.isParameterAnnotationRemovalAllowed(options) && isAnnotationTypeLive;
+ }
+
+ if (annotation.isTypeAnnotation()) {
+ if (!options.isKeepRuntimeVisibleTypeAnnotationsEnabled()) {
+ return false;
+ }
+ return !keepInfo.isTypeAnnotationRemovalAllowed(options) && isAnnotationTypeLive;
+ }
+
+ if (!options.isKeepRuntimeVisibleAnnotationsEnabled()) {
return false;
}
return !keepInfo.isAnnotationRemovalAllowed(options) && isAnnotationTypeLive;
@@ -154,17 +161,25 @@
return true;
}
if (kind.isParameter()) {
- if (!options.isKeepRuntimeInvisibleParameterAnnotationsEnabled()) {
+ KeepMethodInfo methodInfo = keepInfo.asMethodInfo();
+ if (methodInfo == null || !options.isKeepRuntimeInvisibleParameterAnnotationsEnabled()) {
return false;
}
- } else if (!annotation.isTypeAnnotation()
- && !options.isKeepRuntimeInvisibleAnnotationsEnabled()) {
- return false;
- } else if (annotation.isTypeAnnotation()
- && !options.isKeepRuntimeInvisibleTypeAnnotationsEnabled()) {
+ return !methodInfo.isParameterAnnotationRemovalAllowed(options) && isAnnotationTypeLive;
+ }
+
+ if (annotation.isTypeAnnotation()) {
+ if (!options.isKeepRuntimeInvisibleTypeAnnotationsEnabled()) {
+ return false;
+ }
+ return !keepInfo.isTypeAnnotationRemovalAllowed(options) && isAnnotationTypeLive;
+ }
+
+ if (!options.isKeepRuntimeInvisibleAnnotationsEnabled()) {
return false;
}
return !keepInfo.isAnnotationRemovalAllowed(options) && isAnnotationTypeLive;
+
default:
throw new Unreachable("Unexpected annotation visibility.");
}
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
index d2e5f1f..1424a52 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
@@ -25,6 +25,7 @@
private final boolean allowSignatureRemoval;
private final boolean checkDiscarded;
private final KeepAnnotationCollectionInfo annotationsInfo;
+ private final KeepAnnotationCollectionInfo typeAnnotationsInfo;
private KeepInfo(
boolean allowAccessModification,
@@ -34,7 +35,8 @@
boolean allowShrinking,
boolean allowSignatureRemoval,
boolean checkDiscarded,
- KeepAnnotationCollectionInfo annotationsInfo) {
+ KeepAnnotationCollectionInfo annotationsInfo,
+ KeepAnnotationCollectionInfo typeAnnotationsInfo) {
this.allowAccessModification = allowAccessModification;
this.allowAccessModificationForTesting = allowAccessModificationForTesting;
this.allowMinification = allowMinification;
@@ -43,6 +45,7 @@
this.allowSignatureRemoval = allowSignatureRemoval;
this.checkDiscarded = checkDiscarded;
this.annotationsInfo = annotationsInfo;
+ this.typeAnnotationsInfo = typeAnnotationsInfo;
}
KeepInfo(B builder) {
@@ -54,7 +57,8 @@
builder.isShrinkingAllowed(),
builder.isSignatureRemovalAllowed(),
builder.isCheckDiscardedEnabled(),
- builder.getAnnotationsInfo().build());
+ builder.getAnnotationsInfo().build(),
+ builder.getTypeAnnotationsInfo().build());
}
public static Joiner<?, ?, ?> newEmptyJoinerFor(DexReference reference) {
@@ -66,6 +70,10 @@
abstract B builder();
+ public KeepMethodInfo asMethodInfo() {
+ return null;
+ }
+
/**
* True if an item may have all of its annotations removed.
*
@@ -73,13 +81,23 @@
* keep all annotation attributes.
*/
public boolean isAnnotationRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
+ assert internalAnnotationsInfo().isTop() || internalAnnotationsInfo().isBottom();
return configuration.isAnnotationRemovalEnabled() && internalAnnotationsInfo().isBottom();
}
+ public boolean isTypeAnnotationRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
+ assert internalTypeAnnotationsInfo().isTop() || internalTypeAnnotationsInfo().isBottom();
+ return configuration.isAnnotationRemovalEnabled() && internalTypeAnnotationsInfo().isBottom();
+ }
+
KeepAnnotationCollectionInfo internalAnnotationsInfo() {
return annotationsInfo;
}
+ KeepAnnotationCollectionInfo internalTypeAnnotationsInfo() {
+ return typeAnnotationsInfo;
+ }
+
public boolean isCheckDiscardedEnabled(GlobalKeepInfoConfiguration configuration) {
return internalIsCheckDiscardedEnabled();
}
@@ -230,7 +248,8 @@
&& (allowShrinking || !other.internalIsShrinkingAllowed())
&& (allowSignatureRemoval || !other.internalIsSignatureRemovalAllowed())
&& (!checkDiscarded || other.internalIsCheckDiscardedEnabled())
- && annotationsInfo.isLessThanOrEquals(other.internalAnnotationsInfo());
+ && annotationsInfo.isLessThanOrEquals(other.internalAnnotationsInfo())
+ && typeAnnotationsInfo.isLessThanOrEquals(other.internalTypeAnnotationsInfo());
}
/** Builder to construct an arbitrary keep info object. */
@@ -255,6 +274,7 @@
private boolean allowSignatureRemoval;
private boolean checkDiscarded;
private KeepAnnotationCollectionInfo.Builder annotationsInfo;
+ private KeepAnnotationCollectionInfo.Builder typeAnnotationsInfo;
Builder() {
// Default initialized. Use should be followed by makeTop/makeBottom.
@@ -270,12 +290,14 @@
allowSignatureRemoval = original.internalIsSignatureRemovalAllowed();
checkDiscarded = original.internalIsCheckDiscardedEnabled();
annotationsInfo = original.internalAnnotationsInfo().toBuilder();
+ typeAnnotationsInfo = original.internalTypeAnnotationsInfo().toBuilder();
}
B makeTop() {
disallowAccessModification();
disallowAccessModificationForTesting();
disallowAnnotationRemoval();
+ disallowTypeAnnotationRemoval();
disallowMinification();
disallowOptimization();
disallowShrinking();
@@ -288,6 +310,7 @@
allowAccessModification();
allowAccessModificationForTesting();
allowAnnotationRemoval();
+ allowTypeAnnotationRemoval();
allowMinification();
allowOptimization();
allowShrinking();
@@ -320,7 +343,8 @@
&& isShrinkingAllowed() == other.internalIsShrinkingAllowed()
&& isSignatureRemovalAllowed() == other.internalIsSignatureRemovalAllowed()
&& isCheckDiscardedEnabled() == other.internalIsCheckDiscardedEnabled()
- && annotationsInfo.isEqualTo(other.internalAnnotationsInfo());
+ && annotationsInfo.isEqualTo(other.internalAnnotationsInfo())
+ && typeAnnotationsInfo.isEqualTo(other.internalTypeAnnotationsInfo());
}
public boolean isAccessModificationAllowed() {
@@ -446,6 +470,23 @@
return setAnnotationsInfo(KeepAnnotationCollectionInfo.Builder.makeTop());
}
+ KeepAnnotationCollectionInfo.Builder getTypeAnnotationsInfo() {
+ return typeAnnotationsInfo;
+ }
+
+ private B setTypeAnnotationsInfo(KeepAnnotationCollectionInfo.Builder typeAnnotationsInfo) {
+ this.typeAnnotationsInfo = typeAnnotationsInfo;
+ return self();
+ }
+
+ public B allowTypeAnnotationRemoval() {
+ return setTypeAnnotationsInfo(KeepAnnotationCollectionInfo.Builder.makeBottom());
+ }
+
+ public B disallowTypeAnnotationRemoval() {
+ return setTypeAnnotationsInfo(KeepAnnotationCollectionInfo.Builder.makeTop());
+ }
+
private B setAllowSignatureRemoval(boolean allowSignatureRemoval) {
this.allowSignatureRemoval = allowSignatureRemoval;
return self();
@@ -577,6 +618,11 @@
return self();
}
+ public J disallowTypeAnnotationRemoval() {
+ builder.disallowTypeAnnotationRemoval();
+ return self();
+ }
+
public J disallowMinification() {
builder.disallowMinification();
return self();
@@ -614,6 +660,7 @@
applyIf(!otherBuilder.isSignatureRemovalAllowed(), Joiner::disallowSignatureRemoval);
applyIf(otherBuilder.isCheckDiscardedEnabled(), Joiner::setCheckDiscarded);
builder.getAnnotationsInfo().join(otherBuilder.getAnnotationsInfo());
+ builder.getTypeAnnotationsInfo().join(otherBuilder.getTypeAnnotationsInfo());
reasons.addAll(joiner.reasons);
rules.addAll(joiner.rules);
return self();
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java
index 879369c..ad4ea9f 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepMethodInfo.java
@@ -39,6 +39,7 @@
private final boolean allowSingleCallerInlining;
private final boolean allowUnusedArgumentOptimization;
private final boolean allowUnusedReturnValueOptimization;
+ private final KeepAnnotationCollectionInfo parameterAnnotationsInfo;
protected KeepMethodInfo(Builder builder) {
super(builder);
@@ -55,6 +56,7 @@
this.allowSingleCallerInlining = builder.isSingleCallerInliningAllowed();
this.allowUnusedArgumentOptimization = builder.isUnusedArgumentOptimizationAllowed();
this.allowUnusedReturnValueOptimization = builder.isUnusedReturnValueOptimizationAllowed();
+ this.parameterAnnotationsInfo = builder.getParameterAnnotationsInfo().build();
}
// This builder is not private as there are known instances where it is safe to modify keep info
@@ -64,6 +66,22 @@
return new Builder(this);
}
+ @Override
+ public KeepMethodInfo asMethodInfo() {
+ return this;
+ }
+
+ public boolean isParameterAnnotationRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
+ assert internalParameterAnnotationsInfo().isTop()
+ || internalParameterAnnotationsInfo().isBottom();
+ return configuration.isAnnotationRemovalEnabled()
+ && internalParameterAnnotationsInfo().isBottom();
+ }
+
+ KeepAnnotationCollectionInfo internalParameterAnnotationsInfo() {
+ return parameterAnnotationsInfo;
+ }
+
public boolean isArgumentPropagationAllowed(GlobalKeepInfoConfiguration configuration) {
return isParameterRemovalAllowed(configuration);
}
@@ -229,6 +247,7 @@
private boolean allowSingleCallerInlining;
private boolean allowUnusedArgumentOptimization;
private boolean allowUnusedReturnValueOptimization;
+ private KeepAnnotationCollectionInfo.Builder parameterAnnotationsInfo;
public Builder() {
super();
@@ -250,6 +269,7 @@
allowUnusedArgumentOptimization = original.internalIsUnusedArgumentOptimizationAllowed();
allowUnusedReturnValueOptimization =
original.internalIsUnusedReturnValueOptimizationAllowed();
+ parameterAnnotationsInfo = original.internalParameterAnnotationsInfo().toBuilder();
}
// Class inlining.
@@ -500,6 +520,22 @@
return setAllowUnusedReturnValueOptimization(false);
}
+ // Parameter annotations
+
+ KeepAnnotationCollectionInfo.Builder getParameterAnnotationsInfo() {
+ return parameterAnnotationsInfo;
+ }
+
+ public Builder allowParameterAnnotationsRemoval() {
+ parameterAnnotationsInfo = KeepAnnotationCollectionInfo.Builder.makeBottom();
+ return self();
+ }
+
+ public Builder disallowParameterAnnotationsRemoval() {
+ parameterAnnotationsInfo = KeepAnnotationCollectionInfo.Builder.makeTop();
+ return self();
+ }
+
@Override
public Builder self() {
return this;
@@ -539,7 +575,8 @@
&& isUnusedArgumentOptimizationAllowed()
== other.internalIsUnusedArgumentOptimizationAllowed()
&& isUnusedReturnValueOptimizationAllowed()
- == other.internalIsUnusedReturnValueOptimizationAllowed();
+ == other.internalIsUnusedReturnValueOptimizationAllowed()
+ && parameterAnnotationsInfo.isEqualTo(other.parameterAnnotationsInfo);
}
@Override
@@ -562,7 +599,8 @@
.disallowReturnTypeStrengthening()
.disallowSingleCallerInlining()
.disallowUnusedArgumentOptimization()
- .disallowUnusedReturnValueOptimization();
+ .disallowUnusedReturnValueOptimization()
+ .disallowParameterAnnotationsRemoval();
}
@Override
@@ -580,7 +618,8 @@
.allowReturnTypeStrengthening()
.allowSingleCallerInlining()
.allowUnusedArgumentOptimization()
- .allowUnusedReturnValueOptimization();
+ .allowUnusedReturnValueOptimization()
+ .allowParameterAnnotationsRemoval();
}
}
@@ -659,6 +698,11 @@
return self();
}
+ public Joiner disallowParameterAnnotationsRemoval() {
+ builder.disallowParameterAnnotationsRemoval();
+ return self();
+ }
+
@Override
public Joiner asMethodJoiner() {
return this;
@@ -667,8 +711,9 @@
@Override
public Joiner merge(Joiner joiner) {
// Should be extended to merge the fields of this class in case any are added.
- return super.merge(joiner)
- .applyIf(!joiner.builder.isClassInliningAllowed(), Joiner::disallowClassInlining)
+ super.merge(joiner);
+ builder.getParameterAnnotationsInfo().join(joiner.builder.getParameterAnnotationsInfo());
+ return applyIf(!joiner.builder.isClassInliningAllowed(), Joiner::disallowClassInlining)
.applyIf(
!joiner.builder.isClosedWorldReasoningAllowed(), Joiner::disallowClosedWorldReasoning)
.applyIf(
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 17a3591..d9add46 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -1623,9 +1623,15 @@
}
if (appView.options().isAnnotationRemovalEnabled() && !modifiers.allowsAnnotationRemoval) {
- dependentMinimumKeepInfo
- .getOrCreateMinimumKeepInfoFor(preconditionEvent, item.getReference())
- .disallowAnnotationRemoval();
+ Joiner<?, ?, ?> joiner =
+ dependentMinimumKeepInfo
+ .getOrCreateMinimumKeepInfoFor(preconditionEvent, item.getReference())
+ .disallowAnnotationRemoval()
+ .disallowTypeAnnotationRemoval();
+ KeepMethodInfo.Joiner methodJoiner = joiner.asMethodJoiner();
+ if (methodJoiner != null) {
+ methodJoiner.disallowParameterAnnotationsRemoval();
+ }
context.markAsUsed();
}