blob: 88a4755535191fc53b97329167a6f584418a3862 [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;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Lets assume we are merging a class A that looks like:
*
* <pre>
* class A {
* A() { ... }
* A(int) { ... }
* }
* </pre>
*
* If {@code A::<init>()} is merged with other constructors, then we need to prevent a conflict with
* {@code A::<init>(int)}. To do this we introduce a synthetic class so that the new signature for
* the merged constructor is {@code A::<init>(SyntheticClass, int)}, as this is guaranteed to be
* unique.
*
* <p>This class generates a synthetic class in the package of the first class to be merged.
*/
public class SyntheticArgumentClass {
private final List<DexType> syntheticClassTypes;
private SyntheticArgumentClass(List<DexType> syntheticClassTypes) {
this.syntheticClassTypes = syntheticClassTypes;
}
public List<DexType> getArgumentClasses() {
return syntheticClassTypes;
}
public static class Builder {
private final AppView<AppInfoWithLiveness> appView;
Builder(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
}
private DexProgramClass synthesizeClass(DexProgramClass context, SyntheticKind syntheticKind) {
return appView
.getSyntheticItems()
.createFixedClass(syntheticKind, context, appView, builder -> {});
}
public SyntheticArgumentClass build(Collection<MergeGroup> mergeGroups) {
DexProgramClass context = getDeterministicContext(mergeGroups);
List<DexType> syntheticArgumentTypes = new ArrayList<>();
syntheticArgumentTypes.add(
synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_1).getType());
syntheticArgumentTypes.add(
synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_2).getType());
syntheticArgumentTypes.add(
synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_3).getType());
return new SyntheticArgumentClass(syntheticArgumentTypes);
}
private static DexProgramClass getDeterministicContext(Collection<MergeGroup> mergeGroups) {
// Relies on the determinism of the merge groups.
MergeGroup mergeGroup = mergeGroups.iterator().next();
assert mergeGroup.hasTarget();
return mergeGroup.getTarget();
}
}
}