Account for non-rebound super method reference in class merger
Bug: 233586763
Change-Id: I878e520097f2d0f563fca02650abe51213db3aa0
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java
index 3a10c5d..2f1a3c6 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteVirtuallyMergedMethodCode.java
@@ -23,6 +23,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.horizontalclassmerging.VirtualMethodMerger.SuperMethodReference;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.IterableUtils;
@@ -45,13 +46,13 @@
private final DexField classIdField;
private final Int2ReferenceSortedMap<DexMethod> mappedMethods;
private final DexMethod originalMethod;
- private final DexMethod superMethod;
+ private final SuperMethodReference superMethod;
public IncompleteVirtuallyMergedMethodCode(
DexField classIdField,
Int2ReferenceSortedMap<DexMethod> mappedMethods,
DexMethod originalMethod,
- DexMethod superMethod) {
+ SuperMethodReference superMethod) {
this.mappedMethods = mappedMethods;
this.classIdField = classIdField;
this.superMethod = superMethod;
@@ -139,7 +140,12 @@
fallthroughTarget =
lens.getNextMethodSignature(mappedMethods.get(mappedMethods.lastIntKey()));
} else {
- fallthroughTarget = lens.lookupInvokeSuper(superMethod, method).getReference();
+ DexMethod reboundFallthroughTarget =
+ lens.lookupInvokeSuper(superMethod.getReboundReference(), method).getReference();
+ fallthroughTarget =
+ reboundFallthroughTarget.withHolder(
+ lens.lookupClassType(superMethod.getReference().getHolderType()),
+ appView.dexItemFactory());
}
instructions.add(
new CfInvoke(Opcodes.INVOKESPECIAL, fallthroughTarget, method.getHolder().isInterface()));
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index 1103c8f..8d50100 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -27,17 +27,36 @@
public class VirtualMethodMerger {
+ static class SuperMethodReference {
+
+ DexMethod reference;
+ DexMethod reboundReference;
+
+ SuperMethodReference(DexMethod reference, DexMethod reboundReference) {
+ this.reference = reference;
+ this.reboundReference = reboundReference;
+ }
+
+ public DexMethod getReference() {
+ return reference;
+ }
+
+ public DexMethod getReboundReference() {
+ return reboundReference;
+ }
+ }
+
private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final DexItemFactory dexItemFactory;
private final MergeGroup group;
private final List<ProgramMethod> methods;
- private final DexMethod superMethod;
+ private final SuperMethodReference superMethod;
public VirtualMethodMerger(
AppView<? extends AppInfoWithClassHierarchy> appView,
MergeGroup group,
List<ProgramMethod> methods,
- DexMethod superMethod) {
+ SuperMethodReference superMethod) {
this.appView = appView;
this.dexItemFactory = appView.dexItemFactory();
this.group = group;
@@ -54,7 +73,7 @@
}
/** Get the super method handle if this method overrides a parent method. */
- private DexMethod superMethod(
+ private SuperMethodReference superMethod(
AppView<? extends AppInfoWithClassHierarchy> appView, MergeGroup group) {
DexMethod template = methods.iterator().next().getReference();
SingleResolutionResult resolutionResult =
@@ -66,20 +85,22 @@
// If there is no super method or the method is abstract it should not be called.
return null;
}
- if (resolutionResult.getResolvedHolder().isInterface()) {
- // Ensure that invoke virtual isn't called on an interface method.
- return resolutionResult
- .getResolvedMethod()
- .getReference()
- .withHolder(group.getSuperType(), appView.dexItemFactory());
- }
- return resolutionResult.getResolvedMethod().getReference();
+ DexMethod reboundReference = resolutionResult.getResolvedMethod().getReference();
+ DexMethod reference =
+ resolutionResult.getResolvedHolder().isInterface()
+ ? resolutionResult
+ .getResolvedMethod()
+ .getReference()
+ .withHolder(group.getSuperType(), appView.dexItemFactory())
+ : reboundReference;
+ return new SuperMethodReference(reference, reboundReference);
}
public VirtualMethodMerger build(
AppView<? extends AppInfoWithClassHierarchy> appView, MergeGroup group) {
// If not all the classes are in the merge group, find the fallback super method to call.
- DexMethod superMethod = methods.size() < group.size() ? superMethod(appView, group) : null;
+ SuperMethodReference superMethod =
+ methods.size() < group.size() ? superMethod(appView, group) : null;
return new VirtualMethodMerger(appView, group, methods, superMethod);
}
}