Minor changes part of new horizontal class merger

Change-Id: I00fc6df753fcdda7b41df6fc8faf97388911ab3b
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
index b541bfc..d7108bd 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
@@ -92,19 +92,22 @@
     virtualInvokes.keySet().forEach(ConsumerUtils.acceptIfNotSeen(method, seen));
   }
 
-  public void forEachDirectInvoke(BiConsumer<DexMethod, ProgramMethodSet> consumer) {
+  public void forEachDirectInvoke(
+      BiConsumer<? super DexMethod, ? super ProgramMethodSet> consumer) {
     directInvokes.forEach(consumer);
   }
 
-  public void forEachInterfaceInvoke(BiConsumer<DexMethod, ProgramMethodSet> consumer) {
+  public void forEachInterfaceInvoke(
+      BiConsumer<? super DexMethod, ? super ProgramMethodSet> consumer) {
     interfaceInvokes.forEach(consumer);
   }
 
-  public void forEachStaticInvoke(BiConsumer<DexMethod, ProgramMethodSet> consumer) {
+  public void forEachStaticInvoke(
+      BiConsumer<? super DexMethod, ? super ProgramMethodSet> consumer) {
     staticInvokes.forEach(consumer);
   }
 
-  public void forEachSuperInvoke(BiConsumer<DexMethod, ProgramMethodSet> consumer) {
+  public void forEachSuperInvoke(BiConsumer<? super DexMethod, ? super ProgramMethodSet> consumer) {
     superInvokes.forEach(consumer);
   }
 
@@ -116,7 +119,8 @@
     superInvokes.getOrDefault(method, ProgramMethodSet.empty()).forEach(consumer);
   }
 
-  public void forEachVirtualInvoke(BiConsumer<DexMethod, ProgramMethodSet> consumer) {
+  public void forEachVirtualInvoke(
+      BiConsumer<? super DexMethod, ? super ProgramMethodSet> consumer) {
     virtualInvokes.forEach(consumer);
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java
index c75bc43..1a190ae 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import java.util.Collection;
 import java.util.Set;
 import java.util.function.BiConsumer;
 
@@ -16,6 +17,8 @@
 
   DexType getMergeTargetOrDefault(DexType type, DexType defaultValue);
 
+  Collection<DexType> getSourcesFor(DexType type);
+
   boolean isMergeSource(DexType type);
 
   default boolean isMergeSourceOrTarget(DexType type) {
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java
index 386a256..ccb9955 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import java.util.function.BiConsumer;
@@ -34,6 +35,11 @@
   }
 
   @Override
+  public Collection<DexType> getSourcesFor(DexType type) {
+    throw new Unreachable();
+  }
+
+  @Override
   public boolean isMergeSource(DexType type) {
     for (MergedClasses mergedClasses : collection) {
       if (mergedClasses.isMergeSource(type)) {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
index 197f2b8..559539a 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
@@ -65,6 +65,7 @@
     return mergedClasses.keySet();
   }
 
+  @Override
   public Set<DexType> getSourcesFor(DexType type) {
     return mergedClasses.getKeys(type);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index d5e82ff..d64ad03 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -645,7 +645,7 @@
             : "Expected reference to "
                 + classTypeLattice.getClassType().getTypeName()
                 + " to be rewritten at instruction "
-                + instruction.toString();
+                + instruction;
         assert !classTypeLattice
             .getInterfaces()
             .anyMatch(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 08143ae..2bd7ab1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -556,7 +556,6 @@
       }
     }
     // Finally check that the dex instructions for the generated code actually are the same.
-    InternalOptions options = allocator.options();
     if (conversionOptions.isGeneratingDex()
         && !DexBuilder.identicalInstructionsAfterBuildingDexCode(
             this, other, allocator, conversionOptions)) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 0a16889..d8d3bf8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -798,6 +798,7 @@
           int intValue = (int) constNumber.getRawValue();
           boolean useBinaryRepresentation =
               (constNumberValue.phiUsers == null || !constNumberValue.hasPhiUsers())
+                  && constNumberValue.uniqueUsers != null
                   && constNumberValue.uniqueUsers().stream()
                       .allMatch(
                           user ->
diff --git a/src/main/java/com/android/tools/r8/optimize/BridgeHoistingToSharedSyntheticSuperClass.java b/src/main/java/com/android/tools/r8/optimize/BridgeHoistingToSharedSyntheticSuperClass.java
index f06f226..b4036b7 100644
--- a/src/main/java/com/android/tools/r8/optimize/BridgeHoistingToSharedSyntheticSuperClass.java
+++ b/src/main/java/com/android/tools/r8/optimize/BridgeHoistingToSharedSyntheticSuperClass.java
@@ -59,7 +59,7 @@
     if (!options.isOptimizing() || !options.isShrinking()) {
       return;
     }
-    if (!appView.options().canHaveNonReboundConstructorInvoke()) {
+    if (!appView.options().canInitNewInstanceUsingSuperclassConstructor()) {
       // TODO(b/309575527): Extend to all runtimes.
       return;
     }
diff --git a/src/main/java/com/android/tools/r8/utils/ArrayUtils.java b/src/main/java/com/android/tools/r8/utils/ArrayUtils.java
index 176ca67..0e57243 100644
--- a/src/main/java/com/android/tools/r8/utils/ArrayUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ArrayUtils.java
@@ -18,6 +18,19 @@
 
 public class ArrayUtils {
 
+  public static <T> boolean any(T[] array, Predicate<T> predicate) {
+    for (T element : array) {
+      if (predicate.test(element)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static <T> boolean none(T[] array, Predicate<T> predicate) {
+    return !any(array, predicate);
+  }
+
   public static boolean containsInt(int[] array, int value) {
     for (int element : array) {
       if (element == value) {
diff --git a/src/main/java/com/android/tools/r8/utils/BiForEachable.java b/src/main/java/com/android/tools/r8/utils/BiForEachable.java
index f1dd413..4cddd44 100644
--- a/src/main/java/com/android/tools/r8/utils/BiForEachable.java
+++ b/src/main/java/com/android/tools/r8/utils/BiForEachable.java
@@ -7,5 +7,5 @@
 
 public interface BiForEachable<S, T> {
 
-  void forEach(BiConsumer<S, T> consumer);
+  void forEach(BiConsumer<? super S, ? super T> consumer);
 }
diff --git a/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMemberMap.java b/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMemberMap.java
index 6dd73cf..840ecca 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMemberMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMemberMap.java
@@ -4,15 +4,18 @@
 
 package com.android.tools.r8.utils.collections;
 
+import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.graph.DexClassAndMember;
+import com.android.tools.r8.utils.BiForEachable;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.TraversalContinuation;
 import com.android.tools.r8.utils.TriPredicate;
 import com.google.common.base.Equivalence.Wrapper;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.BiPredicate;
@@ -21,7 +24,8 @@
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 
-public abstract class DexClassAndMemberMap<K extends DexClassAndMember<?, ?>, V> {
+public abstract class DexClassAndMemberMap<K extends DexClassAndMember<?, ?>, V>
+    implements BiForEachable<K, V>, Map<K, V> {
 
   private final Map<Wrapper<K>, V> backing;
 
@@ -33,6 +37,7 @@
     this.backing = backing;
   }
 
+  @Override
   public void clear() {
     backing.clear();
   }
@@ -49,11 +54,28 @@
     return backing.computeIfAbsent(wrapper, key -> fn.apply(key.get()));
   }
 
+  @SuppressWarnings("unchecked")
+  @Override
+  public boolean containsKey(Object key) {
+    return containsKey((K) key);
+  }
+
   public boolean containsKey(K member) {
     return backing.containsKey(wrap(member));
   }
 
-  public void forEach(BiConsumer<K, V> consumer) {
+  @Override
+  public boolean containsValue(Object value) {
+    throw new Unimplemented();
+  }
+
+  @Override
+  public Set<Entry<K, V>> entrySet() {
+    throw new Unimplemented();
+  }
+
+  @Override
+  public void forEach(BiConsumer<? super K, ? super V> consumer) {
     backing.forEach((wrapper, value) -> consumer.accept(wrapper.get(), value));
   }
 
@@ -65,6 +87,12 @@
     backing.values().forEach(consumer);
   }
 
+  @SuppressWarnings("unchecked")
+  @Override
+  public V get(Object key) {
+    return get((K) key);
+  }
+
   public V get(K member) {
     return backing.get(wrap(member));
   }
@@ -73,10 +101,20 @@
     return backing.get(wrapper);
   }
 
-  public List<K> getKeysSorted() {
+  public List<K> getKeys() {
     List<K> keys = new ArrayList<>(size());
     backing.keySet().forEach(key -> keys.add(key.get()));
-    return ListUtils.sort(keys, (x, y) -> x.getReference().compareTo(y.getReference()));
+    return keys;
+  }
+
+  public List<K> getKeysSorted() {
+    return ListUtils.sort(getKeys(), (x, y) -> x.getReference().compareTo(y.getReference()));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public V getOrDefault(Object key, V defaultValue) {
+    return getOrDefault((K) key, defaultValue);
   }
 
   public V getOrDefault(K member, V defaultValue) {
@@ -88,15 +126,33 @@
     return value != null ? value : defaultValue.get();
   }
 
+  @Override
   public boolean isEmpty() {
     return backing.isEmpty();
   }
 
+  @Override
+  public Set<K> keySet() {
+    throw new Unimplemented();
+  }
+
+  @Override
   public V put(K member, V value) {
     Wrapper<K> wrapper = wrap(member);
     return backing.put(wrapper, value);
   }
 
+  @Override
+  public void putAll(Map<? extends K, ? extends V> m) {
+    throw new Unimplemented();
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public V remove(Object key) {
+    return remove((K) key);
+  }
+
   public V remove(K member) {
     return backing.remove(wrap(member));
   }
@@ -113,6 +169,7 @@
         .removeIf(entry -> predicate.test(entry.getKey().get(), entry.getValue(), entry));
   }
 
+  @Override
   public int size() {
     return backing.size();
   }
@@ -137,5 +194,10 @@
     return TraversalContinuation.doContinue();
   }
 
+  @Override
+  public Collection<V> values() {
+    throw new Unimplemented();
+  }
+
   protected abstract Wrapper<K> wrap(K member);
 }
diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
index 1147830..78093de 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/ProgramMethodSet.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.utils.ForEachable;
 import com.google.common.collect.ImmutableMap;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
@@ -56,7 +57,7 @@
     return result;
   }
 
-  public static ProgramMethodSet create(ProgramMethodSet methodSet) {
+  public static ProgramMethodSet create(Collection<ProgramMethod> methodSet) {
     ProgramMethodSet newMethodSet = create(methodSet.size());
     newMethodSet.addAll(methodSet);
     return newMethodSet;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java
index 9728275..4fa1a73 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java
@@ -66,6 +66,7 @@
     return mergedClasses.values();
   }
 
+  @Override
   public Collection<DexType> getSourcesFor(DexType type) {
     return mergedClasses.getKeys(type);
   }