Mercurial > hg > icedtea8-forest > hotspot
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,