Store the feature of synthetics in their context description.
Bug: 179174151
Change-Id: I2ff924a3386a43ce0225ced093de7b5d514a0404
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index fa7e21d..1db8182 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -646,7 +646,7 @@
// TODO(b/181636450): Reconsider the code mapping setup now that synthetics are never
// duplicated in outputs.
boolean isSharedSynthetic =
- appView.getSyntheticItems().getSynthesizingContexts(clazz.getType()).size() > 1;
+ appView.getSyntheticItems().getSynthesizingContextTypes(clazz.getType()).size() > 1;
clazz.forEachMethod(
method -> {
DexCode code =
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 889fc27..9b7c9da 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -690,7 +690,7 @@
writeEncodedFields(clazz.staticFields());
writeEncodedFields(clazz.instanceFields());
boolean isSharedSynthetic =
- appInfo.getSyntheticItems().getSynthesizingContexts(clazz.getType()).size() > 1;
+ appInfo.getSyntheticItems().getSynthesizingContextTypes(clazz.getType()).size() > 1;
writeEncodedMethods(clazz.directMethods(), isSharedSynthetic);
writeEncodedMethods(clazz.virtualMethods(), isSharedSynthetic);
}
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index e44973a..fa17d7c 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -330,7 +330,7 @@
// Assign dedicated virtual files for all program classes.
for (DexProgramClass clazz : appView.appInfo().classes()) {
Collection<DexType> contexts =
- appView.getSyntheticItems().getSynthesizingContexts(clazz.getType());
+ appView.getSyntheticItems().getSynthesizingContextTypes(clazz.getType());
// TODO(b/181636450): Simplify this making use of the assumption that synthetics are never
// duplicated.
if (!combineSyntheticClassesWithPrimaryClass || contexts.isEmpty()) {
@@ -354,7 +354,7 @@
}
for (DexProgramClass synthetic : synthetics) {
for (DexType context :
- appView.getSyntheticItems().getSynthesizingContexts(synthetic.getType())) {
+ appView.getSyntheticItems().getSynthesizingContextTypes(synthetic.getType())) {
DexProgramClass inputType = appView.definitionForProgramType(context);
VirtualFile file = files.get(inputType);
file.addClass(synthetic);
diff --git a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
index c8c462b..f460b50 100644
--- a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
+++ b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
@@ -22,10 +22,8 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.Sets;
-import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
-import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -95,6 +93,10 @@
public int compareFeatureSplitsForDexTypes(DexType a, DexType b, SyntheticItems syntheticItems) {
FeatureSplit featureSplitA = getFeatureSplit(a, syntheticItems);
FeatureSplit featureSplitB = getFeatureSplit(b, syntheticItems);
+ return compareFeatureSplits(featureSplitA, featureSplitB);
+ }
+
+ public int compareFeatureSplits(FeatureSplit featureSplitA, FeatureSplit featureSplitB) {
assert featureSplitA != null;
assert featureSplitB != null;
if (featureSplitA == featureSplitB) {
@@ -129,26 +131,20 @@
}
public FeatureSplit getFeatureSplit(DexType type, SyntheticItems syntheticItems) {
- Collection<DexType> contexts = syntheticItems.getSynthesizingContexts(type);
- if (!contexts.isEmpty()) {
- Iterator<DexType> iterator = contexts.iterator();
- DexType context = iterator.next();
- FeatureSplit feature = classToFeatureSplitMap.getOrDefault(context, FeatureSplit.BASE);
- assert verifyConsistentFeatureContexts(iterator, feature);
+ FeatureSplit feature = classToFeatureSplitMap.get(type);
+ if (feature != null) {
return feature;
}
- return classToFeatureSplitMap.getOrDefault(type, FeatureSplit.BASE);
- }
-
- private boolean verifyConsistentFeatureContexts(
- Iterator<DexType> contextIterator, FeatureSplit feature) {
- while (contextIterator.hasNext()) {
- assert feature
- == classToFeatureSplitMap.getOrDefault(contextIterator.next(), FeatureSplit.BASE);
+ feature = syntheticItems.getContextualFeatureSplit(type);
+ if (feature != null) {
+ return feature;
}
- return true;
+ return FeatureSplit.BASE;
}
+ // Note, this predicate may be misleading as the map does not include synthetics.
+ // In practice it should not be an issue as there should not be a way to have a feature shrink
+ // to only contain synthetic content. At a minimum the entry points of the feature must remain.
public boolean isEmpty() {
return classToFeatureSplitMap.isEmpty();
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
index c8cc19e..88a4755 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
@@ -53,7 +53,7 @@
private DexProgramClass synthesizeClass(DexProgramClass context, SyntheticKind syntheticKind) {
return appView
.getSyntheticItems()
- .createFixedClass(syntheticKind, context, appView.dexItemFactory(), builder -> {});
+ .createFixedClass(syntheticKind, context, appView, builder -> {});
}
public SyntheticArgumentClass build(Collection<MergeGroup> mergeGroups) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 832fd8c..cc28692 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -1442,7 +1442,7 @@
.createMethod(
SyntheticNaming.SyntheticKind.BACKPORT,
methodProcessingContext.createUniqueContext(),
- appView.dexItemFactory(),
+ appView,
builder ->
builder
.setProto(getProto(appView.dexItemFactory()))
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java
index 5770e22..b9a8880 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/RecordRewriter.java
@@ -228,7 +228,7 @@
.createMethod(
SyntheticNaming.SyntheticKind.RECORD_HELPER,
methodProcessingContext.createUniqueContext(),
- factory,
+ appView,
builder ->
builder
.setProto(helperProto)
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 0899b2d..180c2aa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -25,6 +25,7 @@
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
@@ -455,7 +456,7 @@
.createMethod(
SyntheticNaming.SyntheticKind.STATIC_INTERFACE_CALL,
methodProcessingContext.createUniqueContext(),
- factory,
+ appView,
syntheticMethodBuilder ->
syntheticMethodBuilder
.setProto(invokedMethod.proto)
@@ -907,18 +908,18 @@
private static void recordCompanionClassReference(
AppView<?> appView, DexClassAndMethod method, DexMethod rewritten) {
+ ClasspathOrLibraryClass context = method.getHolder().asClasspathOrLibraryClass();
// If the interface class is a program class, we shouldn't need to synthesize the companion
// class on the classpath.
- if (method.getHolder().isProgramClass()) {
+ if (context == null) {
return;
}
-
appView
.getSyntheticItems()
.ensureDirectMethodOnSyntheticClasspathClassWhileMigrating(
SyntheticKind.COMPANION_CLASS,
rewritten.getHolderType(),
- method.getHolder(),
+ context,
appView,
rewritten,
builder ->
@@ -1149,7 +1150,7 @@
if (consumer != null) {
Origin dependencyOrigin = dependency.getOrigin();
java.util.Collection<DexType> dependents =
- appInfo.getSyntheticItems().getSynthesizingContexts(dependent.getType());
+ appInfo.getSyntheticItems().getSynthesizingContextTypes(dependent.getType());
if (dependents.isEmpty()) {
reportDependencyEdge(consumer, dependencyOrigin, dependent);
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
index 667397b..ad1cacb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
@@ -148,7 +148,7 @@
.createClass(
SyntheticNaming.SyntheticKind.LAMBDA,
methodProcessingContext.createUniqueContext(),
- appView.dexItemFactory(),
+ appView,
builder -> box.set(new LambdaClass(builder, appView, this, context, descriptor)));
// Immediately set the actual program class on the lambda.
LambdaClass lambdaClass = box.get();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index a3bdc56..a7f094e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -325,7 +325,7 @@
.createFixedClass(
SyntheticKind.INIT_TYPE_ARGUMENT,
method.asProgramMethod().getHolder(),
- dexItemFactory,
+ appView,
builder -> {})
.getType();
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrCloseResourceInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrCloseResourceInstructionDesugaring.java
index 30e7702..212259a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrCloseResourceInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrCloseResourceInstructionDesugaring.java
@@ -71,7 +71,7 @@
.createMethod(
SyntheticKind.TWR_CLOSE_RESOURCE,
methodProcessingContext.createUniqueContext(),
- appView.dexItemFactory(),
+ appView,
methodBuilder ->
methodBuilder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 2f32c5c..f7a59dd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -1367,7 +1367,7 @@
.createMethod(
SyntheticKind.OUTLINE,
methodProcessingContext.createUniqueContext(),
- appView.dexItemFactory(),
+ appView,
builder -> {
builder
.setAccessFlags(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index d532b9b..9b9dc08 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -193,7 +193,7 @@
.createMethod(
SyntheticKind.SERVICE_LOADER,
methodProcessingContext.createUniqueContext(),
- appView.dexItemFactory(),
+ appView,
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
index 687a9bf..953a78c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
@@ -38,7 +38,7 @@
syntheticItems.createMethod(
SyntheticNaming.SyntheticKind.TO_STRING_IF_NOT_NULL,
methodProcessingContext.createUniqueContext(),
- dexItemFactory,
+ appView,
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
@@ -65,7 +65,7 @@
syntheticItems.createMethod(
SyntheticNaming.SyntheticKind.THROW_CCE_IF_NOT_NULL,
positionContext,
- dexItemFactory,
+ appView,
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
@@ -93,7 +93,7 @@
syntheticItems.createMethod(
SyntheticNaming.SyntheticKind.THROW_IAE,
methodProcessingContext.createUniqueContext(),
- dexItemFactory,
+ appView,
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
@@ -119,7 +119,7 @@
syntheticItems.createMethod(
SyntheticNaming.SyntheticKind.THROW_ICCE,
methodProcessingContext.createUniqueContext(),
- dexItemFactory,
+ appView,
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
@@ -147,7 +147,7 @@
syntheticItems.createMethod(
SyntheticNaming.SyntheticKind.THROW_NSME,
methodProcessingContext.createUniqueContext(),
- dexItemFactory,
+ appView,
builder ->
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
index 96e263c..5be14a3 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
@@ -113,7 +113,7 @@
return false;
}
DexType type = reference.getContextType();
- for (DexType context : synthetics.getSynthesizingContexts(type)) {
+ for (DexType context : synthetics.getSynthesizingContextTypes(type)) {
if (items.contains(context)) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/MissingClasses.java b/src/main/java/com/android/tools/r8/shaking/MissingClasses.java
index 0330dca..aa87461 100644
--- a/src/main/java/com/android/tools/r8/shaking/MissingClasses.java
+++ b/src/main/java/com/android/tools/r8/shaking/MissingClasses.java
@@ -191,7 +191,9 @@
// Rewrite the synthetic context to its synthesizing contexts.
Set<DexReference> synthesizingContextReferences =
- appView.getSyntheticItems().getSynthesizingContexts(clazz, synthesizingContextOracle);
+ appView
+ .getSyntheticItems()
+ .getSynthesizingContextReferences(clazz, synthesizingContextOracle);
assert synthesizingContextReferences != null;
assert !synthesizingContextReferences.isEmpty();
for (DexReference synthesizingContextReference : synthesizingContextReferences) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index 04ec40a..6a611dc 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -6,8 +6,9 @@
import static com.android.tools.r8.utils.DescriptorUtils.getBinaryNameFromDescriptor;
import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;
+import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
@@ -37,37 +38,55 @@
private final DexType inputContextType;
private final Origin inputContextOrigin;
- static SynthesizingContext fromNonSyntheticInputContext(DexClass context) {
+ private final FeatureSplit featureSplit;
+
+ static SynthesizingContext fromNonSyntheticInputContext(ClasspathOrLibraryClass context) {
// A context that is itself non-synthetic is the single context, thus both the input context
// and synthesizing context coincide.
return new SynthesizingContext(
- context.getContextType(), context.getContextType(), context.getOrigin());
+ context.getContextType(),
+ context.getContextType(),
+ context.getOrigin(),
+ // Synthesizing from a non-program context is just considered to be "base".
+ FeatureSplit.BASE);
}
static SynthesizingContext fromType(DexType type) {
- return new SynthesizingContext(type, type, Origin.unknown());
+ // This method should only be used for synthesizing from a non-program context!
+ // Thus we have no origin info and place the context in the "base" feature.
+ return new SynthesizingContext(type, type, Origin.unknown(), FeatureSplit.BASE);
}
- static SynthesizingContext fromNonSyntheticInputContext(ProgramDefinition context) {
+ static SynthesizingContext fromNonSyntheticInputContext(
+ ProgramDefinition context, FeatureSplit featureSplit) {
// A context that is itself non-synthetic is the single context, thus both the input context
// and synthesizing context coincide.
return new SynthesizingContext(
- context.getContextType(), context.getContextType(), context.getOrigin());
+ context.getContextType(), context.getContextType(), context.getOrigin(), featureSplit);
}
static SynthesizingContext fromSyntheticInputClass(
- DexProgramClass clazz, DexType synthesizingContextType) {
+ DexProgramClass clazz, DexType synthesizingContextType, AppView<?> appView) {
assert synthesizingContextType != null;
// A context that is itself synthetic must denote a synthesizing context from which to ensure
// hygiene. This synthesizing context type is encoded on the synthetic for intermediate builds.
- return new SynthesizingContext(synthesizingContextType, clazz.type, clazz.origin);
+ FeatureSplit featureSplit =
+ appView
+ .appInfoForDesugaring()
+ .getClassToFeatureSplitMap()
+ .getFeatureSplit(clazz, appView.getSyntheticItems());
+ return new SynthesizingContext(synthesizingContextType, clazz.type, clazz.origin, featureSplit);
}
private SynthesizingContext(
- DexType synthesizingContextType, DexType inputContextType, Origin inputContextOrigin) {
+ DexType synthesizingContextType,
+ DexType inputContextType,
+ Origin inputContextOrigin,
+ FeatureSplit featureSplit) {
this.synthesizingContextType = synthesizingContextType;
this.inputContextType = inputContextType;
this.inputContextOrigin = inputContextOrigin;
+ this.featureSplit = featureSplit;
}
@Override
@@ -81,10 +100,18 @@
.compare(this, other);
}
+ DexType getSynthesizingContextType() {
+ return synthesizingContextType;
+ }
+
Origin getInputContextOrigin() {
return inputContextOrigin;
}
+ FeatureSplit getFeatureSplit() {
+ return featureSplit;
+ }
+
SynthesizingContext rewrite(NonIdentityGraphLens lens) {
DexType rewrittenInputeContextType = lens.lookupType(inputContextType);
DexType rewrittenSynthesizingContextType = lens.lookupType(synthesizingContextType);
@@ -92,11 +119,10 @@
&& rewrittenSynthesizingContextType == synthesizingContextType
? this
: new SynthesizingContext(
- rewrittenSynthesizingContextType, rewrittenInputeContextType, inputContextOrigin);
- }
-
- DexType getSynthesizingContextType() {
- return synthesizingContextType;
+ rewrittenSynthesizingContextType,
+ rewrittenInputeContextType,
+ inputContextOrigin,
+ featureSplit);
}
void registerPrefixRewriting(DexType hygienicType, AppView<?> appView) {
@@ -128,7 +154,10 @@
@Override
public String toString() {
- return "SynthesizingContext{" + getSynthesizingContextType() + "}";
+ return "SynthesizingContext{"
+ + getSynthesizingContextType()
+ + (featureSplit != FeatureSplit.BASE ? ", feature:" + featureSplit : "")
+ + "}";
}
// TODO(b/181858113): Remove once deprecated main-dex-list is removed.
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
index f6577d3..3c91d68 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
@@ -81,13 +81,7 @@
// single context.
getContext().getSynthesizingContextType().hashWithTypeEquivalence(hasher, map);
}
- if (!classToFeatureSplitMap.isEmpty()) {
- hasher.putInt(
- classToFeatureSplitMap
- .getFeatureSplit(getContext().getSynthesizingContextType(), syntheticItems)
- .hashCode());
- }
-
+ hasher.putInt(context.getFeatureSplit().hashCode());
internalComputeHash(hasher, map);
return hasher.hash();
}
@@ -121,17 +115,12 @@
return order;
}
}
- if (!classToFeatureSplitMap.isEmpty()) {
- DexType synthesizingContextType = this.getContext().getSynthesizingContextType();
- DexType otherSynthesizingContextType = other.getContext().getSynthesizingContextType();
- if (!classToFeatureSplitMap.isInSameFeatureOrBothInBase(
- synthesizingContextType, otherSynthesizingContextType, syntheticItems)) {
- int order =
- classToFeatureSplitMap.compareFeatureSplitsForDexTypes(
- synthesizingContextType, otherSynthesizingContextType, syntheticItems);
- assert order != 0;
- return order;
- }
+ if (getContext().getFeatureSplit() != other.getContext().getFeatureSplit()) {
+ int order =
+ classToFeatureSplitMap.compareFeatureSplits(
+ context.getFeatureSplit(), other.getContext().getFeatureSplit());
+ assert order != 0;
+ return order;
}
RepresentativeMap map = null;
// If the synthetics have been moved include the original types in the equivalence.
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 b90083a..6a539f0 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -3,9 +3,12 @@
// 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.contexts.CompilationContext.UniqueContext;
+import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClasspathClass;
@@ -123,8 +126,7 @@
synthetics.committed.builderForSyntheticInputs();
// TODO(b/158159959): Consider identifying synthetics in the input reader to speed this up.
for (DexProgramClass clazz : appView.appInfo().classes()) {
- SyntheticMarker marker =
- SyntheticMarker.stripMarkerFromClass(clazz, appView.dexItemFactory());
+ SyntheticMarker marker = SyntheticMarker.stripMarkerFromClass(clazz, appView);
if (marker.isSyntheticMethods()) {
clazz.forEachProgramMethod(
// TODO(b/158159959): Support having multiple methods per class.
@@ -260,7 +262,37 @@
return isSyntheticClass(clazz.type);
}
- public Collection<DexType> getSynthesizingContexts(DexType type) {
+ public FeatureSplit getContextualFeatureSplit(DexType type) {
+ List<SynthesizingContext> contexts = getSynthesizingContexts(type);
+ if (contexts.isEmpty()) {
+ return null;
+ }
+ assert verifyAllContextsHaveSameFeature(contexts);
+ 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();
+ }
+ return true;
+ }
+
+ private List<SynthesizingContext> getSynthesizingContexts(DexType type) {
+ SyntheticReference<?, ?, ?> reference = committed.getNonLegacyItem(type);
+ if (reference != null) {
+ return Collections.singletonList(reference.getContext());
+ }
+ SyntheticDefinition<?, ?, ?> definition = pending.nonLegacyDefinitions.get(type);
+ if (definition != null) {
+ return Collections.singletonList(definition.getContext());
+ }
+ return Collections.emptyList();
+ }
+
+ public Collection<DexType> getSynthesizingContextTypes(DexType type) {
SyntheticReference<?, ?, ?> reference = committed.getNonLegacyItem(type);
if (reference != null) {
return Collections.singletonList(reference.getContext().getSynthesizingContextType());
@@ -281,7 +313,7 @@
}
// TODO(b/180091213): Implement this and remove client provided the oracle.
- public Set<DexReference> getSynthesizingContexts(
+ public Set<DexReference> getSynthesizingContextReferences(
DexProgramClass clazz, SynthesizingContextOracle oracle) {
assert isSyntheticClass(clazz);
return oracle.getSynthesizingContexts(clazz);
@@ -317,7 +349,14 @@
return ListUtils.map(pending.legacyClasses.values(), LegacySyntheticDefinition::getDefinition);
}
- private SynthesizingContext getSynthesizingContext(ProgramDefinition context) {
+ private SynthesizingContext getSynthesizingContext(
+ ProgramDefinition context, AppView<?> appView) {
+ return getSynthesizingContext(
+ context, appView.appInfoForDesugaring().getClassToFeatureSplitMap());
+ }
+
+ private SynthesizingContext getSynthesizingContext(
+ ProgramDefinition context, ClassToFeatureSplitMap featureSplits) {
DexType contextType = context.getContextType();
SyntheticDefinition<?, ?, ?> existingDefinition = pending.nonLegacyDefinitions.get(contextType);
if (existingDefinition != null) {
@@ -328,7 +367,8 @@
return existingReference.getContext();
}
// This context is not nested in an existing synthetic context so create a new "leaf" context.
- return SynthesizingContext.fromNonSyntheticInputContext(context);
+ FeatureSplit featureSplit = featureSplits.getFeatureSplit(context, this);
+ return SynthesizingContext.fromNonSyntheticInputContext(context, featureSplit);
}
// Addition and creation of synthetic items.
@@ -358,16 +398,16 @@
public DexProgramClass createClass(
SyntheticKind kind,
UniqueContext context,
- DexItemFactory factory,
+ AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> fn) {
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
- SynthesizingContext outerContext = getSynthesizingContext(context.getClassContext());
+ SynthesizingContext outerContext = getSynthesizingContext(context.getClassContext(), appView);
DexType type =
SyntheticNaming.createInternalType(
- kind, outerContext, context.getSyntheticSuffix(), factory);
+ kind, outerContext, context.getSyntheticSuffix(), appView.dexItemFactory());
SyntheticProgramClassBuilder classBuilder =
- new SyntheticProgramClassBuilder(type, outerContext, factory);
+ new SyntheticProgramClassBuilder(type, outerContext, appView.dexItemFactory());
fn.accept(classBuilder);
DexProgramClass clazz = classBuilder.build();
addPendingDefinition(new SyntheticProgramClassDefinition(kind, outerContext, clazz));
@@ -378,14 +418,14 @@
public DexProgramClass createFixedClass(
SyntheticKind kind,
DexProgramClass context,
- DexItemFactory factory,
+ AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> fn) {
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
- SynthesizingContext outerContext = getSynthesizingContext(context);
- DexType type = SyntheticNaming.createFixedType(kind, outerContext, factory);
+ SynthesizingContext outerContext = getSynthesizingContext(context, appView);
+ DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
SyntheticProgramClassBuilder classBuilder =
- new SyntheticProgramClassBuilder(type, outerContext, factory);
+ new SyntheticProgramClassBuilder(type, outerContext, appView.dexItemFactory());
fn.accept(classBuilder);
DexProgramClass clazz = classBuilder.build();
addPendingDefinition(new SyntheticProgramClassDefinition(kind, outerContext, clazz));
@@ -409,7 +449,7 @@
}
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
- SynthesizingContext outerContext = getSynthesizingContext(context);
+ SynthesizingContext outerContext = getSynthesizingContext(context, appView);
SyntheticProgramClassBuilder classBuilder =
new SyntheticProgramClassBuilder(legacyType, outerContext, appView.dexItemFactory());
fn.accept(classBuilder);
@@ -436,7 +476,7 @@
// like a hygienic synthetic, but use the legacyType passed as parameter instead of the
// hygienic type.
private DexClasspathClass ensureFixedClasspathClassWhileMigrating(
- SyntheticKind kind, DexType legacyType, DexClass context, AppView<?> appView) {
+ SyntheticKind kind, DexType legacyType, ClasspathOrLibraryClass context, AppView<?> appView) {
synchronized (context) {
DexClass dexClass = appView.definitionFor(legacyType);
if (dexClass != null) {
@@ -460,7 +500,7 @@
public void ensureDirectMethodOnSyntheticClasspathClassWhileMigrating(
SyntheticKind kind,
DexType legacyType,
- DexClass context,
+ ClasspathOrLibraryClass context,
AppView<?> appView,
DexMethod method,
Consumer<SyntheticMethodBuilder> builderConsumer) {
@@ -498,25 +538,26 @@
public ProgramMethod createMethod(
SyntheticKind kind,
UniqueContext context,
- DexItemFactory factory,
+ AppView<?> appView,
Consumer<SyntheticMethodBuilder> fn) {
- return createMethod(kind, context.getClassContext(), factory, fn, context::getSyntheticSuffix);
+ return createMethod(kind, context.getClassContext(), appView, fn, context::getSyntheticSuffix);
}
private ProgramMethod createMethod(
SyntheticKind kind,
ProgramDefinition context,
- DexItemFactory factory,
+ AppView<?> appView,
Consumer<SyntheticMethodBuilder> fn,
Supplier<String> syntheticIdSupplier) {
assert nextSyntheticId != INVALID_ID_AFTER_SYNTHETIC_FINALIZATION;
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
- SynthesizingContext outerContext = getSynthesizingContext(context);
+ SynthesizingContext outerContext = getSynthesizingContext(context, appView);
DexType type =
- SyntheticNaming.createInternalType(kind, outerContext, syntheticIdSupplier.get(), factory);
+ SyntheticNaming.createInternalType(
+ kind, outerContext, syntheticIdSupplier.get(), appView.dexItemFactory());
SyntheticProgramClassBuilder classBuilder =
- new SyntheticProgramClassBuilder(type, outerContext, factory);
+ new SyntheticProgramClassBuilder(type, outerContext, appView.dexItemFactory());
DexProgramClass clazz =
classBuilder
.addMethod(fn.andThen(m -> m.setName(SyntheticNaming.INTERNAL_SYNTHETIC_METHOD_PREFIX)))
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
index 03b7e36..d68558d 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.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.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -28,26 +29,27 @@
kind, context.getSynthesizingContextType(), factory)));
}
- public static SyntheticMarker stripMarkerFromClass(
- DexProgramClass clazz, DexItemFactory factory) {
- SyntheticMarker marker = internalStripMarkerFromClass(clazz, factory);
+ public static SyntheticMarker stripMarkerFromClass(DexProgramClass clazz, AppView<?> appView) {
+ SyntheticMarker marker = internalStripMarkerFromClass(clazz, appView);
assert marker != NO_MARKER
- || DexAnnotation.getSynthesizedClassAnnotationContextType(clazz.annotations(), factory)
+ || DexAnnotation.getSynthesizedClassAnnotationContextType(
+ clazz.annotations(), appView.dexItemFactory())
== null;
return marker;
}
private static SyntheticMarker internalStripMarkerFromClass(
- DexProgramClass clazz, DexItemFactory factory) {
+ DexProgramClass clazz, AppView<?> appView) {
ClassAccessFlags flags = clazz.accessFlags;
- if (clazz.superType != factory.objectType) {
+ if (clazz.superType != appView.dexItemFactory().objectType) {
return NO_MARKER;
}
if (!flags.isSynthetic() || flags.isAbstract() || flags.isEnum()) {
return NO_MARKER;
}
Pair<SyntheticKind, DexType> info =
- DexAnnotation.getSynthesizedClassAnnotationContextType(clazz.annotations(), factory);
+ DexAnnotation.getSynthesizedClassAnnotationContextType(
+ clazz.annotations(), appView.dexItemFactory());
if (info == null) {
return NO_MARKER;
}
@@ -65,7 +67,8 @@
}
}
clazz.setAnnotations(DexAnnotationSet.empty());
- return new SyntheticMarker(kind, SynthesizingContext.fromSyntheticInputClass(clazz, context));
+ return new SyntheticMarker(
+ kind, SynthesizingContext.fromSyntheticInputClass(clazz, context, appView));
}
private static final SyntheticMarker NO_MARKER = new SyntheticMarker(null, null);