Materialize wildcards with captures to apply -if rules in parallel.
Bug: 79486261
Change-Id: Ie0d197bb7365fe7dad76b75fe4fe88deee4c5daf
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
index b007f83..568ad3d 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
@@ -83,6 +83,10 @@
return nameList == null ? Collections::emptyIterator : nameList.getWildcards();
}
+ protected ProguardClassNameList materialize() {
+ return this;
+ }
+
public abstract void forEachTypeMatcher(Consumer<ProguardTypeMatcher> consumer);
private static class EmptyClassNameList extends ProguardClassNameList {
@@ -149,6 +153,11 @@
}
@Override
+ protected SingleClassNameList materialize() {
+ return new SingleClassNameList(className.materialize());
+ }
+
+ @Override
public void forEachTypeMatcher(Consumer<ProguardTypeMatcher> consumer) {
consumer.accept(className);
}
@@ -202,6 +211,12 @@
}
@Override
+ protected PositiveClassNameList materialize() {
+ return new PositiveClassNameList(
+ classNames.stream().map(ProguardTypeMatcher::materialize).collect(Collectors.toList()));
+ }
+
+ @Override
public void forEachTypeMatcher(Consumer<ProguardTypeMatcher> consumer) {
classNames.forEach(consumer);
}
@@ -260,6 +275,13 @@
}
@Override
+ protected ProguardClassNameList materialize() {
+ Builder builder = builder();
+ classNames.forEach((m, negated) -> builder.addClassName(negated, m.materialize()));
+ return builder.build();
+ }
+
+ @Override
public void forEachTypeMatcher(Consumer<ProguardTypeMatcher> consumer) {
classNames.object2BooleanEntrySet().forEach(entry -> consumer.accept(entry.getKey()));
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardIfRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardIfRule.java
index 2e8cccc..47f26ed 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardIfRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardIfRule.java
@@ -5,6 +5,7 @@
import com.google.common.collect.Iterables;
import java.util.List;
+import java.util.stream.Collectors;
public class ProguardIfRule extends ProguardKeepRule {
@@ -51,6 +52,24 @@
}
@Override
+ protected ProguardIfRule materialize() {
+ return new ProguardIfRule(
+ getClassAnnotation(),
+ getClassAccessFlags(),
+ getNegatedClassAccessFlags(),
+ getClassTypeNegated(),
+ getClassType(),
+ getClassNames().materialize(),
+ getInheritanceAnnotation() == null ? null : getInheritanceAnnotation().materialize(),
+ getInheritanceClassName() == null ? null : getInheritanceClassName().materialize(),
+ getInheritanceIsExtends(),
+ getMemberRules() == null ? null :
+ getMemberRules().stream()
+ .map(ProguardMemberRule::materialize).collect(Collectors.toList()),
+ subsequentRule.materialize());
+ }
+
+ @Override
public boolean equals(Object o) {
if (!(o instanceof ProguardIfRule)) {
return false;
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java
index 8756f1a..6651dae 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java
@@ -5,6 +5,7 @@
import java.util.List;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
public class ProguardKeepRule extends ProguardConfigurationRule {
@@ -68,6 +69,24 @@
return modifiers;
}
+ protected ProguardKeepRule materialize() {
+ return new ProguardKeepRule(
+ getClassAnnotation(),
+ getClassAccessFlags(),
+ getNegatedClassAccessFlags(),
+ getClassTypeNegated(),
+ getClassType(),
+ getClassNames() == null ? null : getClassNames().materialize(),
+ getInheritanceAnnotation() == null ? null : getInheritanceAnnotation().materialize(),
+ getInheritanceClassName() == null ? null : getInheritanceClassName().materialize(),
+ getInheritanceIsExtends(),
+ getMemberRules() == null ? null :
+ getMemberRules().stream()
+ .map(ProguardMemberRule::materialize).collect(Collectors.toList()),
+ getType(),
+ getModifiers());
+ }
+
@Override
public boolean equals(Object o) {
if (!(o instanceof ProguardKeepRule)) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
index c3454a7..39737ea 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java
@@ -12,6 +12,7 @@
import com.google.common.collect.Iterables;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class ProguardMemberRule {
@@ -278,6 +279,20 @@
);
}
+ ProguardMemberRule materialize() {
+ return new ProguardMemberRule(
+ getAnnotation() == null ? null : getAnnotation().materialize(),
+ getAccessFlags(),
+ getNegatedAccessFlags(),
+ getRuleType(),
+ getType() == null ? null : getType().materialize(),
+ getName() == null ? null : getName().materialize(),
+ getArguments() == null ? null :
+ getArguments().stream()
+ .map(ProguardTypeMatcher::materialize).collect(Collectors.toList()),
+ getReturnValue());
+ }
+
@Override
public boolean equals(Object o) {
if (!(o instanceof ProguardMemberRule)) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardNameMatcher.java b/src/main/java/com/android/tools/r8/shaking/ProguardNameMatcher.java
index 4adb948..c217d45 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardNameMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardNameMatcher.java
@@ -9,6 +9,7 @@
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
public abstract class ProguardNameMatcher {
@@ -96,11 +97,19 @@
return nameMatcher == null ? Collections::emptyIterator : nameMatcher.getWildcards();
}
+ protected ProguardNameMatcher materialize() {
+ return this;
+ }
+
private static class MatchAllNames extends ProguardNameMatcher {
private final ProguardWildcard wildcard;
MatchAllNames() {
- this.wildcard = new Pattern("*");
+ this(new Pattern("*"));
+ }
+
+ private MatchAllNames(ProguardWildcard wildcard) {
+ this.wildcard = wildcard;
}
@Override
@@ -115,6 +124,11 @@
}
@Override
+ protected MatchAllNames materialize() {
+ return new MatchAllNames(wildcard.materialize());
+ }
+
+ @Override
public String toString() {
return "*";
}
@@ -145,6 +159,15 @@
}
@Override
+ protected MatchNamePattern materialize() {
+ List<ProguardWildcard> materializedWildcards =
+ wildcards.stream().map(ProguardWildcard::materialize).collect(Collectors.toList());
+ IdentifierPatternWithWildcards identifierPatternWithMaterializedWildcards =
+ new IdentifierPatternWithWildcards(pattern, materializedWildcards);
+ return new MatchNamePattern(identifierPatternWithMaterializedWildcards);
+ }
+
+ @Override
public String toString() {
return pattern;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java b/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
index 0d5016b..34ee554 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
@@ -13,6 +13,7 @@
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
public abstract class ProguardTypeMatcher {
@@ -40,6 +41,10 @@
return typeMatcher == null ? Collections::emptyIterator : typeMatcher.getWildcards();
}
+ protected ProguardTypeMatcher materialize() {
+ return this;
+ }
+
@Override
public abstract String toString();
@@ -99,7 +104,11 @@
private final ProguardWildcard wildcard;
MatchAllTypes() {
- this.wildcard = new Pattern(MATCH_ALL_PATTERN);
+ this(new Pattern(MATCH_ALL_PATTERN));
+ }
+
+ private MatchAllTypes(ProguardWildcard wildcard) {
+ this.wildcard = wildcard;
}
@Override
@@ -114,6 +123,11 @@
}
@Override
+ protected MatchAllTypes materialize() {
+ return new MatchAllTypes(wildcard.materialize());
+ }
+
+ @Override
public String toString() {
return MATCH_ALL_PATTERN;
}
@@ -170,9 +184,13 @@
private final ProguardWildcard wildcard;
private MatchClassTypes(String pattern) {
+ this(pattern, new Pattern(pattern));
+ }
+
+ private MatchClassTypes(String pattern, ProguardWildcard wildcard) {
assert pattern.equals(LEGACY_MATCH_CLASS_PATTERN) || pattern.equals(MATCH_CLASS_PATTERN);
this.pattern = pattern;
- this.wildcard = new Pattern(pattern);
+ this.wildcard = wildcard;
}
@Override
@@ -190,6 +208,11 @@
}
@Override
+ protected MatchClassTypes materialize() {
+ return new MatchClassTypes(pattern, wildcard.materialize());
+ }
+
+ @Override
public String toString() {
return pattern;
}
@@ -212,7 +235,11 @@
private final ProguardWildcard wildcard;
MatchBasicTypes() {
- this.wildcard = new Pattern(MATCH_BASIC_PATTERN);
+ this(new Pattern(MATCH_BASIC_PATTERN));
+ }
+
+ private MatchBasicTypes(ProguardWildcard wildcard) {
+ this.wildcard = wildcard;
}
@Override
@@ -230,6 +257,11 @@
}
@Override
+ protected MatchBasicTypes materialize() {
+ return new MatchBasicTypes(wildcard.materialize());
+ }
+
+ @Override
public String toString() {
return MATCH_BASIC_PATTERN;
}
@@ -311,6 +343,15 @@
return wildcards;
}
+ @Override
+ protected MatchTypePattern materialize() {
+ List<ProguardWildcard> materializedWildcards =
+ wildcards.stream().map(ProguardWildcard::materialize).collect(Collectors.toList());
+ IdentifierPatternWithWildcards identifierPatternWithMaterializedWildcards =
+ new IdentifierPatternWithWildcards(pattern, materializedWildcards);
+ return new MatchTypePattern(identifierPatternWithMaterializedWildcards, kind);
+ }
+
private static boolean matchClassOrTypeNameImpl(
String pattern, int patternIndex,
String name, int nameIndex,
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardWildcard.java b/src/main/java/com/android/tools/r8/shaking/ProguardWildcard.java
index 84151e8..b6cb8e5 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardWildcard.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardWildcard.java
@@ -10,6 +10,7 @@
abstract void setCaptured(String captured);
abstract void clearCaptured();
abstract String getCaptured();
+ abstract ProguardWildcard materialize();
boolean isPattern() {
return false;
@@ -29,7 +30,6 @@
static class Pattern extends ProguardWildcard {
final String pattern;
- // TODO(b/79486261): Having captured part here makes back-reference handling not thread-safe.
private String captured = null;
Pattern(String pattern) {
@@ -37,21 +37,31 @@
}
@Override
- void setCaptured(String captured) {
+ synchronized void setCaptured(String captured) {
this.captured = captured;
}
@Override
- void clearCaptured() {
+ synchronized void clearCaptured() {
captured = null;
}
@Override
- String getCaptured() {
+ synchronized String getCaptured() {
return captured;
}
@Override
+ Pattern materialize() {
+ if (captured == null) {
+ return this;
+ }
+ Pattern copy = new Pattern(pattern);
+ copy.setCaptured(captured);
+ return copy;
+ }
+
+ @Override
boolean isPattern() {
return true;
}
@@ -96,6 +106,16 @@
}
@Override
+ BackReference materialize() {
+ if (reference == null || reference.getCaptured() == null) {
+ return this;
+ }
+ BackReference copy = new BackReference(referenceIndex);
+ copy.setReference(reference.materialize());
+ return copy;
+ }
+
+ @Override
boolean isBackReference() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 6a8adfa..700e146 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -348,10 +348,9 @@
if (ifRule.getClassNames().matches(currentLiveType)) {
Collection<ProguardMemberRule> memberKeepRules = ifRule.getMemberRules();
if (memberKeepRules.isEmpty()) {
- runPerRule(executorService, futures, ifRule.subsequentRule, ifRule);
- // TODO(b/79486261): remove this barrier per rule.
- ThreadUtils.awaitFutures(futures);
- futures.clear();
+ ProguardIfRule materializedRule = ifRule.materialize();
+ runPerRule(
+ executorService, futures, materializedRule.subsequentRule, materializedRule);
// No member rule to satisfy. Move on to the next live type.
continue;
}
@@ -391,17 +390,15 @@
}
}
if (satisfied) {
- runPerRule(executorService, futures, ifRule.subsequentRule, ifRule);
- // TODO(b/79486261): remove this barrier per rule.
- ThreadUtils.awaitFutures(futures);
- futures.clear();
+ ProguardIfRule materializedRule = ifRule.materialize();
+ runPerRule(
+ executorService, futures, materializedRule.subsequentRule, materializedRule);
}
}
}
}
}
- // TODO(b/79486261): This is the best place to fully utilize available threads.
- // ThreadUtils.awaitFutures(futures);
+ ThreadUtils.awaitFutures(futures);
}
} finally {
application.timing.end();