Merge
authorxdono
Tue, 12 May 2009 14:05:09 -0700
changeset 2765 b17924394fab
parent 2762 c56ab46cf4f7 (current diff)
parent 2764 2e45af54c0f9 (diff)
child 2766 4f2b43ae01b8
Merge
--- a/jdk/make/common/Release.gmk	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/make/common/Release.gmk	Tue May 12 14:05:09 2009 -0700
@@ -52,6 +52,9 @@
                         com.sun.java.swing.plaf.motif    \
                         com.sun.java.swing.plaf.gtk
 
+# This is a stopgap until 6839872 is fixed.
+EXCLUDE_PROPWARN_PKGS += sun.dyn
+
 # 64-bit solaris has a few special cases. We define the variable
 # SOLARIS64 for use in this Makefile to easily test those cases
 ifeq ($(PLATFORM), solaris)
--- a/jdk/make/docs/CORE_PKGS.gmk	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/make/docs/CORE_PKGS.gmk	Tue May 12 14:05:09 2009 -0700
@@ -97,6 +97,7 @@
   java.awt.print                                 \
   java.beans                                     \
   java.beans.beancontext                         \
+  java.dyn                                       \
   java.io                                        \
   java.lang                                      \
   java.lang.annotation                           \
--- a/jdk/src/share/classes/java/dyn/CallSite.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/java/dyn/CallSite.java	Tue May 12 14:05:09 2009 -0700
@@ -28,18 +28,28 @@
 import sun.dyn.util.BytecodeName;
 
 /**
- * An <code>invokedynamic</code> call site, as reified to the bootstrap method.
- * Every instance of a call site corresponds to a distinct instance
- * of the <code>invokedynamic</code> instruction.
- * Call sites have state, one reference word, called the <code>target</code>,
- * and typed as a {@link MethodHandle}.  When this state is null (as it is
- * initially) the call site is in the unlinked state.  Otherwise, it is said
- * to be linked to its target.
+ * An {@code invokedynamic} call site, as reified by the
+ * containing class's bootstrap method.
+ * Every call site object corresponds to a distinct instance
+ * of the <code>invokedynamic</code> instruction, and vice versa.
+ * Every call site has one state variable, called the {@code target}.
+ * It is typed as a {@link MethodHandle}.  This state is never null, and
+ * it is the responsibility of the bootstrap method to produce call sites
+ * which have been pre-linked to an initial target method.
  * <p>
- * When an unlinked call site is executed, a bootstrap routine is called
- * to finish the execution of the call site, and optionally to link
- * the call site.
+ * (Note:  The bootstrap method may elect to produce call sites of a
+ * language-specific subclass of {@code CallSite}.  In such a case,
+ * the subclass may claim responsibility for initializing its target to
+ * a non-null value, by overriding {@link #initialTarget}.)
  * <p>
+ * An {@code invokedynamic} instruction which has not yet been executed
+ * is said to be <em>unlinked</em>.  When an unlinked call site is executed,
+ * the containing class's bootstrap method is called to manufacture a call site,
+ * for the instruction.  If the bootstrap method does not assign a non-null
+ * value to the new call site's target variable, the method {@link #initialTarget}
+ * is called to produce the new call site's first target method.
+ * <p>
+ * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
  * @author John Rose, JSR 292 EG
  */
 public class CallSite {
@@ -52,6 +62,15 @@
     final String name;
     final MethodType type;
 
+    /**
+     * Make a call site given the parameters from a call to the bootstrap method.
+     * The resulting call site is in an unlinked state, which means that before
+     * it is returned from a bootstrap method call it must be provided with
+     * a target method via a call to {@link CallSite#setTarget}.
+     * @param caller the class in which the relevant {@code invokedynamic} instruction occurs
+     * @param name the name specified by the {@code invokedynamic} instruction
+     * @param type the method handle type derived from descriptor of the {@code invokedynamic} instruction
+     */
     public CallSite(Object caller, String name, MethodType type) {
         this.caller = caller;
         this.name = name;
@@ -73,7 +92,9 @@
      * <p>
      * If the bootstrap method itself does not initialize the call site,
      * this method must be overridden, because it just raises an
-     * {@code InvokeDynamicBootstrapError}.
+     * {@code InvokeDynamicBootstrapError}, which in turn causes the
+     * linkage of the {@code invokedynamic} instruction to terminate
+     * abnormally.
      */
     protected MethodHandle initialTarget() {
         throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+this);
@@ -81,7 +102,7 @@
 
     /**
      * Report the current linkage state of the call site.  (This is mutable.)
-     * The value is null if and only if the call site is currently unlinked.
+     * The value maybe null only if the call site is currently unlinked.
      * When a linked call site is invoked, the target method is used directly.
      * When an unlinked call site is invoked, its bootstrap method receives
      * the call, as if via {@link Linkage#bootstrapInvokeDynamic}.
@@ -113,8 +134,9 @@
      * into the bootstrap method and/or the target methods used
      * at any given call site.
      * @param target the new target, or null if it is to be unlinked
-     * @throws WrongMethodTypeException if the new target is not null
-     *         and has a method type that differs from the call site's {@link #type}
+     * @throws NullPointerException if the proposed new target is null
+     * @throws WrongMethodTypeException if the proposed new target
+     *         has a method type that differs from the call site's {@link #type()}
      */
     public void setTarget(MethodHandle target) {
         checkTarget(target);
@@ -122,6 +144,7 @@
     }
 
     protected void checkTarget(MethodHandle target) {
+        target.type();  // provoke NPE
         if (!canSetTarget(target))
             throw new WrongMethodTypeException(String.valueOf(target));
     }
@@ -132,7 +155,7 @@
 
     /**
      * Report the class containing the call site.
-     * This is immutable static context.
+     * This is an immutable property of the call site, set from the first argument to the constructor.
      * @return class containing the call site
      */
     public Class<?> callerClass() {
@@ -141,7 +164,7 @@
 
     /**
      * Report the method name specified in the {@code invokedynamic} instruction.
-     * This is immutable static context.
+     * This is an immutable property of the call site, set from the second argument to the constructor.
      * <p>
      * Note that the name is a JVM bytecode name, and as such can be any
      * non-empty string, as long as it does not contain certain "dangerous"
@@ -187,7 +210,7 @@
      * which are derived from its bytecode-level invocation descriptor.
      * The types are packaged into a {@link MethodType}.
      * Any linked target of this call site must be exactly this method type.
-     * This is immutable static context.
+     * This is an immutable property of the call site, set from the third argument to the constructor.
      * @return method type specified by the call site
      */
     public MethodType type() {
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Tue May 12 14:05:09 2009 -0700
@@ -26,10 +26,25 @@
 package java.dyn;
 
 /**
- * Syntactic marker interface to request javac to emit an {@code invokedynamic} instruction.
+ * Syntactic marker to request javac to emit an {@code invokedynamic} instruction.
+ * An {@code invokedynamic} instruction is a 5-byte bytecoded instruction
+ * which begins with an opcode byte of value 186 ({@code 0xBA}),
+ * and is followed by a two-byte index of a {@code NameAndType} constant
+ * pool entry, then by two zero bytes.  The constant pool reference gives
+ * the method name and argument and return types of the call site; there
+ * is no other information provided at the call site.
  * <p>
- * This type has no particular meaning as a class or interface supertype, and can never be instantiated.
+ * The {@code invokedynamic} instruction is incomplete without a target method.
+ * The target method is a property of the reified call site object
+ * (of type {@link CallSite}) which is in a one-to-one association with each
+ * corresponding {@code invokedynamic} instruction.  The call site object
+ * is initially produced by a <em>bootstrap method</em> associated with
+ * the call site, via the various overloadings of {@link Linkage#registerBootstrapMethod}.
+ * <p>
+ * The type {@code InvokeDynamic} has no particular meaning as a
+ * class or interface supertype, or an object type; it can never be instantiated.
  * Logically, it denotes a source of all dynamically typed methods.
+ * It may be viewed as a pure syntactic marker (an importable one) of static calls.
  * @author John Rose, JSR 292 EG
  */
 public final class InvokeDynamic {
--- a/jdk/src/share/classes/java/dyn/Linkage.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/java/dyn/Linkage.java	Tue May 12 14:05:09 2009 -0700
@@ -37,16 +37,19 @@
     private Linkage() {}  // do not instantiate
 
     /**
-     * Register a bootstrap method for use for a given caller class.
-     * The method handle must be of a type equivalent to {@link Linkage#makeCallSite}.
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Register a <em>bootstrap method</em> to use when linking a given caller class.
+     * It must be a method handle of a type equivalent to {@link CallSite#CallSite}.
+     * In other words, it must act as a factory method which accepts the arguments
+     * to {@code CallSite}'s constructor (a class, a string, and a method type),
+     * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
      * <p>
-     * The operation will fail with an exception if any of the following conditions hold:
+     * The registration will fail with an {@code IllegalStateException} if any of the following conditions hold:
      * <ul>
      * <li>The caller of this method is in a different package than the {@code callerClass},
      *     and there is a security manager, and its {@code checkPermission} call throws
      *     when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass).
-     * <li>The given class already has a bootstrap method, either from an embedded
-     *     {@code BootstrapInvokeDynamic} classfile attribute, or from a previous
+     * <li>The given class already has a bootstrap method from a previous
      *     call to this method.
      * <li>The given class is already fully initialized.
      * <li>The given class is in the process of initialization, in another thread.
@@ -75,9 +78,10 @@
     }
 
     /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Simplified version of registerBootstrapMethod for self-registration,
      * to be called from a static initializer.
-     * Finds a static method of type (CallSite, Object[]) -> Object in the
+     * Finds a static method of the required type in the
      * given class, and installs it on the caller.
      * @throws IllegalArgumentException if there is no such method
      */
@@ -92,9 +96,10 @@
     }
 
     /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Simplified version of registerBootstrapMethod for self-registration,
      * to be called from a static initializer.
-     * Finds a static method of type (CallSite, Object[]) -> Object in the
+     * Finds a static method of the required type in the
      * caller's class, and installs it on the caller.
      * @throws IllegalArgumentException if there is no such method
      */
@@ -109,6 +114,7 @@
     }
 
     /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Report the bootstrap method registered for a given class.
      * Returns null if the class has never yet registered a bootstrap method,
      * or if the class has explicitly registered a null bootstrap method.
@@ -125,8 +131,10 @@
         }
     }
 
-    /** The type of any bootstrap method is a three-argument method
-     * {@code (Class<?>, String, MethodType)} returning a {@code CallSite}.
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * The type of any bootstrap method is a three-argument method
+     * {@code (Class, String, MethodType)} returning a {@code CallSite}.
      */
     public static final MethodType BOOTSTRAP_METHOD_TYPE
             = MethodType.make(CallSite.class,
@@ -140,6 +148,7 @@
             new WeakHashMap<Class, MethodHandle>();
 
     /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Invalidate all <code>invokedynamic</code> call sites everywhere.
      * <p>
      * When this method returns, every <code>invokedynamic</code> instruction
@@ -163,6 +172,7 @@
     }
 
     /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * Invalidate all <code>invokedynamic</code> call sites associated
      * with the given class.
      * (These are exactly those sites which report the given class
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/java/dyn/MethodHandles.java	Tue May 12 14:05:09 2009 -0700
@@ -73,6 +73,7 @@
     }
 
     /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
      * A factory object for creating method handles, when the creation
      * requires access checking.  Method handles do not perform
      * access checks when they are called; this is a major difference
@@ -108,8 +109,10 @@
      * access.  In any of these cases, an exception will be
      * thrown from the attempted lookup.
      * In general, the conditions under which a method handle may be
-     * created for a method M are exactly as restrictive as the conditions
-     * under which the lookup class could have compiled a call to M.
+     * created for a method {@code M} are exactly as restrictive as the conditions
+     * under which the lookup class could have compiled a call to {@code M}.
+     * At least some of these error conditions are likely to be
+     * represented by checked exceptions in the final version of this API.
      */
     public static final
     class Lookup {
@@ -142,27 +145,30 @@
             this.lookupClass = lookupClass;
         }
 
+        private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
+
         /** Version of lookup which is trusted minimally.
          *  It can only be used to create method handles to
          *  publicly accessible members.
          */
-        public static final Lookup PUBLIC_LOOKUP = new Lookup(null);
+        public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
 
         /** Package-private version of lookup which is trusted. */
-        static final Lookup IMPL_LOOKUP = new Lookup(Access.class);
+        static final Lookup IMPL_LOOKUP = new Lookup(null);
         static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
 
         private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
-            if (lookupClass == null ||
-                lookupClass == Access.class ||
-                lookupClass.getName().startsWith("java.dyn."))
+            String name = lookupClass.getName();
+            if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
                 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
         }
 
         @Override
         public String toString() {
+            if (lookupClass == PUBLIC_ONLY)
+                return "public";
             if (lookupClass == null)
-                return "public";
+                return "privileged";
             return lookupClass.getName();
         }
 
@@ -202,6 +208,13 @@
          * with the receiver type ({@code defc}) prepended.
          * The method and all its argument types must be accessible to the lookup class.
          * <p>
+         * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
+         * of the receiver type, if the receiver type is not on the boot class path.
+         * This is due to a temporary JVM limitation, in which MethodHandle
+         * claims to be unable to access such classes.  To work around this
+         * bug, use {@code convertArguments} to normalize the type of the leading
+         * argument to a type on the boot class path, such as {@code Object}.)
+         * <p>
          * When called, the handle will treat the first argument as a receiver
          * and dispatch on the receiver's type to determine which method
          * implementation to enter.
@@ -222,11 +235,11 @@
 
         /**
          * Produce an early-bound method handle for a virtual method,
-         * or a handle for a constructor, as if called from an {@code invokespecial}
+         * as if called from an {@code invokespecial}
          * instruction from {@code caller}.
-         * The type of the method handle will be that of the method or constructor,
+         * The type of the method handle will be that of the method,
          * with a suitably restricted receiver type (such as {@code caller}) prepended.
-         * The method or constructor and all its argument types must be accessible
+         * The method and all its argument types must be accessible
          * to the caller.
          * <p>
          * When called, the handle will treat the first argument as a receiver,
@@ -250,8 +263,7 @@
             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
             checkStatic(false, method, lookupClass);
             if (name.equals("<init>")) {
-                if (defc != specialCaller)
-                    throw newNoAccessException("constructor must be local to lookup class", method, lookupClass);
+                throw newNoAccessException("cannot directly invoke a constructor", method, null);
             } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
                 throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
             }
--- a/jdk/src/share/classes/java/dyn/MethodType.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/java/dyn/MethodType.java	Tue May 12 14:05:09 2009 -0700
@@ -333,7 +333,7 @@
 
     /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
      * Convert all wrapper types to their corresponding primitive types.
-     * A return type of {@java.lang.Void} is changed to {@code void}.
+     * A return type of {@code java.lang.Void} is changed to {@code void}.
      * @return a version of the original type with all wrapper types replaced
      */
     public MethodType unwrap() {
--- a/jdk/src/share/classes/sun/dyn/DirectMethodHandle.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/sun/dyn/DirectMethodHandle.java	Tue May 12 14:05:09 2009 -0700
@@ -45,8 +45,6 @@
         if (!m.isResolved())
             throw new InternalError();
 
-        // Null check and replace privilege token (as passed to JVM) with null.
-        if (lookupClass.equals(Access.class))  lookupClass = null;
         MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
     }
 
--- a/jdk/src/share/classes/sun/dyn/MemberName.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/sun/dyn/MemberName.java	Tue May 12 14:05:09 2009 -0700
@@ -450,7 +450,7 @@
             for (;;) {
                 int bufCount = MethodHandleNatives.getMembers(defc,
                         matchName, matchSig, matchFlags,
-                        MethodHandleNatives.asNativeCaller(lookupClass),
+                        lookupClass,
                         totalCount, buf);
                 if (bufCount <= buf.length) {
                     if (bufCount >= 0)
@@ -487,14 +487,13 @@
             return result;
         }
         boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
-            Class<?> caller = MethodHandleNatives.asNativeCaller(lookupClass);
-            MethodHandleNatives.resolve(m, caller);
+            MethodHandleNatives.resolve(m, lookupClass);
             if (m.isResolved())  return true;
             int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
             String matchSig = m.getSignature();
             MemberName[] buf = { m };
             int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
-                    m.getName(), matchSig, matchFlags, caller, 0, buf);
+                    m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
             if (n != 1)  return false;
             return m.isResolved();
         }
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Tue May 12 14:05:09 2009 -0700
@@ -95,7 +95,7 @@
 
     public static void initLookup(Access token, Lookup lookup) {
         Access.check(token);
-        if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != Access.class)
+        if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != null)
             throw new InternalError();
         IMPL_LOOKUP_INIT = lookup;
     }
@@ -144,19 +144,28 @@
             boolean doDispatch, Class<?> lookupClass) {
         Access.check(token);  // only trusted calls
         MethodType mtype = method.getMethodType();
+        MethodType rtype = mtype;
         if (method.isStatic()) {
             doDispatch = false;
         } else {
             // adjust the advertised receiver type to be exactly the one requested
             // (in the case of invokespecial, this will be the calling class)
-            mtype = mtype.insertParameterType(0, method.getDeclaringClass());
+            Class<?> recvType = method.getDeclaringClass();
+            mtype = mtype.insertParameterType(0, recvType);
             if (method.isConstructor())
                 doDispatch = true;
+            // FIXME: JVM has trouble building MH.invoke sites for
+            // classes off the boot class path
+            rtype = mtype;
+            if (recvType.getClassLoader() != null)
+                rtype = rtype.changeParameterType(0, Object.class);
         }
         DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
         if (!mh.isValid())
             throw newNoAccessException(method, lookupClass);
-        return mh;
+        MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh);
+        if (rmh == null)  throw new InternalError();
+        return rmh;
     }
 
     public static
@@ -189,6 +198,15 @@
     MethodHandle bindReceiver(Access token,
                               MethodHandle target, Object receiver) {
         Access.check(token);
+        if (target instanceof AdapterMethodHandle) {
+            Object info = MethodHandleNatives.getTargetInfo(target);
+            if (info instanceof DirectMethodHandle) {
+                DirectMethodHandle dmh = (DirectMethodHandle) info;
+                if (receiver == null ||
+                    dmh.type().parameterType(0).isAssignableFrom(receiver.getClass()))
+                    target = dmh;
+            }
+        }
         if (target instanceof DirectMethodHandle)
             return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
         return null;   // let caller try something else
--- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Tue May 12 14:05:09 2009 -0700
@@ -47,14 +47,6 @@
     static native int getMembers(Class<?> defc, String matchName, String matchSig,
             int matchFlags, Class<?> caller, int skip, MemberName[] results);
 
-    static Class<?> asNativeCaller(Class<?> lookupClass) {
-        if (lookupClass == null)  // means "public only, non-privileged"
-            return sun.dyn.empty.Empty.class;
-        if (lookupClass == Access.class)  // means "internal, privileged"
-            return null;    // to the JVM, null means completely privileged
-        return lookupClass;
-    }
-
     /// MethodHandle support
 
     /** Initialize the method handle to adapt the call. */
--- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java	Tue May 12 00:40:13 2009 -0700
+++ b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java	Tue May 12 14:05:09 2009 -0700
@@ -95,7 +95,7 @@
     public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
         if (class1 == class2)
             return true;
-        if (loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
+        if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
             return false;
         String name1 = class1.getName(), name2 = class2.getName();
         int dot = name1.lastIndexOf('.');
@@ -159,7 +159,7 @@
      */
     public static void checkBootstrapPrivilege(Class requestingClass, Class subjectClass,
                                                String permissionName) {
-        if (requestingClass == Access.class)  return;
+        if (requestingClass == null)          return;
         if (requestingClass == subjectClass)  return;
         SecurityManager security = System.getSecurityManager();
         if (security == null)  return;  // open season