Identify assertion code with conditions for assertion handler callbacks

Before the code required that anything guarded by an assertions enabled
check would always throw. For assertions with conditions the true
branches does not throw but continue execution.

Now the only the code strictly dominated by the assertions enabled check
needs to be identified as always throwing from a single throw
instruction.

Bug: b/226370094
Change-Id: I27e4766f71291b9e812898ad6131cadaeb24d39f
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
index 72b8d6a..db7343c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionsRewriter.java
@@ -32,7 +32,6 @@
 import com.android.tools.r8.utils.LazyBox;
 import com.android.tools.r8.utils.ThrowingCharIterator;
 import com.android.tools.r8.utils.Timing;
-import com.android.tools.r8.utils.WorkList;
 import com.google.common.collect.ImmutableList;
 import java.io.UTFDataFormatException;
 import java.util.IdentityHashMap;
@@ -382,9 +381,9 @@
                           theIf.lhs().getDefinition().asStaticGet());
                   BasicBlock assertionBlockEntry =
                       theIf.targetFromBoolean(conditionForAssertionBlock);
-                  List<BasicBlock> blocks =
-                      dominatorTree.computeIfAbsent().dominatedBlocks(assertionBlockEntry);
-                  Throw throwInstruction = isAlwaysThrowingEntry(assertionBlockEntry, blocks);
+                  Throw throwInstruction =
+                      dominatedBlocksHasSingleThrow(
+                          assertionBlockEntry, dominatorTree.computeIfAbsent());
                   if (throwInstruction != null) {
                     assertionEntryIfs.put(theIf, conditionForAssertionBlock);
                     throwSuccessorAfterHandler.put(
@@ -394,7 +393,6 @@
               });
     }
     assert assertionEntryIfs.size() == throwSuccessorAfterHandler.size();
-
     // For javac generated code it is assumed that the code in <clinit> will tell if the code
     // in other methods of the class can have assertion checks.
     boolean isInitializerEnablingJavaVmAssertions =
@@ -541,15 +539,10 @@
         : null;
   }
 
-  private Throw isAlwaysThrowingEntry(BasicBlock block, List<BasicBlock> blocks) {
-    WorkList<BasicBlock> workList = WorkList.newIdentityWorkList(block);
+  private Throw dominatedBlocksHasSingleThrow(BasicBlock block, DominatorTree dominatorTree) {
     Throw theThrow = null;
-    while (workList.hasNext()) {
-      BasicBlock current = workList.next();
-      workList.addIfNotSeen(current.getNormalSuccessors());
-      if (!blocks.containsAll(current.getNormalSuccessors())) {
-        return null;
-      }
+    List<BasicBlock> blocks = dominatorTree.dominatedBlocks(block);
+    for (BasicBlock current : blocks) {
       if (current.exit().isReturn()) {
         return null;
       }
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationAssertionHandlerWithConditionsTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationAssertionHandlerWithConditionsTest.java
new file mode 100644
index 0000000..af2c8db
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationAssertionHandlerWithConditionsTest.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2022, 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.rewrite.assertions;
+
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.rewrite.assertions.assertionhandler.AssertionHandlers;
+import com.android.tools.r8.rewrite.assertions.assertionhandler.AssertionsWithConditions;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class AssertionConfigurationAssertionHandlerWithConditionsTest
+    extends AssertionConfigurationAssertionHandlerTestBase {
+
+  private static final String EXPECTED_OUTPUT =
+      StringUtils.lines(
+          "assertionHandler: assertionWithSimpleCondition",
+          "assertionHandler: assertionWithCondition");
+
+  @Override
+  String getExpectedOutput() {
+    return EXPECTED_OUTPUT;
+  }
+
+  @Override
+  MethodReference getAssertionHandler() throws Exception {
+    return Reference.methodFromMethod(
+        AssertionHandlers.class.getMethod("assertionHandler", Throwable.class));
+  }
+
+  @Override
+  List<Class<?>> getTestClasses() {
+    return ImmutableList.of(AssertionsWithConditions.class);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/assertionhandler/AssertionsWithConditions.java b/src/test/java/com/android/tools/r8/rewrite/assertions/assertionhandler/AssertionsWithConditions.java
new file mode 100644
index 0000000..17d4d54
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/assertionhandler/AssertionsWithConditions.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2022, 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.rewrite.assertions.assertionhandler;
+
+import com.android.tools.r8.Keep;
+
+public class AssertionsWithConditions {
+
+  @Keep
+  public static void assertionWithSimpleCondition(int x) {
+    assert x < 0;
+  }
+
+  private static boolean isZero(int x) {
+    return x == 0;
+  }
+
+  private static boolean isNegative(int x) {
+    return x < 0;
+  }
+
+  @Keep
+  public static void assertionWithCondition(int x, int y, int z) {
+    assert x == 0 && isZero(y) && isNegative(z);
+  }
+
+  public static void main(String[] args) {
+    assertionWithSimpleCondition(args.length);
+    assertionWithCondition(args.length, args.length, args.length);
+  }
+}