Account for synthetics with restricted package private merging in D8
Bug: b/269651270
Change-Id: I61aa088e68e6e4ec9870f924c1f0a686a372f1a6
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java
index 2d11359..1e3e943 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java
@@ -57,7 +57,7 @@
import com.android.tools.r8.horizontalclassmerging.policies.SameInstanceFields;
import com.android.tools.r8.horizontalclassmerging.policies.SameMainDexGroup;
import com.android.tools.r8.horizontalclassmerging.policies.SameNestHost;
-import com.android.tools.r8.horizontalclassmerging.policies.SamePackageForApiOutline;
+import com.android.tools.r8.horizontalclassmerging.policies.SamePackageForNonGlobalMergeSynthetic;
import com.android.tools.r8.horizontalclassmerging.policies.SameParentClass;
import com.android.tools.r8.horizontalclassmerging.policies.SyntheticItemsPolicy;
import com.android.tools.r8.horizontalclassmerging.policies.VerifyMultiClassPolicyAlwaysSatisfied;
@@ -265,7 +265,7 @@
new SameParentClass(),
new SyntheticItemsPolicy(appView, mode),
new NoApiOutlineWithNonApiOutline(appView),
- new SamePackageForApiOutline(appView, mode),
+ new SamePackageForNonGlobalMergeSynthetic(appView),
new NoDifferentApiReferenceLevel(appView),
new LimitClassGroups(appView));
assert verifyMultiClassPoliciesIrrelevantForMergingSyntheticsInD8(appView, mode, builder);
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SamePackageForApiOutline.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SamePackageForNonGlobalMergeSynthetic.java
similarity index 83%
rename from src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SamePackageForApiOutline.java
rename to src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SamePackageForNonGlobalMergeSynthetic.java
index 30a3200..db6d282 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SamePackageForApiOutline.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/SamePackageForNonGlobalMergeSynthetic.java
@@ -9,23 +9,21 @@
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
import com.android.tools.r8.horizontalclassmerging.MergeGroup;
import com.android.tools.r8.horizontalclassmerging.MultiClassPolicy;
import com.android.tools.r8.synthesis.SyntheticItems;
+import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
-public class SamePackageForApiOutline extends MultiClassPolicy {
+public class SamePackageForNonGlobalMergeSynthetic extends MultiClassPolicy {
private final AppView<AppInfo> appView;
- private final Mode mode;
- public SamePackageForApiOutline(AppView<AppInfo> appView, Mode mode) {
+ public SamePackageForNonGlobalMergeSynthetic(AppView<AppInfo> appView) {
this.appView = appView;
- this.mode = mode;
}
/** Sort unrestricted classes into restricted classes if they are in the same package. */
@@ -50,7 +48,12 @@
// Sort all restricted classes into packages.
for (DexProgramClass clazz : group) {
- if (syntheticItems.isSyntheticOfKind(clazz.getType(), k -> k.API_MODEL_OUTLINE)) {
+ assert syntheticItems.isSynthetic(clazz.getType());
+ if (Iterables.any(
+ syntheticItems.getSyntheticKinds(clazz.getType()),
+ kind ->
+ !kind.isSyntheticMethodKind()
+ || !kind.asSyntheticMethodKind().isAllowGlobalMerging())) {
restrictedClasses
.computeIfAbsent(
clazz.getType().getPackageDescriptor(), ignoreArgument(MergeGroup::new))
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
index 292d844..5f65c95 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
@@ -94,25 +94,8 @@
if (context.getDefinition().isD8R8Synthesized()) {
return appView.computedMinApiLevel();
}
- DexReference reference;
- if (instruction.isInvoke()) {
- CfInvoke cfInvoke = instruction.asInvoke();
- if (cfInvoke.isInvokeSpecial()) {
- return appView.computedMinApiLevel();
- }
- reference = cfInvoke.getMethod();
- } else if (instruction.isFieldInstruction()) {
- reference = instruction.asFieldInstruction().getField();
- } else if (instruction.isCheckCast()) {
- reference = instruction.asCheckCast().getType();
- } else if (instruction.isInstanceOf()) {
- reference = instruction.asInstanceOf().getType();
- } else if (instruction.isConstClass()) {
- reference = instruction.asConstClass().getType();
- } else {
- return appView.computedMinApiLevel();
- }
- if (!reference.getContextType().isClassType()) {
+ DexReference reference = getReferenceFromInstruction(instruction);
+ if (reference == null || !reference.getContextType().isClassType()) {
return appView.computedMinApiLevel();
}
DexClass holder = appView.definitionFor(reference.getContextType());
@@ -158,6 +141,22 @@
}
}
+ private DexReference getReferenceFromInstruction(CfInstruction instruction) {
+ if (instruction.isFieldInstruction()) {
+ return instruction.asFieldInstruction().getField();
+ } else if (instruction.isCheckCast()) {
+ return instruction.asCheckCast().getType();
+ } else if (instruction.isInstanceOf()) {
+ return instruction.asInstanceOf().getType();
+ } else if (instruction.isConstClass()) {
+ return instruction.asConstClass().getType();
+ } else if (instruction.isInvoke() && !instruction.asInvoke().isInvokeSpecial()) {
+ return instruction.asInvoke().getMethod();
+ } else {
+ return null;
+ }
+ }
+
private DexEncodedMember<?, ?> simpleLookupInClassHierarchy(
DexLibraryClass holder, Function<DexClass, DexEncodedMember<?, ?>> lookup) {
DexEncodedMember<?, ?> result = lookup.apply(holder);
@@ -208,10 +207,20 @@
ComputedApiLevel apiLevel,
DexItemFactory factory,
ProgramMethod programContext) {
+ DexReference reference = getReferenceFromInstruction(instruction);
+ assert reference != null;
+ DexClass holder = appView.definitionFor(reference.getContextType());
+ assert holder != null;
return appView
.getSyntheticItems()
.createMethod(
- kinds -> kinds.API_MODEL_OUTLINE,
+ kinds ->
+ // We've already checked that the definition the reference is targeting is public
+ // when computing the api-level for desugaring. We still have to ensure that the
+ // class cannot be merged globally if it is package private.
+ holder.isPublic()
+ ? kinds.API_MODEL_OUTLINE
+ : kinds.API_MODEL_OUTLINE_WITHOUT_GLOBAL_MERGING,
context,
appView,
syntheticMethodBuilder -> {
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 d8ae369..631231c 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -466,6 +466,16 @@
return pending.containsTypeOfKind(type, kind) || committed.containsTypeOfKind(type, kind);
}
+ public Iterable<SyntheticKind> getSyntheticKinds(DexType type) {
+ Iterable<SyntheticKind> references =
+ IterableUtils.transform(committed.getItems(type), SyntheticReference::getKind);
+ SyntheticDefinition<?, ?, ?> definition = pending.definitions.get(type);
+ if (definition != null) {
+ references = Iterables.concat(references, IterableUtils.singleton(definition.getKind()));
+ }
+ return references;
+ }
+
boolean isSyntheticInput(DexProgramClass clazz) {
return committed.containsSyntheticInput(clazz.getType());
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 59aff72..5c81e4d 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -68,21 +68,25 @@
// Method synthetics.
public final SyntheticKind ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD =
- generator.forSingleMethod("CheckNotZero");
- public final SyntheticKind RECORD_HELPER = generator.forSingleMethod("Record");
- public final SyntheticKind BACKPORT = generator.forSingleMethod("Backport");
+ generator.forSingleMethodWithGlobalMerging("CheckNotZero");
+ public final SyntheticKind RECORD_HELPER = generator.forSingleMethodWithGlobalMerging("Record");
+ public final SyntheticKind BACKPORT = generator.forSingleMethodWithGlobalMerging("Backport");
public final SyntheticKind BACKPORT_WITH_FORWARDING =
generator.forSingleMethod("BackportWithForwarding");
public final SyntheticKind STATIC_INTERFACE_CALL =
generator.forSingleMethod("StaticInterfaceCall");
- public final SyntheticKind TO_STRING_IF_NOT_NULL = generator.forSingleMethod("ToStringIfNotNull");
- public final SyntheticKind THROW_CCE_IF_NOT_NULL = generator.forSingleMethod("ThrowCCEIfNotNull");
- public final SyntheticKind THROW_IAE = generator.forSingleMethod("ThrowIAE");
- public final SyntheticKind THROW_ICCE = generator.forSingleMethod("ThrowICCE");
- public final SyntheticKind THROW_NSME = generator.forSingleMethod("ThrowNSME");
- public final SyntheticKind THROW_RTE = generator.forSingleMethod("ThrowRTE");
- public final SyntheticKind TWR_CLOSE_RESOURCE = generator.forSingleMethod("TwrCloseResource");
- public final SyntheticKind SERVICE_LOADER = generator.forSingleMethod("ServiceLoad");
+ public final SyntheticKind TO_STRING_IF_NOT_NULL =
+ generator.forSingleMethodWithGlobalMerging("ToStringIfNotNull");
+ public final SyntheticKind THROW_CCE_IF_NOT_NULL =
+ generator.forSingleMethodWithGlobalMerging("ThrowCCEIfNotNull");
+ public final SyntheticKind THROW_IAE = generator.forSingleMethodWithGlobalMerging("ThrowIAE");
+ public final SyntheticKind THROW_ICCE = generator.forSingleMethodWithGlobalMerging("ThrowICCE");
+ public final SyntheticKind THROW_NSME = generator.forSingleMethodWithGlobalMerging("ThrowNSME");
+ public final SyntheticKind THROW_RTE = generator.forSingleMethodWithGlobalMerging("ThrowRTE");
+ public final SyntheticKind TWR_CLOSE_RESOURCE =
+ generator.forSingleMethodWithGlobalMerging("TwrCloseResource");
+ public final SyntheticKind SERVICE_LOADER =
+ generator.forSingleMethodWithGlobalMerging("ServiceLoad");
public final SyntheticKind OUTLINE = generator.forSingleMethod("Outline");
public final SyntheticKind COVARIANT_OUTLINE = generator.forSingleMethod("CovariantOutline");
public final SyntheticKind API_CONVERSION = generator.forSingleMethod("APIConversion");
@@ -90,7 +94,10 @@
generator.forSingleMethod("APIConversionParameters");
public final SyntheticKind COLLECTION_CONVERSION =
generator.forSingleMethod("$CollectionConversion");
- public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod("ApiModelOutline");
+ public final SyntheticKind API_MODEL_OUTLINE =
+ generator.forSingleMethodWithGlobalMerging("ApiModelOutline");
+ public final SyntheticKind API_MODEL_OUTLINE_WITHOUT_GLOBAL_MERGING =
+ generator.forSingleMethod("ApiModelOutline");
private final List<SyntheticKind> ALL_KINDS;
private String lazyVersionHash = null;
@@ -144,7 +151,11 @@
}
SyntheticKind forSingleMethod(String descriptor) {
- return register(new SyntheticMethodKind(getNextId(), descriptor));
+ return register(new SyntheticMethodKind(getNextId(), descriptor, false));
+ }
+
+ SyntheticKind forSingleMethodWithGlobalMerging(String descriptor) {
+ return register(new SyntheticMethodKind(getNextId(), descriptor, true));
}
// TODO(b/214901256): Remove once fixed.
@@ -217,6 +228,14 @@
return descriptor;
}
+ public boolean isSyntheticMethodKind() {
+ return false;
+ }
+
+ public SyntheticMethodKind asSyntheticMethodKind() {
+ return null;
+ }
+
public abstract boolean isShareable();
public abstract boolean isSingleSyntheticMethod();
@@ -236,10 +255,13 @@
public abstract void internalHash(Hasher hasher);
}
- private static class SyntheticMethodKind extends SyntheticKind {
+ public static class SyntheticMethodKind extends SyntheticKind {
- public SyntheticMethodKind(int id, String descriptor) {
+ private final boolean allowGlobalMerging;
+
+ public SyntheticMethodKind(int id, String descriptor, boolean allowGlobalMerging) {
super(id, descriptor);
+ this.allowGlobalMerging = allowGlobalMerging;
}
@Override
@@ -268,6 +290,20 @@
return false;
}
+ public boolean isAllowGlobalMerging() {
+ return allowGlobalMerging;
+ }
+
+ @Override
+ public boolean isSyntheticMethodKind() {
+ return true;
+ }
+
+ @Override
+ public SyntheticMethodKind asSyntheticMethodKind() {
+ return this;
+ }
+
@Override
public void internalHash(Hasher hasher) {
hasher.putString("method", StandardCharsets.UTF_8);