--- a/hotspot/src/share/vm/oops/klassVtable.cpp Sun Oct 06 16:13:50 2013 +0200
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Mon Oct 07 12:20:28 2013 -0400
@@ -83,7 +83,7 @@
GrowableArray<Method*> new_mirandas(20);
// compute the number of mirandas methods that must be added to the end
- get_mirandas(&new_mirandas, all_mirandas, super, methods, local_interfaces);
+ get_mirandas(&new_mirandas, all_mirandas, super, methods, NULL, local_interfaces);
*num_new_mirandas = new_mirandas.length();
vtable_length += *num_new_mirandas * vtableEntry::size();
@@ -186,7 +186,7 @@
assert(methods->at(i)->is_method(), "must be a Method*");
methodHandle mh(THREAD, methods->at(i));
- bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
+ bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, -1, checkconstraints, CHECK);
if (needs_new_entry) {
put_method_at(mh(), initialized);
@@ -195,7 +195,35 @@
}
}
- // add miranda methods to end of vtable.
+ // update vtable with default_methods
+ Array<Method*>* default_methods = ik()->default_methods();
+ if (default_methods != NULL) {
+ len = default_methods->length();
+ if (len > 0) {
+ Array<int>* def_vtable_indices = NULL;
+ if ((def_vtable_indices = ik()->default_vtable_indices()) == NULL) {
+ def_vtable_indices = ik()->create_new_default_vtable_indices(len, CHECK);
+ } else {
+ assert(def_vtable_indices->length() == len, "reinit vtable len?");
+ }
+ for (int i = 0; i < len; i++) {
+ HandleMark hm(THREAD);
+ assert(default_methods->at(i)->is_method(), "must be a Method*");
+ methodHandle mh(THREAD, default_methods->at(i));
+
+ bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, i, checkconstraints, CHECK);
+
+ // needs new entry
+ if (needs_new_entry) {
+ put_method_at(mh(), initialized);
+ def_vtable_indices->at_put(i, initialized); //set vtable index
+ initialized++;
+ }
+ }
+ }
+ }
+
+ // add miranda methods; it will also return the updated initialized
initialized = fill_in_mirandas(initialized);
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
@@ -230,14 +258,19 @@
#ifndef PRODUCT
if (PrintVtables && Verbose) {
ResourceMark rm(THREAD);
+ char* sig = target_method()->name_and_sig_as_C_string();
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
supersuperklass->internal_name(),
- _klass->internal_name(), (target_method() != NULL) ?
- target_method()->name()->as_C_string() : "<NULL>", vtable_index);
+ _klass->internal_name(), sig, vtable_index);
super_method->access_flags().print_on(tty);
+ if (super_method->is_default_method()) {
+ tty->print("default");
+ }
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
- tty->cr();
+ if (target_method->is_default_method()) {
+ tty->print("default");
+ }
}
#endif /*PRODUCT*/
break; // return found superk
@@ -258,16 +291,31 @@
// OR return true if a new vtable entry is required.
// Only called for InstanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
-bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len,
- bool checkconstraints, TRAPS) {
+bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method,
+ int super_vtable_len, int default_index,
+ bool checkconstraints, TRAPS) {
ResourceMark rm;
bool allocate_new = true;
assert(klass->oop_is_instance(), "must be InstanceKlass");
- assert(klass == target_method()->method_holder(), "caller resp.");
- // Initialize the method's vtable index to "nonvirtual".
- // If we allocate a vtable entry, we will update it to a non-negative number.
- target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
+ Array<int>* def_vtable_indices = NULL;
+ bool is_default = false;
+ // default methods are concrete methods in superinterfaces which are added to the vtable
+ // with their real method_holder
+ // Since vtable and itable indices share the same storage, don't touch
+ // the default method's real vtable/itable index
+ // default_vtable_indices stores the vtable value relative to this inheritor
+ if (default_index >= 0 ) {
+ is_default = true;
+ def_vtable_indices = klass->default_vtable_indices();
+ assert(def_vtable_indices != NULL, "def vtable alloc?");
+ assert(default_index <= def_vtable_indices->length(), "def vtable len?");
+ } else {
+ assert(klass == target_method()->method_holder(), "caller resp.");
+ // Initialize the method's vtable index to "nonvirtual".
+ // If we allocate a vtable entry, we will update it to a non-negative number.
+ target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
+ }
// Static and <init> methods are never in
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
@@ -284,6 +332,8 @@
// An interface never allocates new vtable slots, only inherits old ones.
// This method will either be assigned its own itable index later,
// or be assigned an inherited vtable index in the loop below.
+ // default methods store their vtable indices in the inheritors default_vtable_indices
+ assert (default_index == -1, "interfaces don't store resolved default methods");
target_method()->set_vtable_index(Method::pending_itable_index);
}
@@ -307,8 +357,15 @@
Symbol* name = target_method()->name();
Symbol* signature = target_method()->signature();
- Handle target_loader(THREAD, _klass()->class_loader());
- Symbol* target_classname = _klass->name();
+
+ KlassHandle target_klass(THREAD, target_method()->method_holder());
+ if (target_klass == NULL) {
+ target_klass = _klass;
+ }
+
+ Handle target_loader(THREAD, target_klass->class_loader());
+
+ Symbol* target_classname = target_klass->name();
for(int i = 0; i < super_vtable_len; i++) {
Method* super_method = method_at(i);
// Check if method name matches
@@ -317,10 +374,14 @@
// get super_klass for method_holder for the found method
InstanceKlass* super_klass = super_method->method_holder();
- if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) ||
- ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
- && ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader,
- target_classname, THREAD)) != (InstanceKlass*)NULL))) {
+ if (is_default
+ || ((super_klass->is_override(super_method, target_loader, target_classname, THREAD))
+ || ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
+ && ((super_klass = find_transitive_override(super_klass,
+ target_method, i, target_loader,
+ target_classname, THREAD))
+ != (InstanceKlass*)NULL))))
+ {
// overriding, so no new entry
allocate_new = false;
@@ -347,7 +408,7 @@
"%s used in the signature";
char* sig = target_method()->name_and_sig_as_C_string();
const char* loader1 = SystemDictionary::loader_name(target_loader());
- char* current = _klass->name()->as_C_string();
+ char* current = target_klass->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(super_loader());
char* failed_type_name = failed_type_symbol->as_C_string();
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
@@ -360,16 +421,39 @@
}
}
- put_method_at(target_method(), i);
- target_method()->set_vtable_index(i);
+ put_method_at(target_method(), i);
+ if (!is_default) {
+ target_method()->set_vtable_index(i);
+ } else {
+ if (def_vtable_indices != NULL) {
+ def_vtable_indices->at_put(default_index, i);
+ }
+ assert(super_method->is_default_method() || super_method->is_overpass()
+ || super_method->is_abstract(), "default override error");
+ }
+
+
#ifndef PRODUCT
if (PrintVtables && Verbose) {
+ ResourceMark rm(THREAD);
+ char* sig = target_method()->name_and_sig_as_C_string();
tty->print("overriding with %s::%s index %d, original flags: ",
- _klass->internal_name(), (target_method() != NULL) ?
- target_method()->name()->as_C_string() : "<NULL>", i);
+ target_klass->internal_name(), sig, i);
super_method->access_flags().print_on(tty);
+ if (super_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (super_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
+ if (target_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (target_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->cr();
}
#endif /*PRODUCT*/
@@ -378,12 +462,25 @@
// but not override another. Once we override one, not need new
#ifndef PRODUCT
if (PrintVtables && Verbose) {
+ ResourceMark rm(THREAD);
+ char* sig = target_method()->name_and_sig_as_C_string();
tty->print("NOT overriding with %s::%s index %d, original flags: ",
- _klass->internal_name(), (target_method() != NULL) ?
- target_method()->name()->as_C_string() : "<NULL>", i);
+ target_klass->internal_name(), sig,i);
super_method->access_flags().print_on(tty);
+ if (super_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (super_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
+ if (target_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (target_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->cr();
}
#endif /*PRODUCT*/
@@ -438,6 +535,14 @@
return false;
}
+ // Concrete interface methods do not need new entries, they override
+ // abstract method entries using default inheritance rules
+ if (target_method()->method_holder() != NULL &&
+ target_method()->method_holder()->is_interface() &&
+ !target_method()->is_abstract() ) {
+ return false;
+ }
+
// we need a new entry if there is no superclass
if (super == NULL) {
return true;
@@ -446,7 +551,7 @@
// private methods in classes always have a new entry in the vtable
// specification interpretation since classic has
// private methods not overriding
- // JDK8 adds private methods in interfaces which require invokespecial
+ // JDK8 adds private methods in interfaces which require invokespecial
if (target_method()->is_private()) {
return true;
}
@@ -526,35 +631,40 @@
if (mhk->is_interface()) {
assert(m->is_public(), "should be public");
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
- assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method");
+ assert(is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super()), "should be a miranda_method");
return true;
}
return false;
}
-// check if a method is a miranda method, given a class's methods table and its super
-// "miranda" means not static, not defined by this class, and not defined
-// in super unless it is private and therefore inaccessible to this class.
+// check if a method is a miranda method, given a class's methods table,
+// its default_method table and its super
+// "miranda" means not static, not defined by this class.
+// private methods in interfaces do not belong in the miranda list.
// the caller must make sure that the method belongs to an interface implemented by the class
// Miranda methods only include public interface instance methods
-// Not private methods, not static methods, not default = concrete abstract
-bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
- if (m->is_static()) {
+// Not private methods, not static methods, not default == concrete abstract
+bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
+ Array<Method*>* default_methods, Klass* super) {
+ if (m->is_static() || m->is_private()) {
return false;
}
Symbol* name = m->name();
Symbol* signature = m->signature();
if (InstanceKlass::find_method(class_methods, name, signature) == NULL) {
// did not find it in the method table of the current class
- if (super == NULL) {
- // super doesn't exist
- return true;
- }
+ if ((default_methods == NULL) ||
+ InstanceKlass::find_method(default_methods, name, signature) == NULL) {
+ if (super == NULL) {
+ // super doesn't exist
+ return true;
+ }
- Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
- if (mo == NULL || mo->access_flags().is_private() ) {
- // super class hierarchy does not implement it or protection is different
- return true;
+ Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
+ if (mo == NULL || mo->access_flags().is_private() ) {
+ // super class hierarchy does not implement it or protection is different
+ return true;
+ }
}
}
@@ -562,7 +672,7 @@
}
// Scans current_interface_methods for miranda methods that do not
-// already appear in new_mirandas and are also not defined-and-non-private
+// already appear in new_mirandas, or default methods, and are also not defined-and-non-private
// in super (superclass). These mirandas are added to all_mirandas if it is
// not null; in addition, those that are not duplicates of miranda methods
// inherited by super from its interfaces are added to new_mirandas.
@@ -572,7 +682,8 @@
void klassVtable::add_new_mirandas_to_lists(
GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
- Klass* super) {
+ Array<Method*>* default_methods, Klass* super) {
+
// iterate thru the current interface's method to see if it a miranda
int num_methods = current_interface_methods->length();
for (int i = 0; i < num_methods; i++) {
@@ -590,7 +701,7 @@
}
if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable
- if (is_miranda(im, class_methods, super)) { // is it a miranda at all?
+ if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all?
InstanceKlass *sk = InstanceKlass::cast(super);
// check if it is a duplicate of a super's miranda
if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) {
@@ -607,6 +718,7 @@
void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
GrowableArray<Method*>* all_mirandas,
Klass* super, Array<Method*>* class_methods,
+ Array<Method*>* default_methods,
Array<Klass*>* local_interfaces) {
assert((new_mirandas->length() == 0) , "current mirandas must be 0");
@@ -615,14 +727,16 @@
for (int i = 0; i < num_local_ifs; i++) {
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
- ik->methods(), class_methods, super);
+ ik->methods(), class_methods,
+ default_methods, super);
// iterate thru each local's super interfaces
Array<Klass*>* super_ifs = ik->transitive_interfaces();
int num_super_ifs = super_ifs->length();
for (int j = 0; j < num_super_ifs; j++) {
InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j));
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
- sik->methods(), class_methods, super);
+ sik->methods(), class_methods,
+ default_methods, super);
}
}
}
@@ -633,8 +747,22 @@
int klassVtable::fill_in_mirandas(int initialized) {
GrowableArray<Method*> mirandas(20);
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
- ik()->local_interfaces());
+ ik()->default_methods(), ik()->local_interfaces());
for (int i = 0; i < mirandas.length(); i++) {
+ if (PrintVtables && Verbose) {
+ Method* meth = mirandas.at(i);
+ ResourceMark rm(Thread::current());
+ if (meth != NULL) {
+ char* sig = meth->name_and_sig_as_C_string();
+ tty->print("fill in mirandas with %s index %d, flags: ",
+ sig, initialized);
+ meth->access_flags().print_on(tty);
+ if (meth->is_default_method()) {
+ tty->print("default");
+ }
+ tty->cr();
+ }
+ }
put_method_at(mirandas.at(i), initialized);
++initialized;
}
@@ -648,6 +776,26 @@
}
#if INCLUDE_JVMTI
+bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Method* new_method) {
+ // If old_method is default, find this vtable index in default_vtable_indices
+ // and replace that method in the _default_methods list
+ bool updated = false;
+
+ Array<Method*>* default_methods = ik()->default_methods();
+ if (default_methods != NULL) {
+ int len = default_methods->length();
+ for (int idx = 0; idx < len; idx++) {
+ if (vtable_index == ik()->default_vtable_indices()->at(idx)) {
+ if (default_methods->at(idx) == old_method) {
+ default_methods->at_put(idx, new_method);
+ updated = true;
+ }
+ break;
+ }
+ }
+ }
+ return updated;
+}
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed) {
// search the vtable for uses of either obsolete or EMCP methods
@@ -663,18 +811,26 @@
for (int index = 0; index < length(); index++) {
if (unchecked_method_at(index) == old_method) {
put_method_at(new_method, index);
+ // For default methods, need to update the _default_methods array
+ // which can only have one method entry for a given signature
+ bool updated_default = false;
+ if (old_method->is_default_method()) {
+ updated_default = adjust_default_method(index, old_method, new_method);
+ }
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
- RC_TRACE_MESG(("adjust: name=%s",
+ RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
+ klass()->external_name(),
old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
- RC_TRACE(0x00100000, ("vtable method update: %s(%s)",
+ RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
new_method->name()->as_C_string(),
- new_method->signature()->as_C_string()));
+ new_method->signature()->as_C_string(),
+ updated_default ? "true" : "false"));
}
// cannot 'break' here; see for-loop comment above.
}
@@ -701,6 +857,12 @@
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
+ if (m->is_default_method()) {
+ tty->print("default");
+ }
+ if (m->is_overpass()) {
+ tty->print("overpass");
+ }
tty->print(" -- ");
m->print_name(tty);
tty->cr();
@@ -757,9 +919,9 @@
// Initialization
void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
if (_klass->is_interface()) {
- // This needs to go after vtable indexes are assigned but
- // before implementors need to know the number of itable indexes.
- assign_itable_indexes_for_interface(_klass());
+ // This needs to go after vtable indices are assigned but
+ // before implementors need to know the number of itable indices.
+ assign_itable_indices_for_interface(_klass());
}
// Cannot be setup doing bootstrapping, interfaces don't have
@@ -803,7 +965,7 @@
return true;
}
-int klassItable::assign_itable_indexes_for_interface(Klass* klass) {
+int klassItable::assign_itable_indices_for_interface(Klass* klass) {
// an interface does not have an itable, but its methods need to be numbered
if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count,
klass->name()->as_C_string());
@@ -846,7 +1008,7 @@
}
nof_methods -= 1;
}
- // no methods have itable indexes
+ // no methods have itable indices
return 0;
}
@@ -907,6 +1069,21 @@
int ime_num = m->itable_index();
assert(ime_num < ime_count, "oob");
itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target());
+ if (TraceItables && Verbose) {
+ ResourceMark rm(THREAD);
+ if (target() != NULL) {
+ char* sig = target()->name_and_sig_as_C_string();
+ tty->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
+ interf_h()->internal_name(), ime_num, sig,
+ target()->method_holder()->internal_name());
+ tty->print("target_method flags: ");
+ target()->access_flags().print_on(tty);
+ if (target()->is_default_method()) {
+ tty->print("default");
+ }
+ tty->cr();
+ }
+ }
}
}
}
@@ -980,6 +1157,9 @@
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
+ if (m->is_default_method()) {
+ tty->print("default");
+ }
tty->print(" -- ");
m->print_name(tty);
tty->cr();
@@ -1116,7 +1296,7 @@
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
if (itable_index < 0 || itable_index >= method_count_for_interface(intf))
- return NULL; // help caller defend against bad indexes
+ return NULL; // help caller defend against bad indices
int index = itable_index;
Method* m = methods->at(index);