Update CF to CF desugaring to have a prepare step for adding methods

In the prepare step each desugaring can synthesize methods on
program classes so that these methods are present when the actual
desugaring take place.

This does not affect true synthetics, only synthetic methods which
must be synthesized on program classes.

Also the D8 addition of bridges for access from methods on classpath
is not affected.

Bug: 192310793
Change-Id: If645f0e3446fb5fb757ab7a7437c2497ceb2f6b9
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
index 8f83dca..136d452 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/ClassConverter.java
@@ -56,6 +56,7 @@
     D8CfClassDesugaringEventConsumer classDesugaringEventConsumer =
         CfClassDesugaringEventConsumer.createForD8(methodProcessor);
     converter.desugarClassesForD8(classes, classDesugaringEventConsumer, executorService);
+    converter.prepareDesugaringForD8(executorService);
 
     while (!classes.isEmpty()) {
       Set<DexType> seenNestHosts = Sets.newIdentityHashSet();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index c1d343c..7338143 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -53,6 +53,7 @@
 import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
 import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter.Mode;
 import com.android.tools.r8.ir.desugar.DesugaredLibraryRetargeter;
+import com.android.tools.r8.ir.desugar.ProgramAdditions;
 import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter;
 import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter.Flavor;
 import com.android.tools.r8.ir.desugar.lambda.LambdaDeserializationMethodRemover;
@@ -482,13 +483,27 @@
         classes, clazz -> desugarClassForD8(clazz, desugaringEventConsumer), executorService);
   }
 
-  public void desugarClassForD8(
+  private void desugarClassForD8(
       DexProgramClass clazz, D8CfClassDesugaringEventConsumer desugaringEventConsumer) {
     if (classDesugaring.needsDesugaring(clazz)) {
       classDesugaring.desugar(clazz, desugaringEventConsumer);
     }
   }
 
+  public void prepareDesugaringForD8(ExecutorService executorService) throws ExecutionException {
+    // Prepare desugaring by collecting all the synthetic methods required on program classes.
+    ProgramAdditions programAdditions = new ProgramAdditions();
+    ThreadUtils.processItems(
+        appView.appInfo().classes(),
+        clazz -> {
+          clazz.forEachProgramMethodMatching(
+              method -> method.hasCode() && method.getCode().isCfCode(),
+              method -> instructionDesugaring.prepare(method, programAdditions));
+        },
+        executorService);
+    programAdditions.apply(executorService);
+  }
+
   void convertMethods(
       DexProgramClass clazz,
       D8CfInstructionDesugaringEventConsumer desugaringEventConsumer,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java
index 11c18d0..bb7cc79 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java
@@ -13,11 +13,23 @@
 /** Interface for desugaring a single class-file instruction. */
 public interface CfInstructionDesugaring {
 
+  // TODO(193004879): Merge the scan and prepare methods.
   default void scan(ProgramMethod method, CfInstructionDesugaringEventConsumer eventConsumer) {
     // Default scan is to do nothing.
   }
 
   /**
+   * Prepare step which is called on all classes scheduled for desugaring before the actual
+   * instruction level desugaring is preformed. This allows the desugaring to prepare and provide
+   * additional methods for program classes which will be needed for desugaring. During desugaring
+   * synthetic items can be added and the instruction stream can be altered, but program methods
+   * cannot be added.
+   */
+  default void prepare(ProgramMethod method, ProgramAdditions programAdditions) {
+    // Default prepare is to do nothing.
+  }
+
+  /**
    * Given an instruction, returns the list of instructions that the instruction should be desugared
    * to. If no desugaring is needed, {@code null} should be returned (for efficiency).
    */
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java
index 3fb9329..61d37b8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java
@@ -35,6 +35,8 @@
     return EmptyCfInstructionDesugaringCollection.getInstance();
   }
 
+  public abstract void prepare(ProgramMethod method, ProgramAdditions programAdditions);
+
   public abstract void scan(
       ProgramMethod method, CfInstructionDesugaringEventConsumer eventConsumer);
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
index a0c4c64..605013c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
@@ -150,17 +150,17 @@
 
     @Override
     public void acceptNestFieldGetBridge(ProgramField target, ProgramMethod bridge) {
-      methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
+      assert false;
     }
 
     @Override
     public void acceptNestFieldPutBridge(ProgramField target, ProgramMethod bridge) {
-      methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
+      assert false;
     }
 
     @Override
     public void acceptNestMethodBridge(ProgramMethod target, ProgramMethod bridge) {
-      methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
+      assert false;
     }
 
     @Override
@@ -281,20 +281,17 @@
 
     @Override
     public void acceptNestFieldGetBridge(ProgramField target, ProgramMethod bridge) {
-      // Intentionally empty. These bridges will be hit by the tracing in R8 as if they were present
-      // in the input code, and thus nothing needs to be done.
+      assert false;
     }
 
     @Override
     public void acceptNestFieldPutBridge(ProgramField target, ProgramMethod bridge) {
-      // Intentionally empty. These bridges will be hit by the tracing in R8 as if they were present
-      // in the input code, and thus nothing needs to be done.
+      assert false;
     }
 
     @Override
     public void acceptNestMethodBridge(ProgramMethod target, ProgramMethod bridge) {
-      // Intentionally empty. These bridges will be hit by the tracing in R8 as if they were present
-      // in the input code, and thus nothing needs to be done.
+      assert false;
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/EmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/EmptyCfInstructionDesugaringCollection.java
index c8b6147..5178f05 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/EmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/EmptyCfInstructionDesugaringCollection.java
@@ -24,6 +24,11 @@
   }
 
   @Override
+  public void prepare(ProgramMethod method, ProgramAdditions additionalProgramMethods) {
+    // Intentionally empty.
+  }
+
+  @Override
   public void scan(ProgramMethod method, CfInstructionDesugaringEventConsumer eventConsumer) {
     // Intentionally empty.
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index 26a2c5c..c56874b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -98,6 +98,12 @@
   }
 
   @Override
+  public void prepare(ProgramMethod method, ProgramAdditions programAdditions) {
+    ensureCfCode(method);
+    desugarings.forEach(d -> d.prepare(method, programAdditions));
+  }
+
+  @Override
   public void scan(ProgramMethod method, CfInstructionDesugaringEventConsumer eventConsumer) {
     ensureCfCode(method);
     desugarings.forEach(d -> d.scan(method, eventConsumer));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ProgramAdditions.java b/src/main/java/com/android/tools/r8/ir/desugar/ProgramAdditions.java
new file mode 100644
index 0000000..cf57453
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ProgramAdditions.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2021, 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.ir.desugar;
+
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMember;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.utils.ThreadUtils;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+
+public class ProgramAdditions implements BiConsumer<DexMember<?, ?>, Supplier<ProgramMethod>> {
+  private final Set<DexReference> added = Sets.newConcurrentHashSet();
+  private final Map<DexProgramClass, List<DexEncodedMethod>> additions = new ConcurrentHashMap<>();
+
+  @Override
+  public synchronized void accept(
+      DexMember<?, ?> reference, Supplier<ProgramMethod> programMethodSupplier) {
+    if (added.add(reference)) {
+      ProgramMethod method = programMethodSupplier.get();
+      List<DexEncodedMethod> methods =
+          additions.computeIfAbsent(method.getHolder(), k -> new ArrayList<>());
+      synchronized (methods) {
+        assert !methods.contains(method.getDefinition());
+        assert method.getHolder().lookupProgramMethod(method.getReference()) == null;
+        methods.add(method.getDefinition());
+      }
+    }
+  }
+
+  public void apply(ExecutorService executorService) throws ExecutionException {
+    ThreadUtils.processMap(
+        additions,
+        (clazz, methods) -> {
+          methods.sort(Comparator.comparing(DexEncodedMethod::getReference));
+          clazz.getMethodCollection().addDirectMethods(methods);
+        },
+        executorService);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index b052672..87adb53 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.graph.DexClassAndMember;
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMember;
 import com.android.tools.r8.graph.DexMethod;
@@ -33,6 +34,7 @@
 import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
 import com.android.tools.r8.ir.desugar.FreshLocalProvider;
 import com.android.tools.r8.ir.desugar.LocalStackAllocator;
+import com.android.tools.r8.ir.desugar.ProgramAdditions;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.google.common.collect.ImmutableList;
@@ -98,6 +100,121 @@
     }
   }
 
+  private static class BridgeAndTarget<T extends DexClassAndMember<?, ?>> {
+    private final DexMethod bridge;
+    private final T target;
+
+    public BridgeAndTarget(DexMethod bridge, T target) {
+      this.bridge = bridge;
+      this.target = target;
+      assert bridge.holder == target.getHolderType();
+    }
+
+    public DexMethod getBridge() {
+      return bridge;
+    }
+
+    public T getTarget() {
+      return target;
+    }
+
+    public boolean shouldAddBridge() {
+      return target.isProgramMember() && target.getHolder().lookupDirectMethod(bridge) == null;
+    }
+  }
+
+  @Override
+  public void prepare(ProgramMethod method, ProgramAdditions programAdditions) {
+    method
+        .getDefinition()
+        .getCode()
+        .asCfCode()
+        .getInstructions()
+        .forEach(
+            instruction -> {
+              if (instruction.isFieldInstruction()) {
+                DexField field = instruction.asFieldInstruction().getField();
+                if (needsDesugaring(field, method)) {
+                  prepareDesugarFieldInstruction(
+                      field,
+                      instruction.asFieldInstruction().isFieldGet(),
+                      method,
+                      programAdditions);
+                }
+              } else if (instruction.isInvoke()) {
+                DexMethod invokedMethod = instruction.asInvoke().getMethod();
+                if (needsDesugaring(invokedMethod, method)) {
+                  prepareDesugarMethodInstruction(invokedMethod, method, programAdditions);
+                }
+              }
+            });
+  }
+
+  private void prepareDesugarFieldInstruction(
+      DexField field, boolean isGet, ProgramMethod context, ProgramAdditions programAdditions) {
+    BridgeAndTarget<DexClassAndField> bridgeAndTarget =
+        bridgeAndTargetForDesugaring(field, isGet, context);
+    if (bridgeAndTarget == null || !bridgeAndTarget.shouldAddBridge()) {
+      return;
+    }
+
+    programAdditions.accept(
+        bridgeAndTarget.getBridge(),
+        () ->
+            AccessBridgeFactory.createFieldAccessorBridge(
+                bridgeAndTarget.getBridge(), bridgeAndTarget.getTarget().asProgramField(), isGet));
+  }
+
+  private void prepareDesugarMethodInstruction(
+      DexMethod method, ProgramMethod context, ProgramAdditions programAdditions) {
+    BridgeAndTarget<DexClassAndMethod> bridgeAndTarget =
+        bridgeAndTargetForDesugaring(method, context);
+    if (bridgeAndTarget == null || !bridgeAndTarget.shouldAddBridge()) {
+      return;
+    }
+    programAdditions.accept(
+        bridgeAndTarget.getBridge(),
+        () ->
+            bridgeAndTarget.getTarget().getDefinition().isInstanceInitializer()
+                ? AccessBridgeFactory.createInitializerAccessorBridge(
+                    bridgeAndTarget.getBridge(),
+                    bridgeAndTarget.getTarget().asProgramMethod(),
+                    dexItemFactory)
+                : AccessBridgeFactory.createMethodAccessorBridge(
+                    bridgeAndTarget.getBridge(),
+                    bridgeAndTarget.getTarget().asProgramMethod(),
+                    dexItemFactory));
+  }
+
+  private BridgeAndTarget<DexClassAndMethod> bridgeAndTargetForDesugaring(
+      DexMethod method, ProgramMethod context) {
+    if (!method.getHolderType().isClassType()) {
+      return null;
+    }
+    // Since we only need to desugar accesses to private methods, and all accesses to private
+    // methods must be accessing the private method directly on its holder, we can lookup the
+    // method on the holder instead of resolving the method.
+    DexClass holder = appView.definitionForHolder(method, context);
+    DexClassAndMethod target = method.lookupMemberOnClass(holder);
+    if (target == null || !needsDesugaring(target, context)) {
+      return null;
+    }
+    return new BridgeAndTarget<>(getMethodBridgeReference(target), target);
+  }
+
+  private BridgeAndTarget<DexClassAndField> bridgeAndTargetForDesugaring(
+      DexField field, boolean isGet, ProgramMethod context) {
+    // Since we only need to desugar accesses to private fields, and all accesses to private
+    // fields must be accessing the private field directly on its holder, we can lookup the
+    // field on the holder instead of resolving the field.
+    DexClass holder = appView.definitionForHolder(field, context);
+    DexClassAndField target = field.lookupMemberOnClass(holder);
+    if (target == null || !needsDesugaring(target, context)) {
+      return null;
+    }
+    return new BridgeAndTarget<>(getFieldAccessBridgeReference(target, isGet), target);
+  }
+
   public boolean needsDesugaring(ProgramMethod method) {
     if (!method.getHolder().isInANest() || !method.getDefinition().hasCode()) {
       return false;
@@ -166,18 +283,21 @@
       CfFieldInstruction instruction,
       ProgramMethod context,
       NestBasedAccessDesugaringEventConsumer eventConsumer) {
-    // Since we only need to desugar accesses to private fields, and all accesses to private
-    // fields must be accessing the private field directly on its holder, we can lookup the
-    // field on the holder instead of resolving the field.
-    DexClass holder = appView.definitionForHolder(instruction.getField(), context);
-    DexClassAndField field = instruction.getField().lookupMemberOnClass(holder);
-    if (field == null || !needsDesugaring(field, context)) {
+
+    BridgeAndTarget<DexClassAndField> bridgeAndTarget =
+        bridgeAndTargetForDesugaring(instruction.getField(), instruction.isFieldGet(), context);
+    if (bridgeAndTarget == null) {
       return null;
     }
-
-    DexMethod bridge = ensureFieldAccessBridge(field, instruction.isFieldGet(), eventConsumer);
+    // All bridges for program fields must have been added through the prepare step.
+    assert !bridgeAndTarget.getTarget().isProgramField()
+        || bridgeAndTarget.getTarget().getHolder().lookupDirectMethod(bridgeAndTarget.getBridge())
+            != null;
     return ImmutableList.of(
-        new CfInvoke(Opcodes.INVOKESTATIC, bridge, field.getHolder().isInterface()));
+        new CfInvoke(
+            Opcodes.INVOKESTATIC,
+            bridgeAndTarget.getBridge(),
+            bridgeAndTarget.getTarget().getHolder().isInterface()));
   }
 
   private List<CfInstruction> desugarInvokeInstruction(
@@ -186,29 +306,27 @@
       ProgramMethod context,
       NestBasedAccessDesugaringEventConsumer eventConsumer) {
     DexMethod invokedMethod = invoke.getMethod();
-    if (!invokedMethod.getHolderType().isClassType()) {
+
+    BridgeAndTarget<DexClassAndMethod> bridgeAndTarget =
+        bridgeAndTargetForDesugaring(invokedMethod, context);
+    if (bridgeAndTarget == null) {
       return null;
     }
-
-    // Since we only need to desugar accesses to private methods, and all accesses to private
-    // methods must be accessing the private method directly on its holder, we can lookup the
-    // method on the holder instead of resolving the method.
-    DexClass holder = appView.definitionForHolder(invokedMethod, context);
-    DexClassAndMethod target = invokedMethod.lookupMemberOnClass(holder);
-    if (target == null || !needsDesugaring(target, context)) {
-      return null;
-    }
-
-    DexMethod bridge = ensureMethodBridge(target, eventConsumer);
-    if (target.getDefinition().isInstanceInitializer()) {
+    // All bridges for program methods must have been added through the prepare step.
+    assert !bridgeAndTarget.getTarget().isProgramMethod()
+        || bridgeAndTarget.getTarget().getHolder().lookupDirectMethod(bridgeAndTarget.getBridge())
+            != null;
+    if (bridgeAndTarget.getTarget().getDefinition().isInstanceInitializer()) {
       assert !invoke.isInterface();
       // Ensure room on the stack for the extra null argument.
       localStackAllocator.allocateLocalStack(1);
       return ImmutableList.of(
-          new CfConstNull(), new CfInvoke(Opcodes.INVOKESPECIAL, bridge, false));
+          new CfConstNull(),
+          new CfInvoke(Opcodes.INVOKESPECIAL, bridgeAndTarget.getBridge(), false));
     }
 
-    return ImmutableList.of(new CfInvoke(Opcodes.INVOKESTATIC, bridge, invoke.isInterface()));
+    return ImmutableList.of(
+        new CfInvoke(Opcodes.INVOKESTATIC, bridgeAndTarget.getBridge(), invoke.isInterface()));
   }
 
   private RuntimeException reportIncompleteNest(LibraryMember<?, ?> member) {
@@ -279,6 +397,7 @@
     return dexItemFactory.createString(prefix + field.getName().toString());
   }
 
+  // This is only used for generating bridge methods for class path references.
   DexMethod ensureMethodBridge(
       DexClassAndMethod method, NestBasedAccessDesugaringEventConsumer eventConsumer) {
     if (method.isProgramMethod()) {
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 69f05f4..2a36d0d 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -102,6 +102,7 @@
 import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
 import com.android.tools.r8.ir.desugar.LambdaClass;
 import com.android.tools.r8.ir.desugar.LambdaDescriptor;
+import com.android.tools.r8.ir.desugar.ProgramAdditions;
 import com.android.tools.r8.kotlin.KotlinMetadataEnqueuerExtension;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult;
@@ -3177,6 +3178,13 @@
     if (pendingDesugaring.isEmpty()) {
       return;
     }
+
+    // Prepare desugaring by collecting all the synthetic methods required on program classes.
+    ProgramAdditions programAdditions = new ProgramAdditions();
+    ThreadUtils.processItems(
+        pendingDesugaring, method -> desugaring.prepare(method, programAdditions), executorService);
+    programAdditions.apply(executorService);
+
     R8CfInstructionDesugaringEventConsumer desugaringEventConsumer =
         CfInstructionDesugaringEventConsumer.createForR8(
             appView,
diff --git a/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java b/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java
index 797d8b6..e57fd90 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java
@@ -40,6 +40,10 @@
     methods.forEach(this::add);
   }
 
+  public boolean contains(DexMethod method) {
+    return backing.containsKey(method);
+  }
+
   public boolean contains(DexEncodedMethod method) {
     return backing.containsKey(method.getReference());
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/ConcurrencyTest.java b/src/test/java/com/android/tools/r8/desugar/ConcurrencyTest.java
index 639d6ae..848fc6d 100644
--- a/src/test/java/com/android/tools/r8/desugar/ConcurrencyTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/ConcurrencyTest.java
@@ -6,7 +6,6 @@
 import static com.android.tools.r8.TestRuntime.CfVm.JDK11;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.cf.CfVersion;
@@ -77,43 +76,22 @@
 
   @Test
   public void testD8() throws Exception {
-    try {
-      testForD8(parameters.getBackend())
-          .addProgramClasses(getClasses())
-          .addProgramClassFileData(getTransformedClasses())
-          .compile();
-    } catch (CompilationFailedException e) {
-      if (e.getCause() instanceof ArrayIndexOutOfBoundsException) {
-        // TODO(b/192310793): This should not happen.
-        return;
-      }
-      throw e;
-    }
+    testForD8(parameters.getBackend())
+        .addProgramClasses(getClasses())
+        .addProgramClassFileData(getTransformedClasses())
+        .compile();
   }
 
   @Test
   public void testR8() throws Exception {
     assumeTrue(parameters.getBackend().isDex());
 
-    try {
-      testForR8(parameters.getBackend())
-          .addProgramClasses(getClasses())
-          .addProgramClassFileData(getTransformedClasses())
-          .setMinApi(parameters.getApiLevel())
-          .addKeepAllClassesRule()
-          .compile();
-    } catch (CompilationFailedException e) {
-      if (e.getCause() instanceof AssertionError
-          && e.getCause()
-              .getStackTrace()[0]
-              .getClassName()
-              .equals(
-                  "com.android.tools.r8.ir.desugar.NonEmptyCfInstructionDesugaringCollection")) {
-        // TODO(b/192446461): This should not happen.
-        return;
-      }
-      throw e;
-    }
+    testForR8(parameters.getBackend())
+        .addProgramClasses(getClasses())
+        .addProgramClassFileData(getTransformedClasses())
+        .setMinApi(parameters.getApiLevel())
+        .addKeepAllClassesRule()
+        .compile();
   }
 
   static class Host {
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
index 30dc93f..236cf7e 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
@@ -91,9 +91,9 @@
             parameters.isCfRuntime(),
             result ->
                 result.assertSuccessWithOutputLines(
-                    "int, int, Outer$Inner-IA, 3",
-                    "int, Outer$Inner-IA, 2",
                     "Outer$Inner-IA, 1",
+                    "int, Outer$Inner-IA, 2",
+                    "int, int, Outer$Inner-IA, 3",
                     "int, int, 2",
                     "int, 1",
                     "0"),