Reintroduce context aware placement of main-dex synthetics.
Bug: 178127572
Fixes: 181010111
Change-Id: I970479d758ddf876c058e2a18d43fe419b7e5f2a
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java
index f7b8c6e..41c240f 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreventMergeIntoDifferentMainDexGroups.java
@@ -10,20 +10,23 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.shaking.MainDexInfo.MainDexGroup;
+import com.android.tools.r8.synthesis.SyntheticItems;
public class PreventMergeIntoDifferentMainDexGroups
extends MultiClassSameReferencePolicy<MainDexGroup> {
private final MainDexInfo mainDexInfo;
+ private final SyntheticItems synthetics;
public PreventMergeIntoDifferentMainDexGroups(AppView<AppInfoWithLiveness> appView) {
- this.mainDexInfo = appView.appInfo().getMainDexInfo();
+ mainDexInfo = appView.appInfo().getMainDexInfo();
+ synthetics = appView.getSyntheticItems();
}
@Override
public MainDexGroup getMergeKey(DexProgramClass clazz) {
- return mainDexInfo.canMerge(clazz)
- ? mainDexInfo.getMergeKey(clazz)
+ return mainDexInfo.canMerge(clazz, synthetics)
+ ? mainDexInfo.getMergeKey(clazz, synthetics)
: ineligibleForClassMerging();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 33e414f..8e66601 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -201,13 +201,13 @@
// If we do this it can increase the size of the main dex dependent classes.
if (reason != Reason.FORCE
&& inliner.mainDexInfo.disallowInliningIntoContext(
- appView.appInfo(), method, singleTarget)) {
+ appView.appInfo(), method, singleTarget, appView.getSyntheticItems())) {
whyAreYouNotInliningReporter.reportInlineeRefersToClassesNotInMainDex();
return false;
}
assert reason != Reason.FORCE
|| !inliner.mainDexInfo.disallowInliningIntoContext(
- appView.appInfo(), method, singleTarget);
+ appView.appInfo(), method, singleTarget, appView.getSyntheticItems());
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index f5f4d70..fa3886e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -391,6 +391,9 @@
}
private boolean isRebindingNewClassIntoMainDex(ProgramMethod context, DexMethod reboundMethod) {
- return !appView.appInfo().getMainDexInfo().canRebindReference(context, reboundMethod);
+ return !appView
+ .appInfo()
+ .getMainDexInfo()
+ .canRebindReference(context, reboundMethod, appView.getSyntheticItems());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
index 289b2ba..802fdb3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
@@ -92,7 +92,8 @@
&& !appView
.appInfo()
.getMainDexInfo()
- .canRebindReference(code.context(), baseClass.getType())) {
+ .canRebindReference(
+ code.context(), baseClass.getType(), appView.getSyntheticItems())) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index fd3c069..e818526 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1695,7 +1695,7 @@
assert !mode.isFinalMainDexTracing()
|| !options.testing.checkForNotExpandingMainDexTracingResult
- || appView.appInfo().getMainDexInfo().isTracedRoot(clazz)
+ || appView.appInfo().getMainDexInfo().isTracedRoot(clazz, appView.getSyntheticItems())
|| clazz.toSourceString().contains(ENUM_UNBOXING_UTILITY_CLASS_SUFFIX)
: "Class " + clazz.toSourceString() + " was not a main dex root in the first round";
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 4e579f2..5d3309a 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.shaking.MainDexInfo.MainDexGroup.MAIN_DEX_ROOT;
import static com.android.tools.r8.utils.LensUtils.rewriteAndApplyIfNotPrimitiveType;
-import static com.android.tools.r8.utils.PredicateUtils.not;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.DexMethod;
@@ -17,6 +16,7 @@
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
+import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.utils.ConsumerUtils;
import com.google.common.collect.Sets;
import java.util.Collections;
@@ -81,16 +81,16 @@
return this == NONE;
}
- public boolean isFromList(ProgramDefinition definition) {
- return isFromList(definition.getContextType());
+ public boolean isFromList(ProgramDefinition definition, SyntheticItems synthetics) {
+ return isFromList(definition.getContextType(), synthetics);
}
- private boolean isFromList(DexReference reference) {
- return classList.contains(reference.getContextType());
+ private boolean isFromList(DexReference reference, SyntheticItems synthetics) {
+ return isContainedOrHasContainedContext(reference, classList, synthetics);
}
- public boolean isTracedRoot(ProgramDefinition definition) {
- return isTracedRoot(definition.getContextType());
+ public boolean isTracedRoot(ProgramDefinition definition, SyntheticItems synthetics) {
+ return isTracedRoot(definition.getContextType(), synthetics);
}
public boolean isTracedMethodRoot(DexMethod method) {
@@ -98,8 +98,22 @@
return tracedMethodRoots.contains(method);
}
- private boolean isTracedRoot(DexReference reference) {
- return tracedRoots.contains(reference.getContextType());
+ private boolean isTracedRoot(DexReference reference, SyntheticItems synthetics) {
+ return isContainedOrHasContainedContext(reference, tracedRoots, synthetics);
+ }
+
+ private boolean isContainedOrHasContainedContext(
+ DexReference reference, Set<DexType> items, SyntheticItems synthetics) {
+ if (items.isEmpty()) {
+ return false;
+ }
+ DexType type = reference.getContextType();
+ for (DexType context : synthetics.getSynthesizingContexts(type)) {
+ if (items.contains(context)) {
+ return true;
+ }
+ }
+ return items.contains(type);
}
private boolean isDependency(ProgramDefinition definition) {
@@ -119,8 +133,9 @@
this.tracedMethodRoots = Sets.newIdentityHashSet();
}
- public boolean canRebindReference(ProgramMethod context, DexReference referenceToTarget) {
- MainDexGroup holderGroup = getMainDexGroupInternal(context);
+ public boolean canRebindReference(
+ ProgramMethod context, DexReference referenceToTarget, SyntheticItems synthetics) {
+ MainDexGroup holderGroup = getMainDexGroupInternal(context, synthetics);
if (holderGroup == MainDexGroup.NOT_IN_MAIN_DEX
|| holderGroup == MainDexGroup.MAIN_DEX_DEPENDENCY) {
// We are always free to rebind/inline into something not in main-dex or traced dependencies.
@@ -133,20 +148,21 @@
}
assert holderGroup == MAIN_DEX_ROOT;
// Otherwise we allow if either is both root.
- return getMainDexGroupInternal(referenceToTarget) == MAIN_DEX_ROOT;
+ return getMainDexGroupInternal(referenceToTarget, synthetics) == MAIN_DEX_ROOT;
}
- public boolean canMerge(ProgramDefinition candidate) {
- return !isFromList(candidate);
+ public boolean canMerge(ProgramDefinition candidate, SyntheticItems synthetics) {
+ return !isFromList(candidate, synthetics);
}
- public boolean canMerge(ProgramDefinition source, ProgramDefinition target) {
- return canMerge(source.getContextType(), target.getContextType());
+ public boolean canMerge(
+ ProgramDefinition source, ProgramDefinition target, SyntheticItems synthetics) {
+ return canMerge(source.getContextType(), target.getContextType(), synthetics);
}
- private boolean canMerge(DexReference source, DexReference target) {
- MainDexGroup sourceGroup = getMainDexGroupInternal(source);
- MainDexGroup targetGroup = getMainDexGroupInternal(target);
+ private boolean canMerge(DexReference source, DexReference target, SyntheticItems synthetics) {
+ MainDexGroup sourceGroup = getMainDexGroupInternal(source, synthetics);
+ MainDexGroup targetGroup = getMainDexGroupInternal(target, synthetics);
if (sourceGroup != targetGroup) {
return false;
}
@@ -155,21 +171,22 @@
return sourceGroup != MainDexGroup.MAIN_DEX_LIST;
}
- public MainDexGroup getMergeKey(ProgramDefinition mergeCandidate) {
- assert canMerge(mergeCandidate);
- MainDexGroup mainDexGroupInternal = getMainDexGroupInternal(mergeCandidate);
+ public MainDexGroup getMergeKey(ProgramDefinition mergeCandidate, SyntheticItems synthetics) {
+ assert canMerge(mergeCandidate, synthetics);
+ MainDexGroup mainDexGroupInternal = getMainDexGroupInternal(mergeCandidate, synthetics);
return mainDexGroupInternal == MainDexGroup.MAIN_DEX_LIST ? null : mainDexGroupInternal;
}
- private MainDexGroup getMainDexGroupInternal(ProgramDefinition definition) {
- return getMainDexGroupInternal(definition.getReference());
+ private MainDexGroup getMainDexGroupInternal(
+ ProgramDefinition definition, SyntheticItems synthetics) {
+ return getMainDexGroupInternal(definition.getReference(), synthetics);
}
- private MainDexGroup getMainDexGroupInternal(DexReference reference) {
- if (isFromList(reference)) {
+ private MainDexGroup getMainDexGroupInternal(DexReference reference, SyntheticItems synthetics) {
+ if (isFromList(reference, synthetics)) {
return MainDexGroup.MAIN_DEX_LIST;
}
- if (isTracedRoot(reference)) {
+ if (isTracedRoot(reference, synthetics)) {
return MAIN_DEX_ROOT;
}
if (isDependency(reference)) {
@@ -179,22 +196,25 @@
}
public boolean disallowInliningIntoContext(
- AppInfoWithClassHierarchy appInfo, ProgramDefinition context, ProgramMethod method) {
+ AppInfoWithClassHierarchy appInfo,
+ ProgramDefinition context,
+ ProgramMethod method,
+ SyntheticItems synthetics) {
if (context.getContextType() == method.getContextType()) {
return false;
}
- MainDexGroup mainDexGroupInternal = getMainDexGroupInternal(context);
+ MainDexGroup mainDexGroupInternal = getMainDexGroupInternal(context, synthetics);
if (mainDexGroupInternal == MainDexGroup.NOT_IN_MAIN_DEX
|| mainDexGroupInternal == MainDexGroup.MAIN_DEX_DEPENDENCY) {
return false;
}
if (mainDexGroupInternal == MainDexGroup.MAIN_DEX_LIST) {
return MainDexDirectReferenceTracer.hasReferencesOutsideMainDexClasses(
- appInfo, method, not(this::isFromList));
+ appInfo, method, t -> !isFromList(t, synthetics));
}
assert mainDexGroupInternal == MAIN_DEX_ROOT;
return MainDexDirectReferenceTracer.hasReferencesOutsideMainDexClasses(
- appInfo, method, not(this::isTracedRoot));
+ appInfo, method, t -> !isTracedRoot(t, synthetics));
}
public boolean isEmpty() {
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index afc9e50..761b314 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -826,7 +826,7 @@
}
// Check with main dex classes to see if we are allowed to merge.
- if (!mainDexInfo.canMerge(clazz, targetClass)) {
+ if (!mainDexInfo.canMerge(clazz, targetClass, appView.getSyntheticItems())) {
return;
}
@@ -1657,7 +1657,8 @@
}
// Constructors can have references beyond the root main dex classes. This can increase the
// size of the main dex dependent classes and we should bail out.
- if (mainDexInfo.disallowInliningIntoContext(appView.appInfo(), context, method)) {
+ if (mainDexInfo.disallowInliningIntoContext(
+ appView.appInfo(), context, method, appView.getSyntheticItems())) {
return AbortReason.MAIN_DEX_ROOT_OUTSIDE_REFERENCE;
}
return null;