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);
     }
   }