8264079: Improve abstractions

Reviewed-by: yan
diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp
index 8839eba..746dd18 100644
--- a/src/hotspot/share/code/dependencies.cpp
+++ b/src/hotspot/share/code/dependencies.cpp
@@ -1301,9 +1301,9 @@
   // the spot-checking version:
   Klass* find_witness_in(KlassDepChange& changes,
                          Klass* context_type,
-                           bool participants_hide_witnesses);
-  bool witnessed_reabstraction_in_supers(Klass* k);
+                         bool participants_hide_witnesses);
  public:
+  bool witnessed_reabstraction_in_supers(Klass* k);
   Klass* find_witness_subtype(Klass* context_type, KlassDepChange* changes = NULL) {
     assert(doing_subtype_search(), "must set up a subtype search");
     // When looking for unexpected concrete types,
@@ -1414,15 +1414,8 @@
     }
   }
 
-  if (is_witness(new_type)) {
-    if (!ignore_witness(new_type)) {
-      return new_type;
-    }
-  } else if (!doing_subtype_search()) {
-    // No witness found, but is_witness() doesn't detect method re-abstraction in case of spot-checking.
-    if (witnessed_reabstraction_in_supers(new_type)) {
-      return new_type;
-    }
+  if (is_witness(new_type) && !ignore_witness(new_type)) {
+    return new_type;
   }
 
   return NULL;
@@ -1804,18 +1797,91 @@
   return num;
 }
 
+
+// Try to determine whether root method in some context is concrete or not based on the information about the unique method
+// in that context. It exploits the fact that concrete root method is always inherited into the context when there's a unique method.
+// Hence, unique method holder is always a supertype of the context class when root method is concrete.
+// Examples for concrete_root_method
+//      C (C.m uniqm)
+//      |
+//      CX (ctxk) uniqm is inherited into context.
+//
+//      CX (ctxk) (CX.m uniqm) here uniqm is defined in ctxk.
+// Examples for !concrete_root_method
+//      CX (ctxk)
+//      |
+//      C (C.m uniqm) uniqm is in subtype of ctxk.
+bool Dependencies::is_concrete_root_method(Method* uniqm, Klass* ctxk) {
+  if (uniqm == NULL) {
+    return false; // match Dependencies::is_concrete_method() behavior
+  }
+  // Theoretically, the "direction" of subtype check matters here.
+  // On one hand, in case of interface context with a single implementor, uniqm can be in a superclass of the implementor which
+  // is not related to context class.
+  // On another hand, uniqm could come from an interface unrelated to the context class, but right now it is not possible:
+  // it is required that uniqm->method_holder() is the participant (uniqm->method_holder() <: ctxk), hence a default method
+  // can't be used as unique.
+  if (ctxk->is_interface()) {
+    Klass* implementor = InstanceKlass::cast(ctxk)->implementor();
+    assert(implementor != ctxk, "single implementor only"); // should have been invalidated earlier
+    ctxk = implementor;
+  }
+  InstanceKlass* holder = uniqm->method_holder();
+  assert(!holder->is_interface(), "no default methods allowed");
+  assert(ctxk->is_subclass_of(holder) || holder->is_subclass_of(ctxk), "not related");
+  return ctxk->is_subclass_of(holder);
+}
+
 // If a class (or interface) has a unique concrete method uniqm, return NULL.
 // Otherwise, return a class that contains an interfering method.
-Klass* Dependencies::check_unique_concrete_method(Klass* ctxk, Method* uniqm,
-                                                    KlassDepChange* changes) {
-  // Here is a missing optimization:  If uniqm->is_final(),
-  // we don't really need to search beneath it for overrides.
-  // This is probably not important, since we don't use dependencies
-  // to track final methods.  (They can't be "definalized".)
+Klass* Dependencies::check_unique_concrete_method(Klass* ctxk,
+                                                  Method* uniqm,
+                                                  KlassDepChange* changes) {
   ClassHierarchyWalker wf(uniqm->method_holder(), uniqm);
-  return wf.find_witness_definer(ctxk, changes);
+  Klass* witness = wf.find_witness_definer(ctxk, changes);
+  if (witness != NULL) {
+    return witness;
+  }
+  if (!Dependencies::is_concrete_root_method(uniqm, ctxk) || changes != NULL) {
+    Klass* conck = find_witness_AME(ctxk, uniqm, changes);
+    if (conck != NULL) {
+      // Found a concrete subtype 'conck' which does not override abstract root method.
+      return conck;
+    }
+  }
+  return NULL;
 }
 
+// Search for AME.
+// There are two version of checks.
+//   1) Spot checking version(Classload time). Newly added class is checked for AME.
+//      Checks whether abstract/overpass method is inherited into/declared in newly added concrete class.
+//   2) Compile time analysis for abstract/overpass(abstract klass) root_m. The non uniqm subtrees are checked for concrete classes.
+Klass* Dependencies::find_witness_AME(Klass* ctxk, Method* m, KlassDepChange* changes) {
+  if (m != NULL) {
+    if (changes != NULL) {
+      // Spot checking version.
+      ClassHierarchyWalker wf(m);
+      Klass* new_type = changes->new_type();
+      if (wf.witnessed_reabstraction_in_supers(new_type)) {
+        return new_type;
+      }
+    } else {
+      // Note: It is required that uniqm->method_holder() is the participant (see ClassHierarchyWalker::found_method()).
+      ClassHierarchyWalker wf(m->method_holder());
+      Klass* conck = wf.find_witness_subtype(ctxk);
+      if (conck != NULL) {
+        Method* cm = InstanceKlass::cast(conck)->find_instance_method(m->name(), m->signature(), Klass::skip_private);
+        if (!Dependencies::is_concrete_method(cm, conck)) {
+          return conck;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+
 // Find the set of all non-abstract methods under ctxk that match m.
 // (The method m must be defined or inherited in ctxk.)
 // Include m itself in the set, unless it is abstract.
@@ -1840,7 +1906,11 @@
       // (This can happen if m is inherited into ctxk and fm overrides it.)
       return NULL;
     }
+  } else if (Dependencies::find_witness_AME(ctxk, fm) != NULL) {
+    // Found a concrete subtype which does not override abstract root method.
+    return NULL;
   }
+  assert(Dependencies::is_concrete_root_method(fm, ctxk) == Dependencies::is_concrete_method(m, ctxk), "mismatch");
 #ifndef PRODUCT
   // Make sure the dependency mechanism will pass this discovery:
   if (VerifyDependencies && fm != NULL) {
diff --git a/src/hotspot/share/code/dependencies.hpp b/src/hotspot/share/code/dependencies.hpp
index 07c17a2..52409dc 100644
--- a/src/hotspot/share/code/dependencies.hpp
+++ b/src/hotspot/share/code/dependencies.hpp
@@ -393,6 +393,9 @@
   static bool is_concrete_method(Method* m, Klass* k);  // m is invocable
   static Klass* find_finalizable_subclass(Klass* k);
 
+  static bool is_concrete_root_method(Method* uniqm, Klass* ctxk);
+  static Klass* find_witness_AME(Klass* ctxk, Method* m, KlassDepChange* changes = NULL);
+
   // These versions of the concreteness queries work through the CI.
   // The CI versions are allowed to skew sometimes from the VM
   // (oop-based) versions.  The cost of such a difference is a
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
index f102b79..99caa1c 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
@@ -367,10 +367,6 @@
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", holder->external_name()));
   }
 
-  if (method->is_abstract()) {
-    return NULL;
-  }
-
   methodHandle ucm;
   {
     MutexLocker locker(Compile_lock);
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java
index f496522..d95a683 100644
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java
@@ -116,8 +116,6 @@
         testMappedByteBuffer(MappedByteBuffer::get);
     }
 
-    // TODO Re-enable this test once JDK-8259360 got fixed.
-    /*
     @Test
     public void testCompiled() throws IOException {
         Assume.assumeFalse("Crashes on AArch64 (GR-8351)", System.getProperty("os.arch").equalsIgnoreCase("aarch64"));
@@ -139,7 +137,6 @@
             }
         });
     }
-    */
 
     private static final int BLOCK_SIZE = 512;
     private static final int BLOCK_COUNT = 16;