Compute features split for legacy synthetics.
Bug: 186523004
Change-Id: Iaf148f0bd85239b393a7cdd87fc6b44d538f1906
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index ab55c16..17f8d1b 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.FieldResolutionResult.SuccessfulFieldResolutionResult;
import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter;
import com.android.tools.r8.origin.Origin;
@@ -130,7 +131,8 @@
public void addSynthesizedClass(DexProgramClass clazz, ProgramDefinition context) {
assert checkIfObsolete();
assert context != null;
- syntheticItems.addLegacySyntheticClass(clazz, context);
+ syntheticItems.addLegacySyntheticClass(
+ clazz, context, ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap());
}
public void addSynthesizedClass(DexProgramClass clazz, Iterable<DexProgramClass> contexts) {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index c2c02ad..26b1f96 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -156,6 +156,13 @@
return this;
}
+ @Override
+ public void addSynthesizedClass(DexProgramClass clazz, ProgramDefinition context) {
+ assert checkIfObsolete();
+ assert context != null;
+ getSyntheticItems().addLegacySyntheticClass(clazz, context, classToFeatureSplitMap);
+ }
+
/**
* Primitive traversal over all supertypes of a given type.
*
diff --git a/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticDefinition.java
index 47a9556..3e50bf5 100644
--- a/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticDefinition.java
@@ -3,25 +3,28 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
+import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramDefinition;
+import com.android.tools.r8.utils.IterableUtils;
import com.google.common.collect.ImmutableSet;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class LegacySyntheticDefinition {
private final DexProgramClass clazz;
- private final Map<DexType, DexType> contexts = new ConcurrentHashMap<>();
+ private final Map<DexType, FeatureSplit> contexts = new ConcurrentHashMap<>();
public LegacySyntheticDefinition(DexProgramClass clazz) {
this.clazz = clazz;
}
- public void addContext(ProgramDefinition clazz) {
+ public void addContext(ProgramDefinition clazz, FeatureSplit featureSplit) {
DexType type = clazz.getContextType();
- contexts.put(type, type);
+ contexts.put(type, featureSplit);
}
public Set<DexType> getContexts() {
@@ -29,7 +32,22 @@
}
public LegacySyntheticReference toReference() {
- return new LegacySyntheticReference(clazz.getType(), ImmutableSet.copyOf(contexts.keySet()));
+ return new LegacySyntheticReference(
+ clazz.getType(), ImmutableSet.copyOf(contexts.keySet()), getFeatureSplit());
+ }
+
+ public FeatureSplit getFeatureSplit() {
+ assert verifyConsistentFeatures();
+ if (contexts.isEmpty()) {
+ return FeatureSplit.BASE;
+ }
+ return IterableUtils.first(contexts.values());
+ }
+
+ private boolean verifyConsistentFeatures() {
+ HashSet<FeatureSplit> features = new HashSet<>(contexts.values());
+ assert features.size() < 2;
+ return true;
}
public DexProgramClass getDefinition() {
diff --git a/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticReference.java b/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticReference.java
index 06d2e2c..715e790 100644
--- a/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/LegacySyntheticReference.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
+import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import java.util.Set;
@@ -10,10 +11,12 @@
public class LegacySyntheticReference implements Rewritable<LegacySyntheticReference> {
private final DexType type;
private final Set<DexType> contexts;
+ private final FeatureSplit featureSplit;
- public LegacySyntheticReference(DexType type, Set<DexType> contexts) {
+ public LegacySyntheticReference(DexType type, Set<DexType> contexts, FeatureSplit featureSplit) {
this.type = type;
this.contexts = contexts;
+ this.featureSplit = featureSplit;
}
@Override
@@ -25,6 +28,10 @@
return contexts;
}
+ public FeatureSplit getFeatureSplit() {
+ return featureSplit;
+ }
+
@Override
public LegacySyntheticReference rewrite(NonIdentityGraphLens lens) {
DexType rewrittenType = lens.lookupType(type);
@@ -32,6 +39,6 @@
if (type == rewrittenType && contexts.equals(rewrittenContexts)) {
return this;
}
- return new LegacySyntheticReference(rewrittenType, rewrittenContexts);
+ return new LegacySyntheticReference(rewrittenType, rewrittenContexts, featureSplit);
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index befe594..d0164d7 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -261,19 +261,32 @@
}
public FeatureSplit getContextualFeatureSplit(DexType type) {
+ if (pending.legacyClasses.containsKey(type)) {
+ LegacySyntheticDefinition definition = pending.legacyClasses.get(type);
+ return definition.getFeatureSplit();
+ }
+ if (committed.containsLegacyType(type)) {
+ List<LegacySyntheticReference> types = committed.getLegacyTypes(type);
+ if (types.isEmpty()) {
+ return null;
+ }
+ assert verifyAllHaveSameFeature(types, LegacySyntheticReference::getFeatureSplit);
+ return types.get(0).getFeatureSplit();
+ }
List<SynthesizingContext> contexts = getSynthesizingContexts(type);
if (contexts.isEmpty()) {
return null;
}
- assert verifyAllContextsHaveSameFeature(contexts);
+ assert verifyAllHaveSameFeature(contexts, SynthesizingContext::getFeatureSplit);
return contexts.get(0).getFeatureSplit();
}
- private boolean verifyAllContextsHaveSameFeature(List<SynthesizingContext> contexts) {
- assert !contexts.isEmpty();
- FeatureSplit featureSplit = contexts.get(0).getFeatureSplit();
- for (int i = 1; i < contexts.size(); i++) {
- assert featureSplit == contexts.get(i).getFeatureSplit();
+ private static <T> boolean verifyAllHaveSameFeature(
+ List<T> items, Function<T, FeatureSplit> getter) {
+ assert !items.isEmpty();
+ FeatureSplit featureSplit = getter.apply(items.get(0));
+ for (int i = 1; i < items.size(); i++) {
+ assert featureSplit == getter.apply(items.get(i));
}
return true;
}
@@ -379,9 +392,13 @@
}
// TODO(b/158159959): Remove the usage of this direct class addition.
- public void addLegacySyntheticClass(DexProgramClass clazz, ProgramDefinition context) {
+ public void addLegacySyntheticClass(
+ DexProgramClass clazz,
+ ProgramDefinition context,
+ ClassToFeatureSplitMap classToFeatureSplitMap) {
LegacySyntheticDefinition legacyItem = internalAddLegacySyntheticClass(clazz);
- legacyItem.addContext(context);
+ FeatureSplit featureSplit = classToFeatureSplitMap.getFeatureSplit(context, this);
+ legacyItem.addContext(context, featureSplit);
}
private LegacySyntheticDefinition internalAddLegacySyntheticClass(DexProgramClass clazz) {