Fix race in horizontal merging leading to nondeterministic art profile

Bug: b/434861604
Change-Id: I56f5d8a4f95be92c56804c663cde7b56223ad702
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/UndoConstructorInlining.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/UndoConstructorInlining.java
index 70a2a9a..af621ab 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/UndoConstructorInlining.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/UndoConstructorInlining.java
@@ -63,7 +63,6 @@
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
-import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -247,9 +246,8 @@
                     info.getProgramClass(),
                     info.getInvokedMethod(),
                     ensureConstructorsOnClasses,
-                    newConstructor ->
-                        profileCollectionAdditions.addMethodIfContextIsInProfile(
-                            newConstructor, method));
+                    method,
+                    profileCollectionAdditions);
         if (newInvokedMethod.getArity() != info.getInvokedMethod().getArity()) {
           assert newInvokedMethod.getArity() > info.getInvokedMethod().getArity();
           return rewriteIR(method, code);
@@ -310,9 +308,8 @@
                       noSkipClass,
                       invokedMethod,
                       ensureConstructorsOnClasses,
-                      newConstructor ->
-                          profileCollectionAdditions.addMethodIfContextIsInProfile(
-                              newConstructor, method));
+                      method,
+                      profileCollectionAdditions);
           InvokeDirect.Builder invokeDirectBuilder =
               InvokeDirect.builder()
                   .setArguments(invoke.arguments())
@@ -484,19 +481,30 @@
         DexProgramClass clazz,
         DexMethod target,
         Map<DexType, DexProgramClass> ensureConstructorsOnClasses,
-        Consumer<ProgramMethod> creationConsumer) {
-      return constructorCache
-          .computeIfAbsent(clazz, ignoreKey(IdentityHashMap::new))
-          .computeIfAbsent(
-              target,
-              k -> createConstructor(clazz, target, ensureConstructorsOnClasses, creationConsumer));
+        ProgramMethod context,
+        ProfileCollectionAdditions profileCollectionAdditions) {
+      ProgramMethod constructor =
+          constructorCache
+              .computeIfAbsent(clazz, ignoreKey(IdentityHashMap::new))
+              .computeIfAbsent(
+                  target,
+                  k ->
+                      createConstructor(
+                          clazz,
+                          target,
+                          ensureConstructorsOnClasses,
+                          context,
+                          profileCollectionAdditions));
+      profileCollectionAdditions.addMethodIfContextIsInProfile(constructor, context);
+      return constructor;
     }
 
     private ProgramMethod createConstructor(
         DexProgramClass clazz,
         DexMethod target,
         Map<DexType, DexProgramClass> ensureConstructorsOnClasses,
-        Consumer<ProgramMethod> creationConsumer) {
+        ProgramMethod context,
+        ProfileCollectionAdditions profileCollectionAdditions) {
       // Create a fresh constructor on the given class that calls target. If there is a class in the
       // hierarchy inbetween `clazz` and `target.holder`, which is also subject to class merging,
       // then we must create a constructor that calls a constructor on that intermediate class,
@@ -510,7 +518,11 @@
         if (ensureConstructorsOnClasses.containsKey(currentType)) {
           target =
               getOrCreateConstructor(
-                      currentClass, target, ensureConstructorsOnClasses, creationConsumer)
+                      currentClass,
+                      target,
+                      ensureConstructorsOnClasses,
+                      context,
+                      profileCollectionAdditions)
                   .getReference();
           break;
         }
@@ -538,9 +550,7 @@
               .setApiLevelForDefinition(
                   appView.apiLevelCompute().computeInitialMinApiLevel(appView.options()))
               .build();
-      ProgramMethod programMethod = method.asProgramMethod(clazz);
-      creationConsumer.accept(programMethod);
-      return programMethod;
+      return method.asProgramMethod(clazz);
     }
 
     private LirCode<Integer> createConstructorCode(DexMethod methodReference, DexMethod target) {
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/UndoConstructorInliningProfileFlagsTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/UndoConstructorInliningProfileFlagsTest.java
index b74ec6c..68c15f2 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/UndoConstructorInliningProfileFlagsTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/UndoConstructorInliningProfileFlagsTest.java
@@ -10,7 +10,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.profile.art.ArtProfileMethodRuleInfoImpl;
 import com.android.tools.r8.profile.art.model.ExternalArtProfile;
 import com.android.tools.r8.references.Reference;
@@ -68,14 +67,11 @@
                   .assertContainsMethodRule(initializerSubject)
                   .inspectMethodRule(
                       initializerSubject,
-                      methodRuleInspector -> {
-                        try {
-                          methodRuleInspector.assertIsHot().assertIsPostStartup().assertIsStartup();
-                          throw new Unreachable();
-                        } catch (AssertionError e) {
-                          // Expected.
-                        }
-                      });
+                      methodRuleInspector ->
+                          methodRuleInspector
+                              .assertIsHot()
+                              .assertIsPostStartup()
+                              .assertIsStartup());
             });
   }