blob: 705c8cd3fa2e9697f0a9a2eadf3463eacac43ad9 [file] [log] [blame]
// Copyright (c) 2020, 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.horizontalclassmerging.policies;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
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.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
import java.util.Collection;
import java.util.Set;
/**
* Identifies when instance initializer merging is required and bails out. This is needed to ensure
* that we don't need to append extra null arguments at constructor call sites, such that the result
* of the final round of class merging can be described as a renaming only.
*
* <p>This policy requires that all instance initializers with the same signature (relaxed, by
* converting references types to java.lang.Object) have the same behavior.
*/
public class FinalizeMergeGroup extends MultiClassPolicy {
private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final Mode mode;
public FinalizeMergeGroup(AppView<? extends AppInfoWithClassHierarchy> appView, Mode mode) {
this.appView = appView;
this.mode = mode;
}
@Override
public Collection<MergeGroup> apply(MergeGroup group) {
if (mode.isInitial() || group.isInterfaceGroup()) {
group.selectTarget(appView);
group.selectInstanceFieldMap(appView);
} else {
// In the final round of merging each group should be finalized by the
// NoInstanceInitializerMerging policy.
assert verifyAlreadyFinalized(group);
}
return ListUtils.newLinkedList(group);
}
@Override
public String getName() {
return "FinalizeMergeGroup";
}
@Override
public boolean isIdentityForInterfaceGroups() {
return true;
}
private boolean verifyAlreadyFinalized(MergeGroup group) {
assert group.hasTarget();
assert group.getClasses().contains(group.getTarget());
assert group.hasInstanceFieldMap();
Set<DexType> types =
SetUtils.newIdentityHashSet(
builder -> group.forEach(clazz -> builder.accept(clazz.getType())));
group
.getInstanceFieldMap()
.forEach(
(sourceField, targetField) -> {
assert types.contains(sourceField.getHolderType());
assert types.contains(targetField.getHolderType());
});
return true;
}
}