changeset 10933:2a6952bb3909 jdk8u292-b10 jdk8u292-ga

8244543: Enhanced handling of abstract classes 8227467: Better class method invocations Summary: Includes changes to find_instance_method from JDK-8010319 Reviewed-by: mbalao Contributed-by: alvdavi@amazon.com
author andrew
date Wed, 31 Mar 2021 17:51:16 +0100
parents 91b61f678a19
children c137543b09a7
files src/share/vm/code/dependencies.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp
diffstat 3 files changed, 55 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/code/dependencies.cpp	Sat Mar 27 19:01:26 2021 +0000
+++ b/src/share/vm/code/dependencies.cpp	Wed Mar 31 17:51:16 2021 +0100
@@ -29,6 +29,7 @@
 #include "ci/ciMethod.hpp"
 #include "code/dependencies.hpp"
 #include "compiler/compileLog.hpp"
+#include "oops/klass.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
@@ -896,8 +897,9 @@
     } else if (!k->oop_is_instance()) {
       return false; // no methods to find in an array type
     } else {
-      // Search class hierarchy first.
-      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+      // Search class hierarchy first, skipping private implementations
+      // as they never override any inherited methods
+      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
       if (!Dependencies::is_concrete_method(m, k)) {
         // Check for re-abstraction of method
         if (!k->is_interface() && m != NULL && m->is_abstract()) {
@@ -907,7 +909,7 @@
           ClassHierarchyWalker wf(_participants, _num_participants);
           Klass* w = wf.find_witness_subtype(k);
           if (w != NULL) {
-            Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature);
+            Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature, Klass::skip_private);
             if (!Dependencies::is_concrete_method(wm, w)) {
               // Found a concrete subtype 'w' which does not override abstract method 'm'.
               // Bail out because 'm' could be called with 'w' as receiver (leading to an
@@ -968,6 +970,7 @@
   Klass* find_witness_in(KlassDepChange& changes,
                          Klass* context_type,
                            bool participants_hide_witnesses);
+  bool witnessed_reabstraction_in_supers(Klass* k);
  public:
   Klass* find_witness_subtype(Klass* context_type, KlassDepChange* changes = NULL) {
     assert(doing_subtype_search(), "must set up a subtype search");
@@ -1042,7 +1045,6 @@
 #define count_find_witness_calls() (0)
 #endif //PRODUCT
 
-
 Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
                                                Klass* context_type,
                                                bool participants_hide_witnesses) {
@@ -1080,15 +1082,20 @@
     }
   }
 
-  if (is_witness(new_type) &&
-      !ignore_witness(new_type)) {
-    return new_type;
+  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;
+    }
   }
 
   return NULL;
 }
 
-
 // Walk hierarchy under a context type, looking for unexpected types.
 // Do not report participant types, and recursively walk beneath
 // them only if participants_hide_witnesses is false.
@@ -1207,6 +1214,32 @@
 #undef ADD_SUBCLASS_CHAIN
 }
 
+bool ClassHierarchyWalker::witnessed_reabstraction_in_supers(Klass* k) {
+  if (!k->oop_is_instance()) {
+    return false; // no methods to find in an array type
+  } else {
+    // Looking for a case when an abstract method is inherited into a concrete class.
+    if (Dependencies::is_concrete_klass(k) && !k->is_interface()) {
+      Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
+      if (m != NULL) {
+        return false; // no reabstraction possible: local method found
+      }
+      for (InstanceKlass* super = InstanceKlass::cast(k)->java_super(); super != NULL; super = super->java_super()) {
+        m = super->find_instance_method(_name, _signature, Klass::skip_private);
+        if (m != NULL) { // inherited method found
+          if (m->is_abstract() || m->is_overpass()) {
+            _found_methods[_num_participants] = m;
+            return true; // abstract method found
+          }
+          return false;
+        }
+      }
+      assert(false, "root method not found");
+      return true;
+    }
+    return false;
+  }
+}
 
 bool Dependencies::is_concrete_klass(Klass* k) {
   if (k->is_abstract())  return false;
--- a/src/share/vm/oops/instanceKlass.cpp	Sat Mar 27 19:01:26 2021 +0000
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Mar 31 17:51:16 2021 +0100
@@ -1494,18 +1494,22 @@
 
 // find_instance_method looks up the name/signature in the local methods array
 // and skips over static methods
-Method* InstanceKlass::find_instance_method(
-    Array<Method*>* methods, Symbol* name, Symbol* signature) {
+Method* InstanceKlass::find_instance_method(Array<Method*>* methods,
+                                            Symbol* name,
+                                            Symbol* signature,
+                                            PrivateLookupMode private_mode) {
   Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
-                                                 find_overpass, skip_static, find_private);
+                                                 find_overpass, skip_static, private_mode);
   assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
   return meth;
 }
 
 // find_instance_method looks up the name/signature in the local methods array
 // and skips over static methods
-Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
-    return InstanceKlass::find_instance_method(methods(), name, signature);
+Method* InstanceKlass::find_instance_method(Symbol* name,
+                                            Symbol* signature,
+                                            PrivateLookupMode private_mode) {
+  return InstanceKlass::find_instance_method(methods(), name, signature, private_mode);
 }
 
 // Find looks up the name/signature in the local methods array
--- a/src/share/vm/oops/instanceKlass.hpp	Sat Mar 27 19:01:26 2021 +0000
+++ b/src/share/vm/oops/instanceKlass.hpp	Wed Mar 31 17:51:16 2021 +0100
@@ -526,8 +526,11 @@
   static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
 
   // find a local method, but skip static methods
-  Method* find_instance_method(Symbol* name, Symbol* signature);
-  static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+  Method* find_instance_method(Symbol* name, Symbol* signature,
+                               PrivateLookupMode private_mode);
+  static Method* find_instance_method(Array<Method*>* methods,
+                                      Symbol* name, Symbol* signature,
+                                      PrivateLookupMode private_mode);
 
   // find a local method (returns NULL if not found)
   Method* find_local_method(Symbol* name, Symbol* signature,