changeset 4900:3480d7ff09ec

Merge
author mduigou
date Wed, 19 Jun 2013 19:42:37 -0700
parents 1beed1f6f9ed 2ec664fe8e21
children 7b772f9e0365
files .hgtags .jcheck/conf src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/defaultMethods.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/oops/constMethod.cpp src/share/vm/oops/constantPool.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp src/share/vm/oops/method.cpp src/share/vm/oops/method.hpp src/share/vm/prims/methodHandles.cpp src/share/vm/runtime/reflection.cpp
diffstat 12 files changed, 574 insertions(+), 175 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Jun 07 09:25:19 2013 -0700
+++ b/.hgtags	Wed Jun 19 19:42:37 2013 -0700
@@ -273,6 +273,7 @@
 54240c1b8e87758f28da2c6a569a926fd9e0910a jdk8-b53
 9e3ae661284dc04185b029d85440fe7811f1ed07 hs24-b21
 e8fb566b94667f88462164defa654203f0ab6820 jdk8-b54
+203d2c0ee7c4fe648464fe2c506bd91003b7a5b7 lambda-b56
 09ea7e0752b306b8ae74713aeb4eb6263e1c6836 hs24-b22
 af0c8a0808516317333dcf9af15567cdd52761ce jdk8-b55
 6124ff4218296c91e4a72f1a76c064892d39d61b jdk8-b56
--- a/.jcheck/conf	Fri Jun 07 09:25:19 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-project=jdk8
--- a/src/share/vm/classfile/classFileParser.cpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Wed Jun 19 19:42:37 2013 -0700
@@ -2362,6 +2362,7 @@
       runtime_visible_type_annotations_length +
            runtime_invisible_type_annotations_length,
       annotation_default_length,
+      0,
       0);
 
   Method* m = Method::allocate(
--- a/src/share/vm/classfile/defaultMethods.cpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/classfile/defaultMethods.cpp	Wed Jun 19 19:42:37 2013 -0700
@@ -318,17 +318,17 @@
   }
 };
 
+
 // A method family contains a set of all methods that implement a single
-// language-level method.  Because of erasure, these methods may have different
-// signatures.  As members of the set are collected while walking over the
+// erased method. As members of the set are collected while walking over the
 // hierarchy, they are tagged with a qualification state.  The qualification
 // state for an erased method is set to disqualified if there exists a path
 // from the root of hierarchy to the method that contains an interleaving
-// language-equivalent method defined in an interface.
+// erased method defined in an interface.
+
 class MethodFamily : public ResourceObj {
  private:
 
-  generic::MethodDescriptor* _descriptor; // language-level description
   GrowableArray<Pair<Method*,QualifiedState> > _members;
   ResourceHashtable<Method*, int> _member_index;
 
@@ -358,15 +358,8 @@
 
  public:
 
-  MethodFamily(generic::MethodDescriptor* canonical_desc)
-      : _descriptor(canonical_desc), _selected_target(NULL),
-        _exception_message(NULL) {}
-
-  generic::MethodDescriptor* descriptor() const { return _descriptor; }
-
-  bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) {
-    return descriptor()->covariant_match(md, ctx);
-  }
+  MethodFamily()
+      : _selected_target(NULL), _exception_message(NULL) {} 
 
   void set_target_if_empty(Method* m) {
     if (_selected_target == NULL && !m->is_overpass()) {
@@ -445,12 +438,14 @@
     print_on(str, 0);
   }
 
-  void print_on(outputStream* str, int indent) const {
+  void print_on(outputStream* str, Symbol* sig) const {
+    print_on(str, sig, 0);
+  }
+
+  void print_on(outputStream* str, Symbol* signature, int indent) const {
     streamIndentor si(str, indent * 2);
 
-    generic::Context ctx(NULL); // empty, as _descriptor already canonicalized
-    TempNewSymbol family = descriptor()->reify_signature(&ctx, Thread::current());
-    str->indent().print_cr("Logical Method %s:", family->as_C_string());
+    str->indent().print_cr("Logical Method %s:", signature->as_C_string());
 
     streamIndentor si2(str);
     for (int i = 0; i < _members.length(); ++i) {
@@ -516,36 +511,97 @@
   return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
 }
 
+// A generic method family contains a set of all methods that implement a single
+// language-level method.  Because of erasure, these methods may have different
+// signatures.  As members of the set are collected while walking over the
+// hierarchy, they are tagged with a qualification state.  The qualification
+// state for an erased method is set to disqualified if there exists a path
+// from the root of hierarchy to the method that contains an interleaving
+// language-equivalent method defined in an interface.
+class GenericMethodFamily: public MethodFamily {
+ private:
+
+  generic::MethodDescriptor* _descriptor; // language-level description
+
+ public:
+
+  GenericMethodFamily(generic::MethodDescriptor* canonical_desc)
+      : _descriptor(canonical_desc) {}
+
+  generic::MethodDescriptor* descriptor() const { return _descriptor; }
+
+  bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) {
+    return descriptor()->covariant_match(md, ctx);
+  }
+
+#ifndef PRODUCT
+  void print_on(outputStream* str) const {
+    print_on(str, 0);
+  }
+
+  void print_on(outputStream* str, int indent) const {
+    streamIndentor si(str, indent * 2);
+
+    generic::Context ctx(NULL); // empty, as _descriptor already canonicalized
+    TempNewSymbol family = descriptor()->reify_signature(&ctx, Thread::current());
+    MethodFamily::print_on(str, (Symbol*)family, indent);
+  }
+#endif // ndef PRODUCT
+};
+
 class StateRestorer;
 
-// StatefulMethodFamily is a wrapper around MethodFamily that maintains the
+// StatefulMethodFamily is a wrapper around a MethodFamily that maintains the
 // qualification state during hierarchy visitation, and applies that state
-// when adding members to the MethodFamily.
-class StatefulMethodFamily : public ResourceObj {
+// when adding members to the MethodFamily
+class StatefulMethodFamily: public ResourceObj {
   friend class StateRestorer;
  private:
-  MethodFamily* _method;
   QualifiedState _qualification_state;
 
   void set_qualification_state(QualifiedState state) {
     _qualification_state = state;
   }
 
+ protected:
+  MethodFamily* _method_family;
+
  public:
-  StatefulMethodFamily(generic::MethodDescriptor* md, generic::Context* ctx) {
-    _method = new MethodFamily(md->canonicalize(ctx));
-    _qualification_state = QUALIFIED;
+  StatefulMethodFamily() {
+   _method_family = new MethodFamily();
+   _qualification_state = QUALIFIED;
   }
 
-  void set_target_if_empty(Method* m) { _method->set_target_if_empty(m); }
+  StatefulMethodFamily(MethodFamily* mf) {
+   _method_family = mf;
+   _qualification_state = QUALIFIED;
+  }
 
-  MethodFamily* get_method_family() { return _method; }
+  void set_target_if_empty(Method* m) { _method_family->set_target_if_empty(m); }
+
+  MethodFamily* get_method_family() { return _method_family; }
+
+  StateRestorer* record_method_and_dq_further(Method* mo);
+};
+
+
+// StatefulGenericMethodFamily is a wrapper around GenericMethodFamily that maintains the
+// qualification state during hierarchy visitation, and applies that state
+// when adding members to the GenericMethodFamily.
+class StatefulGenericMethodFamily : public StatefulMethodFamily {
+
+ public:
+  StatefulGenericMethodFamily(generic::MethodDescriptor* md, generic::Context* ctx) 
+  : StatefulMethodFamily(new GenericMethodFamily(md->canonicalize(ctx))) {
+    
+  }
+  GenericMethodFamily* get_method_family() { 
+    return (GenericMethodFamily*)_method_family;
+  }
 
   bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) {
-    return _method->descriptor_matches(md, ctx);
+    return get_method_family()->descriptor_matches(md, ctx);
   }
-
-  StateRestorer* record_method_and_dq_further(Method* mo);
 };
 
 class StateRestorer : public PseudoScopeMark {
@@ -563,9 +619,9 @@
 StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) {
   StateRestorer* mark = new StateRestorer(this, _qualification_state);
   if (_qualification_state == QUALIFIED) {
-    _method->record_qualified_method(mo);
+    _method_family->record_qualified_method(mo);
   } else {
-    _method->record_disqualified_method(mo);
+    _method_family->record_disqualified_method(mo);
   }
   // Everything found "above"??? this method in the hierarchy walk is set to
   // disqualified
@@ -573,15 +629,15 @@
   return mark;
 }
 
-class StatefulMethodFamilies : public ResourceObj {
+class StatefulGenericMethodFamilies : public ResourceObj {
  private:
-  GrowableArray<StatefulMethodFamily*> _methods;
+  GrowableArray<StatefulGenericMethodFamily*> _methods;
 
  public:
-  StatefulMethodFamily* find_matching(
+  StatefulGenericMethodFamily* find_matching(
       generic::MethodDescriptor* md, generic::Context* ctx) {
     for (int i = 0; i < _methods.length(); ++i) {
-      StatefulMethodFamily* existing = _methods.at(i);
+      StatefulGenericMethodFamily* existing = _methods.at(i);
       if (existing->descriptor_matches(md, ctx)) {
         return existing;
       }
@@ -589,17 +645,17 @@
     return NULL;
   }
 
-  StatefulMethodFamily* find_matching_or_create(
+  StatefulGenericMethodFamily* find_matching_or_create(
       generic::MethodDescriptor* md, generic::Context* ctx) {
-    StatefulMethodFamily* method = find_matching(md, ctx);
+    StatefulGenericMethodFamily* method = find_matching(md, ctx);
     if (method == NULL) {
-      method = new StatefulMethodFamily(md, ctx);
+      method = new StatefulGenericMethodFamily(md, ctx);
       _methods.append(method);
     }
     return method;
   }
 
-  void extract_families_into(GrowableArray<MethodFamily*>* array) {
+  void extract_families_into(GrowableArray<GenericMethodFamily*>* array) {
     for (int i = 0; i < _methods.length(); ++i) {
       array->append(_methods.at(i)->get_method_family());
     }
@@ -683,26 +739,82 @@
   return slots;
 }
 
+// Iterates over the superinterface type hierarchy looking for all methods
+// with a specific erased signature.
+class FindMethodsByErasedSig: public HierarchyVisitor<FindMethodsByErasedSig> {
+ private:
+  // Context data
+  Thread* THREAD;
+  Symbol* _method_name;
+  Symbol* _method_signature;
+  StatefulMethodFamily*  _family;
+
+ public:
+  FindMethodsByErasedSig(Symbol* name, Symbol* signature, Thread* thread) :
+      _method_name(name), _method_signature(signature), THREAD(thread), 
+      _family(NULL) {}
+
+  void get_discovered_family(MethodFamily** family) {
+      if (_family != NULL) {
+        *family = _family->get_method_family();
+      } else {
+        *family = NULL;
+      }
+  }
+
+  void* new_node_data(InstanceKlass* cls) { return new PseudoScope(); }
+  void free_node_data(void* node_data) {
+    PseudoScope::cast(node_data)->destroy();
+  }
+
+  // Find all methods on this hierarchy that match this
+  // method's erased (name, signature)
+  bool visit() {
+    PseudoScope* scope = PseudoScope::cast(current_data());
+    InstanceKlass* iklass = current_class();
+    InstanceKlass* sub = current_depth() > 0 ? class_at_depth(1) : NULL;
+
+    Method* m = iklass->find_method(_method_name, _method_signature);
+    if (m != NULL) {
+      if (_family == NULL) {
+        _family = new StatefulMethodFamily();
+      }
+    
+      if (iklass->is_interface()) {
+        StateRestorer* restorer = _family->record_method_and_dq_further(m);
+        scope->add_mark(restorer);
+      } else {
+        // This is the rule that methods in classes "win" (bad word) over
+        // methods in interfaces. This work because of single inheritance
+        // TODO - is this just for abstract methods ?
+        _family->set_target_if_empty(m);
+      }
+    }
+    return true;
+  }
+
+};
+    
 // Iterates over the type hierarchy looking for all methods with a specific
 // method name.  The result of this is a set of method families each of
 // which is populated with a set of methods that implement the same
 // language-level signature.
-class FindMethodsByName : public HierarchyVisitor<FindMethodsByName> {
+class FindMethodsByGenericSig : public HierarchyVisitor<FindMethodsByGenericSig> {
  private:
   // Context data
   Thread* THREAD;
   generic::DescriptorCache* _cache;
   Symbol* _method_name;
   generic::Context* _ctx;
-  StatefulMethodFamilies _families;
+  StatefulGenericMethodFamilies _families;
 
  public:
 
-  FindMethodsByName(generic::DescriptorCache* cache, Symbol* name,
+  FindMethodsByGenericSig(generic::DescriptorCache* cache, Symbol* name,
       generic::Context* ctx, Thread* thread) :
     _cache(cache), _method_name(name), _ctx(ctx), THREAD(thread) {}
 
-  void get_discovered_families(GrowableArray<MethodFamily*>* methods) {
+  void get_discovered_families(GrowableArray<GenericMethodFamily*>* methods) {
     _families.extract_families_into(methods);
   }
 
@@ -733,7 +845,7 @@
         // Find all methods on this hierarchy that match this method
         // (name, signature).   This class collects other families of this
         // method name.
-        StatefulMethodFamily* family =
+        StatefulGenericMethodFamily* family =
             _families.find_matching_or_create(md, _ctx);
 
         if (klass->is_interface()) {
@@ -753,7 +865,7 @@
 
 #ifndef PRODUCT
 static void print_families(
-    GrowableArray<MethodFamily*>* methods, Symbol* match) {
+    GrowableArray<GenericMethodFamily*>* methods, Symbol* match) {
   streamIndentor si(tty, 4);
   if (methods->length() == 0) {
     tty->indent();
@@ -761,7 +873,7 @@
   }
   for (int i = 0; i < methods->length(); ++i) {
     tty->indent();
-    MethodFamily* lm = methods->at(i);
+    GenericMethodFamily* lm = methods->at(i);
     if (lm->contains_signature(match)) {
       tty->print_cr("<Matching>");
     } else {
@@ -772,10 +884,64 @@
 }
 #endif // ndef PRODUCT
 
+static void create_overpasses(
+    GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
+
+static void generate_generic_defaults(
+      InstanceKlass* klass, GrowableArray<EmptyVtableSlot*>* empty_slots,
+      EmptyVtableSlot* slot, int curslotidx, TRAPS) {
+
+    generic::DescriptorCache cache; 
+
+    generic::Context ctx(&cache);
+    FindMethodsByGenericSig visitor(&cache, slot->name(), &ctx, CHECK);
+    visitor.run(klass);
+
+    GrowableArray<GenericMethodFamily*> discovered_families;
+    visitor.get_discovered_families(&discovered_families);
+
+#ifndef PRODUCT
+    if (TraceDefaultMethods) {
+      print_families(&discovered_families, slot->signature());
+    }
+#endif // ndef PRODUCT
+
+    // Find and populate any other slots that match the discovered families
+    for (int j = curslotidx; j < empty_slots->length(); ++j) {
+      EmptyVtableSlot* open_slot = empty_slots->at(j);
+
+      if (slot->name() == open_slot->name()) {
+        for (int k = 0; k < discovered_families.length(); ++k) {
+          GenericMethodFamily* lm = discovered_families.at(k);
+
+          if (lm->contains_signature(open_slot->signature())) {
+            lm->determine_target(klass, CHECK);
+            open_slot->bind_family(lm);
+          }
+        }
+      }
+    }
+
+}
+
+static void generate_erased_defaults(
+     InstanceKlass* klass, GrowableArray<EmptyVtableSlot*>* empty_slots,
+     EmptyVtableSlot* slot, TRAPS) {
+
+  // sets up a set of methods with the same exact erased signature
+  FindMethodsByErasedSig visitor(slot->name(), slot->signature(), CHECK);
+  visitor.run(klass);
+
+  MethodFamily* family; 
+  visitor.get_discovered_family(&family);
+  if (family != NULL) {
+    family->determine_target(klass, CHECK);
+    slot->bind_family(family);
+  }
+}
+
 static void merge_in_new_methods(InstanceKlass* klass,
     GrowableArray<Method*>* new_methods, TRAPS);
-static void create_overpasses(
-    GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
 
 // This is the guts of the default methods implementation.  This is called just
 // after the classfile has been parsed if some ancestor has default methods.
@@ -807,8 +973,6 @@
   // whatever scope it's in.
   ResourceMark rm(THREAD);
 
-  generic::DescriptorCache cache;
-
   // Keep entire hierarchy alive for the duration of the computation
   KeepAliveRegistrar keepAlive(THREAD);
   KeepAliveVisitor loadKeepAlive(&keepAlive);
@@ -842,42 +1006,18 @@
       if (TraceDefaultMethods) {
         streamIndentor si(tty, 4);
         tty->indent().print_cr("Already bound to logical method:");
-        slot->get_binding()->print_on(tty, 1);
+        slot->get_binding()->print_on(tty, slot->signature(), 1);
       }
 #endif // ndef PRODUCT
       continue; // covered by previous processing
     }
 
-    generic::Context ctx(&cache);
-    FindMethodsByName visitor(&cache, slot->name(), &ctx, CHECK);
-    visitor.run(klass);
-
-    GrowableArray<MethodFamily*> discovered_families;
-    visitor.get_discovered_families(&discovered_families);
-
-#ifndef PRODUCT
-    if (TraceDefaultMethods) {
-      print_families(&discovered_families, slot->signature());
+    if (ParseGenericDefaults) {
+      generate_generic_defaults(klass, empty_slots, slot, i, CHECK);
+    } else {
+      generate_erased_defaults(klass, empty_slots, slot, CHECK);
     }
-#endif // ndef PRODUCT
-
-    // Find and populate any other slots that match the discovered families
-    for (int j = i; j < empty_slots->length(); ++j) {
-      EmptyVtableSlot* open_slot = empty_slots->at(j);
-
-      if (slot->name() == open_slot->name()) {
-        for (int k = 0; k < discovered_families.length(); ++k) {
-          MethodFamily* lm = discovered_families.at(k);
-
-          if (lm->contains_signature(open_slot->signature())) {
-            lm->determine_target(klass, CHECK);
-            open_slot->bind_family(lm);
-          }
-        }
-      }
-    }
-  }
-
+ }
 #ifndef PRODUCT
   if (TraceDefaultMethods) {
     tty->print_cr("Creating overpasses...");
@@ -893,7 +1033,6 @@
 #endif // ndef PRODUCT
 }
 
-
 /**
  * Generic analysis was used upon interface '_target' and found a unique
  * default method candidate with generic signature '_method_desc'.  This
@@ -912,16 +1051,86 @@
  * the selected method along that path.
  */
 class ShadowChecker : public HierarchyVisitor<ShadowChecker> {
- private:
-  generic::DescriptorCache* _cache;
+ protected:
   Thread* THREAD;
 
   InstanceKlass* _target;
 
   Symbol* _method_name;
   InstanceKlass* _method_holder;
+  bool _found_shadow;
+
+
+ public:
+
+  ShadowChecker(Thread* thread, Symbol* name, InstanceKlass* holder, 
+                InstanceKlass* target)
+                : THREAD(thread), _method_name(name), _method_holder(holder),
+                _target(target), _found_shadow(false) {}
+
+  void* new_node_data(InstanceKlass* cls) { return NULL; }
+  void free_node_data(void* data) { return; }
+
+  bool visit() {
+    InstanceKlass* ik = current_class();
+    if (ik == _target && current_depth() == 1) {
+      return false; // This was the specified super -- no need to search it
+    }
+    if (ik == _method_holder || ik == _target) {
+      // We found a path that should be examined to see if it shadows _method
+      if (path_has_shadow()) {
+        _found_shadow = true;
+        cancel_iteration();
+      }
+      return false; // no need to continue up hierarchy
+    }
+    return true;
+  }
+
+  virtual bool path_has_shadow() { ShouldNotReachHere(); return true;} 
+  bool found_shadow() { return _found_shadow; }
+};
+
+// Used for Invokespecial.
+// Invokespecial is allowed to invoke a concrete interface method
+// and can be used to disambuiguate among qualified candidates,
+// but may not be used to invoke a candidate that would be shadowed
+// from the perspective of the caller.
+// Only called if the resolved_klass is a direct superinterface of
+// the caller's class.
+// Invokespecial is also used in the overpass generation today
+// We re-run the shadowchecker because we can't distinguish this case,
+// but it should return the same answer, since the overpass target
+// is now the invokespecial caller.
+class ErasedShadowChecker : public ShadowChecker {
+ private:
+  bool path_has_shadow() {
+
+    for (int i = current_depth() - 1; i > 0; --i) {
+      InstanceKlass* ik = class_at_depth(i);
+      InstanceKlass* sub = class_at_depth(i + 1);
+
+      if (ik->is_interface()) {
+        int end;
+        int start = ik->find_method_by_name(_method_name, &end);
+        if (start != -1) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+ public:
+ 
+  ErasedShadowChecker(Thread* thread, Symbol* name, InstanceKlass* holder, 
+                InstanceKlass* target)
+    : ShadowChecker(thread, name, holder, target) {}
+};
+
+class GenericShadowChecker : public ShadowChecker {
+ private:
+  generic::DescriptorCache* _cache;
   generic::MethodDescriptor* _method_desc;
-  bool _found_shadow;
 
   bool path_has_shadow() {
     generic::Context ctx(_cache);
@@ -950,39 +1159,129 @@
 
  public:
 
-  ShadowChecker(generic::DescriptorCache* cache, Thread* thread,
+  GenericShadowChecker(generic::DescriptorCache* cache, Thread* thread,
       Symbol* name, InstanceKlass* holder, generic::MethodDescriptor* desc,
       InstanceKlass* target)
-    : _cache(cache), THREAD(thread), _method_name(name), _method_holder(holder),
-      _method_desc(desc), _target(target), _found_shadow(false) {}
+    : ShadowChecker(thread, name, holder, target) {
+      _cache = cache;
+      _method_desc = desc;
+ }
+};
 
-  void* new_node_data(InstanceKlass* cls) { return NULL; }
-  void free_node_data(void* data) { return; }
 
-  bool visit() {
-    InstanceKlass* ik = current_class();
-    if (ik == _target && current_depth() == 1) {
-      return false; // This was the specified super -- no need to search it
-    }
-    if (ik == _method_holder || ik == _target) {
-      // We found a path that should be examined to see if it shadows _method
-      if (path_has_shadow()) {
-        _found_shadow = true;
-        cancel_iteration();
-      }
-      return false; // no need to continue up hierarchy
-    }
-    return true;
+
+// Find the unique qualified candidate from the perspective of the direction
+// which is the resolved_klass, which must be an immediate superinterface
+// of klass
+Method* find_erased_super_default(InstanceKlass* current_class, InstanceKlass* direction, 
+                                  Symbol* method_name, Symbol* sig, TRAPS) {
+
+  FindMethodsByErasedSig visitor(method_name, sig, CHECK_NULL);
+  visitor.run(direction);      // find candidates from resolved_klass
+
+  MethodFamily* family;
+  visitor.get_discovered_family(&family);
+
+  if (family != NULL) {
+    family->determine_target(current_class, CHECK_NULL);  // get target from current_class
   }
 
-  bool found_shadow() { return _found_shadow; }
-};
+  if (family->has_target()) {
+    Method* target = family->get_selected_target();
+    InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
+
+    // Verify that the identified method is valid from the context of
+    // the current class, which is the caller class for invokespecial
+    // link resolution, i.e. ensure there it is not shadowed.
+    // You can use invokespecial to disambiguate interface methods, but
+    // you can not use it to skip over an interface method that would shadow it.
+    ErasedShadowChecker checker(THREAD, target->name(), holder, direction);
+    checker.run(current_class);
+
+    if (checker.found_shadow()) {
+#ifndef PRODUCT
+      if (TraceDefaultMethods) {
+        tty->print_cr("    Only candidate found was shadowed.");
+      }
+#endif // ndef PRODUCT
+      THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+                 "Accessible default method not found", NULL);
+    } else {
+      return target;
+    }
+  } else {
+    assert(family->throws_exception(), "must have target or throw");
+    THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+               family->get_exception_message()->as_C_string(), NULL);
+  }
+}      
+
+// direction is assumed to be the direct super of current_class
+Method* find_generic_super_default( InstanceKlass* current_class, 
+                                    InstanceKlass* direction, 
+                                    Symbol* method_name, Symbol* sig, TRAPS) {
+  generic::DescriptorCache cache;
+  generic::Context ctx(&cache);
+
+  // Prime the initial generic context for current -> direction
+  ctx.apply_type_arguments(current_class, direction, CHECK_NULL);
+
+  FindMethodsByGenericSig visitor(&cache, method_name, &ctx, CHECK_NULL);
+  visitor.run(direction);
+
+  GrowableArray<GenericMethodFamily*> families;
+  visitor.get_discovered_families(&families);
+
+#ifndef PRODUCT
+  if (TraceDefaultMethods) {
+    print_families(&families, sig);
+  }
+#endif // ndef PRODUCT
+
+  GenericMethodFamily* selected_family = NULL;
+
+  for (int i = 0; i < families.length(); ++i) {
+    GenericMethodFamily* lm = families.at(i);
+    if (lm->contains_signature(sig)) {
+      lm->determine_target(current_class, CHECK_NULL);
+      selected_family = lm;
+    }
+  }
+
+  if (selected_family->has_target()) {
+    Method* target = selected_family->get_selected_target();
+    InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
+
+    // Verify that the identified method is valid from the context of
+    // the current class
+    GenericShadowChecker checker(&cache, THREAD, target->name(),
+        holder, selected_family->descriptor(), direction);
+    checker.run(current_class);
+
+    if (checker.found_shadow()) {
+#ifndef PRODUCT
+      if (TraceDefaultMethods) {
+        tty->print_cr("    Only candidate found was shadowed.");
+      }
+#endif // ndef PRODUCT
+      THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+                 "Accessible default method not found", NULL);
+    } else {
+      return target;
+    }
+  } else {
+    assert(selected_family->throws_exception(), "must have target or throw");
+    THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
+               selected_family->get_exception_message()->as_C_string(), NULL);
+  }
+}
 
 // This is called during linktime when we find an invokespecial call that
 // refers to a direct superinterface.  It indicates that we should find the
 // default method in the hierarchy of that superinterface, and if that method
 // would have been a candidate from the point of view of 'this' class, then we
 // return that method.
+// This logic assumes that the super is a direct superclass of the caller
 Method* DefaultMethods::find_super_default(
     Klass* cls, Klass* super, Symbol* method_name, Symbol* sig, TRAPS) {
 
@@ -996,7 +1295,7 @@
   // Keep entire hierarchy alive for the duration of the computation
   KeepAliveRegistrar keepAlive(THREAD);
   KeepAliveVisitor loadKeepAlive(&keepAlive);
-  loadKeepAlive.run(current_class);
+  loadKeepAlive.run(current_class);   // get hierarchy from current class
 
 #ifndef PRODUCT
   if (TraceDefaultMethods) {
@@ -1012,67 +1311,25 @@
     return NULL;
   }
 
-  generic::DescriptorCache cache;
-  generic::Context ctx(&cache);
-
-  // Prime the initial generic context for current -> direction
-  ctx.apply_type_arguments(current_class, direction, CHECK_NULL);
-
-  FindMethodsByName visitor(&cache, method_name, &ctx, CHECK_NULL);
-  visitor.run(direction);
-
-  GrowableArray<MethodFamily*> families;
-  visitor.get_discovered_families(&families);
+  Method* target = NULL;
+  if (ParseGenericDefaults) {
+    target = find_generic_super_default(current_class, direction, 
+                                        method_name, sig, THREAD);
+  } else {
+    target = find_erased_super_default(current_class, direction, 
+                                       method_name, sig, THREAD);
+  }
 
 #ifndef PRODUCT
-  if (TraceDefaultMethods) {
-    print_families(&families, sig);
+  if (target != NULL) {
+    if (TraceDefaultMethods) {
+      tty->print("    Returning ");
+      print_method(tty, target, true);
+      tty->print_cr("");
+    }
   }
 #endif // ndef PRODUCT
-
-  MethodFamily* selected_family = NULL;
-
-  for (int i = 0; i < families.length(); ++i) {
-    MethodFamily* lm = families.at(i);
-    if (lm->contains_signature(sig)) {
-      lm->determine_target(current_class, CHECK_NULL);
-      selected_family = lm;
-    }
-  }
-
-  if (selected_family->has_target()) {
-    Method* target = selected_family->get_selected_target();
-    InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
-
-    // Verify that the identified method is valid from the context of
-    // the current class
-    ShadowChecker checker(&cache, THREAD, target->name(),
-        holder, selected_family->descriptor(), direction);
-    checker.run(current_class);
-
-    if (checker.found_shadow()) {
-#ifndef PRODUCT
-      if (TraceDefaultMethods) {
-        tty->print_cr("    Only candidate found was shadowed.");
-      }
-#endif // ndef PRODUCT
-      THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
-                 "Accessible default method not found", NULL);
-    } else {
-#ifndef PRODUCT
-      if (TraceDefaultMethods) {
-        tty->print("    Returning ");
-        print_method(tty, target, true);
-        tty->print_cr("");
-      }
-#endif // ndef PRODUCT
-      return target;
-    }
-  } else {
-    assert(selected_family->throws_exception(), "must have target or throw");
-    THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
-               selected_family->get_exception_message()->as_C_string(), NULL);
-  }
+  return target;
 }
 
 
@@ -1139,14 +1396,20 @@
   return 3; // max stack size: [ exception, exception, string ]
 }
 
+// Also used to create an empty method for erased overpasses/symlinks
 static Method* new_method(
     BytecodeConstantPool* cp, BytecodeBuffer* bytecodes, Symbol* name,
     Symbol* sig, AccessFlags flags, int max_stack, int params,
-    ConstMethod::MethodType mt, TRAPS) {
+    ConstMethod::MethodType mt, Method* target, TRAPS) {
 
-  address code_start = static_cast<address>(bytecodes->adr_at(0));
-  int code_length = bytecodes->length();
-  InlineTableSizes sizes;
+  address code_start = 0;
+  int code_length = 0;
+  InlineTableSizes sizes(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, sizeof(Method*), 0 );
+
+  if (bytecodes != NULL && bytecodes->length() > 0) {
+    code_start = static_cast<address>(bytecodes->adr_at(0));
+    code_length = bytecodes->length();
+  }
 
   Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
                                code_length, flags, &sizes,
@@ -1165,6 +1428,9 @@
   m->constMethod()->set_stackmap_data(NULL);
   m->set_code(code_start);
   m->set_force_inline(true);
+  if (mt = ConstMethod::OVERPASS) {
+    m->set_target_method(target);
+  }
 
   return m;
 }
@@ -1224,8 +1490,9 @@
         }
       }
 #endif // ndef PRODUCT
+      Method* selected = NULL;
       if (method->has_target()) {
-        Method* selected = method->get_selected_target();
+        selected = method->get_selected_target();
         max_stack = assemble_redirect(
             &bpool, &buffer, slot->signature(), selected, CHECK);
       } else if (method->throws_exception()) {
@@ -1236,7 +1503,7 @@
           JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
       Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
           flags, max_stack, slot->size_of_parameters(),
-          ConstMethod::OVERPASS, CHECK);
+          ConstMethod::OVERPASS, selected, CHECK);
       if (m != NULL) {
         overpasses.push(m);
       }
@@ -1349,7 +1616,7 @@
 
   // Replace klass methods with new merged lists
   klass->set_methods(merged_methods);
-  klass->set_initial_method_idnum(new_size);
+  klass->set_initial_method_idnum(merged_methods->length());
 
   ClassLoaderData* cld = klass->class_loader_data();
   MetadataFactory::free_array(cld, original_methods);
--- a/src/share/vm/classfile/defaultMethods.hpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/classfile/defaultMethods.hpp	Wed Jun 19 19:42:37 2013 -0700
@@ -53,6 +53,7 @@
   static Method* find_super_default(
       Klass* this_klass, Klass* super_iface,
       Symbol* method_name, Symbol* method_sig, TRAPS);
+
 };
 
 #endif // SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
--- a/src/share/vm/interpreter/linkResolver.cpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/interpreter/linkResolver.cpp	Wed Jun 19 19:42:37 2013 -0700
@@ -552,6 +552,20 @@
       }
     }
   }
+
+  if (TraceItables && Verbose) {
+    ResourceMark rm(THREAD);
+    tty->print("invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
+                   (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
+                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+                   Method::name_and_sig_as_C_string(resolved_klass(),
+                                                    resolved_method->name(),
+                                                    resolved_method->signature()),
+                   resolved_method->method_holder()->internal_name()
+                  );
+    resolved_method->access_flags().print_on(tty);
+    tty->cr();
+  }
 }
 
 //------------------------------------------------------------------------------------------------------------------------
@@ -759,6 +773,20 @@
         Method* method = DefaultMethods::find_super_default(current_klass(),
             resolved_klass(), method_name, method_signature, CHECK);
         resolved_method = methodHandle(THREAD, method);
+
+        if (TraceItables && Verbose) {
+          ResourceMark rm(THREAD);
+          tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
+                      (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
+                      (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+                      Method::name_and_sig_as_C_string(resolved_klass(),
+                                                       resolved_method->name(),
+                                                       resolved_method->signature()),
+                      resolved_method->method_holder()->internal_name()
+                     );
+          resolved_method->access_flags().print_on(tty);
+          tty->cr();
+        }
         return;
       }
     }
@@ -855,6 +883,19 @@
 
   // setup result
   result.set_static(resolved_klass, sel_method, CHECK);
+
+    if (TraceItables && Verbose) {
+      ResourceMark rm(THREAD);
+      tty->print("invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
+                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+                   Method::name_and_sig_as_C_string(resolved_klass(),
+                                                    sel_method->name(),
+                                                    sel_method->signature()),
+                   sel_method->method_holder()->internal_name()
+                  );
+      sel_method->access_flags().print_on(tty);
+      tty->cr();
+    }
 }
 
 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass,
@@ -884,6 +925,20 @@
                                                                                                              resolved_method->signature()));
     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
+
+  if (PrintVtables && Verbose) {
+    ResourceMark rm(THREAD);
+    tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
+                   (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
+                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+                   Method::name_and_sig_as_C_string(resolved_klass(),
+                                                    resolved_method->name(),
+                                                    resolved_method->signature()),
+                   resolved_method->method_holder()->internal_name()
+                  );
+    resolved_method->access_flags().print_on(tty);
+    tty->cr();
+  }
 }
 
 // throws runtime exceptions
@@ -964,6 +1019,21 @@
 
   // setup result
   result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
+
+  if (PrintVtables && Verbose) {
+    ResourceMark rm(THREAD);
+    tty->print("invokevirtual selected  method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: ",
+                   (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()),
+                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+                   Method::name_and_sig_as_C_string(resolved_klass(),
+                                                    resolved_method->name(),
+                                                    resolved_method->signature()),
+                   selected_method->method_holder()->internal_name(),
+                   vtable_index
+                  );
+    selected_method->access_flags().print_on(tty);
+    tty->cr();
+  }
 }
 
 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass,
@@ -1047,6 +1117,20 @@
   }
   // setup result
   result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, CHECK);
+
+  if (TraceItables && Verbose) {
+    ResourceMark rm(THREAD);
+    tty->print("invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
+                   (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()),
+                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+                   Method::name_and_sig_as_C_string(resolved_klass(),
+                                                    resolved_method->name(),
+                                                    resolved_method->signature()),
+                   sel_method->method_holder()->internal_name()
+                  );
+    sel_method->access_flags().print_on(tty);
+    tty->cr();
+  }
 }
 
 
--- a/src/share/vm/oops/constMethod.cpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/oops/constMethod.cpp	Wed Jun 19 19:42:37 2013 -0700
@@ -137,6 +137,9 @@
   if (sizes->default_annotations_length() > 0) {
     extra_bytes += sizeof(AnnotationArray*);
   }
+  if (sizes->target_method_length() > 0) {
+    extra_bytes += sizeof(Method*);
+  }
 
   int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
   assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");
@@ -163,6 +166,7 @@
   if (has_parameter_annotations()) offset++;
   if (has_type_annotations()) offset++;
   if (has_default_annotations()) offset++;
+  if (has_target_method()) offset++;
   return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;
 }
 
@@ -256,6 +260,8 @@
     _flags |= _has_type_annotations;
   if (sizes->default_annotations_length() > 0)
     _flags |= _has_default_annotations;
+  if (sizes->target_method_length() > 0)
+    _flags |= _has_target_method;
 
   // This code is extremely brittle and should possibly be revised.
   // The *_length_addr functions walk backwards through the
@@ -363,6 +369,16 @@
   return (AnnotationArray**)constMethod_end() - offset;
 }
 
+Method** ConstMethod::target_method_addr() const {
+  assert(has_target_method(), "should only be called if overpass target method is present");
+  int offset = 1;
+  if (has_method_annotations()) offset++;
+  if (has_parameter_annotations()) offset++;
+  if (has_type_annotations()) offset++;
+  if (has_default_annotations()) offset++;
+  return (Method**)constMethod_end() - offset;
+}
+
 // copy annotations from 'cm' to 'this'
 void ConstMethod::copy_annotations_from(ConstMethod* cm) {
   if (cm->has_method_annotations()) {
--- a/src/share/vm/oops/constMethod.hpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/oops/constMethod.hpp	Wed Jun 19 19:42:37 2013 -0700
@@ -86,6 +86,9 @@
 // | generic signature index (u2)                         |
 // |  (indexed from start of constMethodOop)              |
 // |------------------------------------------------------|
+// | word-aligned Method* target_method if overpass       |
+// |  (access flags bit tells if present)                 |
+// |------------------------------------------------------|
 // | annotations arrays - method, parameter, type, default|
 // | pointer to Array<u1> if annotation is present        |
 // |------------------------------------------------------|
@@ -141,7 +144,8 @@
   do_element(method_annotations_length)         \
   do_element(parameter_annotations_length)      \
   do_element(type_annotations_length)           \
-  do_element(default_annotations_length)
+  do_element(default_annotations_length)        \
+  do_element(target_method_length)
 
 #define INLINE_TABLE_DECLARE(sym)    int _##sym;
 #define INLINE_TABLE_PARAM(sym)      int sym,
@@ -193,7 +197,8 @@
     _has_method_annotations = 0x0080,
     _has_parameter_annotations = 0x0100,
     _has_type_annotations = 0x0200,
-    _has_default_annotations = 0x0400
+    _has_default_annotations = 0x0400,
+    _has_target_method = 0x0800
   };
 
   // Bit vector of signature
@@ -395,6 +400,8 @@
   bool has_default_annotations() const
     { return (_flags & _has_default_annotations) != 0; }
 
+  bool has_target_method() const
+    { return (_flags & _has_target_method) != 0; }
 
   AnnotationArray** method_annotations_addr() const;
   AnnotationArray* method_annotations() const  {
@@ -428,6 +435,15 @@
     *(default_annotations_addr()) = anno;
   }
 
+  Method** target_method_addr() const;
+  Method* target_method() const {
+    return has_target_method() ? *(target_method_addr()) : NULL;
+  }
+  void set_target_method(Method* target) {
+    assert(has_target_method(), "only set target method for OVERPASS");
+    *(target_method_addr()) = target;
+  }
+
   int method_annotations_length() const {
     return has_method_annotations() ? method_annotations()->length() : 0;
   }
@@ -440,6 +456,11 @@
   int default_annotations_length() const {
     return has_default_annotations() ? default_annotations()->length() : 0;
   }
+  // This is just used to determine existence, not to count length
+  // returning nonzero is sufficient
+  int target_method_length() const {
+    return has_target_method() ? sizeof(Method*) : 0;
+  }
 
   // Copy annotations from other ConstMethod
   void copy_annotations_from(ConstMethod* cm);
--- a/src/share/vm/oops/klassVtable.cpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/oops/klassVtable.cpp	Wed Jun 19 19:42:37 2013 -0700
@@ -519,7 +519,7 @@
 // check if a method is a miranda method, given a class's methods table and it's super
 // the caller must make sure that the method belongs to an interface implemented by the class
 bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
-  if (m->is_static()) {
+  if (m->is_static() || m->is_private()) {
     return false;
   }
   Symbol* name = m->name();
--- a/src/share/vm/oops/method.cpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/oops/method.cpp	Wed Jun 19 19:42:37 2013 -0700
@@ -1124,6 +1124,7 @@
   int parameter_annotations_len = cm->parameter_annotations_length();
   int type_annotations_len = cm->type_annotations_length();
   int default_annotations_len = cm->default_annotations_length();
+  int target_method_len = cm->target_method_length();
 
   InlineTableSizes sizes(
       localvariable_len,
@@ -1136,6 +1137,7 @@
       parameter_annotations_len,
       type_annotations_len,
       default_annotations_len,
+      target_method_len,
       0);
 
   ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
--- a/src/share/vm/oops/method.hpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/oops/method.hpp	Wed Jun 19 19:42:37 2013 -0700
@@ -198,7 +198,11 @@
   AnnotationArray* type_annotations() const      {
     return constMethod()->type_annotations();
   }
-
+  // overpass support
+  void set_target_method(Method* target)         {
+     constMethod()->set_target_method(target); 
+  }
+  Method* target_method() const                  { return constMethod()->target_method(); }
 #ifdef CC_INTERP
   void set_result_index(BasicType type);
   int  result_index()                            { return _result_index; }
--- a/src/share/vm/runtime/globals.hpp	Fri Jun 07 09:25:19 2013 -0700
+++ b/src/share/vm/runtime/globals.hpp	Wed Jun 19 19:42:37 2013 -0700
@@ -3665,6 +3665,9 @@
   develop(bool, ParseAllGenericSignatures, false,                           \
           "Parse all generic signatures while classloading")                \
                                                                             \
+  product(bool, ParseGenericDefaults, false,                                \
+          "Parse all generic signatures while classloading")                \
+                                                                            \
   develop(bool, VerifyGenericSignatures, false,                             \
           "Abort VM on erroneous or inconsistent generic signatures")       \
                                                                             \