blob: ec03a7e2ac07aac1013a58ac94099a70083216e8 [file] [log] [blame]
// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.verticalclassmerging;
import com.android.tools.r8.classmerging.Policy;
import com.android.tools.r8.classmerging.PolicyExecutor;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.verticalclassmerging.policies.NoAnnotationClassesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoClassInitializationChangesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoDirectlyInstantiatedClassesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoEnclosingMethodAttributesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoFieldResolutionChangesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoIllegalAccessesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoInnerClassAttributesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoInterfacesWithInvokeSpecialToDefaultMethodIntoClassPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoInterfacesWithUnknownSubtypesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoInvokeSuperNoSuchMethodErrorsPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoKeptClassesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoLockMergingPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoMethodResolutionChangesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoNonSerializableClassIntoSerializableClassPolicy;
import com.android.tools.r8.verticalclassmerging.policies.NoServiceInterfacesPolicy;
import com.android.tools.r8.verticalclassmerging.policies.SafeConstructorInliningPolicy;
import com.android.tools.r8.verticalclassmerging.policies.SameApiReferenceLevelPolicy;
import com.android.tools.r8.verticalclassmerging.policies.SameFeatureSplitPolicy;
import com.android.tools.r8.verticalclassmerging.policies.SameMainDexGroupPolicy;
import com.android.tools.r8.verticalclassmerging.policies.SameNestPolicy;
import com.android.tools.r8.verticalclassmerging.policies.SameStartupPartitionPolicy;
import com.android.tools.r8.verticalclassmerging.policies.VerticalClassMergerPolicy;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
public class VerticalClassMergerPolicyExecutor extends PolicyExecutor<VerticalMergeGroup> {
private final AppView<AppInfoWithLiveness> appView;
private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
private final Set<DexProgramClass> pinnedClasses;
VerticalClassMergerPolicyExecutor(
AppView<AppInfoWithLiveness> appView,
ImmediateProgramSubtypingInfo immediateSubtypingInfo,
Set<DexProgramClass> pinnedClasses) {
this.appView = appView;
this.immediateSubtypingInfo = immediateSubtypingInfo;
this.pinnedClasses = pinnedClasses;
}
ConnectedComponentVerticalClassMerger run(
Set<DexProgramClass> connectedComponent, ExecutorService executorService, Timing timing)
throws ExecutionException {
Collection<VerticalMergeGroup> groups = createInitialMergeGroups(connectedComponent);
Collection<VerticalClassMergerPolicy> policies =
List.of(
new NoDirectlyInstantiatedClassesPolicy(appView),
new NoInterfacesWithUnknownSubtypesPolicy(appView),
new NoKeptClassesPolicy(appView, pinnedClasses),
new SameFeatureSplitPolicy(appView),
new SameStartupPartitionPolicy(appView),
new NoServiceInterfacesPolicy(appView),
new NoAnnotationClassesPolicy(),
new NoNonSerializableClassIntoSerializableClassPolicy(appView),
new SafeConstructorInliningPolicy(appView),
new NoEnclosingMethodAttributesPolicy(),
new NoInnerClassAttributesPolicy(),
new SameNestPolicy(),
new SameMainDexGroupPolicy(appView),
new NoLockMergingPolicy(appView),
new SameApiReferenceLevelPolicy(appView),
new NoFieldResolutionChangesPolicy(appView),
new NoMethodResolutionChangesPolicy(appView),
new NoIllegalAccessesPolicy(appView),
new NoClassInitializationChangesPolicy(appView),
new NoInterfacesWithInvokeSpecialToDefaultMethodIntoClassPolicy(appView),
new NoInvokeSuperNoSuchMethodErrorsPolicy(appView));
groups = run(groups, policies, executorService, timing);
return new ConnectedComponentVerticalClassMerger(appView, groups);
}
@SuppressWarnings("JdkObsolete")
private LinkedList<VerticalMergeGroup> createInitialMergeGroups(
Set<DexProgramClass> connectedComponent) {
LinkedList<VerticalMergeGroup> groups = new LinkedList<>();
for (DexProgramClass mergeCandidate : connectedComponent) {
List<DexProgramClass> subclasses = immediateSubtypingInfo.getSubclasses(mergeCandidate);
if (subclasses.size() == 1) {
groups.add(new VerticalMergeGroup(mergeCandidate, ListUtils.first(subclasses)));
}
}
return groups;
}
@Override
protected LinkedList<VerticalMergeGroup> apply(
Policy policy, LinkedList<VerticalMergeGroup> linkedGroups, ExecutorService executorService)
throws ExecutionException {
assert policy.isVerticalClassMergerPolicy();
return apply(policy.asVerticalClassMergerPolicy(), linkedGroups);
}
private LinkedList<VerticalMergeGroup> apply(
VerticalClassMergerPolicy policy, LinkedList<VerticalMergeGroup> linkedGroups) {
linkedGroups.removeIf(group -> !policy.canMerge(group));
return linkedGroups;
}
}