8028438: static superclass method masks default methods
authoracorn
Tue, 03 Dec 2013 11:13:14 -0800
changeset 21913 0e2fd7282ac6
parent 21912 8d2924674592
child 21915 d14f8009ad2a
8028438: static superclass method masks default methods Reviewed-by: hseigel, lfoltan, coleenp
hotspot/src/share/vm/classfile/defaultMethods.cpp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/oops/klassVtable.cpp
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp	Tue Dec 03 08:36:15 2013 -0800
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp	Tue Dec 03 11:13:14 2013 -0800
@@ -625,13 +625,13 @@
   while (super != NULL) {
     for (int i = 0; i < super->methods()->length(); ++i) {
       Method* m = super->methods()->at(i);
-      if (m->is_overpass()) {
+      if (m->is_overpass() || m->is_static()) {
         // m is a method that would have been a miranda if not for the
         // default method processing that occurred on behalf of our superclass,
         // so it's a method we want to re-examine in this new context.  That is,
         // unless we have a real implementation of it in the current class.
         Method* impl = klass->lookup_method(m->name(), m->signature());
-        if (impl == NULL || impl->is_overpass()) {
+        if (impl == NULL || impl->is_overpass() || impl->is_static()) {
           if (!already_in_vtable_slots(slots, m)) {
             slots->append(new EmptyVtableSlot(m));
           }
@@ -648,7 +648,7 @@
         // so it's a method we want to re-examine in this new context.  That is,
         // unless we have a real implementation of it in the current class.
         Method* impl = klass->lookup_method(m->name(), m->signature());
-        if (impl == NULL || impl->is_overpass()) {
+        if (impl == NULL || impl->is_overpass() || impl->is_static()) {
           if (!already_in_vtable_slots(slots, m)) {
             slots->append(new EmptyVtableSlot(m));
           }
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Tue Dec 03 08:36:15 2013 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Tue Dec 03 11:13:14 2013 -0800
@@ -267,8 +267,8 @@
   Method* result_oop = klass->uncached_lookup_method(name, signature);
   result = methodHandle(THREAD, result_oop);
   while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) {
-    klass = KlassHandle(THREAD, result->method_holder()->super());
-    result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
+    KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super());
+    result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature));
   }
 
   if (result.is_null()) {
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Dec 03 08:36:15 2013 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Dec 03 11:13:14 2013 -0800
@@ -1427,6 +1427,17 @@
   return InstanceKlass::find_method(methods(), name, signature);
 }
 
+// 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* meth = InstanceKlass::find_method(methods, name, signature);
+  if (meth != NULL && meth->is_static()) {
+      meth = NULL;
+  }
+  return meth;
+}
+
 // find_method looks up the name/signature in the local methods array
 Method* InstanceKlass::find_method(
     Array<Method*>* methods, Symbol* name, Symbol* signature) {
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Tue Dec 03 08:36:15 2013 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Tue Dec 03 11:13:14 2013 -0800
@@ -515,6 +515,7 @@
   // find a local method (returns NULL if not found)
   Method* find_method(Symbol* name, Symbol* signature) const;
   static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+  static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
 
   // find a local method index in default_methods (returns -1 if not found)
   static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature);
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Tue Dec 03 08:36:15 2013 -0800
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Tue Dec 03 11:13:14 2013 -0800
@@ -665,6 +665,11 @@
 
 // check if a method is a miranda method, given a class's methods table,
 // its default_method table  and its super
+// Miranda methods are calculated twice:
+// first: before vtable size calculation: including abstract and default
+// This is seen by default method creation
+// Second: recalculated during vtable initialization: only abstract
+// This is seen by link resolution and selection.
 // "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
@@ -678,7 +683,8 @@
   }
   Symbol* name = m->name();
   Symbol* signature = m->signature();
-  if (InstanceKlass::find_method(class_methods, name, signature) == NULL) {
+
+  if (InstanceKlass::find_instance_method(class_methods, name, signature) == NULL) {
     // did not find it in the method table of the current class
     if ((default_methods == NULL) ||
         InstanceKlass::find_method(default_methods, name, signature) == NULL) {
@@ -688,6 +694,12 @@
       }
 
       Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
+      while (mo != NULL && mo->access_flags().is_static()
+             && mo->method_holder() != NULL
+             && mo->method_holder()->super() != NULL)
+      {
+         mo = mo->method_holder()->super()->uncached_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;