--- /dev/null	2009-02-04 23:35:20.000000000 -0800
+++ new/src/share/classes/java/dyn/Linkage.java	2009-02-04 23:35:19.000000000 -0800
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.dyn;
+
+import impl.java.dyn.util.MethodHandleInvoker;
+import java.util.WeakHashMap;
+import sun.reflect.Reflection;
+
+/**
+ * Static methods which control the linkage of invokedynamic call sites.
+ * @author John Rose, JSR 292 EG
+ */
+public class Linkage {
+    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#bootstrapInvokeDynamic}.
+     * <p>
+     * The operation will fail with an exception 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
+     *     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.
+     * </ul>
+     * Because of these rules, a class may install its own bootstrap method in
+     * a static initializer.
+     */
+    public static
+    void registerBootstrapMethod(Class callerClass, MethodHandle mh) {
+        Class callc = Reflection.getCallerClass(2);
+        checkPackagePrivilege(callc, callerClass, "registerBootstrapMethod");
+        if (mh != null && mh.type() != BOOTSTRAP_METHOD_TYPE)
+            throw new WrongMethodTypeException(mh.type().toString());
+        synchronized (bootstrapMethods) {
+            if (bootstrapMethods.containsKey(callerClass))
+                throw new IllegalStateException("bootstrap method already declared in "+callerClass);
+            bootstrapMethods.put(callerClass, mh);
+        }
+    }
+    
+    /**
+     * 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.
+     * Only callers privileged to set the bootstrap method may inquire
+     * about it, because a bootstrap method is potentially a back-door entry
+     * points to its class.
+     */
+    public static
+    MethodHandle getBootstrapMethod(Class callerClass) {
+        Class callc = Reflection.getCallerClass(2);
+        checkPackagePrivilege(callc, callerClass, "registerBootstrapMethod");
+        synchronized (bootstrapMethods) {
+            return bootstrapMethods.get(callerClass);
+        }
+    }
+
+    /** The type of any bootstrap method is (CallSite,Object...)Object.
+     *  The varargs marker is required.
+     */
+    public static final MethodType BOOTSTRAP_METHOD_TYPE
+            = MethodType.make(Object.class,
+                              CallSite.class, Object[].class);
+
+    private static MethodHandleInvoker bootstrapMethodInvoker;
+
+    private static final WeakHashMap<Class, MethodHandle> bootstrapMethods =
+            new WeakHashMap<Class, MethodHandle>();
+
+    /** Determine if the caller class has declared or registered its own bootstrap method.
+     *  If so, delegate this call to it.  Otherwise, throw an IncompatibleClassChangeError.
+     */
+    public static
+    Object bootstrapInvokeDynamic(CallSite site, Object... receiverAndArguments) {
+        Class callerClass = site.callerClass();
+        MethodHandle mh;
+        synchronized (bootstrapMethods) {
+            mh = bootstrapMethods.get(callerClass);
+        }
+        if (mh == null)
+            throw new IllegalStateException("no bootstrap method declared in "+callerClass);
+
+        System.out.println(site+": calling bootstrap "+mh);
+        if (bootstrapMethodInvoker == null)
+            bootstrapMethodInvoker = MethodHandleInvoker.make(BOOTSTRAP_METHOD_TYPE);
+        return bootstrapMethodInvoker.invoke(mh, site, receiverAndArguments);
+    }
+
+    /**
+     * Invalidate all <code>invokedynamic</code> call sites everywhere.
+     * <p>
+     * When this method returns, every <code>invokedynamic</code> instruction
+     * will invoke its bootstrap method on next call.
+     * <p>
+     * It is unspecified whether call sites already known to the Java
+     * code will continue to be associated with <code>invokedynamic</code>
+     * instructions.  If any call site is still so associated, its
+     * {@link CallSite#getTarget()} method is guaranteed to return null
+     * the invalidation operation completes.
+     * <p>
+     * Invalidation operations are likely to be slow.  Use them sparingly.
+     */
+    public static
+    Object invalidateAll() {
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    security.checkPermission(new LinkagePermission("invalidateAll"));
+	}
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    /**
+     * Invalidate all <code>invokedynamic</code> call sites associated
+     * with the given class.
+     * (These are exactly those sites which report the given class
+     * via the {@link CallSite#callerClass()} method.)
+     * <p>
+     * When this method returns, every matching <code>invokedynamic</code>
+     * instruction will invoke its bootstrap method on next call.
+     * <p>
+     * For additional semantics of call site invalidation,
+     * see {@link #invalidateAll()}.
+     */
+    public static
+    Object invalidateCallerClass(Class<?> callerClass) {
+	SecurityManager security = System.getSecurityManager();
+	if (security != null) {
+	    security.checkPermission(new LinkagePermission("invalidateAll", callerClass));
+	}
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    /**
+     * Ensure the requesting class have privileges to perform invokedynamic
+     * linkage operations on subjectClass.  True if requestingClass is
+     * null (meaning the request originates from the JVM) or if the
+     * classes are in the same package and have consistent class loaders.
+     * (The subject class loader must be identical with or be a child of
+     * the requesting class loader.)
+     * @param requestingClass
+     * @param subjectClass
+     * @return
+     */
+    static void checkPackagePrivilege(Class requestingClass, Class subjectClass,
+                                    String permissionName) {
+        if (requestingClass == null)  return;
+        if (requestingClass == subjectClass)  return;
+        SecurityManager security = System.getSecurityManager();
+        if (security == null)  return;  // open season
+        ClassLoader rcl = requestingClass.getClassLoader();
+        ClassLoader scl = subjectClass.getClassLoader();
+        if (isParent(rcl, scl)) {
+            String rn = requestingClass.getName();
+            if (rn.startsWith("java.dyn."))  return;
+            String sn = subjectClass.getName();
+            if (samePackage(rn, sn))  return;
+        }
+        security.checkPermission(new LinkagePermission(permissionName, requestingClass));
+    }
+    
+    static
+    MethodHandle findBootstrapMethod(Class callerClass, Class searchBootstrapClass) {
+        if (searchBootstrapClass != null)  throw new UnsupportedOperationException("NYI");
+        MethodHandle mh = getBootstrapMethod(callerClass);
+        System.out.println("reporting bootstrap method to JVM: "+mh);
+        return mh;
+    }
+
+    private static boolean isParent(ClassLoader rcl, ClassLoader scl) {
+        while (scl != null && scl != rcl)
+            scl = scl.getParent();
+        return (scl == rcl);
+    }
+
+    private static boolean samePackage(String rn, String sn) {
+        assert((rn.indexOf('/') & sn.indexOf('/')) < 0);  // no bytecode names
+        int lastDot  = rn.lastIndexOf('.');
+        if (lastDot != sn.lastIndexOf('.'))  return false;
+        return rn.startsWith(sn.substring(0, lastDot+1));
+    }
+
+}
