Reapply "Group if rules without members by equivalence for shared class evaluation"
This reverts commit f827811c408a7310c61b331530747d6e65a3bc3f.
Change-Id: I9034e57fffc5aed3e82c4560d8e23f29024bc97a
diff --git a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
index 8da99d1..c0c05d4 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluator.java
@@ -92,23 +92,27 @@
}
public void processActiveIfRulesWithoutMembers(
- Set<ProguardIfRule> ifRules, Iterable<DexProgramClass> newlyLiveClasses)
+ Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> ifRules,
+ Iterable<DexProgramClass> newlyLiveClasses)
throws ExecutionException {
- ifRules.removeIf(
- ifRule -> {
+ MapUtils.removeIf(
+ ifRules,
+ (ifRuleWrapper, ifRulesInEquivalence) -> {
// Depending on which types that trigger the -if rule, the application of the subsequent
// -keep rule may vary (due to back references). So, we need to try all pairs of -if
// rule and live types.
+ ProguardIfRule ifRuleKey = ifRuleWrapper.get();
for (DexProgramClass clazz : newlyLiveClasses) {
- if (evaluateClassForIfRule(ifRule, clazz)) {
- registerClassCapture(ifRule, clazz, clazz);
- uncheckedMaterializeIfRule(ifRule, clazz);
- if (canRemoveSubsequentKeepRule(ifRule)) {
- return true;
- }
+ if (evaluateClassForIfRule(ifRuleKey, clazz)) {
+ ifRulesInEquivalence.removeIf(
+ ifRule -> {
+ registerClassCapture(ifRule, clazz, clazz);
+ uncheckedMaterializeIfRule(ifRule, clazz);
+ return canRemoveSubsequentKeepRule(ifRule);
+ });
}
}
- return false;
+ return ifRulesInEquivalence.isEmpty();
});
tasks.await();
}
@@ -199,11 +203,7 @@
throws ExecutionException {
incrementNumberOfProguardIfRuleMemberEvaluations();
Collection<ProguardMemberRule> memberKeepRules = rule.getMemberRules();
- if (memberKeepRules.isEmpty()) {
- materializeIfRule(rule, clazz);
- matchedConsumer.accept(rule);
- return;
- }
+ assert !memberKeepRules.isEmpty();
List<DexClassAndField> fieldsInlinedByJavaC = new ArrayList<>();
Set<DexDefinition> filteredMembers = Sets.newIdentityHashSet();
diff --git a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
index d1f15d8c..cc813e2 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
@@ -34,7 +34,7 @@
/** Map of active if rules. This is important for speeding up aapt2 generated keep rules. */
private final Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> activeIfRulesWithMembers;
- private final Set<ProguardIfRule> activeIfRulesWithoutMembers;
+ private final Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> activeIfRulesWithoutMembers;
private final Set<DexProgramClass> effectivelyFakeLiveClasses;
private final Set<DexProgramClass> newlyLiveClasses = Sets.newIdentityHashSet();
@@ -49,8 +49,8 @@
Enqueuer enqueuer,
ExecutorService executorService) {
this.appView = appView;
- this.activeIfRulesWithMembers = createActiveIfRulesWithMembers(appView.rootSet().ifRules);
- this.activeIfRulesWithoutMembers = createActiveIfRulesWithoutMembers(appView.rootSet().ifRules);
+ this.activeIfRulesWithMembers = createActiveIfRules(appView.rootSet().ifRules, true);
+ this.activeIfRulesWithoutMembers = createActiveIfRules(appView.rootSet().ifRules, false);
this.effectivelyFakeLiveClasses = createEffectivelyFakeLiveClasses(appView, enqueuer);
this.tasks = new TaskCollection<>(appView.options(), executorService);
}
@@ -66,14 +66,15 @@
}
}
- private static Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> createActiveIfRulesWithMembers(
- Set<ProguardIfRule> ifRules) {
+ private static Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> createActiveIfRules(
+ Set<ProguardIfRule> ifRules, boolean withMembers) {
// Build the mapping of active if rules. We use a single collection of if-rules to allow
// removing if rules that have a constant sequent keep rule when they materialize.
Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> activeIfRules = new HashMap<>(ifRules.size());
IfRuleClassPartEquivalence equivalence = new IfRuleClassPartEquivalence();
for (ProguardIfRule ifRule : ifRules) {
- if (!ifRule.getMemberRules().isEmpty()) {
+ boolean hasMembers = !ifRule.getMemberRules().isEmpty();
+ if (hasMembers == withMembers) {
Wrapper<ProguardIfRule> wrap = equivalence.wrap(ifRule);
activeIfRules.computeIfAbsent(wrap, ignoreKey(LinkedHashSet::new)).add(ifRule);
}
@@ -81,19 +82,6 @@
return activeIfRules;
}
- private static Set<ProguardIfRule> createActiveIfRulesWithoutMembers(
- Set<ProguardIfRule> ifRules) {
- // Build the mapping of active if rules. We use a single collection of if-rules to allow
- // removing if rules that have a constant sequent keep rule when they materialize.
- Set<ProguardIfRule> activeIfRules = new LinkedHashSet<>(ifRules.size());
- for (ProguardIfRule ifRule : ifRules) {
- if (ifRule.getMemberRules().isEmpty()) {
- activeIfRules.add(ifRule);
- }
- }
- return activeIfRules;
- }
-
@SuppressWarnings("MixedMutabilityReturnType")
private static Set<DexProgramClass> createEffectivelyFakeLiveClasses(
AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {