Split interface method rewriting into invoke-specific rewriting methods

Change-Id: I465d23d8d76512e9608abbfb940543da7dc3b892
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 18d0352..891beb3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -4,6 +4,13 @@
 
 package com.android.tools.r8.ir.desugar;
 
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_CUSTOM;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_DIRECT;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_INTERFACE;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_STATIC;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_SUPER;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_VIRTUAL;
+
 import com.android.tools.r8.DesugarGraphConsumer;
 import com.android.tools.r8.cf.CfVersion;
 import com.android.tools.r8.dex.Constants;
@@ -36,8 +43,10 @@
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InvokeCustom;
 import com.android.tools.r8.ir.code.InvokeDirect;
 import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
 import com.android.tools.r8.ir.code.InvokeStatic;
 import com.android.tools.r8.ir.code.InvokeSuper;
 import com.android.tools.r8.ir.conversion.IRConverter;
@@ -241,271 +250,295 @@
     }
 
     ListIterator<BasicBlock> blocks = code.listIterator();
-    AppInfo appInfo = appView.appInfo();
     while (blocks.hasNext()) {
       BasicBlock block = blocks.next();
       InstructionListIterator instructions = block.listIterator(code);
       while (instructions.hasNext()) {
         Instruction instruction = instructions.next();
-
-        if (instruction.isInvokeCustom()) {
-          // Check that static interface methods are not referenced
-          // from invoke-custom instructions via method handles.
-          DexCallSite callSite = instruction.asInvokeCustom().getCallSite();
-          reportStaticInterfaceMethodHandle(context, callSite.bootstrapMethod);
-          for (DexValue arg : callSite.bootstrapArgs) {
-            if (arg.isDexValueMethodHandle()) {
-              reportStaticInterfaceMethodHandle(context, arg.asDexValueMethodHandle().value);
-            }
-          }
-          continue;
+        switch (instruction.opcode()) {
+          case INVOKE_CUSTOM:
+            rewriteInvokeCustom(instruction.asInvokeCustom(), context);
+            break;
+          case INVOKE_DIRECT:
+            rewriteInvokeDirect(instruction.asInvokeDirect(), instructions, context);
+            break;
+          case INVOKE_STATIC:
+            rewriteInvokeStatic(instruction.asInvokeStatic(), instructions, context);
+            break;
+          case INVOKE_SUPER:
+            rewriteInvokeSuper(instruction.asInvokeSuper(), instructions, context);
+            break;
+          case INVOKE_INTERFACE:
+          case INVOKE_VIRTUAL:
+            rewriteInvokeInterfaceOrInvokeVirtual(
+                instruction.asInvokeMethodWithReceiver(), instructions);
+            break;
+          default:
+            // Intentionally empty.
+            break;
         }
+      }
+    }
+  }
 
-        if (instruction.isInvokeStatic()) {
-          InvokeStatic invokeStatic = instruction.asInvokeStatic();
-          DexMethod method = invokeStatic.getInvokedMethod();
-          if (appView.getSyntheticItems().isPendingSynthetic(method.holder)) {
-            // We did not create this code yet, but it will not require rewriting.
-            continue;
-          }
-          DexClass clazz = appInfo.definitionFor(method.holder);
-          if (clazz == null) {
-            // NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
-            // exception but we can not report it as error since it can also be the intended
-            // behavior.
-            if (invokeStatic.getInterfaceBit()) {
-              leavingStaticInvokeToInterface(context);
-            }
-            warnMissingType(context, method.holder);
-          } else if (clazz.isInterface()) {
-            if (isNonDesugaredLibraryClass(clazz)) {
-              // NOTE: we intentionally don't desugar static calls into static interface
-              // methods coming from android.jar since it is only possible in case v24+
-              // version of android.jar is provided.
-              //
-              // We assume such calls are properly guarded by if-checks like
-              //    'if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XYZ) { ... }'
-              //
-              // WARNING: This may result in incorrect code on older platforms!
-              // Retarget call to an appropriate method of companion class.
+  private void rewriteInvokeCustom(InvokeCustom invoke, ProgramMethod context) {
+    // Check that static interface methods are not referenced from invoke-custom instructions via
+    // method handles.
+    DexCallSite callSite = invoke.getCallSite();
+    reportStaticInterfaceMethodHandle(context, callSite.bootstrapMethod);
+    for (DexValue arg : callSite.bootstrapArgs) {
+      if (arg.isDexValueMethodHandle()) {
+        reportStaticInterfaceMethodHandle(context, arg.asDexValueMethodHandle().value);
+      }
+    }
+  }
 
-              if (!options.canLeaveStaticInterfaceMethodInvokes()) {
-                // On pre-L devices static calls to interface methods result in verifier
-                // rejecting the whole class. We have to create special dispatch classes,
-                // so the user class is not rejected because it make this call directly.
-                // TODO(b/166247515): If this an incorrect invoke-static without the interface bit
-                //  we end up "fixing" the code and remove and ICCE error.
-                ProgramMethod newProgramMethod =
-                    appView
-                        .getSyntheticItems()
-                        .createMethod(
-                            context.getHolder(),
-                            factory,
-                            syntheticMethodBuilder ->
-                                syntheticMethodBuilder
-                                    .setProto(method.proto)
-                                    .setAccessFlags(
-                                        MethodAccessFlags.fromSharedAccessFlags(
-                                            Constants.ACC_PUBLIC
-                                                | Constants.ACC_STATIC
-                                                | Constants.ACC_SYNTHETIC,
-                                            false))
-                                    .setCode(
-                                        m ->
-                                            ForwardMethodBuilder.builder(factory)
-                                                .setStaticTarget(method, true)
-                                                .setStaticSource(m)
-                                                .build()));
-                instructions.replaceCurrentInstruction(
-                    new InvokeStatic(
-                        newProgramMethod.getReference(),
-                        invokeStatic.outValue(),
-                        invokeStatic.arguments()));
-                synchronized (synthesizedMethods) {
-                  // The synthetic dispatch class has static interface method invokes, so set
-                  // the class file version accordingly.
-                  newProgramMethod.getDefinition().upgradeClassFileVersion(CfVersion.V1_8);
-                  synthesizedMethods.add(newProgramMethod);
-                }
-              } else {
-                // When leaving static interface method invokes upgrade the class file version.
-                context.getDefinition().upgradeClassFileVersion(CfVersion.V1_8);
-              }
-            } else {
+  private void rewriteInvokeDirect(
+      InvokeDirect invoke, InstructionListIterator instructions, ProgramMethod context) {
+    DexMethod method = invoke.getInvokedMethod();
+    if (factory.isConstructor(method)) {
+      return;
+    }
+
+    DexClass clazz = appView.definitionForHolder(method, context);
+    if (clazz == null) {
+      // Report missing class since we don't know if it is an interface.
+      warnMissingType(context, method.holder);
+      return;
+    }
+
+    if (!clazz.isInterface()) {
+      return;
+    }
+
+    if (clazz.isLibraryClass()) {
+      throw new CompilationError(
+          "Unexpected call to a private method "
+              + "defined in library class "
+              + clazz.toSourceString(),
+          getMethodOrigin(context.getReference()));
+    }
+
+    DexEncodedMethod directTarget = clazz.lookupMethod(method);
+    if (directTarget != null) {
+      // This can be a private instance method call. Note that the referenced
+      // method is expected to be in the current class since it is private, but desugaring
+      // may move some methods or their code into other classes.
+      instructions.replaceCurrentInstruction(
+          new InvokeStatic(
+              directTarget.isPrivateMethod()
+                  ? privateAsMethodOfCompanionClass(method)
+                  : defaultAsMethodOfCompanionClass(method),
+              invoke.outValue(),
+              invoke.arguments()));
+    } else {
+      // The method can be a default method in the interface hierarchy.
+      DexClassAndMethod virtualTarget =
+          appView.appInfoForDesugaring().lookupMaximallySpecificMethod(clazz, method);
+      if (virtualTarget != null) {
+        // This is a invoke-direct call to a virtual method.
+        instructions.replaceCurrentInstruction(
+            new InvokeStatic(
+                defaultAsMethodOfCompanionClass(virtualTarget.getDefinition().method),
+                invoke.outValue(),
+                invoke.arguments()));
+      } else {
+        // The below assert is here because a well-type program should have a target, but we
+        // cannot throw a compilation error, since we have no knowledge about the input.
+        assert false;
+      }
+    }
+  }
+
+  private void rewriteInvokeStatic(
+      InvokeStatic invoke, InstructionListIterator instructions, ProgramMethod context) {
+    DexMethod invokedMethod = invoke.getInvokedMethod();
+    if (appView.getSyntheticItems().isPendingSynthetic(invokedMethod.holder)) {
+      // We did not create this code yet, but it will not require rewriting.
+      return;
+    }
+
+    DexClass clazz = appView.definitionFor(invokedMethod.holder, context);
+    if (clazz == null) {
+      // NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
+      // exception but we can not report it as error since it can also be the intended
+      // behavior.
+      if (invoke.getInterfaceBit()) {
+        leavingStaticInvokeToInterface(context);
+      }
+      warnMissingType(context, invokedMethod.holder);
+      return;
+    }
+
+    if (!clazz.isInterface()) {
+      if (invoke.getInterfaceBit()) {
+        leavingStaticInvokeToInterface(context);
+      }
+      return;
+    }
+
+    if (isNonDesugaredLibraryClass(clazz)) {
+      // NOTE: we intentionally don't desugar static calls into static interface
+      // methods coming from android.jar since it is only possible in case v24+
+      // version of android.jar is provided.
+      //
+      // We assume such calls are properly guarded by if-checks like
+      //    'if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XYZ) { ... }'
+      //
+      // WARNING: This may result in incorrect code on older platforms!
+      // Retarget call to an appropriate method of companion class.
+
+      if (!options.canLeaveStaticInterfaceMethodInvokes()) {
+        // On pre-L devices static calls to interface methods result in verifier
+        // rejecting the whole class. We have to create special dispatch classes,
+        // so the user class is not rejected because it make this call directly.
+        // TODO(b/166247515): If this an incorrect invoke-static without the interface bit
+        //  we end up "fixing" the code and remove and ICCE error.
+        ProgramMethod newProgramMethod =
+            appView
+                .getSyntheticItems()
+                .createMethod(
+                    context.getHolder(),
+                    factory,
+                    syntheticMethodBuilder ->
+                        syntheticMethodBuilder
+                            .setProto(invokedMethod.proto)
+                            .setAccessFlags(
+                                MethodAccessFlags.fromSharedAccessFlags(
+                                    Constants.ACC_PUBLIC
+                                        | Constants.ACC_STATIC
+                                        | Constants.ACC_SYNTHETIC,
+                                    false))
+                            .setCode(
+                                m ->
+                                    ForwardMethodBuilder.builder(factory)
+                                        .setStaticTarget(invokedMethod, true)
+                                        .setStaticSource(m)
+                                        .build()));
+        instructions.replaceCurrentInstruction(
+            new InvokeStatic(
+                newProgramMethod.getReference(), invoke.outValue(), invoke.arguments()));
+        synchronized (synthesizedMethods) {
+          // The synthetic dispatch class has static interface method invokes, so set
+          // the class file version accordingly.
+          newProgramMethod.getDefinition().upgradeClassFileVersion(CfVersion.V1_8);
+          synthesizedMethods.add(newProgramMethod);
+        }
+      } else {
+        // When leaving static interface method invokes upgrade the class file version.
+        context.getDefinition().upgradeClassFileVersion(CfVersion.V1_8);
+      }
+    } else {
+      instructions.replaceCurrentInstruction(
+          new InvokeStatic(
+              staticAsMethodOfCompanionClass(invokedMethod),
+              invoke.outValue(),
+              invoke.arguments()));
+    }
+  }
+
+  private void rewriteInvokeSuper(
+      InvokeSuper invoke, InstructionListIterator instructions, ProgramMethod context) {
+    DexMethod invokedMethod = invoke.getInvokedMethod();
+    DexClass clazz = appView.definitionFor(invokedMethod.holder, context);
+    if (clazz == null) {
+      // NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
+      // exception but we can not report it as error since it can also be the intended
+      // behavior.
+      warnMissingType(context, invokedMethod.holder);
+      return;
+    }
+
+    if (clazz.isInterface() && !clazz.isLibraryClass()) {
+      // NOTE: we intentionally don't desugar super calls into interface methods
+      // coming from android.jar since it is only possible in case v24+ version
+      // of android.jar is provided.
+      //
+      // We assume such calls are properly guarded by if-checks like
+      //    'if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XYZ) { ... }'
+      //
+      // WARNING: This may result in incorrect code on older platforms!
+      // Retarget call to an appropriate method of companion class.
+      DexMethod amendedMethod = amendDefaultMethod(context.getHolder(), invokedMethod);
+      instructions.replaceCurrentInstruction(
+          new InvokeStatic(
+              defaultAsMethodOfCompanionClass(amendedMethod),
+              invoke.outValue(),
+              invoke.arguments()));
+    } else {
+      DexType emulatedItf = maximallySpecificEmulatedInterfaceOrNull(invokedMethod);
+      if (emulatedItf == null) {
+        if (clazz.isInterface() && appView.rewritePrefix.hasRewrittenType(clazz.type, appView)) {
+          DexClassAndMethod target =
+              appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, context);
+          if (target != null && target.getDefinition().isDefaultMethod()) {
+            DexClass holder = target.getHolder();
+            if (holder.isLibraryClass() && holder.isInterface()) {
               instructions.replaceCurrentInstruction(
-                  new InvokeStatic(staticAsMethodOfCompanionClass(method),
-                      invokeStatic.outValue(), invokeStatic.arguments()));
-            }
-          } else {
-            assert !clazz.isInterface();
-            if (invokeStatic.getInterfaceBit()) {
-              leavingStaticInvokeToInterface(context);
+                  new InvokeStatic(
+                      defaultAsMethodOfCompanionClass(target.getReference(), factory),
+                      invoke.outValue(),
+                      invoke.arguments()));
             }
           }
-          continue;
         }
-
-        if (instruction.isInvokeSuper()) {
-          InvokeSuper invokeSuper = instruction.asInvokeSuper();
-          DexMethod invokedMethod = invokeSuper.getInvokedMethod();
-          DexClass clazz = appInfo.definitionFor(invokedMethod.holder);
-          if (clazz == null) {
-            // NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
-            // exception but we can not report it as error since it can also be the intended
-            // behavior.
-            warnMissingType(context, invokedMethod.holder);
-          } else if (clazz.isInterface() && !clazz.isLibraryClass()) {
-            // NOTE: we intentionally don't desugar super calls into interface methods
-            // coming from android.jar since it is only possible in case v24+ version
-            // of android.jar is provided.
-            //
-            // We assume such calls are properly guarded by if-checks like
-            //    'if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XYZ) { ... }'
-            //
-            // WARNING: This may result in incorrect code on older platforms!
-            // Retarget call to an appropriate method of companion class.
-            DexMethod amendedMethod = amendDefaultMethod(context.getHolder(), invokedMethod);
+      } else {
+        // That invoke super may not resolve since the super method may not be present
+        // since it's in the emulated interface. We need to force resolution. If it resolves
+        // to a library method, then it needs to be rewritten.
+        // If it resolves to a program overrides, the invoke-super can remain.
+        DexClassAndMethod superTarget =
+            appView.appInfoForDesugaring().lookupSuperTarget(invoke.getInvokedMethod(), context);
+        if (superTarget != null && superTarget.isLibraryMethod()) {
+          // Rewriting is required because the super invoke resolves into a missing
+          // method (method is on desugared library). Find out if it needs to be
+          // retarget or if it just calls a companion class method and rewrite.
+          DexMethod retargetMethod =
+              options.desugaredLibraryConfiguration.retargetMethod(superTarget, appView);
+          if (retargetMethod == null) {
+            DexMethod originalCompanionMethod =
+                instanceAsMethodOfCompanionClass(
+                    superTarget.getReference(), DEFAULT_METHOD_PREFIX, factory);
+            DexMethod companionMethod =
+                factory.createMethod(
+                    getCompanionClassType(emulatedItf),
+                    factory.protoWithDifferentFirstParameter(
+                        originalCompanionMethod.proto, emulatedItf),
+                    originalCompanionMethod.name);
             instructions.replaceCurrentInstruction(
-                new InvokeStatic(defaultAsMethodOfCompanionClass(amendedMethod),
-                    invokeSuper.outValue(), invokeSuper.arguments()));
+                new InvokeStatic(companionMethod, invoke.outValue(), invoke.arguments()));
           } else {
-            DexType emulatedItf = maximallySpecificEmulatedInterfaceOrNull(invokedMethod);
-            if (emulatedItf == null) {
-              if (clazz.isInterface()
-                  && appView.rewritePrefix.hasRewrittenType(clazz.type, appView)) {
-                DexClassAndMethod target =
-                    appView.appInfoForDesugaring().lookupSuperTarget(invokedMethod, code.context());
-                if (target != null && target.getDefinition().isDefaultMethod()) {
-                  DexClass holder = target.getHolder();
-                  if (holder.isLibraryClass() && holder.isInterface()) {
-                    instructions.replaceCurrentInstruction(
-                        new InvokeStatic(
-                            defaultAsMethodOfCompanionClass(target.getReference(), factory),
-                            invokeSuper.outValue(),
-                            invokeSuper.arguments()));
-                  }
-                }
-              }
-            } else {
-              // That invoke super may not resolve since the super method may not be present
-              // since it's in the emulated interface. We need to force resolution. If it resolves
-              // to a library method, then it needs to be rewritten.
-              // If it resolves to a program overrides, the invoke-super can remain.
-              DexClassAndMethod superTarget =
-                  appView
-                      .appInfoForDesugaring()
-                      .lookupSuperTarget(invokeSuper.getInvokedMethod(), code.context());
-              if (superTarget != null && superTarget.isLibraryMethod()) {
-                // Rewriting is required because the super invoke resolves into a missing
-                // method (method is on desugared library). Find out if it needs to be
-                // retarget or if it just calls a companion class method and rewrite.
-                DexMethod retargetMethod =
-                    options.desugaredLibraryConfiguration.retargetMethod(superTarget, appView);
-                if (retargetMethod == null) {
-                  DexMethod originalCompanionMethod =
-                      instanceAsMethodOfCompanionClass(
-                          superTarget.getReference(), DEFAULT_METHOD_PREFIX, factory);
-                  DexMethod companionMethod =
-                      factory.createMethod(
-                          getCompanionClassType(emulatedItf),
-                          factory.protoWithDifferentFirstParameter(
-                              originalCompanionMethod.proto, emulatedItf),
-                          originalCompanionMethod.name);
-                  instructions.replaceCurrentInstruction(
-                      new InvokeStatic(
-                          companionMethod, invokeSuper.outValue(), invokeSuper.arguments()));
-                } else {
-                  instructions.replaceCurrentInstruction(
-                      new InvokeStatic(
-                          retargetMethod, invokeSuper.outValue(), invokeSuper.arguments()));
-                }
-              }
-            }
-          }
-          continue;
-        }
-
-        if (instruction.isInvokeDirect()) {
-          InvokeDirect invokeDirect = instruction.asInvokeDirect();
-          DexMethod method = invokeDirect.getInvokedMethod();
-          if (factory.isConstructor(method)) {
-            continue;
-          }
-
-          DexClass clazz = appInfo.definitionForHolder(method, context);
-          if (clazz == null) {
-            // Report missing class since we don't know if it is an interface.
-            warnMissingType(context, method.holder);
-          } else if (clazz.isInterface()) {
-            if (clazz.isLibraryClass()) {
-              throw new CompilationError(
-                  "Unexpected call to a private method "
-                      + "defined in library class "
-                      + clazz.toSourceString(),
-                  getMethodOrigin(context.getReference()));
-            }
-            DexEncodedMethod directTarget = clazz.lookupMethod(method);
-            if (directTarget != null) {
-              // This can be a private instance method call. Note that the referenced
-              // method is expected to be in the current class since it is private, but desugaring
-              // may move some methods or their code into other classes.
-              if (directTarget.isPrivateMethod()) {
-                instructions.replaceCurrentInstruction(
-                    new InvokeStatic(
-                        privateAsMethodOfCompanionClass(method),
-                        invokeDirect.outValue(),
-                        invokeDirect.arguments()));
-              } else {
-                instructions.replaceCurrentInstruction(
-                    new InvokeStatic(
-                        defaultAsMethodOfCompanionClass(method),
-                        invokeDirect.outValue(),
-                        invokeDirect.arguments()));
-              }
-            } else {
-              // The method can be a default method in the interface hierarchy.
-              DexClassAndMethod virtualTarget =
-                  appView.appInfoForDesugaring().lookupMaximallySpecificMethod(clazz, method);
-              if (virtualTarget != null) {
-                // This is a invoke-direct call to a virtual method.
-                instructions.replaceCurrentInstruction(
-                    new InvokeStatic(
-                        defaultAsMethodOfCompanionClass(virtualTarget.getDefinition().method),
-                        invokeDirect.outValue(),
-                        invokeDirect.arguments()));
-              } else {
-                // The below assert is here because a well-type program should have a target, but we
-                // cannot throw a compilation error, since we have no knowledge about the input.
-                assert false;
-              }
-            }
-          }
-        }
-
-        if (instruction.isInvokeVirtual() || instruction.isInvokeInterface()) {
-          InvokeMethod invokeMethod = instruction.asInvokeMethod();
-          DexMethod invokedMethod = invokeMethod.getInvokedMethod();
-          DexType emulatedItf = maximallySpecificEmulatedInterfaceOrNull(invokedMethod);
-          if (emulatedItf != null) {
-            // The call potentially ends up in a library class, in which case we need to rewrite,
-            // since the code may be in the desugared library.
-            SingleResolutionResult resolution =
-                appView
-                    .appInfoForDesugaring()
-                    .resolveMethod(invokedMethod, invokeMethod.getInterfaceBit())
-                    .asSingleResolution();
-            if (resolution != null
-                && (resolution.getResolvedHolder().isLibraryClass()
-                    || appView.options().isDesugaredLibraryCompilation())) {
-              rewriteCurrentInstructionToEmulatedInterfaceCall(
-                  emulatedItf, invokedMethod, invokeMethod, instructions);
-            }
+            instructions.replaceCurrentInstruction(
+                new InvokeStatic(retargetMethod, invoke.outValue(), invoke.arguments()));
           }
         }
       }
     }
   }
 
+  private void rewriteInvokeInterfaceOrInvokeVirtual(
+      InvokeMethodWithReceiver invoke, InstructionListIterator instructions) {
+    DexMethod invokedMethod = invoke.getInvokedMethod();
+    DexType emulatedItf = maximallySpecificEmulatedInterfaceOrNull(invokedMethod);
+    if (emulatedItf == null) {
+      return;
+    }
+
+    // The call potentially ends up in a library class, in which case we need to rewrite, since the
+    // code may be in the desugared library.
+    SingleResolutionResult resolution =
+        appView
+            .appInfoForDesugaring()
+            .resolveMethod(invokedMethod, invoke.getInterfaceBit())
+            .asSingleResolution();
+    if (resolution != null
+        && (resolution.getResolvedHolder().isLibraryClass()
+            || appView.options().isDesugaredLibraryCompilation())) {
+      rewriteCurrentInstructionToEmulatedInterfaceCall(
+          emulatedItf, invokedMethod, invoke, instructions);
+    }
+  }
+
   private DexType maximallySpecificEmulatedInterfaceOrNull(DexMethod invokedMethod) {
     // Here we try to avoid doing the expensive look-up on all invokes.
     if (!emulatedMethods.contains(invokedMethod.name)) {