Fix CHA in the presence of default conflict methods.

We don't want to set single implementation bits for default
conflict methods, as we need to thor ICCE for them.

bug: 112189179
Test: 966-default-conflict
Change-Id: I768f307f1996b775e3942c87cbe388ce22bebf5d
diff --git a/runtime/cha.cc b/runtime/cha.cc
index 3ea920d..d8cb525 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -507,7 +507,8 @@
     return;
   }
   DCHECK(!single_impl->IsAbstract());
-  if (single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) {
+  if ((single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) &&
+      !implementation_method->IsDefaultConflicting()) {
     // Same implementation. Since implementation_method may be a copy of a default
     // method, we need to check the declaring class for equality.
     return;
@@ -543,7 +544,10 @@
       method->SetHasSingleImplementation(true);
       DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
     }
-  } else {
+  // Default conflicting methods cannot be treated with single implementations,
+  // as we need to call them (and not inline them) in case of ICCE.
+  // See class_linker.cc:EnsureThrowsInvocationError.
+  } else if (!method->IsDefaultConflicting()) {
     method->SetHasSingleImplementation(true);
     // Single implementation of non-abstract method is itself.
     DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e19dedc..489d602 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7039,9 +7039,12 @@
       // mark this as a default, non-abstract method, since thats what it is. Also clear the
       // kAccSkipAccessChecks bit since this class hasn't been verified yet it shouldn't have
       // methods that are skipping access checks.
+      // Also clear potential kAccSingleImplementation to avoid CHA trying to inline
+      // the default method.
       DCHECK_EQ(new_method.GetAccessFlags() & kAccNative, 0u);
       constexpr uint32_t kSetFlags = kAccDefault | kAccDefaultConflict | kAccCopied;
-      constexpr uint32_t kMaskFlags = ~(kAccAbstract | kAccSkipAccessChecks);
+      constexpr uint32_t kMaskFlags =
+          ~(kAccAbstract | kAccSkipAccessChecks | kAccSingleImplementation);
       new_method.SetAccessFlags((new_method.GetAccessFlags() | kSetFlags) & kMaskFlags);
       DCHECK(new_method.IsDefaultConflicting());
       // The actual method might or might not be marked abstract since we just copied it from a
diff --git a/test/966-default-conflict/expected.txt b/test/966-default-conflict/expected.txt
index fad2c25..bbd733c 100644
--- a/test/966-default-conflict/expected.txt
+++ b/test/966-default-conflict/expected.txt
@@ -1,3 +1,4 @@
+JNI_OnLoad called
 Create Main instance
 Calling functions on concrete Main
 Calling non-conflicting function on Main
diff --git a/test/966-default-conflict/src/Main.java b/test/966-default-conflict/src/Main.java
index ce8cb47..f466715 100644
--- a/test/966-default-conflict/src/Main.java
+++ b/test/966-default-conflict/src/Main.java
@@ -15,6 +15,13 @@
  */
 class Main implements Iface, Iface2 {
   public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+    // Ensure we JIT compile the methods to test CHA behavior with default
+    // methods.
+    ensureJitCompiled(Main.class, "callMain");
+    ensureJitCompiled(Main.class, "callIface");
+    ensureJitCompiled(Main.class, "callIface2");
+
     System.out.println("Create Main instance");
     Main m = new Main();
     System.out.println("Calling functions on concrete Main");
@@ -68,4 +75,6 @@
     }
     return;
   }
+
+  private static native void ensureJitCompiled(Class<?> cls, String method_name);
 }