changeset 7324:7c663f528ff6

8008140: Better method handle resolution Reviewed-by: jrose, twisti, jdn
author vlivanov
date Fri, 01 Mar 2013 04:45:12 +0400
parents 269b7955a885
children b057eaf53935
files src/share/classes/java/lang/invoke/MethodHandles.java
diffstat 1 files changed, 24 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/MethodHandles.java	Thu Mar 28 09:50:40 2013 +0000
+++ b/src/share/classes/java/lang/invoke/MethodHandles.java	Fri Mar 01 04:45:12 2013 +0400
@@ -1237,6 +1237,30 @@
             checkMethod(refKind, refc, method);
             if (method.isMethodHandleInvoke())
                 return fakeMethodHandleInvoke(method);
+
+            Class<?> refcAsSuper;
+            if (refKind == REF_invokeSpecial &&
+                refc != lookupClass() &&
+                refc != (refcAsSuper = lookupClass().getSuperclass()) &&
+                refc.isAssignableFrom(lookupClass())) {
+                assert(!method.getName().equals("<init>"));  // not this code path
+                // Per JVMS 6.5, desc. of invokespecial instruction:
+                // If the method is in a superclass of the LC,
+                // and if our original search was above LC.super,
+                // repeat the search (symbolic lookup) from LC.super.
+                // FIXME: MemberName.resolve should handle this instead.
+                MemberName m2 = new MemberName(refcAsSuper,
+                                               method.getName(),
+                                               method.getMethodType(),
+                                               REF_invokeSpecial);
+                m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
+                if (m2 == null)  throw new InternalError(method.toString());
+                method = m2;
+                refc = refcAsSuper;
+                // redo basic checks
+                checkMethod(refKind, refc, method);
+            }
+
             MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
             mh = maybeBindCaller(method, mh, callerClass);
             mh = mh.setVarargs(method);