changeset 5904:00ac926c1297

8244543: Enhanced handling of abstract classes Reviewed-by: andrew, bae
author alvdavi
date Mon, 11 Jan 2021 13:06:46 +0000
parents 062bd42c5e2b
children 35022cb9d778
files src/share/vm/code/dependencies.cpp
diffstat 1 files changed, 38 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/code/dependencies.cpp	Mon Jan 18 15:29:27 2021 +0300
+++ b/src/share/vm/code/dependencies.cpp	Mon Jan 11 13:06:46 2021 +0000
@@ -884,6 +884,7 @@
   klassOop find_witness_in(KlassDepChange& changes,
                            klassOop context_type,
                            bool participants_hide_witnesses);
+  bool witnessed_reabstraction_in_supers(klassOop k);
  public:
   klassOop find_witness_subtype(klassOop context_type, KlassDepChange* changes = NULL) {
     assert(doing_subtype_search(), "must set up a subtype search");
@@ -996,15 +997,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.
@@ -1122,6 +1128,34 @@
 #undef ADD_SUBCLASS_CHAIN
 }
 
+bool ClassHierarchyWalker::witnessed_reabstraction_in_supers(klassOop ctxk) {
+  Klass* k = Klass::cast(ctxk);
+  instanceKlass* ik = instanceKlass::cast(ctxk);
+  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(ctxk) && !k->is_interface()) {
+      methodOop m = instanceKlass::cast(ctxk)->find_instance_method(_name, _signature);
+      if (m != NULL) {
+        return false; // no reabstraction possible: local method found
+      }
+      for (instanceKlass* super = instanceKlass::cast(ik->java_super()); super != NULL; super = instanceKlass::cast(super->java_super())) {
+        m = super->find_instance_method(_name, _signature);
+        if (m != NULL) { // inherited method found
+          if (m->is_abstract()) {
+            _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(klassOop k) {
   if (Klass::cast(k)->is_abstract())  return false;