Mercurial > hg > openjdk > jdk7u > hotspot
changeset 5827:0dc659da232e
8190877: Better handling of abstract classes
Reviewed-by: kvn, vlivanov, rhalade, ahgross, jwilhelm
Contributed-by: tobias.hartmann@oracle.com
author | thartmann |
---|---|
date | Wed, 23 May 2018 17:39:33 +0100 |
parents | 7d1eb0dcab5a |
children | 82e6757505da |
files | src/share/vm/code/dependencies.cpp |
diffstat | 1 files changed, 27 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/code/dependencies.cpp Tue Apr 17 22:51:28 2018 +0100 +++ b/src/share/vm/code/dependencies.cpp Wed May 23 17:39:33 2018 +0100 @@ -723,6 +723,14 @@ _signature = NULL; initialize(participant); } + ClassHierarchyWalker(klassOop participants[], int num_participants) { + _name = NULL; + _signature = NULL; + initialize(NULL); + for (int i = 0; i < num_participants; ++i) { + add_participant(participants[i]); + } + } // This is common code for two searches: One for concrete subtypes, // the other for concrete method implementations and overrides. @@ -813,7 +821,25 @@ // Search class hierarchy first. methodOop m = instanceKlass::cast(k)->find_instance_method(_name, _signature); if (!Dependencies::is_concrete_method(m)) { - return false; + // Check for re-abstraction of method + if (!k->klass_part()->is_interface() && m != NULL && m->is_abstract()) { + // Found a matching abstract method 'm' in the class hierarchy. + // This is fine iff 'k' is an abstract class and all concrete subtypes + // of 'k' override 'm' and are participates of the current search. + ClassHierarchyWalker wf(_participants, _num_participants); + klassOop w = wf.find_witness_subtype(k); + if (w != NULL) { + methodOop wm = instanceKlass::cast(w)->find_instance_method(_name, _signature); + if (!Dependencies::is_concrete_method(wm)) { + // 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 + // AbstractMethodError) and thus the method we are looking for is not unique. + _found_methods[_num_participants] = m; + return true; + } + } + } + return false; } _found_methods[_num_participants] = m; // Note: If add_participant(k) is called,