8154587: Resolution fails for default method named 'clone'

Make sure default methods with the same names as those in j.l.Object get put in the default methods table where resolution can find them.

Reviewed-by: acorn, lfoltan
This commit is contained in:
Harold Seigel 2017-12-15 11:23:50 -05:00
parent e817cd88c1
commit 47bbcac667
20 changed files with 1478 additions and 33 deletions

View file

@ -26,6 +26,7 @@
#include "classfile/bytecodeAssembler.hpp"
#include "classfile/defaultMethods.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.hpp"
@ -683,10 +684,11 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
Symbol* _method_name;
Symbol* _method_signature;
StatefulMethodFamily* _family;
bool _cur_class_is_interface;
public:
FindMethodsByErasedSig(Symbol* name, Symbol* signature) :
_method_name(name), _method_signature(signature),
FindMethodsByErasedSig(Symbol* name, Symbol* signature, bool is_interf) :
_method_name(name), _method_signature(signature), _cur_class_is_interface(is_interf),
_family(NULL) {}
void get_discovered_family(MethodFamily** family) {
@ -709,14 +711,17 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
InstanceKlass* iklass = current_class();
Method* m = iklass->find_method(_method_name, _method_signature);
// private interface methods are not candidates for default methods
// invokespecial to private interface methods doesn't use default method logic
// private class methods are not candidates for default methods,
// private methods do not override default methods, so need to perform
// default method inheritance without including private methods
// The overpasses are your supertypes' errors, we do not include them
// future: take access controls into account for superclass methods
if (m != NULL && !m->is_static() && !m->is_overpass() && !m->is_private()) {
// Private interface methods are not candidates for default methods.
// invokespecial to private interface methods doesn't use default method logic.
// Private class methods are not candidates for default methods.
// Private methods do not override default methods, so need to perform
// default method inheritance without including private methods.
// The overpasses are your supertypes' errors, we do not include them.
// Non-public methods in java.lang.Object are not candidates for default
// methods.
// Future: take access controls into account for superclass methods
if (m != NULL && !m->is_static() && !m->is_overpass() && !m->is_private() &&
(!_cur_class_is_interface || !SystemDictionary::is_nonpublic_Object_method(m))) {
if (_family == NULL) {
_family = new StatefulMethodFamily();
}
@ -726,8 +731,8 @@ class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
scope->add_mark(restorer);
} else {
// This is the rule that methods in classes "win" (bad word) over
// methods in interfaces. This works because of single inheritance
// private methods in classes do not "win", they will be found
// methods in interfaces. This works because of single inheritance.
// Private methods in classes do not "win", they will be found
// first on searching, but overriding for invokevirtual needs
// to find default method candidates for the same signature
_family->set_target_if_empty(m);
@ -745,10 +750,10 @@ static void create_defaults_and_exceptions(
static void generate_erased_defaults(
InstanceKlass* klass, GrowableArray<EmptyVtableSlot*>* empty_slots,
EmptyVtableSlot* slot, TRAPS) {
EmptyVtableSlot* slot, bool is_intf, TRAPS) {
// sets up a set of methods with the same exact erased signature
FindMethodsByErasedSig visitor(slot->name(), slot->signature());
FindMethodsByErasedSig visitor(slot->name(), slot->signature(), is_intf);
visitor.run(klass);
MethodFamily* family;
@ -817,7 +822,7 @@ void DefaultMethods::generate_default_methods(
slot->print_on(&ls);
ls.cr();
}
generate_erased_defaults(klass, empty_slots, slot, CHECK);
generate_erased_defaults(klass, empty_slots, slot, klass->is_interface(), CHECK);
}
log_debug(defaultmethods)("Creating defaults and overpasses...");
create_defaults_and_exceptions(empty_slots, klass, CHECK);