meth, indy: change impl.java.dyn => sun.dyn; consolidate final 6655638 changes
authorjrose
Wed Apr 08 02:53:50 2009 -0700 (7 months ago)
changeset 22ebca5d6f234d
parent 21daca8baee5f4
child 23a5f19be63c32
meth, indy: change impl.java.dyn => sun.dyn; consolidate final 6655638 changes
indy.patch
meth.patch
--- a/indy.patch Tue Apr 07 02:06:36 2009 -0700
+++ b/indy.patch Wed Apr 08 02:53:50 2009 -0700
@@ -17,10 +17,677 @@ diff --git a/make/Makefile b/make/Makefi
all build::
$(SUBDIRS-loop)
-diff --git a/src/share/classes/impl/java/dyn/AdapterMethodHandle.java b/src/share/classes/impl/java/dyn/AdapterMethodHandle.java
---- a/src/share/classes/impl/java/dyn/AdapterMethodHandle.java
-+++ b/src/share/classes/impl/java/dyn/AdapterMethodHandle.java
-@@ -341,10 +341,7 @@
+diff --git a/src/share/classes/java/dyn/CallSite.java b/src/share/classes/java/dyn/CallSite.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/java/dyn/CallSite.java
+@@ -0,0 +1,176 @@
++/*
++ * 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 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.
++ * <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.
++ * <p>
++ * @author John Rose, JSR 292 EG
++ */
++public abstract class CallSite {
++ protected MethodHandle target;
++ protected final Object caller; // usually a class
++ protected final String name;
++ protected final MethodType type;
++
++ protected CallSite(Object caller, String name, MethodType type) {
++ this.caller = caller;
++ this.name = name;
++ this.type = type;
++ }
++
++ /**
++ * 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.
++ * 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}.
++ * <p>
++ * The interactions of {@code getTarget} with memory are the same
++ * as of a read from an ordinary variable, such as an array element or a
++ * non-volatile, non-final field.
++ * <p>
++ * In particular, the current thread may choose to reuse the result
++ * of a previous read of the target from memory, and may fail to see
++ * a recent update to the target by another thread.
++ * @return the current linkage state of the call site
++ * @see #setTarget
++ */
++ public MethodHandle getTarget() {
++ return target;
++ }
++
++ /**
++ * Link or relink the call site, by setting its target method.
++ * <p>
++ * The interactions of {@code setTarget} with memory are the same
++ * as of a write to an ordinary variable, such as an array element or a
++ * non-volatile, non-final field.
++ * <p>
++ * In particular, unrelated threads may fail to see the updated target
++ * until they perform a read from memory.
++ * Stronger guarantees can be created by putting appropriate operations
++ * 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}
++ */
++ public void setTarget(MethodHandle target) {
++ checkTarget(target);
++ this.target = target;
++ }
++
++ protected void checkTarget(MethodHandle target) {
++ if (!canSetTarget(target))
++ throw new WrongMethodTypeException(String.valueOf(target));
++ }
++
++ protected boolean canSetTarget(MethodHandle target) {
++ return (target == null || target.type() == type());
++ }
++
++ /**
++ * Report the class containing the call site.
++ * This is immutable static context.
++ * @return class containing the call site
++ */
++ public Class<?> callerClass() {
++ return (Class) caller;
++ }
++
++ /**
++ * Report the method name specified in the {@code invokedynamic} instruction.
++ * This is immutable static context.
++ * <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"
++ * characters such as slash {@code '/'} and dot {@code '.'}.
++ * See the Java Virtual Machine specification for more details.
++ * <p>
++ * Application such as a language runtimes may need to encode
++ * arbitrary program element names and other configuration information
++ * into the name. A standard convention for doing this is
++ * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
++ * @return method name specified by the call site
++ */
++ public String name() {
++ return name;
++ }
++
++ /**
++ * Report the method name specified in the {@code invokedynamic} instruction,
++ * as a series of components, individually demangled according to
++ * the standard convention
++ * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
++ * <p>
++ * Non-empty runs of characters between dangerous characters are demangled.
++ * Each component is either a completely arbitrary demangled string,
++ * or else a character constant for a punctuation character, typically ':'.
++ * (In principle, the character can be any dangerous character that the
++ * JVM lets through in a method name, such as '$' or ']'.
++ * Runtime implementors are encouraged to use colon ':' for building
++ * structured names.)
++ * <p>
++ * In the common case where the name contains no dangerous characters,
++ * the result is an array whose only element array is the demangled
++ * name at the call site. Such a demangled name can be any sequence
++ * of any number of any unicode characters.
++ * @return method name components specified by the call site
++ */
++ public Object[] nameComponents() {
++ return BytecodeName.parseBytecodeName(name);
++ }
++
++ /**
++ * Report the resolved result and parameter types of this call site,
++ * 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.
++ * @return method type specified by the call site
++ */
++ public MethodType type() {
++ return type;
++ }
++
++ @Override
++ public String toString() {
++ return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]";
++ }
++}
+diff --git a/src/share/classes/java/dyn/Dynamic.java b/src/share/classes/java/dyn/Dynamic.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/java/dyn/Dynamic.java
+@@ -0,0 +1,50 @@
++/*
++ * 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;
++
++/**
++ * Syntactic marker interface to request javac to emit an {@code invokedynamic} instruction.
++ * A language compiler might use this interface to express invokedynamic instructions as follows:
++ * <blockquote><pre>
++ * Dynamic.greet("hello world", 123);
++ * // previous line generates invokedynamic "greet" "(Ljava/lang/String;I)Ljava/lang/Object;"
++ * Dynamic.&gt;void&lt;println(123);
++ * // previous line generates invokedynamic "println" "(I)V"
++ * Dynamic.#"long:strange:name"();
++ * // previous line generates invokedynamic "long:strange:name" "()Ljava/lang/Object;"
++ * </pre></blockquote>
++ * <p>
++ * This type has no particular meaning as a class or interface supertype, and need never be implemented by any class.
++ * Logically, it denotes a dynamically typed reference to any object.
++ * As such it may be viewed as logically containing all methods on any of those types.
++ * <p>
++ * This type may be used as a marker interface for arguments to method handles, in order
++ * to distinguish the static type {@code Object} from a dynamically typed reference.
++ * @author John Rose, JSR 292 EG
++ */
++public interface Dynamic {
++ // no methods
++}
+diff --git a/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
+@@ -0,0 +1,53 @@
++/*
++ * 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;
++
++/**
++ * Thrown to indicate that an {@code invokedynamic} instruction has
++ * failed to find its bootstrap method.
++ * This must have been declared during a class's initialization
++ * by a call to {@link Linkage#registerBootstrapMethod}.
++ *
++ * @author John Rose, JSR 292 EG
++ */
++public class InvokeDynamicBootstrapError extends LinkageError {
++ /**
++ * Constructs a {@code InvokeDynamicBootstrapError} with no detail message.
++ */
++ public InvokeDynamicBootstrapError() {
++ super();
++ }
++
++ /**
++ * Constructs a {@code InvokeDynamicBootstrapError} with the specified
++ * detail message.
++ *
++ * @param s the detail message.
++ */
++ public InvokeDynamicBootstrapError(String s) {
++ super(s);
++ }
++}
+diff --git a/src/share/classes/java/dyn/Linkage.java b/src/share/classes/java/dyn/Linkage.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/java/dyn/Linkage.java
+@@ -0,0 +1,252 @@
++/*
++ * 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 sun.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);
++ }
++ }
++
++ /**
++ * 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
++ * caller's class, and installs it on the caller.
++ * @throws IllegalArgumentException if there is no such method
++ */
++ public static
++ void registerBootstrapMethod(String name) {
++ Class callc = Reflection.getCallerClass(2);
++ MethodHandle bootstrapMethod =
++ MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE);
++ if (bootstrapMethod == null)
++ throw new IllegalArgumentException("cannot find bootstrap method: "+name);
++ Linkage.registerBootstrapMethod(callc, bootstrapMethod);
++ }
++
++ /**
++ * 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
++ * point into 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.
++ * <p>
++ * This routine, or an equivalent sequence of actions, is called from the
++ * JVM when an {@code invokedynamic} instruction is executed
++ * but its call site is unlinked (has a null target method).
++ * <p>
++ * This routine can be called from Java code whether or not the call site
++ * currently has a target, and will invoke the bootstrap method regardless
++ * of he call site's linkage state.
++ * <p>
++ * Although invoking the bootstrap method does not in and of itself cause
++ * state change in the call site, the actions eventually performed by
++ * the bootstrap method may include installed a new target on the call site.
++ * <p>
++ * Note that linkage state changes are individually atomic, but are not
++ * serialized in any way with respect to calls to the bootstrap method,
++ * or executions of the {@code invokedynamic} instruction. Therefore,
++ * an {@code invokedynamic} call site may be linked several times if
++ * several threads concurrently execute it in an unlinked state.
++ * It is up to the user-defined bootstrap method to make sure this
++ * race condition is resolved safely, either by performing linkage
++ * decisions under suitable locks (as the JVM does) or by ensuring
++ * that all racing threads come to the same conclusion, and independently
++ * install equivalent target methods.
++ */
++ public static
++ Object bootstrapInvokeDynamic(CallSite site, Object... arguments) {
++ 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); // FIXME
++ if (bootstrapMethodInvoker == null)
++ bootstrapMethodInvoker = MethodHandleInvoker.make(BOOTSTRAP_METHOD_TYPE);
++ return bootstrapMethodInvoker.invoke(mh, site, arguments);
++ }
++
++ /**
++ * 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
++ */
++ // FIXME: factor this logic into sun.dyn.util.VerifyAccess
++ 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); //FIXME
++ 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));
++ }
++
++}
+diff --git a/src/share/classes/java/dyn/LinkagePermission.java b/src/share/classes/java/dyn/LinkagePermission.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/java/dyn/LinkagePermission.java
+@@ -0,0 +1,111 @@
++/*
++ * 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 java.security.*;
++import java.util.Enumeration;
++import java.util.Hashtable;
++import java.util.StringTokenizer;
++
++/**
++ * This class is for runtime permissions. A RuntimePermission
++ * contains a name (also referred to as a "target name") but
++ * no actions list; you either have the named permission
++ * or you don't.
++ *
++ * <P>
++ * The target name is the name of the runtime permission (see below). The
++ * naming convention follows the hierarchical property naming convention.
++ * Also, an asterisk
++ * may appear at the end of the name, following a ".", or by itself, to
++ * signify a wildcard match. For example: "loadLibrary.*" or "*" is valid,
++ * "*loadLibrary" or "a*b" is not valid.
++ * <P>
++ * The following table lists all the possible RuntimePermission target names,
++ * and for each provides a description of what the permission allows
++ * and a discussion of the risks of granting code the permission.
++ * <P>
++ *
++ * <table border=1 cellpadding=5 summary="permission target name,
++ * what the target allows,and associated risks">
++ * <tr>
++ * <th>Permission Target Name</th>
++ * <th>What the Permission Allows</th>
++ * <th>Risks of Allowing this Permission</th>
++ * </tr>
++ *
++ * <tr>
++ * <td>registerBootstrapMethod.{class name}</td>
++ * <td>Specifying a bootstrap method for invokedynamic, within a class of the given name</td>
++ * <td>An attacker could attempt to attach a bootstrap method to a class which
++ * has just been loaded, thus gaining control of its invokedynamic calls.</td>
++ * </tr>
++ *
++ * <tr>
++ * <td>invalidateAll</td>
++ * <td>Force the relinking of invokedynamic call sites everywhere.</td>
++ * <td>This could allow an attacker to slow down the system, or perhaps surface timing bugs in a dynamic language implementations, by forcing redundant relinking operations.</td>
++ * </tr>
++ *
++ *
++ * <tr>
++ * <td>invalidateCallerClass.{class name}</td>
++ * <td>Force the relinking of invokedynamic call sites in the given class.</td>
++ * <td>See {@code invalidateAll}.</td>
++ * </tr>
++ * </table>
++ *
++ * @see java.security.BasicPermission
++ * @see java.lang.SecurityManager
++ *
++ * @author John Rose, JSR 292 EG
++ */
++
++public final class LinkagePermission extends BasicPermission {
++ /**
++ * Create a new LinkagePermission with the given name.
++ * The name is the symbolic name of the LinkagePermission, such as
++ * "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk
++ * may appear at the end of the name, following a ".", or by itself, to
++ * signify a wildcard match.
++ *
++ * @param name the name of the LinkagePermission
++ */
++ public LinkagePermission(String name) {
++ super(name);
++ }
++
++ /**
++ * Create a new LinkagePermission with the given name on the given class.
++ * Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}.
++ *
++ * @param name the name of the LinkagePermission
++ * @param clazz the class affected by the permission
++ */
++ public LinkagePermission(String name, Class<?> clazz) {
++ super(name + "." + clazz.getName());
++ }
++}
+diff --git a/src/share/classes/sun/dyn/AdapterMethodHandle.java b/src/share/classes/sun/dyn/AdapterMethodHandle.java
+--- a/src/share/classes/sun/dyn/AdapterMethodHandle.java
++++ b/src/share/classes/sun/dyn/AdapterMethodHandle.java
+@@ -338,10 +338,7 @@
@Override
public String toString() {
@@ -32,10 +699,10 @@ diff --git a/src/share/classes/impl/java
}
private static MethodHandle nonAdapter(MethodHandle mh) {
-diff --git a/src/share/classes/impl/java/dyn/CallSiteImpl.java b/src/share/classes/impl/java/dyn/CallSiteImpl.java
+diff --git a/src/share/classes/sun/dyn/CallSiteImpl.java b/src/share/classes/sun/dyn/CallSiteImpl.java
new file mode 100644
--- /dev/null
-+++ b/src/share/classes/impl/java/dyn/CallSiteImpl.java
++++ b/src/share/classes/sun/dyn/CallSiteImpl.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
@@ -62,7 +729,7 @@ new file mode 100644
+ * have any questions.
+ */
+
-+package impl.java.dyn;
++package sun.dyn;
+
+import java.dyn.*;
+
@@ -102,9 +769,9 @@ new file mode 100644
+ return site;
+ }
+}
-diff --git a/src/share/classes/impl/java/dyn/MethodHandleImpl.java b/src/share/classes/impl/java/dyn/MethodHandleImpl.java
---- a/src/share/classes/impl/java/dyn/MethodHandleImpl.java
-+++ b/src/share/classes/impl/java/dyn/MethodHandleImpl.java
+diff --git a/src/share/classes/sun/dyn/MethodHandleImpl.java b/src/share/classes/sun/dyn/MethodHandleImpl.java
+--- a/src/share/classes/sun/dyn/MethodHandleImpl.java
++++ b/src/share/classes/sun/dyn/MethodHandleImpl.java
@@ -252,18 +252,23 @@
}
@@ -132,10 +799,23 @@ diff --git a/src/share/classes/impl/java
+ return addTypeString(basicToString((MethodHandle)this));
}
}
-diff --git a/src/share/classes/impl/java/dyn/util/BytecodeName.java b/src/share/classes/impl/java/dyn/util/BytecodeName.java
+diff --git a/src/share/classes/sun/dyn/MethodHandleNatives.java b/src/share/classes/sun/dyn/MethodHandleNatives.java
+--- a/src/share/classes/sun/dyn/MethodHandleNatives.java
++++ b/src/share/classes/sun/dyn/MethodHandleNatives.java
+@@ -59,6 +59,9 @@
+ /** Initialize a method type, once per form. */
+ static native void init(MethodType self);
+
++ /** Tell the JVM that we need to change the target of an invokedynamic. */
++ static native void linkCallSite(CallSiteImpl site, MethodHandle target);
++
+ /** Fetch the vmtarget field.
+ * It will be sanitized as necessary to avoid exposing non-Java references.
+ * This routine is for debugging and reflection.
+diff --git a/src/share/classes/sun/dyn/util/BytecodeName.java b/src/share/classes/sun/dyn/util/BytecodeName.java
new file mode 100644
--- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/BytecodeName.java
++++ b/src/share/classes/sun/dyn/util/BytecodeName.java
@@ -0,0 +1,711 @@
+/*
+ * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
@@ -162,7 +842,7 @@ new file mode 100644
+ * have any questions.
+ */
+
-+package impl.java.dyn.util;
++package sun.dyn.util;
+
+/**
+ * Utility routines for dealing with bytecode-level names.
@@ -848,670 +1528,3 @@ new file mode 100644
+ }
+ }
+}
-diff --git a/src/share/classes/java/dyn/CallSite.java b/src/share/classes/java/dyn/CallSite.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/java/dyn/CallSite.java
-@@ -0,0 +1,176 @@
-+/*
-+ * 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.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.
-+ * <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.
-+ * <p>
-+ * @author John Rose, JSR 292 EG
-+ */
-+public abstract class CallSite {
-+ protected MethodHandle target;
-+ protected final Object caller; // usually a class
-+ protected final String name;
-+ protected final MethodType type;
-+
-+ protected CallSite(Object caller, String name, MethodType type) {
-+ this.caller = caller;
-+ this.name = name;
-+ this.type = type;
-+ }
-+
-+ /**
-+ * 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.
-+ * 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}.
-+ * <p>
-+ * The interactions of {@code getTarget} with memory are the same
-+ * as of a read from an ordinary variable, such as an array element or a
-+ * non-volatile, non-final field.
-+ * <p>
-+ * In particular, the current thread may choose to reuse the result
-+ * of a previous read of the target from memory, and may fail to see
-+ * a recent update to the target by another thread.
-+ * @return the current linkage state of the call site
-+ * @see #setTarget
-+ */
-+ public MethodHandle getTarget() {
-+ return target;
-+ }
-+
-+ /**
-+ * Link or relink the call site, by setting its target method.
-+ * <p>
-+ * The interactions of {@code setTarget} with memory are the same
-+ * as of a write to an ordinary variable, such as an array element or a
-+ * non-volatile, non-final field.
-+ * <p>
-+ * In particular, unrelated threads may fail to see the updated target
-+ * until they perform a read from memory.
-+ * Stronger guarantees can be created by putting appropriate operations
-+ * 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}
-+ */
-+ public void setTarget(MethodHandle target) {
-+ checkTarget(target);
-+ this.target = target;
-+ }
-+
-+ protected void checkTarget(MethodHandle target) {
-+ if (!canSetTarget(target))
-+ throw new WrongMethodTypeException(String.valueOf(target));
-+ }
-+
-+ protected boolean canSetTarget(MethodHandle target) {
-+ return (target == null || target.type() == type());
-+ }
-+
-+ /**
-+ * Report the class containing the call site.
-+ * This is immutable static context.
-+ * @return class containing the call site
-+ */
-+ public Class<?> callerClass() {
-+ return (Class) caller;
-+ }
-+
-+ /**
-+ * Report the method name specified in the {@code invokedynamic} instruction.
-+ * This is immutable static context.
-+ * <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"
-+ * characters such as slash {@code '/'} and dot {@code '.'}.
-+ * See the Java Virtual Machine specification for more details.
-+ * <p>
-+ * Application such as a language runtimes may need to encode
-+ * arbitrary program element names and other configuration information
-+ * into the name. A standard convention for doing this is
-+ * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
-+ * @return method name specified by the call site
-+ */
-+ public String name() {
-+ return name;
-+ }
-+
-+ /**
-+ * Report the method name specified in the {@code invokedynamic} instruction,
-+ * as a series of components, individually demangled according to
-+ * the standard convention
-+ * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
-+ * <p>
-+ * Non-empty runs of characters between dangerous characters are demangled.
-+ * Each component is either a completely arbitrary demangled string,
-+ * or else a character constant for a punctuation character, typically ':'.
-+ * (In principle, the character can be any dangerous character that the
-+ * JVM lets through in a method name, such as '$' or ']'.
-+ * Runtime implementors are encouraged to use colon ':' for building
-+ * structured names.)
-+ * <p>
-+ * In the common case where the name contains no dangerous characters,
-+ * the result is an array whose only element array is the demangled
-+ * name at the call site. Such a demangled name can be any sequence
-+ * of any number of any unicode characters.
-+ * @return method name components specified by the call site
-+ */
-+ public Object[] nameComponents() {
-+ return BytecodeName.parseBytecodeName(name);
-+ }
-+
-+ /**
-+ * Report the resolved result and parameter types of this call site,
-+ * 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.
-+ * @return method type specified by the call site
-+ */
-+ public MethodType type() {
-+ return type;
-+ }
-+
-+ @Override
-+ public String toString() {
-+ return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]";
-+ }
-+}
-diff --git a/src/share/classes/java/dyn/Dynamic.java b/src/share/classes/java/dyn/Dynamic.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/java/dyn/Dynamic.java
-@@ -0,0 +1,50 @@
-+/*
-+ * 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;
-+
-+/**
-+ * Syntactic marker interface to request javac to emit an {@code invokedynamic} instruction.
-+ * A language compiler might use this interface to express invokedynamic instructions as follows:
-+ * <blockquote><pre>
-+ * Dynamic.greet("hello world", 123);
-+ * // previous line generates invokedynamic "greet" "(Ljava/lang/String;I)Ljava/lang/Object;"
-+ * Dynamic.&gt;void&lt;println(123);
-+ * // previous line generates invokedynamic "println" "(I)V"
-+ * Dynamic.#"long:strange:name"();
-+ * // previous line generates invokedynamic "long:strange:name" "()Ljava/lang/Object;"
-+ * </pre></blockquote>
-+ * <p>
-+ * This type has no particular meaning as a class or interface supertype, and need never be implemented by any class.
-+ * Logically, it denotes a dynamically typed reference to any object.
-+ * As such it may be viewed as logically containing all methods on any of those types.
-+ * <p>
-+ * This type may be used as a marker interface for arguments to method handles, in order
-+ * to distinguish the static type {@code Object} from a dynamically typed reference.
-+ * @author John Rose, JSR 292 EG
-+ */
-+public interface Dynamic {
-+ // no methods
-+}
-diff --git a/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
-@@ -0,0 +1,53 @@
-+/*
-+ * 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;
-+
-+/**
-+ * Thrown to indicate that an {@code invokedynamic} instruction has
-+ * failed to find its bootstrap method.
-+ * This must have been declared during a class's initialization
-+ * by a call to {@link Linkage#registerBootstrapMethod}.
-+ *
-+ * @author John Rose, JSR 292 EG
-+ */
-+public class InvokeDynamicBootstrapError extends LinkageError {
-+ /**
-+ * Constructs a {@code InvokeDynamicBootstrapError} with no detail message.
-+ */
-+ public InvokeDynamicBootstrapError() {
-+ super();
-+ }
-+
-+ /**
-+ * Constructs a {@code InvokeDynamicBootstrapError} with the specified
-+ * detail message.
-+ *
-+ * @param s the detail message.
-+ */
-+ public InvokeDynamicBootstrapError(String s) {
-+ super(s);
-+ }
-+}
-diff --git a/src/share/classes/java/dyn/Linkage.java b/src/share/classes/java/dyn/Linkage.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/java/dyn/Linkage.java
-@@ -0,0 +1,252 @@
-+/*
-+ * 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);
-+ }
-+ }
-+
-+ /**
-+ * 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
-+ * caller's class, and installs it on the caller.
-+ * @throws IllegalArgumentException if there is no such method
-+ */
-+ public static
-+ void registerBootstrapMethod(String name) {
-+ Class callc = Reflection.getCallerClass(2);
-+ MethodHandle bootstrapMethod =
-+ MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE);
-+ if (bootstrapMethod == null)
-+ throw new IllegalArgumentException("cannot find bootstrap method: "+name);
-+ Linkage.registerBootstrapMethod(callc, bootstrapMethod);
-+ }
-+
-+ /**
-+ * 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
-+ * point into 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.
-+ * <p>
-+ * This routine, or an equivalent sequence of actions, is called from the
-+ * JVM when an {@code invokedynamic} instruction is executed
-+ * but its call site is unlinked (has a null target method).
-+ * <p>
-+ * This routine can be called from Java code whether or not the call site
-+ * currently has a target, and will invoke the bootstrap method regardless
-+ * of he call site's linkage state.
-+ * <p>
-+ * Although invoking the bootstrap method does not in and of itself cause
-+ * state change in the call site, the actions eventually performed by
-+ * the bootstrap method may include installed a new target on the call site.
-+ * <p>
-+ * Note that linkage state changes are individually atomic, but are not
-+ * serialized in any way with respect to calls to the bootstrap method,
-+ * or executions of the {@code invokedynamic} instruction. Therefore,
-+ * an {@code invokedynamic} call site may be linked several times if
-+ * several threads concurrently execute it in an unlinked state.
-+ * It is up to the user-defined bootstrap method to make sure this
-+ * race condition is resolved safely, either by performing linkage
-+ * decisions under suitable locks (as the JVM does) or by ensuring
-+ * that all racing threads come to the same conclusion, and independently
-+ * install equivalent target methods.
-+ */
-+ public static
-+ Object bootstrapInvokeDynamic(CallSite site, Object... arguments) {
-+ 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); // FIXME
-+ if (bootstrapMethodInvoker == null)
-+ bootstrapMethodInvoker = MethodHandleInvoker.make(BOOTSTRAP_METHOD_TYPE);
-+ return bootstrapMethodInvoker.invoke(mh, site, arguments);
-+ }
-+
-+ /**
-+ * 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
-+ */
-+ // FIXME: factor this logic into impl.java.dyn.util.VerifyAccess
-+ 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); //FIXME
-+ 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));
-+ }
-+
-+}
-diff --git a/src/share/classes/java/dyn/LinkagePermission.java b/src/share/classes/java/dyn/LinkagePermission.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/java/dyn/LinkagePermission.java
-@@ -0,0 +1,111 @@
-+/*
-+ * 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 java.security.*;
-+import java.util.Enumeration;
-+import java.util.Hashtable;
-+import java.util.StringTokenizer;
-+
-+/**
-+ * This class is for runtime permissions. A RuntimePermission
-+ * contains a name (also referred to as a "target name") but
-+ * no actions list; you either have the named permission
-+ * or you don't.
-+ *
-+ * <P>
-+ * The target name is the name of the runtime permission (see below). The
-+ * naming convention follows the hierarchical property naming convention.
-+ * Also, an asterisk
-+ * may appear at the end of the name, following a ".", or by itself, to
-+ * signify a wildcard match. For example: "loadLibrary.*" or "*" is valid,
-+ * "*loadLibrary" or "a*b" is not valid.
-+ * <P>
-+ * The following table lists all the possible RuntimePermission target names,
-+ * and for each provides a description of what the permission allows
-+ * and a discussion of the risks of granting code the permission.
-+ * <P>
-+ *
-+ * <table border=1 cellpadding=5 summary="permission target name,
-+ * what the target allows,and associated risks">
-+ * <tr>
-+ * <th>Permission Target Name</th>
-+ * <th>What the Permission Allows</th>
-+ * <th>Risks of Allowing this Permission</th>
-+ * </tr>
-+ *
-+ * <tr>
-+ * <td>registerBootstrapMethod.{class name}</td>
-+ * <td>Specifying a bootstrap method for invokedynamic, within a class of the given name</td>
-+ * <td>An attacker could attempt to attach a bootstrap method to a class which
-+ * has just been loaded, thus gaining control of its invokedynamic calls.</td>
-+ * </tr>
-+ *
-+ * <tr>
-+ * <td>invalidateAll</td>
-+ * <td>Force the relinking of invokedynamic call sites everywhere.</td>
-+ * <td>This could allow an attacker to slow down the system, or perhaps surface timing bugs in a dynamic language implementations, by forcing redundant relinking operations.</td>
-+ * </tr>
-+ *
-+ *
-+ * <tr>
-+ * <td>invalidateCallerClass.{class name}</td>
-+ * <td>Force the relinking of invokedynamic call sites in the given class.</td>
-+ * <td>See {@code invalidateAll}.</td>
-+ * </tr>
-+ * </table>
-+ *
-+ * @see java.security.BasicPermission
-+ * @see java.lang.SecurityManager
-+ *
-+ * @author John Rose, JSR 292 EG
-+ */
-+
-+public final class LinkagePermission extends BasicPermission {
-+ /**
-+ * Create a new LinkagePermission with the given name.
-+ * The name is the symbolic name of the LinkagePermission, such as
-+ * "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk
-+ * may appear at the end of the name, following a ".", or by itself, to
-+ * signify a wildcard match.
-+ *
-+ * @param name the name of the LinkagePermission
-+ */
-+ public LinkagePermission(String name) {
-+ super(name);
-+ }
-+
-+ /**
-+ * Create a new LinkagePermission with the given name on the given class.
-+ * Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}.
-+ *
-+ * @param name the name of the LinkagePermission
-+ * @param clazz the class affected by the permission
-+ */
-+ public LinkagePermission(String name, Class<?> clazz) {
-+ super(name + "." + clazz.getName());
-+ }
-+}
--- a/meth.patch Tue Apr 07 02:06:36 2009 -0700
+++ b/meth.patch Wed Apr 08 02:53:50 2009 -0700
@@ -95,3732 +95,6 @@ new file mode 100644
+AUTO_FILES_JAVA_DIRS = java/dyn impl/java/dyn impl/java/dyn/util
+
+include $(BUILDDIR)/common/Classes.gmk
-diff --git a/src/share/classes/impl/java/dyn/Access.java b/src/share/classes/impl/java/dyn/Access.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/Access.java
-@@ -0,0 +1,93 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import java.dyn.MethodHandles;
-+import sun.reflect.Reflection;
-+
-+/**
-+ * Access control to this package.
-+ * Classes in other packages can attempt to acquire the access token,
-+ * but will fail if they are not recognized as friends.
-+ * Certain methods in this package, although public, require a non-null
-+ * access token in order to proceed; they act like package-private methods.
-+ * @author jrose
-+ */
-+
-+public class Access {
-+ private Access() { }
-+
-+ /**
-+ * The heart of this pattern: The list of classes which are
-+ * permitted to acquire the access token, and become honorary
-+ * members of this package.
-+ */
-+ static private final String[] FRIENDS = {
-+ "java.dyn.", "impl.java.dyn."
-+ };
-+
-+ /**
-+ * The following object is NOT public. That's the point of the pattern.
-+ * It is package-private, so that any member of this package
-+ * can acquire the access token, and give it away to trusted friends.
-+ */
-+ static final Access TOKEN = new Access();
-+
-+ /**
-+ * @return Access.TOKEN, if the caller is a friend of this package
-+ */
-+ public static Access getToken() {
-+ Class<?> callc = Reflection.getCallerClass(2);
-+ if (callc.getClassLoader() == Access.class.getClassLoader()) {
-+ String callcName = callc.getName();
-+ for (String friend : FRIENDS) {
-+ if (callcName.startsWith(friend))
-+ return TOKEN;
-+ }
-+ }
-+ throw new IllegalAccessError("bad caller: " + callc);
-+ }
-+
-+ /**
-+ * Throw an IllegalAccessError if the caller does not possess
-+ * the Access.TOKEN.
-+ * @param must be Access.TOKEN
-+ */
-+ public static void check(Access token) {
-+ if (token == null)
-+ fail();
-+ // else it must be the unique Access.TOKEN
-+ assert(token == Access.TOKEN);
-+ }
-+ private static void fail() {
-+ Class<?> callc = Reflection.getCallerClass(3);
-+ throw new IllegalAccessError("bad caller: " + callc);
-+ }
-+
-+ static {
-+ //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/AdapterMethodHandle.java b/src/share/classes/impl/java/dyn/AdapterMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/AdapterMethodHandle.java
-@@ -0,0 +1,596 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import impl.java.dyn.util.VerifyType;
-+import impl.java.dyn.util.Wrappers;
-+import java.dyn.*;
-+import java.util.ArrayList;
-+import java.util.Arrays;
-+import java.util.List;
-+import static impl.java.dyn.MethodHandleNatives.Constants.*;
-+import static impl.java.dyn.MethodHandleImpl.newIllegalArgumentException;
-+
-+/**
-+ * This method handle performs simple conversion or checking of a single argument.
-+ * @author jrose
-+ */
-+public class AdapterMethodHandle extends BoundMethodHandle {
-+
-+ //MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
-+ //Object argument; // parameter to the conversion if needed
-+ //int vmargslot; // which argument slot is affected
-+ private final int conversion; // the type of conversion: RETYPE_ONLY, etc.
-+
-+ // Constructors in this class *must* be package scoped or private.
-+ private AdapterMethodHandle(MethodHandle target, MethodType newType,
-+ long conv, Object convArg) {
-+ super(newType, convArg, newType.parameterSlot(convArgPos(conv)));
-+ this.conversion = convCode(conv);
-+ if (MethodHandleNatives.JVM_SUPPORT) {
-+ // JVM might update VM-specific bits of conversion (ignore)
-+ MethodHandleNatives.init(this, target, convArgPos(conv));
-+ }
-+ }
-+ private AdapterMethodHandle(MethodHandle target, MethodType newType,
-+ long conv) {
-+ this(target, newType, conv, null);
-+ }
-+
-+ private static final Access IMPL_TOKEN = Access.getToken();
-+
-+ // TO DO: When adapting another MH with a null conversion, clone
-+ // the target and change its type, instead of adding another layer.
-+
-+ /** Can a JVM-level adapter directly implement the proposed
-+ * argument conversions, as if by MethodHandles.convertArguments?
-+ */
-+ public static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
-+ // same number of args, of course
-+ int len = newType.parameterCount();
-+ if (len != oldType.parameterCount())
-+ return false;
-+
-+ // Check return type. (Not much can be done with it.)
-+ Class<?> exp = newType.returnType();
-+ Class<?> ret = oldType.returnType();
-+ if (!VerifyType.isNullConversion(ret, exp))
-+ return false;
-+
-+ // Check args pairwise.
-+ for (int i = 0; i < len; i++) {
-+ Class<?> src = newType.parameterType(i); // source type
-+ Class<?> dst = oldType.parameterType(i); // destination type
-+ if (!canConvertArgument(src, dst))
-+ return false;
-+ }
-+
-+ return true;
-+ }
-+
-+ /** Can a JVM-level adapter directly implement the proposed
-+ * argument conversion, as if by MethodHandles.convertArguments?
-+ */
-+ public static boolean canConvertArgument(Class<?> src, Class<?> dst) {
-+ // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
-+ // so we don't need to repeat so much decision making.
-+ if (VerifyType.isNullConversion(src, dst)) {
-+ return true;
-+ } else if (src.isPrimitive()) {
-+ if (dst.isPrimitive())
-+ return canPrimCast(src, dst);
-+ else
-+ return canBoxArgument(src, dst);
-+ } else {
-+ if (dst.isPrimitive())
-+ return canUnboxArgument(src, dst);
-+ else
-+ return true; // any two refs can be interconverted
-+ }
-+ }
-+
-+ /**
-+ * Create a JVM-level adapter method handle to conform the given method
-+ * handle to the similar newType, using only pairwise argument conversions.
-+ * For each argument, convert incoming argument to the exact type needed.
-+ * Only null conversions are allowed on the return value (until
-+ * the JVM supports ricochet adapters).
-+ * The argument conversions allowed are casting, unboxing,
-+ * integral widening or narrowing, and floating point widening or narrowing.
-+ * @param token access check
-+ * @param newType required call type
-+ * @param target original method handle
-+ * @return an adapter to the original handle with the desired new type,
-+ * or the original target if the types are already identical
-+ * @throws IllegalArgumentException if the adaptation cannot be made
-+ * directly by a JVM-level adapter, without help from Java code
-+ */
-+ public static MethodHandle makePairwiseConvert(Access token,
-+ MethodType newType, MethodHandle target) {
-+ Access.check(token);
-+ MethodType oldType = target.type();
-+ if (newType == oldType) return target;
-+
-+ // caller responsibility:
-+ assert(canPairwiseConvert(newType, oldType));
-+
-+ // Find last non-trivial conversion (if any).
-+ int lastConv = newType.parameterCount()-1;
-+ while (lastConv >= 0) {
-+ Class<?> src = newType.parameterType(lastConv); // source type
-+ Class<?> dst = oldType.parameterType(lastConv); // destination type
-+ if (VerifyType.isNullConversion(src, dst)) {
-+ --lastConv;
-+ } else {
-+ break;
-+ }
-+ }
-+ // Now build a chain of one or more adapters.
-+ MethodHandle adapter = target;
-+ MethodType midType = oldType.changeReturnType(newType.returnType());
-+ for (int i = 0; i <= lastConv; i++) {
-+ Class<?> src = newType.parameterType(i); // source type
-+ Class<?> dst = midType.parameterType(i); // destination type
-+ if (VerifyType.isNullConversion(src, dst)) {
-+ // do nothing: difference is trivial
-+ continue;
-+ }
-+ // Work the current type backward toward the desired caller type:
-+ if (i != lastConv) {
-+ midType = midType.changeParameterType(i, src);
-+ } else {
-+ // When doing the last (or only) real conversion,
-+ // force all remaining null conversions to happen also.
-+ assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
-+ midType = newType;
-+ }
-+
-+ // Tricky case analysis follows.
-+ // It parallels canConvertArgument() above.
-+ if (src.isPrimitive()) {
-+ if (dst.isPrimitive()) {
-+ adapter = makePrimCast(token, midType, adapter, i, dst);
-+ } else {
-+ adapter = makeBoxArgument(token, midType, adapter, i, dst);
-+ }
-+ } else {
-+ if (dst.isPrimitive()) {
-+ // Caller has boxed a primitive. Unbox it for the target.
-+ // The box type must correspond exactly to the primitive type.
-+ // This is simpler than the powerful set of widening
-+ // conversions supported by reflect.Method.invoke.
-+ // Those conversions require a big nest of if/then/else logic,
-+ // which we prefer to make a user responsibility.
-+ adapter = makeUnboxArgument(token, midType, adapter, i, dst);
-+ } else {
-+ // Simple reference conversion.
-+ // Note: Do not check for a class hierarchy relation
-+ // between src and dst. In all cases a 'null' argument
-+ // will pass the cast conversion.
-+ adapter = makeCheckCast(token, midType, adapter, i, dst);
-+ }
-+ }
-+ assert(adapter.type() == midType);
-+ }
-+ if (adapter.type() != newType) {
-+ // Only trivial conversions remain.
-+ adapter = makeRetypeOnly(IMPL_TOKEN, newType, adapter);
-+ // Actually, that's because there were no non-trivial ones:
-+ assert(lastConv == -1);
-+ }
-+ assert(adapter.type() == newType);
-+ return adapter;
-+ }
-+
-+ /**
-+ * Create a JVM-level adapter method handle to permute the arguments
-+ * of the given method.
-+ * @param token access check
-+ * @param newType required call type
-+ * @param target original method handle
-+ * @param argumentMap for each target argument, position of its source in newType
-+ * @return an adapter to the original handle with the desired new type,
-+ * or the original target if the types are already identical
-+ * and the permutation is null
-+ * @throws IllegalArgumentException if the adaptation cannot be made
-+ * directly by a JVM-level adapter, without help from Java code
-+ */
-+ public static MethodHandle makePermutation(Access token,
-+ MethodType newType, MethodHandle target,
-+ int[] argumentMap) {
-+ MethodType oldType = target.type();
-+ boolean nullPermutation = true;
-+ for (int i = 0; i < argumentMap.length; i++) {
-+ int pos = argumentMap[i];
-+ if (pos != i)
-+ nullPermutation = false;
-+ if (pos < 0 || pos >= newType.parameterCount()) {
-+ argumentMap = new int[0]; break;
-+ }
-+ }
-+ if (argumentMap.length != oldType.parameterCount())
-+ throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
-+ if (nullPermutation)
-+ return makePairwiseConvert(token, newType, target); // well, that was easy
-+
-+ // Check return type. (Not much can be done with it.)
-+ Class<?> exp = newType.returnType();
-+ Class<?> ret = oldType.returnType();
-+ if (!VerifyType.isNullConversion(ret, exp))
-+ throw newIllegalArgumentException("bad return conversion for "+newType);
-+
-+ // See if the argument types match up.
-+ for (int i = 0; i < argumentMap.length; i++) {
-+ int j = argumentMap[i];
-+ Class<?> src = newType.parameterType(j);
-+ Class<?> dst = oldType.parameterType(i);
-+ if (!VerifyType.isNullConversion(src, dst))
-+ throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
-+ }
-+
-+ // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
-+ // A workable greedy algorithm is as follows:
-+ // Drop unused outgoing arguments (right to left: shallowest first).
-+ // Duplicate doubly-used outgoing arguments (left to right: deepest first).
-+ // Then the remaining problem is a true argument permutation.
-+ // Marshal the outgoing arguments as required from left to right.
-+ // That is, find the deepest outgoing stack position that does not yet
-+ // have the correct argument value, and correct at least that position
-+ // by swapping or rotating in the misplaced value (from a shallower place).
-+ // If the misplaced value is followed by one or more consecutive values
-+ // (also misplaced) issue a rotation which brings as many as possible
-+ // into position. Otherwise make progress with either a swap or a
-+ // rotation. Prefer the swap as cheaper, but do not use it if it
-+ // breaks a slot pair. Prefer the rotation over the swap if it would
-+ // preserve more consecutive values shallower than the target position.
-+ // When more than one rotation will work (because the required value
-+ // is already adjacent to the target position), then use a rotation
-+ // which moves the old value in the target position adjacent to
-+ // one of its consecutive values. Also, prefer shorter rotation
-+ // spans, since they use fewer memory cycles for shuffling.
-+
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ private static byte basicType(Class<?> type) {
-+ if (type == null) return T_VOID;
-+ char c = Wrappers.basicTypeChar(type);
-+ switch (c) {
-+ case 'Z': return T_BOOLEAN;
-+ case 'C': return T_CHAR;
-+ case 'F': return T_FLOAT;
-+ case 'D': return T_DOUBLE;
-+ case 'B': return T_BYTE;
-+ case 'S': return T_SHORT;
-+ case 'I': return T_INT;
-+ case 'J': return T_LONG;
-+ case 'L': return T_OBJECT;
-+ }
-+ return 99; // T_ILLEGAL or some such
-+ }
-+
-+ /** Number of stack slots for the given type.
-+ * Two for T_DOUBLE and T_FLOAT, one for the rest.
-+ */
-+ private static int type2size(int type) {
-+ assert(type >= T_BOOLEAN && type <= T_OBJECT);
-+ return (type == T_FLOAT || type == T_DOUBLE) ? 2 : 1;
-+ }
-+
-+ /** Construct an adapter conversion descriptor for a single-argument conversion. */
-+ private static long makeConv(int convOp, int argnum, int src, int dest) {
-+ assert(src == (src & 0xF));
-+ assert(dest == (dest & 0xF));
-+ assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
-+ long stackMove = type2size(dest) - type2size(src);
-+ return ((long) argnum << 32 |
-+ (long) convOp << CONV_OP_SHIFT |
-+ (int) src << CONV_SRC_TYPE_SHIFT |
-+ (int) dest << CONV_DEST_TYPE_SHIFT |
-+ stackMove << CONV_STACK_MOVE_SHIFT
-+ );
-+ }
-+ private static long makeConv(int convOp, int argnum, int stackMove) {
-+ assert(convOp >= OP_SWAP_ARGS && convOp <= OP_SPREAD_ARGS);
-+ byte src = 0, dest = 0;
-+ if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS)
-+ src = dest = T_OBJECT;
-+ return ((long) argnum << 32 |
-+ (long) convOp << CONV_OP_SHIFT |
-+ (int) src << CONV_SRC_TYPE_SHIFT |
-+ (int) dest << CONV_DEST_TYPE_SHIFT |
-+ stackMove << CONV_STACK_MOVE_SHIFT
-+ );
-+ }
-+ private static long makeConv(int convOp) {
-+ assert(convOp == OP_RETYPE_ONLY);
-+ return (long) convOp << CONV_OP_SHIFT; // stackMove, src, dst, argnum all zero
-+ }
-+ private static int convCode(long conv) {
-+ return (int)conv;
-+ }
-+ private static int convArgPos(long conv) {
-+ return (int)(conv >>> 32);
-+ }
-+
-+ @Override
-+ public String toString() {
-+ MethodType adaptedType = ((MethodHandle)this).type();
-+ Object namh = nonAdapter((MethodHandle)vmtarget);
-+ if (namh == null) namh = "unknown";
-+ return "Adapted[" + adaptedType + "," + namh + "]";
-+ }
-+
-+ private static MethodHandle nonAdapter(MethodHandle mh) {
-+ return (MethodHandle)
-+ MethodHandleNatives.getTarget(mh, ETF_DIRECT_HANDLE);
-+ }
-+
-+ /* Return one plus the position of the first non-trivial difference
-+ * between the given types. This is not a symmetric operation;
-+ * we are considering adapting the targetType to adapterType.
-+ * Trivial differences are those which could be ignored by the JVM
-+ * without subverting the verifier. Otherwise, adaptable differences
-+ * are ones for which we could create an adapter to make the type change.
-+ * Return zero if there are no differences (other than trivial ones).
-+ * Return 1+N if N is the only adaptable argument difference.
-+ * Return the -2-N where N is the first of several adaptable
-+ * argument differences.
-+ * Return -1 if there there are differences which are not adaptable.
-+ */
-+ private static int diffTypes(MethodType adapterType,
-+ MethodType targetType) {
-+ Class<?> src = targetType.returnType();
-+ Class<?> dst = adapterType.returnType();
-+ if (VerifyType.canPassUnchecked(src, dst) <= 0)
-+ return -1;
-+ int nargs = adapterType.parameterCount();
-+ if (nargs != targetType.parameterCount())
-+ return -1;
-+ int diff = diffTypes(adapterType, 0, targetType, 0, nargs);
-+ System.out.println("diff "+adapterType);
-+ System.out.println(" "+diff+" "+targetType);
-+ return diff;
-+ }
-+ private static int diffTypes(MethodType adapterType, int tstart,
-+ MethodType targetType, int astart,
-+ int nargs) {
-+ int res = 0;
-+ for (int i = 0; i < nargs; i++) {
-+ Class<?> src = adapterType.parameterType(tstart+i);
-+ Class<?> dest = targetType.parameterType(astart+i);
-+ if (VerifyType.canPassUnchecked(src, dest) <= 0) {
-+ // found a difference; is it the only one so far?
-+ if (res != 0)
-+ return -1-res; // return -2-i for prev. i
-+ res = 1+i;
-+ }
-+ }
-+ return res;
-+ }
-+
-+ /** Can a retyping adapter (alone) validly convert the target to newType? */
-+ public static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
-+ int diff = diffTypes(newType, targetType);
-+ // %%% This assert is too strong. Factor diff into VerifyType and reconcile.
-+ assert((diff == 0) == VerifyType.isNullConversion(newType, targetType));
-+ return diff == 0;
-+ }
-+
-+ /** Factory method: Performs no conversions; simply retypes the adapter. */
-+ public static MethodHandle makeRetypeOnly(Access token,
-+ MethodType newType, MethodHandle target) {
-+ Access.check(token);
-+ assert(canRetypeOnly(newType, target.type()));
-+ // %%% TO DO: If adapter is already an adapter, fold in the retyping.
-+ return new AdapterMethodHandle(target, newType, makeConv(OP_RETYPE_ONLY));
-+ }
-+
-+ /** Can a checkcast adapter validly convert the target to newType?
-+ * The JVM supports all kind of reference casts, even silly ones.
-+ */
-+ public static boolean canCheckCast(MethodType newType, MethodType targetType,
-+ int arg, Class<?> castType) {
-+ Class<?> src = newType.parameterType(arg);
-+ Class<?> dst = targetType.parameterType(arg);
-+ if (!canCheckCast(src, castType)
-+ || !VerifyType.isNullConversion(castType, dst))
-+ return false;
-+ int diff = diffTypes(newType, targetType);
-+ return (diff == arg+1); // arg is sole non-trivial diff
-+ }
-+ /** Can an primitive conversion adapter validly convert src to dst? */
-+ public static boolean canCheckCast(Class<?> src, Class<?> dst) {
-+ return (!src.isPrimitive() && !dst.isPrimitive());
-+ }
-+
-+ /** Factory method: Forces a cast at the given argument.
-+ * The castType is the target of the cast, and can be any type
-+ * with a null conversion to the corresponding target parameter.
-+ */
-+ public static MethodHandle makeCheckCast(Access token,
-+ MethodType newType, MethodHandle target,
-+ int arg, Class<?> castType) {
-+ Access.check(token);
-+ assert(canCheckCast(newType, target.type(), arg, castType));
-+ long conv = makeConv(OP_CHECK_CAST, arg, 0);
-+ return new AdapterMethodHandle(target, newType, conv, castType);
-+ }
-+
-+ /** Can an primitive conversion adapter validly convert the target to newType?
-+ * The JVM currently supports all conversions except those between
-+ * floating and integral types.
-+ */
-+ public static boolean canPrimCast(MethodType newType, MethodType targetType,
-+ int arg, Class<?> convType) {
-+ Class<?> src = newType.parameterType(arg);
-+ Class<?> dst = targetType.parameterType(arg);
-+ if (!canPrimCast(src, convType)
-+ || !VerifyType.isNullConversion(convType, dst))
-+ return false;
-+ int diff = diffTypes(newType, targetType);
-+ return (diff == arg+1); // arg is sole non-trivial diff
-+ }
-+ /** Can an primitive conversion adapter validly convert src to dst? */
-+ public static boolean canPrimCast(Class<?> src, Class<?> dst) {
-+ if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
-+ return false;
-+ } else if (Wrappers.isFloating(dst)) {
-+ // both must be floating types
-+ return Wrappers.isFloating(src);
-+ } else {
-+ // both are integral, and all combinations work fine
-+ assert(Wrappers.isIntegral(src) && Wrappers.isIntegral(dst));
-+ return true;
-+ }
-+ }
-+
-+ /** Factory method: Truncate the given argument with zero or sign extension,
-+ * and/or convert between single and doubleword versions of integer or float.
-+ * The convType is the target of the conversion, and can be any type
-+ * with a null conversion to the corresponding target parameter.
-+ */
-+ public static MethodHandle makePrimCast(Access token,
-+ MethodType newType, MethodHandle target,
-+ int arg, Class<?> convType) {
-+ Access.check(token);
-+ MethodType oldType = target.type();
-+ Class<?> src = newType.parameterType(arg);
-+ Class<?> dst = oldType.parameterType(arg);
-+ assert(canPrimCast(newType, oldType, arg, convType));
-+ long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType));
-+ return new AdapterMethodHandle(target, newType, conv);
-+ }
-+
-+ /** Can an unboxing conversion validly convert src to dst?
-+ * The JVM currently supports all kinds of casting and unboxing.
-+ * The convType is the unboxed type; it can be either a primitive or wrapper.
-+ */
-+ public static boolean canUnboxArgument(MethodType newType, MethodType targetType,
-+ int arg, Class<?> convType) {
-+ Class<?> src = newType.parameterType(arg);
-+ Class<?> dst = targetType.parameterType(arg);
-+ Class<?> boxType = Wrappers.asWrapperType(convType);
-+ convType = Wrappers.asPrimitiveType(convType);
-+ if (!canCheckCast(src, boxType)
-+ || boxType == convType
-+ || !VerifyType.isNullConversion(convType, dst))
-+ return false;
-+ int diff = diffTypes(newType, targetType);
-+ return (diff == arg+1); // arg is sole non-trivial diff
-+ }
-+ /** Can an primitive unboxing adapter validly convert src to dst? */
-+ public static boolean canUnboxArgument(Class<?> src, Class<?> dst) {
-+ return (!src.isPrimitive() && Wrappers.asPrimitiveType(dst).isPrimitive());
-+ }
-+
-+ /** Factory method: Unbox the given argument. */
-+ public static MethodHandle makeUnboxArgument(Access token,
-+ MethodType newType, MethodHandle target,
-+ int arg, Class<?> convType) {
-+ MethodType oldType = target.type();
-+ Class<?> src = newType.parameterType(arg);
-+ Class<?> dst = oldType.parameterType(arg);
-+ Class<?> boxType = Wrappers.asWrapperType(convType);
-+ Class<?> primType = Wrappers.asPrimitiveType(convType);
-+ assert(canUnboxArgument(newType, oldType, arg, convType));
-+ MethodType castDone = newType;
-+ if (!VerifyType.isNullConversion(src, boxType))
-+ castDone = newType.changeParameterType(arg, boxType);
-+ long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
-+ MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
-+ if (castDone == newType)
-+ return adapter;
-+ return makeCheckCast(token, newType, adapter, arg, boxType);
-+ }
-+
-+ /** Can an primitive boxing adapter validly convert src to dst? */
-+ public static boolean canBoxArgument(Class<?> src, Class<?> dst) {
-+ return false; // PRIM_TO_REF NYI
-+ }
-+
-+ /** Factory method: Unbox the given argument. */
-+ public static MethodHandle makeBoxArgument(Access token,
-+ MethodType newType, MethodHandle target,
-+ int arg, Class<?> convType) {
-+ // this is difficult to do in the JVM because it must GC
-+ throw new InternalError("PRIM_TO_REF NYI");
-+ }
-+
-+ // TO DO: makeSwapArguments, makeRotateArguments, makeDuplicateArguments
-+
-+ /** Can an adapter simply drop arguments to convert the target to newType? */
-+ public static boolean canDropArguments(MethodType newType, MethodType targetType,
-+ int dropArgPos, int dropArgCount) {
-+ List<Class<?>> ptypes = targetType.parameterList();
-+ int nptypes = ptypes.size();
-+ if ((dropArgPos | dropArgCount) < 0)
-+ return false;
-+ if (dropArgPos == 0)
-+ ptypes = ptypes.subList(dropArgCount, nptypes);
-+ else if (dropArgPos + dropArgCount == nptypes)
-+ ptypes = ptypes.subList(0, nptypes - dropArgCount);
-+ else {
-+ if (dropArgPos > nptypes ||
-+ dropArgPos + dropArgCount > nptypes)
-+ return false;
-+ ptypes = new ArrayList<Class<?>>(ptypes);
-+ ptypes.subList(dropArgPos, dropArgPos + dropArgCount).clear();
-+ }
-+ MethodType midType = MethodType.make(targetType.returnType(), ptypes);
-+ return diffTypes(newType, midType) == 0;
-+ }
-+
-+ /** Factory method: Drop selected initial or final arguments. */
-+ public static MethodHandle makeDropArguments(Access token,
-+ MethodType newType, MethodHandle target,
-+ int dropArgPos, int dropArgCount) {
-+ Access.check(token);
-+ assert(canDropArguments(newType, target.type(), dropArgPos, dropArgCount));
-+ MethodType mt = target.type();
-+ int argCount = mt.parameterCount();
-+ int dropSlotCount, dropSlotPos;
-+ if (dropArgCount <= 0) {
-+ return makeRetypeOnly(IMPL_TOKEN, newType, target);
-+ } else if (dropArgCount >= argCount) {
-+ assert(dropArgPos == argCount-1);
-+ dropSlotPos = 0;
-+ dropSlotCount = mt.parameterSlotCount();
-+ } else {
-+ // arglist: [0: keep... | dpos: drop... | dpos+dcount: keep... ]
-+ int lastDroppedArg = dropArgPos + dropArgCount - 1;
-+ int lastKeptArg = dropArgPos - 1; // might be -1, which is OK
-+ dropSlotPos = mt.parameterSlot(lastDroppedArg);
-+ int lastKeptSlot = mt.parameterSlot(lastKeptArg);
-+ dropSlotCount = lastKeptSlot - dropSlotPos;
-+ assert(dropSlotCount >= dropArgCount);
-+ }
-+ long conv = makeConv(OP_DROP_ARGS, dropArgPos, +dropSlotCount);
-+ return new AdapterMethodHandle(target, newType, dropSlotCount, conv);
-+ }
-+
-+ // TO DO: makeCollectArguments, makeSpreadArguments, makeFlyby, makeRicochet
-+}
-diff --git a/src/share/classes/impl/java/dyn/BoundMethodHandle.java b/src/share/classes/impl/java/dyn/BoundMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/BoundMethodHandle.java
-@@ -0,0 +1,88 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import java.dyn.*;
-+
-+/**
-+ * The flavor of method handle which emulates an invoke instruction
-+ * on a predetermined argument. The JVM dispatches to the correct method
-+ * when the handle is created, not when it is invoked.
-+ * @author jrose
-+ */
-+public class BoundMethodHandle extends MethodHandle {
-+ //MethodHandle vmtarget; // next BMH or final DMH or methodOop
-+ private final Object argument; // argument to insert
-+ private final int vmargslot; // position at which it is inserted
-+
-+ // Constructors in this class *must* be package scoped or private.
-+
-+ /** Bind a direct MH to its receiver (or first ref. argument).
-+ * The JVM will pre-dispatch the MH if it is not already static.
-+ */
-+ BoundMethodHandle(DirectMethodHandle mh, Object argument) {
-+ super(Access.TOKEN, mh.type().dropParameterType(0));
-+ // check the type now, once for all:
-+ this.argument = mh.type().parameterType(0).cast(argument);
-+ this.vmargslot = this.type().parameterSlotCount();
-+ if (MethodHandleNatives.JVM_SUPPORT) {
-+ this.vmtarget = null; // maybe updated by JVM
-+ MethodHandleNatives.init(this, mh, 0);
-+ } else {
-+ this.vmtarget = mh;
-+ }
-+ }
-+
-+ /** Insert an argument into an arbitrary method handle.
-+ * If argnum is zero, inserts the first argument, etc.
-+ */
-+ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
-+ super(Access.TOKEN, mh.type().dropParameterType(argnum));
-+ this.argument = mh.type().parameterType(argnum).cast(argument);
-+ this.vmargslot = this.type().parameterSlot(argnum-1);
-+ System.out.println("init BMH type="+type()+" argnum="+argnum+" vmargslot="+vmargslot);
-+ if (MethodHandleNatives.JVM_SUPPORT) {
-+ this.vmtarget = null; // maybe updated by JVM
-+ MethodHandleNatives.init(this, mh, argnum);
-+ } else {
-+ this.vmtarget = mh;
-+ }
-+ }
-+
-+ /** For subclasses only.
-+ */
-+ BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
-+ super(Access.TOKEN, type);
-+ this.argument = argument;
-+ this.vmargslot = vmargslot;
-+ assert(this.getClass() != BoundMethodHandle.class);
-+ }
-+
-+ @Override
-+ public String toString() {
-+ return "Bound[" + super.toString() + "]";
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/DirectMethodHandle.java b/src/share/classes/impl/java/dyn/DirectMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/DirectMethodHandle.java
-@@ -0,0 +1,53 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import java.dyn.*;
-+import static impl.java.dyn.MethodHandleNatives.Constants.*;
-+
-+/**
-+ * The flavor of method handle which emulates invokespecial or invokestatic.
-+ * @author jrose
-+ */
-+class DirectMethodHandle extends MethodHandle {
-+ //inherited oop vmtarget; // methodOop or virtual class/interface oop
-+ private final int vmindex; // method index within class or interface
-+ { vmindex = VM_INDEX_UNINITIALIZED; } // JVM may change this
-+
-+ // Constructors in this class *must* be package scoped or private.
-+ DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> caller) {
-+ super(Access.TOKEN, mtype);
-+
-+ assert(m.isMethod() || !doDispatch && m.isConstructor());
-+ if (!m.isResolved())
-+ throw new InternalError();
-+ MethodHandleNatives.init(this, (Object) m, doDispatch, caller);
-+ }
-+
-+ boolean isValid() {
-+ return (vmindex != VM_INDEX_UNINITIALIZED);
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/JavaMethodHandle.java b/src/share/classes/impl/java/dyn/JavaMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/JavaMethodHandle.java
-@@ -0,0 +1,552 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import impl.java.dyn.util.*;
-+import java.dyn.MethodHandle;
-+import java.dyn.MethodHandles;
-+import java.dyn.MethodType;
-+
-+/**
-+ * General-purpose method handle combinator.
-+ * It is invoked on an argument list, and performs whatever processing
-+ * is needed, eventually returning the required return value.
-+ * Note the distinctions from the low-level adapters supported directly
-+ * by the JVM. Those low-level adapters perform argument conversion
-+ * and delegate directly to target method handles, without executing
-+ * any Java code. These Java-level adapters execute Java code to define
-+ * their method handle semantics; whether they delegate to other method
-+ * handles (as they often do) is a detail of that Java code.
-+ * <p>
-+ * If you are creating a method handle for a specific method type,
-+ * do not use this class; simply use {@link MethodHandles#bind}.
-+ * This class is designed for applications which must be polymorphic
-+ * across a range of method types.
-+ *
-+ * @author jrose
-+ */
-+public abstract class JavaMethodHandle {
-+ private final MethodType exactType;
-+ private final MethodType rawType;
-+ private final String rawName;
-+
-+ // summary of the structure of type
-+ //private final int fingerprint;
-+
-+ /** Intended type of any method handle made from this adapter. */
-+ public final MethodType type() {
-+ return exactType;
-+ }
-+
-+ /** The (exact) type of my invoke function. */
-+ protected final MethodType rawType() {
-+ return rawType;
-+ }
-+
-+ /** The name of my categorical invoke function, e.g., invoke_L2. */
-+ protected final String rawName() {
-+ return rawName;
-+ }
-+
-+ /**
-+ * Subclasses must provide the method type which this adapter
-+ * implements.
-+ * @param type
-+ */
-+ protected JavaMethodHandle(MethodType type) {
-+ this.exactType = type;
-+ this.rawType = computeRawType(type);
-+ this.rawName = computeRawName(type, rawType);
-+ }
-+
-+ /** Return the type of one of my invoke functions.
-+ * Can be extended by subclasses to increase the repertoire
-+ * of raw invocation actions.
-+ */
-+ protected MethodType computeRawType(MethodType type) {
-+ return categoricalMethodType(methodTypeCategory(type));
-+ }
-+
-+ /** Return the type of one of my invoke functions.
-+ * By default, of the form "invoke_$X$N" where $X is a
-+ * single basic-type character (as found in bytecode signatures)
-+ * and $N is the (decimal) number of parameters in the raw type.
-+ * Can be extended by subclasses to increase the repertoire
-+ * of raw invocation actions.
-+ */
-+ protected String computeRawName(MethodType exactType, MethodType rawType) {
-+ char rc = Wrappers.basicTypeChar(rawType.returnType());
-+ int nargs = rawType.parameterCount();
-+ return "invoke_"+rc+nargs;
-+ }
-+
-+ /** Return a permutation array which tells, for each argument
-+ * to the categorical invoker, which incoming argument
-+ * will supply the value (perhaps after suitable conversion).
-+ * Returns null if the conversions are simply pairwise,
-+ * with no reordering of argument values.
-+ */
-+ protected char[] computePermutation(MethodType exactType, MethodType rawType) {
-+ return methodTypeCategoricalPermutation(exactType);
-+ }
-+
-+ protected final RuntimeException illegal() {
-+ return new UnsupportedOperationException();
-+ }
-+
-+ /** Produce a method handle that binds the appropriate invoke
-+ * method of this combinator.
-+ * @return a method handle of this combinator's type
-+ */
-+ public MethodHandle handle() {
-+ //return permuteAndRetypeArguments(rawHandle(), type(), computePermutation());
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ protected MethodHandle rawHandle() {
-+ return MethodHandles.bind(this, rawName(), rawType());
-+ }
-+
-+ // Pluggable behaviors, specific to particular arguments or return values.
-+ protected Object res(Object x) { return exactType.returnType().cast(x); }
-+ protected int res(int x) { return x; }
-+ protected long res(long x) { return x; }
-+
-+ // A categorical method type is one which (a) avoids boxing,
-+ // (b) avoids passing unused arguments, and (c) can represent
-+ // the calling sequence of an original exact type.
-+ //
-+ // It's good to limit the number of categorical types,
-+ // so that we don't have to generate too many different
-+ // code shapes for Java-based adapters.
-+ // We (1) erase all references to Object,
-+ // (2) widen primitives to int when they fit,
-+ // (3) widen other primitive arguments to long,
-+ // (4) sort the argument list (refs, ints, then longs), and
-+ // (5) promote ints to longs if any longs are present.
-+ //
-+ // Because it is harmless to ignore an int return value,
-+ // if the caller is intending a void result, void can be
-+ // erased to int, as with other short primitives.
-+ // The distinction in return values between reference,
-+ // int, long, float, and double.
-+ //
-+ // Therefore, the grammar of signatures is:
-+ // {Object|int|long|float|double} ( Object* {int* | long*} )
-+ // This gives 5(2N+1) as the number of categorical signatures
-+ // of N arguments, or 5(N+1)^2 for signatures of <=N arguments.
-+ // Clearly some of this needs to get code-generated lazily,
-+ // but we supoprt a core set of signatures here.
-+
-+ protected static int category(Class<?> type) {
-+ if (!type.isPrimitive()) return 0;
-+ if (type == void.class) return -1;
-+ if (Wrappers.bitWidth(type) > 32) return 2;
-+ return 1;
-+ }
-+ protected static Class<?> categoricalType(int cat) {
-+ switch (cat) {
-+ case 0: return Object.class;
-+ case 1: return int.class;
-+ case 2: return long.class;
-+ case 3: return void.class;
-+ }
-+ throw new InternalError();
-+ }
-+ protected static int methodTypeCategory(MethodType type) {
-+ int nargs = type.parameterCount();
-+ int nprims = 0;
-+ int nlongs = 0;
-+ for (int i = 0; i < nargs; i++) {
-+ int cat = category(type.parameterType(i));
-+ if (cat != 0) {
-+ ++nprims;
-+ if (cat == 2) ++nlongs;
-+ }
-+ }
-+ int nrefs = nargs - nprims;
-+ int nints = nprims - nlongs;
-+ int rcat = category(type.returnType());
-+ if (nlongs != 0) { nlongs += nints; nints = 0; } // point (5)
-+ return (nlongs << 24) | (nints << 16) | (nrefs << 8) | rcat;
-+ }
-+ protected static char[] methodTypeCategoricalPermutation(MethodType type) {
-+ return methodTypeCategoricalPermutation(type, methodTypeCategory(type));
-+ }
-+ protected static char[] methodTypeCategoricalPermutation(MethodType type, int category) {
-+ int x = category;
-+ int rcat = (x & 0xFF); x >>= 8;
-+ int nrefs = (x & 0xFF); x >>= 8;
-+ int nints = (x & 0xFF); x >>= 8;
-+ int nlongs = (x & 0xFF); x >>= 8;
-+ int nargs = type.parameterCount();
-+ assert(nargs == nrefs + nints + nlongs);
-+ char[] permutation = new char[nargs];
-+ int nextref = 0, nextint = nrefs, nextlong = nrefs + nints;
-+ int reflimit = nextint, intlimit = nextlong, longlimit = nargs;
-+ boolean sawReorder = false;
-+ for (int i = 0; i < nargs; i++) {
-+ int cat = category(type.parameterType(i));
-+ int nextarg;
-+ if (cat == 0)
-+ nextarg = nextref++;
-+ else if (nextint == intlimit || cat == 2)
-+ nextarg = nextlong++;
-+ else
-+ nextarg = nextint++;
-+ // Next outgoing argument (to the categorical invoke method)
-+ // is going to come from exactType.parameterType(i)
-+ assert(permutation[nextarg] == 0);
-+ permutation[nextarg] = (char) i;
-+ if (nextarg != i) sawReorder = true;
-+ }
-+ assert(nextref == reflimit);
-+ assert(nextint == intlimit);
-+ assert(nextlong == longlimit);
-+ if (!sawReorder) return null; // this is always a special case
-+ return permutation;
-+ }
-+ protected static MethodType categoricalMethodType(int category) {
-+ int x = category;
-+ int rcat = (x & 0xFF); x >>= 8;
-+ int nrefs = (x & 0xFF); x >>= 8;
-+ int nints = (x & 0xFF); x >>= 8;
-+ int nlongs = (x & 0xFF); x >>= 8;
-+ return categoricalMethodType(rcat, nrefs, nints, nlongs);
-+ }
-+ protected static MethodType categoricalMethodType(int rcat, int nrefs, int nints, int nlongs) {
-+ int nshorts = nints + nlongs;
-+ Class<?> ptypes[] = new Class<?>[nshorts + nlongs];
-+ int cat = 0;
-+ Class<?> ptype = categoricalType(cat);
-+ for (int i = 0; i < ptypes.length; i++) {
-+ if (i == nrefs) ptype = categoricalType(++cat);
-+ if (i == nshorts) ptype = categoricalType(++cat);
-+ ptypes[i] = ptype;
-+ }
-+ Class<?> rtype = categoricalType(rcat);
-+ return MethodType.make(rtype, ptypes);
-+ }
-+
-+ // Categorical methods up to arity 5 (180 of them).
-+ // They are (arbitrarily) split up in subclasses.
-+ /*
-+ (defun insert-categorical-methods (max-arity &optional max-rcat)
-+ (let* ((types (list "Object" "int " "long " "float " "double"))
-+ (tchars (list "L" "I" "J" "F" "D"))
-+ invoke acat nrefs
-+ (do-case (function (lambda (rcat nargs nrefs nints nlongs)
-+ (setq invoke (format "invoke_%s%d" (elt tchars rcat) nargs))
-+ (insert "\n protected " (elt types rcat) " " invoke "(")
-+ (dotimes (arg nargs)
-+ (setq acat (cond ((< arg nrefs) 0) ((< arg (+ nrefs nints)) 1) (t 2)))
-+ (insert (if (= 0 arg) "" ", ") (elt types acat) (format " a%d" arg)))
-+ (insert ") { throw illegal(); }")))))
-+ (dotimes (rcat (1+ (or max-rcat 4))) (dotimes (nargs (1+ max-arity))
-+ (setq invoke (format "%s%d" (elt tchars rcat) nargs))
-+ (insert "\n static class " invoke " extends JavaMethodHandle {")
-+ (insert "\n " invoke "(MethodType type) { super(type); }")
-+ (funcall do-case rcat nargs nargs 0 0)
-+ (dotimes (j 2) (dotimes (i nargs) (setq nrefs (- nargs i 1))
-+ (if (= j 0) (funcall do-case rcat nargs nrefs (- nargs nrefs) 0)
-+ (funcall do-case rcat nargs nrefs 0 (- nargs nrefs)))))
-+ (insert "\n }")
-+ ))))
-+ */
-+ // (progn (insert-categorical-methods 5 4) (insert "\n}"))
-+ /*
-+ static class L0 extends JavaMethodHandle {
-+ L0(MethodType type) { super(type); }
-+ protected Object invoke_L0() { throw illegal(); }
-+ }
-+ static class L1 extends JavaMethodHandle {
-+ L1(MethodType type) { super(type); }
-+ protected Object invoke_L1(Object a0) { throw illegal(); }
-+ protected Object invoke_L1(int a0) { throw illegal(); }
-+ protected Object invoke_L1(long a0) { throw illegal(); }
-+ }
-+ static class L2 extends JavaMethodHandle {
-+ L2(MethodType type) { super(type); }
-+ protected Object invoke_L2(Object a0, Object a1) { throw illegal(); }
-+ protected Object invoke_L2(Object a0, int a1) { throw illegal(); }
-+ protected Object invoke_L2(int a0, int a1) { throw illegal(); }
-+ protected Object invoke_L2(Object a0, long a1) { throw illegal(); }
-+ protected Object invoke_L2(long a0, long a1) { throw illegal(); }
-+ }
-+ static class L3 extends JavaMethodHandle {
-+ L3(MethodType type) { super(type); }
-+ protected Object invoke_L3(Object a0, Object a1, Object a2) { throw illegal(); }
-+ protected Object invoke_L3(Object a0, Object a1, int a2) { throw illegal(); }
-+ protected Object invoke_L3(Object a0, int a1, int a2) { throw illegal(); }
-+ protected Object invoke_L3(int a0, int a1, int a2) { throw illegal(); }
-+ protected Object invoke_L3(Object a0, Object a1, long a2) { throw illegal(); }
-+ protected Object invoke_L3(Object a0, long a1, long a2) { throw illegal(); }
-+ protected Object invoke_L3(long a0, long a1, long a2) { throw illegal(); }
-+ }
-+ static class L4 extends JavaMethodHandle {
-+ L4(MethodType type) { super(type); }
-+ protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) { throw illegal(); }
-+ protected Object invoke_L4(Object a0, Object a1, Object a2, int a3) { throw illegal(); }
-+ protected Object invoke_L4(Object a0, Object a1, int a2, int a3) { throw illegal(); }
-+ protected Object invoke_L4(Object a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected Object invoke_L4(int a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected Object invoke_L4(Object a0, Object a1, Object a2, long a3) { throw illegal(); }
-+ protected Object invoke_L4(Object a0, Object a1, long a2, long a3) { throw illegal(); }
-+ protected Object invoke_L4(Object a0, long a1, long a2, long a3) { throw illegal(); }
-+ protected Object invoke_L4(long a0, long a1, long a2, long a3) { throw illegal(); }
-+ }
-+ static class L5 extends JavaMethodHandle {
-+ L5(MethodType type) { super(type); }
-+ protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, int a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, Object a1, Object a2, int a3, int a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, Object a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected Object invoke_L5(int a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, long a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, Object a1, Object a2, long a3, long a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, Object a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected Object invoke_L5(Object a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected Object invoke_L5(long a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ }
-+ static class I0 extends JavaMethodHandle {
-+ I0(MethodType type) { super(type); }
-+ protected int invoke_I0() { throw illegal(); }
-+ }
-+ static class I1 extends JavaMethodHandle {
-+ I1(MethodType type) { super(type); }
-+ protected int invoke_I1(Object a0) { throw illegal(); }
-+ protected int invoke_I1(int a0) { throw illegal(); }
-+ protected int invoke_I1(long a0) { throw illegal(); }
-+ }
-+ static class I2 extends JavaMethodHandle {
-+ I2(MethodType type) { super(type); }
-+ protected int invoke_I2(Object a0, Object a1) { throw illegal(); }
-+ protected int invoke_I2(Object a0, int a1) { throw illegal(); }
-+ protected int invoke_I2(int a0, int a1) { throw illegal(); }
-+ protected int invoke_I2(Object a0, long a1) { throw illegal(); }
-+ protected int invoke_I2(long a0, long a1) { throw illegal(); }
-+ }
-+ static class I3 extends JavaMethodHandle {
-+ I3(MethodType type) { super(type); }
-+ protected int invoke_I3(Object a0, Object a1, Object a2) { throw illegal(); }
-+ protected int invoke_I3(Object a0, Object a1, int a2) { throw illegal(); }
-+ protected int invoke_I3(Object a0, int a1, int a2) { throw illegal(); }
-+ protected int invoke_I3(int a0, int a1, int a2) { throw illegal(); }
-+ protected int invoke_I3(Object a0, Object a1, long a2) { throw illegal(); }
-+ protected int invoke_I3(Object a0, long a1, long a2) { throw illegal(); }
-+ protected int invoke_I3(long a0, long a1, long a2) { throw illegal(); }
-+ }
-+ static class I4 extends JavaMethodHandle {
-+ I4(MethodType type) { super(type); }
-+ protected int invoke_I4(Object a0, Object a1, Object a2, Object a3) { throw illegal(); }
-+ protected int invoke_I4(Object a0, Object a1, Object a2, int a3) { throw illegal(); }
-+ protected int invoke_I4(Object a0, Object a1, int a2, int a3) { throw illegal(); }
-+ protected int invoke_I4(Object a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected int invoke_I4(int a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected int invoke_I4(Object a0, Object a1, Object a2, long a3) { throw illegal(); }
-+ protected int invoke_I4(Object a0, Object a1, long a2, long a3) { throw illegal(); }
-+ protected int invoke_I4(Object a0, long a1, long a2, long a3) { throw illegal(); }
-+ protected int invoke_I4(long a0, long a1, long a2, long a3) { throw illegal(); }
-+ }
-+ static class I5 extends JavaMethodHandle {
-+ I5(MethodType type) { super(type); }
-+ protected int invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, Object a1, Object a2, Object a3, int a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, Object a1, Object a2, int a3, int a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, Object a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected int invoke_I5(int a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, Object a1, Object a2, Object a3, long a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, Object a1, Object a2, long a3, long a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, Object a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected int invoke_I5(Object a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected int invoke_I5(long a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ }
-+ static class J0 extends JavaMethodHandle {
-+ J0(MethodType type) { super(type); }
-+ protected long invoke_J0() { throw illegal(); }
-+ }
-+ static class J1 extends JavaMethodHandle {
-+ J1(MethodType type) { super(type); }
-+ protected long invoke_J1(Object a0) { throw illegal(); }
-+ protected long invoke_J1(int a0) { throw illegal(); }
-+ protected long invoke_J1(long a0) { throw illegal(); }
-+ }
-+ static class J2 extends JavaMethodHandle {
-+ J2(MethodType type) { super(type); }
-+ protected long invoke_J2(Object a0, Object a1) { throw illegal(); }
-+ protected long invoke_J2(Object a0, int a1) { throw illegal(); }
-+ protected long invoke_J2(int a0, int a1) { throw illegal(); }
-+ protected long invoke_J2(Object a0, long a1) { throw illegal(); }
-+ protected long invoke_J2(long a0, long a1) { throw illegal(); }
-+ }
-+ static class J3 extends JavaMethodHandle {
-+ J3(MethodType type) { super(type); }
-+ protected long invoke_J3(Object a0, Object a1, Object a2) { throw illegal(); }
-+ protected long invoke_J3(Object a0, Object a1, int a2) { throw illegal(); }
-+ protected long invoke_J3(Object a0, int a1, int a2) { throw illegal(); }
-+ protected long invoke_J3(int a0, int a1, int a2) { throw illegal(); }
-+ protected long invoke_J3(Object a0, Object a1, long a2) { throw illegal(); }
-+ protected long invoke_J3(Object a0, long a1, long a2) { throw illegal(); }
-+ protected long invoke_J3(long a0, long a1, long a2) { throw illegal(); }
-+ }
-+ static class J4 extends JavaMethodHandle {
-+ J4(MethodType type) { super(type); }
-+ protected long invoke_J4(Object a0, Object a1, Object a2, Object a3) { throw illegal(); }
-+ protected long invoke_J4(Object a0, Object a1, Object a2, int a3) { throw illegal(); }
-+ protected long invoke_J4(Object a0, Object a1, int a2, int a3) { throw illegal(); }
-+ protected long invoke_J4(Object a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected long invoke_J4(int a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected long invoke_J4(Object a0, Object a1, Object a2, long a3) { throw illegal(); }
-+ protected long invoke_J4(Object a0, Object a1, long a2, long a3) { throw illegal(); }
-+ protected long invoke_J4(Object a0, long a1, long a2, long a3) { throw illegal(); }
-+ protected long invoke_J4(long a0, long a1, long a2, long a3) { throw illegal(); }
-+ }
-+ static class J5 extends JavaMethodHandle {
-+ J5(MethodType type) { super(type); }
-+ protected long invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, Object a1, Object a2, Object a3, int a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, Object a1, Object a2, int a3, int a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, Object a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected long invoke_J5(int a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, Object a1, Object a2, Object a3, long a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, Object a1, Object a2, long a3, long a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, Object a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected long invoke_J5(Object a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected long invoke_J5(long a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ }
-+ static class F0 extends JavaMethodHandle {
-+ F0(MethodType type) { super(type); }
-+ protected float invoke_F0() { throw illegal(); }
-+ }
-+ static class F1 extends JavaMethodHandle {
-+ F1(MethodType type) { super(type); }
-+ protected float invoke_F1(Object a0) { throw illegal(); }
-+ protected float invoke_F1(int a0) { throw illegal(); }
-+ protected float invoke_F1(long a0) { throw illegal(); }
-+ }
-+ static class F2 extends JavaMethodHandle {
-+ F2(MethodType type) { super(type); }
-+ protected float invoke_F2(Object a0, Object a1) { throw illegal(); }
-+ protected float invoke_F2(Object a0, int a1) { throw illegal(); }
-+ protected float invoke_F2(int a0, int a1) { throw illegal(); }
-+ protected float invoke_F2(Object a0, long a1) { throw illegal(); }
-+ protected float invoke_F2(long a0, long a1) { throw illegal(); }
-+ }
-+ static class F3 extends JavaMethodHandle {
-+ F3(MethodType type) { super(type); }
-+ protected float invoke_F3(Object a0, Object a1, Object a2) { throw illegal(); }
-+ protected float invoke_F3(Object a0, Object a1, int a2) { throw illegal(); }
-+ protected float invoke_F3(Object a0, int a1, int a2) { throw illegal(); }
-+ protected float invoke_F3(int a0, int a1, int a2) { throw illegal(); }
-+ protected float invoke_F3(Object a0, Object a1, long a2) { throw illegal(); }
-+ protected float invoke_F3(Object a0, long a1, long a2) { throw illegal(); }
-+ protected float invoke_F3(long a0, long a1, long a2) { throw illegal(); }
-+ }
-+ static class F4 extends JavaMethodHandle {
-+ F4(MethodType type) { super(type); }
-+ protected float invoke_F4(Object a0, Object a1, Object a2, Object a3) { throw illegal(); }
-+ protected float invoke_F4(Object a0, Object a1, Object a2, int a3) { throw illegal(); }
-+ protected float invoke_F4(Object a0, Object a1, int a2, int a3) { throw illegal(); }
-+ protected float invoke_F4(Object a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected float invoke_F4(int a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected float invoke_F4(Object a0, Object a1, Object a2, long a3) { throw illegal(); }
-+ protected float invoke_F4(Object a0, Object a1, long a2, long a3) { throw illegal(); }
-+ protected float invoke_F4(Object a0, long a1, long a2, long a3) { throw illegal(); }
-+ protected float invoke_F4(long a0, long a1, long a2, long a3) { throw illegal(); }
-+ }
-+ static class F5 extends JavaMethodHandle {
-+ F5(MethodType type) { super(type); }
-+ protected float invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, Object a1, Object a2, Object a3, int a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, Object a1, Object a2, int a3, int a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, Object a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected float invoke_F5(int a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, Object a1, Object a2, Object a3, long a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, Object a1, Object a2, long a3, long a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, Object a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected float invoke_F5(Object a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected float invoke_F5(long a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ }
-+ static class D0 extends JavaMethodHandle {
-+ D0(MethodType type) { super(type); }
-+ protected double invoke_D0() { throw illegal(); }
-+ }
-+ static class D1 extends JavaMethodHandle {
-+ D1(MethodType type) { super(type); }
-+ protected double invoke_D1(Object a0) { throw illegal(); }
-+ protected double invoke_D1(int a0) { throw illegal(); }
-+ protected double invoke_D1(long a0) { throw illegal(); }
-+ }
-+ static class D2 extends JavaMethodHandle {
-+ D2(MethodType type) { super(type); }
-+ protected double invoke_D2(Object a0, Object a1) { throw illegal(); }
-+ protected double invoke_D2(Object a0, int a1) { throw illegal(); }
-+ protected double invoke_D2(int a0, int a1) { throw illegal(); }
-+ protected double invoke_D2(Object a0, long a1) { throw illegal(); }
-+ protected double invoke_D2(long a0, long a1) { throw illegal(); }
-+ }
-+ static class D3 extends JavaMethodHandle {
-+ D3(MethodType type) { super(type); }
-+ protected double invoke_D3(Object a0, Object a1, Object a2) { throw illegal(); }
-+ protected double invoke_D3(Object a0, Object a1, int a2) { throw illegal(); }
-+ protected double invoke_D3(Object a0, int a1, int a2) { throw illegal(); }
-+ protected double invoke_D3(int a0, int a1, int a2) { throw illegal(); }
-+ protected double invoke_D3(Object a0, Object a1, long a2) { throw illegal(); }
-+ protected double invoke_D3(Object a0, long a1, long a2) { throw illegal(); }
-+ protected double invoke_D3(long a0, long a1, long a2) { throw illegal(); }
-+ }
-+ static class D4 extends JavaMethodHandle {
-+ D4(MethodType type) { super(type); }
-+ protected double invoke_D4(Object a0, Object a1, Object a2, Object a3) { throw illegal(); }
-+ protected double invoke_D4(Object a0, Object a1, Object a2, int a3) { throw illegal(); }
-+ protected double invoke_D4(Object a0, Object a1, int a2, int a3) { throw illegal(); }
-+ protected double invoke_D4(Object a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected double invoke_D4(int a0, int a1, int a2, int a3) { throw illegal(); }
-+ protected double invoke_D4(Object a0, Object a1, Object a2, long a3) { throw illegal(); }
-+ protected double invoke_D4(Object a0, Object a1, long a2, long a3) { throw illegal(); }
-+ protected double invoke_D4(Object a0, long a1, long a2, long a3) { throw illegal(); }
-+ protected double invoke_D4(long a0, long a1, long a2, long a3) { throw illegal(); }
-+ }
-+ static class D5 extends JavaMethodHandle {
-+ D5(MethodType type) { super(type); }
-+ protected double invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, Object a1, Object a2, Object a3, int a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, Object a1, Object a2, int a3, int a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, Object a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected double invoke_D5(int a0, int a1, int a2, int a3, int a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, Object a1, Object a2, Object a3, long a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, Object a1, Object a2, long a3, long a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, Object a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected double invoke_D5(Object a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ protected double invoke_D5(long a0, long a1, long a2, long a3, long a4) { throw illegal(); }
-+ }
-+ */
-+}
-diff --git a/src/share/classes/impl/java/dyn/MemberName.java b/src/share/classes/impl/java/dyn/MemberName.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/MemberName.java
-@@ -0,0 +1,550 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import impl.java.dyn.util.BytecodeSignature;
-+import java.dyn.*;
-+import java.lang.reflect.Constructor;
-+import java.lang.reflect.Field;
-+import java.lang.reflect.Method;
-+import java.lang.reflect.Member;
-+import java.lang.reflect.Modifier;
-+import java.util.ArrayList;
-+import java.util.Collections;
-+import java.util.Iterator;
-+import java.util.List;
-+import static impl.java.dyn.MethodHandleNatives.Constants.*;
-+
-+/**
-+ * Compact information which fully characterizes a method or field reference.
-+ * When resolved, it includes a direct pointer to JVM metadata.
-+ * This representation is stateless and only decriptive.
-+ * It provides no private information and no capability to use the member.
-+ * <p>
-+ * By contrast, a java.lang.reflect.Method contains fuller information
-+ * about the internals of a method (except its bytecodes) and also
-+ * allows invocation. A MemberName is much lighter than a reflect.Method,
-+ * since it contains about 7 fields to Method's 16 (plus its sub-arrays),
-+ * and those seven fields omit much of the information in Method.
-+ * @author jrose
-+ */
-+public final class MemberName implements Member, Cloneable {
-+ private Class<?> clazz; // class in which the method is defined
-+ private String name; // may be null if not yet materialized
-+ private Object type; // may be null if not yet materialized
-+ private int flags; // modifier bits; see reflect.Modifier
-+
-+ private Object vmtarget; // VM-specific target value
-+ private int vmindex; // method index within class or interface
-+
-+ { vmindex = VM_INDEX_UNINITIALIZED; }
-+
-+ public Class<?> getDeclaringClass() {
-+ if (clazz == null && isResolved()) {
-+ expandFromVM();
-+ }
-+ return clazz;
-+ }
-+
-+ public ClassLoader getClassLoader() {
-+ return clazz.getClassLoader();
-+ }
-+
-+ public String getName() {
-+ if (name == null) {
-+ expandFromVM();
-+ if (name == null) return null;
-+ }
-+ return name;
-+ }
-+
-+ public MethodType getMethodType() {
-+ if (type == null) {
-+ expandFromVM();
-+ if (type == null) return null;
-+ }
-+ if (!isInvocable())
-+ throw newIllegalArgumentException("not invocable, no method type");
-+ if (type instanceof MethodType) {
-+ return (MethodType) type;
-+ }
-+ if (type instanceof String) {
-+ String sig = (String) type;
-+ MethodType res = MethodType.fromBytecodeString(sig, getClassLoader());
-+ this.type = res;
-+ return res;
-+ }
-+ if (type instanceof Object[]) {
-+ Object[] typeInfo = (Object[]) type;
-+ Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
-+ Class<?> rtype = (Class<?>) typeInfo[0];
-+ MethodType res = MethodType.make(rtype, ptypes);
-+ this.type = res;
-+ return res;
-+ }
-+ throw new InternalError("bad method type "+type);
-+ }
-+
-+ public MethodType getInvocationType() {
-+ MethodType itype = getMethodType();
-+ if (!isStatic())
-+ itype = itype.insertParameterType(0, clazz);
-+ return itype;
-+ }
-+
-+ public Class<?>[] getParameterTypes() {
-+ return getMethodType().parameterArray();
-+ }
-+
-+ public Class<?> getReturnType() {
-+ return getMethodType().returnType();
-+ }
-+
-+ public Class<?> getFieldType() {
-+ if (type == null) {
-+ expandFromVM();
-+ if (type == null) return null;
-+ }
-+ if (isInvocable())
-+ throw newIllegalArgumentException("not a field or nested class, no simple type");
-+ if (type instanceof Class<?>) {
-+ return (Class<?>) type;
-+ }
-+ if (type instanceof String) {
-+ String sig = (String) type;
-+ MethodType mtype = MethodType.fromBytecodeString("()"+sig, getClassLoader());
-+ Class<?> res = mtype.returnType();
-+ this.type = res;
-+ return res;
-+ }
-+ throw new InternalError("bad field type "+type);
-+ }
-+
-+ public Object getType() {
-+ return (isInvocable() ? getMethodType() : getFieldType());
-+ }
-+
-+ public String getSignature() {
-+ if (type == null) {
-+ expandFromVM();
-+ if (type == null) return null;
-+ }
-+ if (type instanceof String)
-+ return (String) type;
-+ if (isInvocable())
-+ return BytecodeSignature.unparse(getMethodType());
-+ else
-+ return BytecodeSignature.unparse(getFieldType());
-+ }
-+
-+ public int getModifiers() {
-+ return (flags & RECOGNIZED_MODIFIERS);
-+ }
-+
-+ private void setFlags(int flags) {
-+ this.flags = flags;
-+ assert(testAnyFlags(ALL_KINDS));
-+ }
-+
-+ private boolean testFlags(int mask, int value) {
-+ return (flags & mask) == value;
-+ }
-+ private boolean testAllFlags(int mask) {
-+ return testFlags(mask, mask);
-+ }
-+ private boolean testAnyFlags(int mask) {
-+ return !testFlags(mask, 0);
-+ }
-+
-+ public boolean isStatic() {
-+ return Modifier.isStatic(flags);
-+ }
-+ public boolean isPublic() {
-+ return Modifier.isPublic(flags);
-+ }
-+ public boolean isPrivate() {
-+ return Modifier.isPrivate(flags);
-+ }
-+ public boolean isProtected() {
-+ return Modifier.isProtected(flags);
-+ }
-+ public boolean isFinal() {
-+ return Modifier.isFinal(flags);
-+ }
-+ public boolean isAbstract() {
-+ return Modifier.isAbstract(flags);
-+ }
-+ // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
-+
-+ // unofficial modifier flags, used by HotSpot:
-+ static final int BRIDGE = 0x00000040;
-+ static final int VARARGS = 0x00000080;
-+ static final int SYNTHETIC = 0x00001000;
-+ static final int ANNOTATION= 0x00002000;
-+ static final int ENUM = 0x00004000;
-+ public boolean isBridge() {
-+ return testAllFlags(IS_METHOD | BRIDGE);
-+ }
-+ public boolean isVarargs() {
-+ return testAllFlags(VARARGS) && isInvocable();
-+ }
-+ public boolean isSynthetic() {
-+ return testAllFlags(SYNTHETIC);
-+ }
-+
-+ static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
-+
-+ // modifiers exported by the JVM:
-+ static final int RECOGNIZED_MODIFIERS = 0xFFFF;
-+
-+ // private flags, not part of RECOGNIZED_MODIFIERS:
-+ static final int
-+ IS_METHOD = MN_IS_METHOD, // method (not constructor)
-+ IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
-+ IS_FIELD = MN_IS_FIELD, // field
-+ IS_TYPE = MN_IS_TYPE; // nested type
-+ static final int // for MethodHandleNatives.getMembers
-+ SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
-+ SEARCH_INTERFACES = MN_SEARCH_INTERFACES;
-+
-+ static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
-+ static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
-+ static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
-+ static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
-+ static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
-+
-+ public boolean isInvocable() {
-+ return testAnyFlags(IS_INVOCABLE);
-+ }
-+ public boolean isFieldOrMethod() {
-+ return testAnyFlags(IS_FIELD_OR_METHOD);
-+ }
-+ public boolean isMethod() {
-+ return testAllFlags(IS_METHOD);
-+ }
-+ public boolean isConstructor() {
-+ return testAllFlags(IS_CONSTRUCTOR);
-+ }
-+ public boolean isField() {
-+ return testAllFlags(IS_FIELD);
-+ }
-+ public boolean isType() {
-+ return testAllFlags(IS_TYPE);
-+ }
-+ public boolean isPackage() {
-+ return !testAnyFlags(ALL_ACCESS);
-+ }
-+
-+ /** Initialize a query. It is not resolved. */
-+ private void init(Class<?> defClass, String name, Object type, int flags) {
-+ // defining class is allowed to be null (for a naked name/type pair)
-+ name.toString(); // null check
-+ type.equals(type); // null check
-+ // fill in fields:
-+ this.clazz = defClass;
-+ this.name = name;
-+ this.type = type;
-+ setFlags(flags);
-+ assert(!isResolved());
-+ }
-+
-+ private void expandFromVM() {
-+ if (!isResolved()) return;
-+ if (type instanceof Object[])
-+ type = null; // don't saddle JVM w/ typeInfo
-+ MethodHandleNatives.expand(this);
-+ }
-+
-+ // Capturing information from the Core Reflection API:
-+ private static int flagsMods(int flags, int mods) {
-+ assert((flags & RECOGNIZED_MODIFIERS) == 0);
-+ assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
-+ return flags | mods;
-+ }
-+ public MemberName(Method m) {
-+ Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
-+ init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
-+ // fill in vmtarget, vmindex while we have m in hand:
-+ MethodHandleNatives.init(this, m);
-+ assert(isResolved());
-+ }
-+ public MemberName(Constructor ctor) {
-+ Object[] typeInfo = { void.class, ctor.getParameterTypes() };
-+ init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
-+ // fill in vmtarget, vmindex while we have ctor in hand:
-+ MethodHandleNatives.init(this, ctor);
-+ assert(isResolved());
-+ }
-+ public MemberName(Field fld) {
-+ init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
-+ // fill in vmtarget, vmindex while we have fld in hand:
-+ MethodHandleNatives.init(this, fld);
-+ assert(isResolved());
-+ }
-+ public MemberName(Class<?> type) {
-+ init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
-+ vmindex = 0; // isResolved
-+ assert(isResolved());
-+ }
-+
-+ // bare-bones constructor; the JVM will fill it in
-+ MemberName() { }
-+
-+ // locally useful cloner
-+ @Override protected MemberName clone() {
-+ try {
-+ return (MemberName) super.clone();
-+ } catch (CloneNotSupportedException ex) {
-+ throw new InternalError();
-+ }
-+ }
-+
-+ // %%% define equals/hashcode?
-+
-+ // Construction from symbolic parts, for queries:
-+ public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
-+ init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
-+ }
-+ public MemberName(Class<?> defClass, String name, Class<?> type) {
-+ this(defClass, name, type, 0);
-+ }
-+ public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
-+ int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
-+ init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
-+ }
-+ public MemberName(Class<?> defClass, String name, MethodType type) {
-+ this(defClass, name, type, 0);
-+ }
-+
-+ boolean isResolved() {
-+ return (vmindex != VM_INDEX_UNINITIALIZED);
-+ }
-+
-+ public boolean hasReceiverTypeDispatch() {
-+ return (isMethod() && getVMIndex(Access.TOKEN) >= 0);
-+ }
-+
-+ @Override
-+ public String toString() {
-+ if (isType())
-+ return type.toString(); // class java.lang.String
-+ // else it is a field, method, or constructor
-+ StringBuilder buf = new StringBuilder();
-+ if (getDeclaringClass() != null) {
-+ buf.append(getName(clazz));
-+ buf.append('.');
-+ }
-+ buf.append(getName());
-+ if (!isInvocable()) buf.append('/');
-+ buf.append(getName(getType()));
-+ /*
-+ buf.append('/');
-+ // key: Public, private, pRotected, sTatic, Final, sYnchronized,
-+ // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
-+ // (annotation), Enum, (unused)
-+ final String FIELD_MOD_CHARS = "PprTF?vt????Y?E?";
-+ final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
-+ String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
-+ for (int i = 0; i < modChars.length(); i++) {
-+ if ((flags & (1 << i)) != 0) {
-+ char mc = modChars.charAt(i);
-+ if (mc != '.')
-+ buf.append(mc);
-+ }
-+ }
-+ */
-+ return buf.toString();
-+ }
-+ private static String getName(Object obj) {
-+ if (obj instanceof Class<?>)
-+ return ((Class<?>)obj).getName();
-+ return obj.toString();
-+ }
-+
-+ // Queries to the JVM:
-+ public int getVMIndex(Access token) {
-+ Access.check(token);
-+ if (!isResolved())
-+ throw newIllegalStateException("not resolved");
-+ return vmindex;
-+ }
-+// public Object getVMTarget(Access token) {
-+// Access.check(token);
-+// if (!isResolved())
-+// throw newIllegalStateException("not resolved");
-+// return vmtarget;
-+// }
-+ private RuntimeException newIllegalStateException(String message) {
-+ return new IllegalStateException(message+": "+this);
-+ }
-+
-+ // handy shared exception makers (they simplify the common case code)
-+ public static RuntimeException newIllegalArgumentException(String message) {
-+ return new IllegalArgumentException(message);
-+ }
-+ public static NoAccessException newNoAccessException(MemberName name, Class<?> caller) {
-+ return newNoAccessException("cannot access", name, caller);
-+ }
-+ public static NoAccessException newNoAccessException(String message,
-+ MemberName name, Class<?> caller) {
-+ message += ": " + name;
-+ if (caller != null) message += ", from " + caller.getName();
-+ return new NoAccessException(message);
-+ }
-+
-+ /** Actually making a query requires an access check. */
-+ public static Factory getFactory(Access token) {
-+ Access.check(token);
-+ return Factory.INSTANCE;
-+ }
-+ public static Factory getFactory() {
-+ return getFactory(Access.getToken());
-+ }
-+ public static class Factory {
-+ private Factory() { } // singleton pattern
-+ static Factory INSTANCE = new Factory();
-+
-+ private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
-+
-+ /// Queries
-+ List<MemberName> getMembers(Class<?> defc,
-+ String matchName, Object matchType,
-+ int matchFlags, Class<?> caller) {
-+ matchFlags &= ALLOWED_FLAGS;
-+ String matchSig = null;
-+ if (matchType != null) {
-+ matchSig = BytecodeSignature.unparse(matchType);
-+ if (matchSig.startsWith("("))
-+ matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
-+ else
-+ matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
-+ }
-+ final int BUF_MAX = 0x2000;
-+ int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
-+ MemberName[] buf = newMemberBuffer(len1);
-+ int totalCount = 0;
-+ ArrayList<MemberName[]> bufs = null;
-+ for (;;) {
-+ int bufCount = MethodHandleNatives.getMembers(defc,
-+ matchName, matchSig, matchFlags, caller,
-+ totalCount, buf);
-+ if (bufCount <= buf.length) {
-+ if (bufCount >= 0)
-+ totalCount += bufCount;
-+ break;
-+ }
-+ // JVM returned tp us with an intentional overflow!
-+ totalCount += buf.length;
-+ int excess = bufCount - buf.length;
-+ if (bufs == null) bufs = new ArrayList<MemberName[]>(1);
-+ bufs.add(buf);
-+ int len2 = buf.length;
-+ len2 = Math.max(len2, excess);
-+ len2 = Math.max(len2, totalCount / 4);
-+ buf = newMemberBuffer(Math.min(BUF_MAX, len2));
-+ }
-+ ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
-+ if (bufs != null) {
-+ for (MemberName[] buf0 : bufs) {
-+ Collections.addAll(result, buf0);
-+ }
-+ }
-+ Collections.addAll(result, buf);
-+ // Signature matching is not the same as type matching, since
-+ // one signature might correspond to several types.
-+ // So if matchType is a Class or MethodType, refilter the results.
-+ if (matchType != null && matchType != matchSig) {
-+ for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
-+ MemberName m = it.next();
-+ if (!matchType.equals(m.getType()))
-+ it.remove();
-+ }
-+ }
-+ return result;
-+ }
-+ boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> caller) {
-+ MethodHandleNatives.resolve(m, caller);
-+ 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);
-+ if (n != 1) return false;
-+ return m.isResolved();
-+ }
-+ public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> caller) {
-+ MemberName result = m.clone();
-+ if (resolveInPlace(result, searchSupers, caller))
-+ return result;
-+ return null;
-+ }
-+ public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> caller) {
-+ MemberName result = resolveOrNull(m, searchSupers, caller);
-+ if (result != null)
-+ return result;
-+ throw newNoAccessException(m, caller);
-+ }
-+ public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
-+ Class<?> caller) {
-+ return getMethods(defc, searchSupers, null, null, caller);
-+ }
-+ public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
-+ String name, MethodType type, Class<?> caller) {
-+ int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-+ return getMembers(defc, name, type, matchFlags, caller);
-+ }
-+ public List<MemberName> getConstructors(Class<?> defc, Class<?> caller) {
-+ return getMembers(defc, null, null, IS_CONSTRUCTOR, caller);
-+ }
-+ public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
-+ Class<?> caller) {
-+ return getFields(defc, searchSupers, null, null, caller);
-+ }
-+ public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
-+ String name, Class<?> type, Class<?> caller) {
-+ int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-+ return getMembers(defc, name, type, matchFlags, caller);
-+ }
-+ public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
-+ Class<?> caller) {
-+ int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-+ return getMembers(defc, null, null, matchFlags, caller);
-+ }
-+ private static MemberName[] newMemberBuffer(int length) {
-+ MemberName[] buf = new MemberName[length];
-+ // fill the buffer with dummy structs for the JVM to fill in
-+ for (int i = 0; i < length; i++)
-+ buf[i] = new MemberName();
-+ return buf;
-+ }
-+ }
-+
-+// static {
-+// System.out.println("Hello world! My methods are:");
-+// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
-+// }
-+}
-\ No newline at end of file
-diff --git a/src/share/classes/impl/java/dyn/MethodHandleImpl.java b/src/share/classes/impl/java/dyn/MethodHandleImpl.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/MethodHandleImpl.java
-@@ -0,0 +1,269 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import java.dyn.MethodHandle;
-+import java.dyn.MethodHandles;
-+import java.dyn.MethodType;
-+import impl.java.dyn.JavaMethodHandle;
-+import impl.java.dyn.util.MethodHandleInvoker;
-+import java.dyn.NoAccessException;
-+import org.omg.PortableInterceptor.AdapterManagerIdHelper;
-+import static impl.java.dyn.MemberName.newIllegalArgumentException;
-+import static impl.java.dyn.MemberName.newNoAccessException;
-+
-+/**
-+ * Base class for method handles which are known to the Hotspot JVM.
-+ * @author jrose
-+ */
-+public abstract class MethodHandleImpl {
-+
-+ // Fields in MethodHandle:
-+ private byte vmentry; // adapter stub or method entry point
-+ //private int vmslots; // optionally, hoist type.form.vmslots
-+ protected Object vmtarget; // VM-specific, class-specific target value
-+ //MethodType type; // defined in MethodHandle
-+
-+ // These two dummy fields are present to force 'I' and 'J' signatures
-+ // into this class's constant pool, so they can be transferred
-+ // to vmentry when this class is loaded.
-+ static final int INT_FIELD = 0;
-+ static final long LONG_FIELD = 0;
-+
-+ // type is defined in java.dyn.MethodHandle, which is platform-independent
-+
-+ // vmentry (a void* field) is used *only* by by the JVM.
-+ // The JVM adjusts its type to int or long depending on system wordsize.
-+ // Since it is statically typed as neither int nor long, it is impossible
-+ // to use this field from Java bytecode. (Please don't try to, either.)
-+
-+ // The vmentry is an assembly-language stub which is jumped to
-+ // immediately after the method type is verified.
-+ // For a direct MH, this stub loads the vmtarget's entry point
-+ // and jumps to it.
-+
-+ /**
-+ * VM-based method handles must have a security token.
-+ * This security token can only be obtained by trusted code.
-+ * Do not create method handles directly; use factory methods.
-+ */
-+ public MethodHandleImpl(Access token) {
-+ Access.check(token);
-+ }
-+
-+ /** Initialize the method type form to participate in JVM calls.
-+ * This is done once for each erased type.
-+ */
-+ public static void init(Access token, MethodType self) {
-+ Access.check(token);
-+ if (MethodHandleNatives.JVM_SUPPORT)
-+ MethodHandleNatives.init(self);
-+ }
-+
-+ /// Factory methods to create method handles:
-+
-+ private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
-+
-+
-+ /** Look up a given method.
-+ * Callable only from java.dyn and related packages.
-+ * <p>
-+ * The resulting method handle type will be of the given type,
-+ * with a receiver type {@code rcvc} prepended if the member is not static.
-+ * <p>
-+ * Access checks are made as of the given caller.
-+ * In particular, if the method is protected and {@code defc} is in a
-+ * different package from the caller, then {@code rcvc} must be
-+ * caller or a subclass.
-+ * @param token Proof that the caller has access to this package.
-+ * @param member Resolved method or constructor to call.
-+ * @param name Name of the desired method.
-+ * @param rcvc Receiver type of desired non-static method (else null)
-+ * @param doDispatch whether the method handle will test the receiver type
-+ * @param caller if not null, access-check relative to this class ????
-+ * @return a direct handle to the matching method
-+ * @throws NoAccessException if the given method cannot be accessed by caller
-+ */
-+ public static
-+ MethodHandle findMethod(Access token, MemberName method,
-+ boolean doDispatch, Class<?> caller) {
-+ Access.check(token); // only trusted calls
-+ MethodType mtype = method.getMethodType();
-+ 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());
-+ if (method.isConstructor())
-+ doDispatch = true;
-+ }
-+ DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, caller);
-+ if (!mh.isValid())
-+ throw newNoAccessException(method, caller);
-+ return mh;
-+ }
-+
-+ public static
-+ MethodHandle accessField(Access token,
-+ MemberName member, boolean isSetter,
-+ Class<?> caller) {
-+ Access.check(token);
-+ // FIXME: Use sun.misc.Unsafe to dig up the dirt on the field.
-+ throw new UnsupportedOperationException("Not yet implemented");
-+ }
-+
-+ public static
-+ MethodHandle accessArrayElement(Access token,
-+ Class<?> arrayClass, boolean isSetter,
-+ Class<?> caller) {
-+ Access.check(token);
-+ if (!arrayClass.isArray())
-+ throw newIllegalArgumentException("not an array: "+arrayClass);
-+ // FIXME: Use sun.misc.Unsafe to dig up the dirt on the array.
-+ throw new UnsupportedOperationException("Not yet implemented");
-+ }
-+
-+ /** Bind a predetermined first argument to the given direct method handle.
-+ * Callable only from MethodHandles.
-+ * @param token Proof that the caller has access to this package.
-+ * @param target Any direct method handle.
-+ * @param receiver Receiver (or first static method argument) to pre-bind.
-+ * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
-+ */
-+ public static
-+ MethodHandle bindReceiver(Access token,
-+ MethodHandle target, Object receiver) {
-+ Access.check(token);
-+ if (target instanceof DirectMethodHandle)
-+ return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
-+ return null; // let caller try something else
-+ }
-+
-+ /** Bind a predetermined argument to the given arbitrary method handle.
-+ * Callable only from MethodHandles.
-+ * @param token Proof that the caller has access to this package.
-+ * @param target Any method handle.
-+ * @param receiver Argument (which can be a boxed primitive) to pre-bind.
-+ * @return a suitable BoundMethodHandle
-+ */
-+ public static
-+ MethodHandle bindArgument(Access token,
-+ MethodHandle target, int argnum, Object receiver) {
-+ Access.check(token);
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ public static MethodHandle convertArguments(Access token,
-+ MethodHandle target,
-+ MethodType newType, boolean newVarargs,
-+ MethodType oldType, boolean oldVarargs,
-+ String permutationOrNull) {
-+ Access.check(token);
-+ if (AdapterMethodHandle.canPairwiseConvert(newType, oldType))
-+ return AdapterMethodHandle.makePairwiseConvert(token, newType, target);
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ public static
-+ MethodHandle dropArguments(Access token, MethodHandle target,
-+ MethodType newType, int argnum) {
-+ Access.check(token);
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ public static
-+ MethodHandle makeGuardWithTest(Access token,
-+ final MethodHandle test,
-+ final MethodHandle target,
-+ final MethodHandle fallback) {
-+ Access.check(token);
-+ // %%% This is just a sketch. It needs to be de-boxed.
-+ // Adjust the handles to accept varargs lists.
-+ MethodType type = target.type();
-+ Class<?> rtype = type.returnType();
-+ if (type.parameterCount() != 1 || type.parameterType(0).isPrimitive()) {
-+ MethodType vatestType = MethodType.make(boolean.class, Object[].class);
-+ MethodType vatargetType = MethodType.make(rtype, Object[].class);
-+ MethodHandle vaguard = makeGuardWithTest(token,
-+ MethodHandles.spreadArguments(test, vatestType),
-+ MethodHandles.spreadArguments(target, vatargetType),
-+ MethodHandles.spreadArguments(fallback, vatargetType));
-+ return MethodHandles.collectArguments(vaguard, type);
-+ }
-+ if (rtype.isPrimitive()) {
-+ MethodType boxtype = type.changeReturnType(Object.class);
-+ MethodHandle boxguard = makeGuardWithTest(token,
-+ test,
-+ MethodHandles.convertArguments(target, boxtype),
-+ MethodHandles.convertArguments(fallback, boxtype));
-+ return MethodHandles.convertArguments(boxguard, type);
-+ }
-+ // Got here? Reduced calling sequence to Object(Object).
-+ final MethodHandleInvoker invoke1
-+ = MethodHandleInvoker.make(test.type());
-+ final MethodHandleInvoker invoke2
-+ = MethodHandleInvoker.make(target.type());
-+ class Guarder {
-+ Object invoke(Object x) {
-+ // If javac supports MethodHandle.invoke directly:
-+ //z = vatest.invoke<boolean>(arguments);
-+ // If javac does not support direct MH.invoke calls:
-+ boolean z = (Boolean) invoke1.invoke_1(test, x);
-+ MethodHandle mh = (z ? target : fallback);
-+ return invoke2.invoke_1(mh, x);
-+ }
-+ MethodHandle handle() {
-+ MethodType invokeType = MethodType.makeGeneric(0, true);
-+ MethodHandle vh = MethodHandles.bind(this, "invoke", invokeType);
-+ return MethodHandles.collectArguments(vh, target.type());
-+ }
-+ }
-+ return new Guarder().handle();
-+ }
-+
-+ public static
-+ MethodHandle combineArguments(Access token, MethodHandle target, MethodHandle checker, int pos) {
-+ Access.check(token);
-+ throw new UnsupportedOperationException("Not yet implemented");
-+ }
-+
-+ protected static String basicToString(MethodHandle target) {
-+ MemberName name = MethodHandleNatives.getMethodName(target);
-+ if (name == null)
-+ name = new MemberName(null, "<unknown>", target.type());
-+ return name.toString();
-+ }
-+
-+ static RuntimeException newIllegalArgumentException(String string) {
-+ return new IllegalArgumentException(string);
-+ }
-+
-+ @Override
-+ public String toString() {
-+ return basicToString((MethodHandle)this);
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/MethodHandleNatives.java b/src/share/classes/impl/java/dyn/MethodHandleNatives.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/MethodHandleNatives.java
-@@ -0,0 +1,245 @@
-+/*
-+ * 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 impl.java.dyn;
-+
-+import java.dyn.MethodHandle;
-+import java.dyn.MethodType;
-+import java.lang.reflect.AccessibleObject;
-+import java.lang.reflect.Field;
-+import static impl.java.dyn.MethodHandleNatives.Constants.*;
-+
-+/**
-+ * The JVM interface for the method handles package is all here.
-+ * @author jrose
-+ */
-+class MethodHandleNatives {
-+
-+ private MethodHandleNatives() { } // static only
-+
-+ /// MethodName support
-+
-+ static native void init(MemberName self, Object ref);
-+ static native void expand(MemberName self);
-+ static native void resolve(MemberName self, Class<?> caller);
-+ static native int getMembers(Class<?> defc, String matchName, String matchSig,
-+ int matchFlags, Class<?> caller, int skip, MemberName[] results);
-+
-+ /// MethodHandle support
-+
-+ /** Initialize the method handle to adapt the call. */
-+ static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
-+ /** Initialize the method handle to call the correct method, directly. */
-+ static native void init(BoundMethodHandle self, Object target, int argnum);
-+ /** Initialize the method handle to call as if by an invoke* instruction. */
-+ static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
-+
-+ /** Initialize a method type, once per form. */
-+ static native void init(MethodType self);
-+
-+ /** Tell the JVM that we need to change the target of an invokedynamic. */
-+ static native void linkCallSite(CallSiteImpl site, MethodHandle target);
-+
-+ /** Fetch the vmtarget field.
-+ * It will be sanitized as necessary to avoid exposing non-Java references.
-+ * This routine is for debugging and reflection.
-+ */
-+ static native Object getTarget(MethodHandle self, int format);
-+
-+ /** Fetch the name of the handled method, if available.
-+ * This routine is for debugging and reflection.
-+ */
-+ static MemberName getMethodName(MethodHandle self) {
-+ if (!JVM_SUPPORT) return null;
-+ return (MemberName) getTarget(self, ETF_METHOD_NAME);
-+ }
-+
-+ /** Fetch the reflective version of the handled method, if available.
-+ */
-+ static AccessibleObject getTargetMethod(MethodHandle self) {
-+ if (!JVM_SUPPORT) return null;
-+ return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
-+ }
-+
-+ /** Fetch the target of this method handle.
-+ * If it directly targets a method, return a tuple of method info.
-+ * The info is of the form new Object[]{defclass, name, sig, refclass}.
-+ * If it is chained to another method handle, return that handle.
-+ */
-+ static Object getTargetInfo(MethodHandle self) {
-+ if (!JVM_SUPPORT) return null;
-+ return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
-+ }
-+
-+ static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
-+ return new Object[] { defc, name, sig, mods, refc };
-+ }
-+
-+ /** Fetch MH-related JVM parameter.
-+ * which=0 retrieves MethodHandlePushLimit
-+ * which=1 retrieves stack slot push size (in address units)
-+ */
-+ static native int getConstant(int which);
-+
-+ /** True iff this HotSpot JVM has built-in support for method handles.
-+ * If false, some test cases might run, but functionality will be missing.
-+ */
-+ public static final boolean JVM_SUPPORT;
-+
-+ /** Java copy of MethodHandlePushLimit in range 2..255. */
-+ static final int JVM_PUSH_LIMIT;
-+ /** JVM stack motion (in words) after one slot is pushed, usually -1.
-+ */
-+ static final int JVM_STACK_MOVE_UNIT;
-+
-+ private static native void registerNatives();
-+ static {
-+ boolean JVM_SUPPORT_;
-+ int JVM_PUSH_LIMIT_;
-+ int JVM_STACK_MOVE_UNIT_;
-+ try {
-+ registerNatives();
-+ JVM_SUPPORT_ = true;
-+ JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
-+ JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_LIMIT);
-+ //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
-+ } catch (UnsatisfiedLinkError ee) {
-+ // ignore; if we use init() methods later we'll see linkage errors
-+ JVM_SUPPORT_ = false;
-+ JVM_PUSH_LIMIT_ = 3; // arbitrary
-+ JVM_STACK_MOVE_UNIT_ = -1; // arbitrary
-+ System.out.println("Warning: Running with JVM_SUPPORT=false");
-+ System.out.println(ee);
-+ }
-+ JVM_SUPPORT = JVM_SUPPORT_;
-+ JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
-+ JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
-+ }
-+
-+ // All compile-time constants go here.
-+ // There is an opportunity to check them against the JVM's idea of them.
-+ static class Constants {
-+ Constants() { } // static only
-+ // MethodHandleImpl
-+ static final int // for getConstant
-+ GC_JVM_PUSH_LIMIT = 0,
-+ GC_JVM_STACK_MOVE_LIMIT = 1;
-+ static final int
-+ ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
-+ ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
-+ ETF_METHOD_NAME = 2, // ultimate method as MemberName
-+ ETF_REFLECT_METHOD = 3; // ultimate method as java.lang.reflect object (sans refClass)
-+
-+ // MemberName
-+ // The JVM uses values of -2 and above for vtable indexes.
-+ // Field values are simple positive offsets.
-+ // Ref: src/share/vm/oops/methodOop.hpp
-+ // This value is negative enough to avoid such numbers,
-+ // but not too negative.
-+ static final int
-+ MN_IS_METHOD = 0x00010000, // method (not constructor)
-+ MN_IS_CONSTRUCTOR = 0x00020000, // constructor
-+ MN_IS_FIELD = 0x00040000, // field
-+ MN_IS_TYPE = 0x00080000, // nested type
-+ MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
-+ MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
-+ VM_INDEX_UNINITIALIZED = -99;
-+
-+ // AdapterMethodHandle
-+ /** Conversions recognized by the JVM.
-+ * They must align with the constants in impl_java_dyn_AdapterMethodHandle,
-+ * in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
-+ */
-+ static final int
-+ OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
-+ OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument
-+ OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another
-+ OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive
-+ OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI)
-+ OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg)
-+ OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg)
-+ OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS)
-+ OP_DROP_ARGS = 0x8, // remove one or more argument slots
-+ OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI)
-+ OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size)
-+ OP_FLYBY = 0xB, // operate first on reified argument list (NYI)
-+ OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI)
-+ CONV_OP_LIMIT = 0xD; // limit of CONV_OP enumeration
-+ /** Shift and mask values for decoding the AMH.conversion field.
-+ * These numbers are shared with the JVM for creating AMHs.
-+ */
-+ static final int
-+ CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
-+ CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
-+ CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
-+ CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
-+ CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
-+ CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
-+ CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
-+ CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
-+
-+ /**
-+ * Basic types as encoded in the JVM. These code values are not
-+ * intended for use outside this class. They are used as part of
-+ * a private interface between the JVM and this class.
-+ */
-+ static final int
-+ T_BOOLEAN = 4,
-+ T_CHAR = 5,
-+ T_FLOAT = 6,
-+ T_DOUBLE = 7,
-+ T_BYTE = 8,
-+ T_SHORT = 9,
-+ T_INT = 10,
-+ T_LONG = 11,
-+ T_OBJECT = 12,
-+ //T_ARRAY = 13
-+ T_VOID = 14;
-+ //T_ADDRESS = 15
-+ }
-+
-+ private static native int getNamedCon(int which, Object[] name);
-+ static boolean verifyConstants() {
-+ Object[] box = { null };
-+ for (int i = 0; ; i++) {
-+ box[0] = null;
-+ int vmval = getNamedCon(i, box);
-+ if (box[0] == null) break;
-+ String name = (String) box[0];
-+ try {
-+ Field con = Constants.class.getDeclaredField(name);
-+ int jval = con.getInt(null);
-+ if (jval != vmval)
-+ throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
-+ } catch (Exception ex) {
-+ throw new InternalError(name+": access failed, got "+ex);
-+ }
-+ }
-+ return true;
-+ }
-+ static {
-+ if (JVM_SUPPORT) verifyConstants();
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/package-info.java b/src/share/classes/impl/java/dyn/package-info.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/package-info.java
-@@ -0,0 +1,35 @@
-+/*
-+ * 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.
-+ */
-+
-+/**
-+ * Implementation details for JSR 292 RI, package java.dyn.
-+ * This particular version is specific to Hotspot.
-+ * There is also a backport version of this sub-package which uses reflection,
-+ * and can therefore run (slowly) on older versions of Java.
-+ * Other JVM vendors may create their own versions of this sub-package.
-+ * @author jrose
-+ */
-+
-+package impl.java.dyn;
-diff --git a/src/share/classes/impl/java/dyn/util/BytecodeSignature.java b/src/share/classes/impl/java/dyn/util/BytecodeSignature.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/BytecodeSignature.java
-@@ -0,0 +1,137 @@
-+/*
-+ * 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 impl.java.dyn.util;
-+
-+import java.dyn.MethodType;
-+import java.util.ArrayList;
-+import java.util.List;
-+
-+/**
-+ * Utility routines for dealing with bytecode-level signatures.
-+ * @author jrose
-+ */
-+public class BytecodeSignature {
-+
-+ private BytecodeSignature() { } // cannot instantiate
-+
-+ public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
-+ return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
-+ }
-+
-+ static List<Class<?>> parseMethod(String bytecodeSignature,
-+ int start, int end, ClassLoader loader) {
-+ if (loader == null)
-+ loader = ClassLoader.getSystemClassLoader();
-+ String str = bytecodeSignature;
-+ int[] i = {start};
-+ ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
-+ if (i[0] < end && str.charAt(i[0]) == '(') {
-+ ++i[0]; // skip '('
-+ while (i[0] < end && str.charAt(i[0]) != ')') {
-+ Class<?> pt = parseSig(str, i, end, loader);
-+ if (pt == null || pt == void.class)
-+ parseError(str, "bad argument type");
-+ ptypes.add(pt);
-+ }
-+ ++i[0]; // skip ')'
-+ } else {
-+ parseError(str, "not a method type");
-+ }
-+ Class<?> rtype = parseSig(str, i, end, loader);
-+ if (rtype == null || i[0] != end)
-+ parseError(str, "bad return type");
-+ ptypes.add(rtype);
-+ return ptypes;
-+ }
-+
-+ static private void parseError(String str, String msg) {
-+ throw new IllegalArgumentException("bad signature: "+str+": "+msg);
-+ }
-+
-+ static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
-+ if (i[0] == end) return null;
-+ char c = str.charAt(i[0]++);
-+ if (c == 'L') {
-+ int begc = i[0], endc = str.indexOf(';', begc);
-+ if (endc < 0) return null;
-+ i[0] = endc+1;
-+ String name = str.substring(begc, endc).replace('/', '.');
-+ try {
-+ return loader.loadClass(name);
-+ } catch (ClassNotFoundException ex) {
-+ throw new TypeNotPresentException(name, ex);
-+ }
-+ } else if (c == '[') {
-+ Class<?> t = parseSig(str, i, end, loader);
-+ if (t != null)
-+ t = java.lang.reflect.Array.newInstance(t, 0).getClass();
-+ return t;
-+ } else {
-+ return Wrappers.basicTypeFromChar(c);
-+ }
-+ }
-+
-+ public static String unparse(Class<?> type) {
-+ StringBuilder sb = new StringBuilder();
-+ unparseSig(type, sb);
-+ return sb.toString();
-+ }
-+
-+ public static String unparse(MethodType type) {
-+ return unparseMethod(type.returnType(), type.parameterList());
-+ }
-+
-+ public static String unparse(Object type) {
-+ if (type instanceof Class<?>)
-+ return unparse((Class<?>) type);
-+ if (type instanceof MethodType)
-+ return unparse((MethodType) type);
-+ return (String) type;
-+ }
-+
-+ public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
-+ StringBuilder sb = new StringBuilder();
-+ sb.append('(');
-+ for (Class<?> pt : ptypes)
-+ unparseSig(pt, sb);
-+ sb.append(')');
-+ unparseSig(rtype, sb);
-+ return sb.toString();
-+ }
-+
-+ static private void unparseSig(Class<?> t, StringBuilder sb) {
-+ char c = Wrappers.basicTypeChar(t);
-+ if (c != 'L') {
-+ sb.append(c);
-+ } else {
-+ boolean lsemi = (!t.isArray());
-+ if (lsemi) sb.append('L');
-+ sb.append(t.getName().replace('.', '/'));
-+ if (lsemi) sb.append(';');
-+ }
-+ }
-+
-+}
-diff --git a/src/share/classes/impl/java/dyn/util/MethodHandleInvoker.java b/src/share/classes/impl/java/dyn/util/MethodHandleInvoker.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/MethodHandleInvoker.java
-@@ -0,0 +1,454 @@
-+/*
-+ * 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 impl.java.dyn.util;
-+
-+import impl.java.dyn.Access;
-+import impl.java.dyn.AdapterMethodHandle;
-+import java.dyn.AnonymousClassLoader;
-+import java.dyn.ConstantPoolParser;
-+import java.dyn.ConstantPoolPatch;
-+import java.dyn.ConstantPoolVisitor;
-+import java.dyn.InvalidConstantPoolFormatException;
-+import java.dyn.MethodHandle;
-+import java.dyn.MethodHandles;
-+import java.dyn.MethodType;
-+import java.dyn.WrongMethodTypeException;
-+import java.io.IOException;
-+import java.lang.reflect.Constructor;
-+import java.lang.reflect.InvocationTargetException;
-+import java.util.IdentityHashMap;
-+
-+/**
-+ * Emulation of method handle invocation.
-+ * Not needed if javac supports direct invocation of MethodHandle.invoke.
-+ * @author jrose
-+ */
-+public abstract
-+class MethodHandleInvoker implements Cloneable {
-+ private static final Access IMPL_TOKEN = Access.getToken();
-+
-+
-+ /** Exact type for all handles targeted by this invoker. */
-+ protected final MethodType exactType;
-+
-+ /** Condensed information about the return type, one of "VLIJFDZBSC". */
-+ protected final char rtypec;
-+
-+ /** Adapter which converts the approximate type to the exact exactType. */
-+ protected final MethodHandle adapter;
-+
-+ /** Maximum number of arguments allowed.
-+ * This is an implementation limit.
-+ */
-+ public static final int ARGUMENT_MAX;
-+ /** Maximum number of double or long arguments allowed.
-+ * This is an implementation limit.
-+ */
-+ public static final int LONG_ARGUMENT_MAX;
-+ static {
-+ LONG_ARGUMENT_MAX = 3; // %%% depends on stack headroom
-+ }
-+
-+ public MethodType type() { return exactType; }
-+
-+ protected MethodHandleInvoker(MethodType exactType, MethodHandle adapter) {
-+ this.exactType = exactType;
-+ this.rtypec = Wrappers.basicTypeChar(exactType.returnType());
-+ this.adapter = adapter;
-+ }
-+
-+ static MethodHandle makeAdapter(MethodType exactType, MethodType approxType) {
-+ // For each argument, convert incoming Object to the exact type needed.
-+ int len = exactType.parameterCount();
-+ assert(len == approxType.parameterCount());
-+ if (exactType.parameterSlotCount() > len + LONG_ARGUMENT_MAX)
-+ throw new IllegalArgumentException("too many long arguments in "+exactType);
-+ MethodHandle invoker = MethodHandles.findVirtual(MethodHandle.class, "invoke", exactType);
-+ MethodType adapterType = approxType.insertParameterType(0, MethodHandle.class);
-+ return AdapterMethodHandle.makePairwiseConvert(IMPL_TOKEN, adapterType, invoker);
-+ }
-+
-+ public Object invoke_0(MethodHandle mh)
-+ { throw wrongType(mh); }
-+ public Object invoke_1(MethodHandle mh, Object a0)
-+ { throw wrongType(mh); }
-+ public Object invoke_2(MethodHandle mh, Object a0, Object a1)
-+ { throw wrongType(mh); }
-+ public Object invoke_3(MethodHandle mh, Object a0, Object a1, Object a2)
-+ { throw wrongType(mh); }
-+ public Object invoke_4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3)
-+ { throw wrongType(mh); }
-+ public Object invoke_5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4)
-+ { throw wrongType(mh); }
-+
-+ /** Reflective style generic invocation. This always delegates
-+ * to one of the invoke_X methods.
-+ * @param mh method handle to invoke (must be of exactly correct type)
-+ * @param args array of arguments to send to method (maybe null if empty)
-+ * @return
-+ */
-+ final // try this...
-+ public Object invoke(MethodHandle mh, Object ... args) {
-+ switch (args == null ? 0 : args.length) {
-+ case 0: return invoke_0(mh);
-+ case 1: return invoke_1(mh, args[0]);
-+ case 2: return invoke_2(mh, args[0], args[1]);
-+ case 3: return invoke_3(mh, args[0], args[1], args[2]);
-+ case 4: return invoke_4(mh, args[0], args[1], args[2], args[3]);
-+ case 5: return invoke_5(mh, args[0], args[1], args[2], args[3], args[4]);
-+ }
-+ throw wrongType(mh);
-+ }
-+
-+ // This class is not used after compile time.
-+ // It is renamed away to MethodHandle itself, to call the MHI.adapter.
-+ // TO DO: Update javac so we can call directly to polymorphic MH.invoke.
-+ private static abstract class FakeMethodHandle extends MethodHandle {
-+ public FakeMethodHandle() { super(null, null); }
-+ // here are all the invokes we need to link against:
-+ public abstract void fake_invoke_V0(MethodHandle mh);
-+ public abstract Object fake_invoke_L0(MethodHandle mh);
-+ public abstract int fake_invoke_I0(MethodHandle mh);
-+ public abstract long fake_invoke_J0(MethodHandle mh);
-+ public abstract double fake_invoke_F0(MethodHandle mh);
-+ public abstract double fake_invoke_D0(MethodHandle mh);
-+ public abstract void fake_invoke_V1(MethodHandle mh, Object a0);
-+ public abstract Object fake_invoke_L1(MethodHandle mh, Object a0);
-+ public abstract int fake_invoke_I1(MethodHandle mh, Object a0);
-+ public abstract long fake_invoke_J1(MethodHandle mh, Object a0);
-+ public abstract float fake_invoke_F1(MethodHandle mh, Object a0);
-+ public abstract double fake_invoke_D1(MethodHandle mh, Object a0);
-+ public abstract void fake_invoke_V2(MethodHandle mh, Object a0, Object a1);
-+ public abstract Object fake_invoke_L2(MethodHandle mh, Object a0, Object a1);
-+ public abstract int fake_invoke_I2(MethodHandle mh, Object a0, Object a1);
-+ public abstract long fake_invoke_J2(MethodHandle mh, Object a0, Object a1);
-+ public abstract float fake_invoke_F2(MethodHandle mh, Object a0, Object a1);
-+ public abstract double fake_invoke_D2(MethodHandle mh, Object a0, Object a1);
-+ public abstract void fake_invoke_V3(MethodHandle mh, Object a0, Object a1, Object a2);
-+ public abstract Object fake_invoke_L3(MethodHandle mh, Object a0, Object a1, Object a2);
-+ public abstract int fake_invoke_I3(MethodHandle mh, Object a0, Object a1, Object a2);
-+ public abstract long fake_invoke_J3(MethodHandle mh, Object a0, Object a1, Object a2);
-+ public abstract float fake_invoke_F3(MethodHandle mh, Object a0, Object a1, Object a2);
-+ public abstract double fake_invoke_D3(MethodHandle mh, Object a0, Object a1, Object a2);
-+ public abstract void fake_invoke_V4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3);
-+ public abstract Object fake_invoke_L4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3);
-+ public abstract int fake_invoke_I4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3);
-+ public abstract long fake_invoke_J4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3);
-+ public abstract float fake_invoke_F4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3);
-+ public abstract double fake_invoke_D4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3);
-+ public abstract void fake_invoke_V5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4);
-+ public abstract Object fake_invoke_L5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4);
-+ public abstract int fake_invoke_I5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4);
-+ public abstract long fake_invoke_J5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4);
-+ public abstract float fake_invoke_F5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4);
-+ public abstract double fake_invoke_D5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4);
-+ }
-+ private static String FMHInvokeName(MethodType approxType) {
-+ assert(isFMHInvokeType(approxType)) : approxType;
-+ return "fake_invoke_"
-+ + Wrappers.basicTypeChar(approxType.returnType())
-+ + approxType.parameterCount();
-+ }
-+ private static boolean isFMHInvokeType(MethodType approxType) {
-+ Class<?> rtype = approxType.returnType();
-+ char rtc = Wrappers.basicTypeChar(approxType.returnType());
-+ if ("VIJFD".indexOf(rtc) < 0 && rtype != Object.class)
-+ return false;
-+ int len = approxType.parameterCount();
-+ for (int i = 0; i < len; i++)
-+ if (approxType.parameterType(i) != Object.class)
-+ return false;
-+ return true;
-+ }
-+
-+ protected Object wrap(int value) {
-+ switch (rtypec) {
-+ case 'Z': return (value != 0);
-+ case 'B': return (byte)value;
-+ case 'S': return (short)value;
-+ case 'C': return (char)value;
-+ }
-+ return value;
-+ }
-+
-+ static class L0 extends MethodHandleInvoker {
-+ public L0(MethodType type, MethodHandle adapter) { super(type, adapter); }
-+ @Override public Object invoke_0(MethodHandle mh) {
-+ checkType(mh);
-+ switch (rtypec) {
-+ // Note: Could unswitch this into 5 classes, but too messy.
-+ case 'L': return ((FakeMethodHandle)adapter).fake_invoke_L0(mh);
-+ default: return wrap(((FakeMethodHandle)adapter).fake_invoke_I0(mh));
-+ case 'J': return ((FakeMethodHandle)adapter).fake_invoke_J0(mh);
-+ case 'F': return ((FakeMethodHandle)adapter).fake_invoke_F0(mh);
-+ case 'D': return ((FakeMethodHandle)adapter).fake_invoke_D0(mh);
-+ case 'V': ((FakeMethodHandle)adapter).fake_invoke_V0(mh);
-+ /* Here is the sort of code we will use when we get javac support:
-+ case 'L': return adapter.invoke(mh);
-+ default: return wrap(adapter.<int>invoke(mh));
-+ case 'J': return adapter.<long>invoke(mh);
-+ case 'F': return adapter.<float>invoke(mh);
-+ case 'D': return adapter.<double>invoke(mh);
-+ case 'V': adapter.<void>invoke(mh);
-+ */
-+ }
-+ return null;
-+ }
-+ }
-+
-+ static class L1 extends MethodHandleInvoker {
-+ public L1(MethodType type, MethodHandle adapter) { super(type, adapter); }
-+ @Override public Object invoke_1(MethodHandle mh, Object a0) {
-+ checkType(mh);
-+ switch (rtypec) {
-+ case 'L': return ((FakeMethodHandle)adapter).fake_invoke_L1(mh, a0);
-+ default: return wrap(((FakeMethodHandle)adapter).fake_invoke_I1(mh, a0));
-+ case 'J': return ((FakeMethodHandle)adapter).fake_invoke_J1(mh, a0);
-+ case 'F': return ((FakeMethodHandle)adapter).fake_invoke_F1(mh, a0);
-+ case 'D': return ((FakeMethodHandle)adapter).fake_invoke_D1(mh, a0);
-+ case 'V': ((FakeMethodHandle)adapter).fake_invoke_V1(mh, a0);
-+ }
-+ return null;
-+ }
-+ }
-+
-+ static class L2 extends MethodHandleInvoker {
-+ public L2(MethodType type, MethodHandle adapter) { super(type, adapter); }
-+ @Override public Object invoke_2(MethodHandle mh, Object a0, Object a1) {
-+ checkType(mh);
-+ switch (rtypec) {
-+ case 'L': return ((FakeMethodHandle)adapter).fake_invoke_L2(mh, a0, a1);
-+ default: return wrap(((FakeMethodHandle)adapter).fake_invoke_I2(mh, a0, a1));
-+ case 'J': return ((FakeMethodHandle)adapter).fake_invoke_J2(mh, a0, a1);
-+ case 'F': return ((FakeMethodHandle)adapter).fake_invoke_F2(mh, a0, a1);
-+ case 'D': return ((FakeMethodHandle)adapter).fake_invoke_D2(mh, a0, a1);
-+ case 'V': ((FakeMethodHandle)adapter).fake_invoke_V2(mh, a0, a1);
-+ }
-+ return null;
-+ }
-+ }
-+
-+ static class L3 extends MethodHandleInvoker {
-+ public L3(MethodType type, MethodHandle adapter) { super(type, adapter); }
-+ @Override public Object invoke_3(MethodHandle mh, Object a0, Object a1, Object a2) {
-+ checkType(mh);
-+ switch (rtypec) {
-+ case 'L': return ((FakeMethodHandle)adapter).fake_invoke_L3(mh, a0, a1, a2);
-+ default: return wrap(((FakeMethodHandle)adapter).fake_invoke_I3(mh, a0, a1, a2));
-+ case 'J': return ((FakeMethodHandle)adapter).fake_invoke_J3(mh, a0, a1, a2);
-+ case 'F': return ((FakeMethodHandle)adapter).fake_invoke_F3(mh, a0, a1, a2);
-+ case 'D': return ((FakeMethodHandle)adapter).fake_invoke_D3(mh, a0, a1, a2);
-+ case 'V': ((FakeMethodHandle)adapter).fake_invoke_V3(mh, a0, a1, a2);
-+ }
-+ return null;
-+ }
-+ }
-+
-+ static class L4 extends MethodHandleInvoker {
-+ public L4(MethodType type, MethodHandle adapter) { super(type, adapter); }
-+ @Override public Object invoke_4(MethodHandle mh, Object a0, Object a1, Object a2, Object a3) {
-+ checkType(mh);
-+ switch (rtypec) {
-+ case 'L': return ((FakeMethodHandle)adapter).fake_invoke_L4(mh, a0, a1, a2, a3);
-+ default: return wrap(((FakeMethodHandle)adapter).fake_invoke_I4(mh, a0, a1, a2, a3));
-+ case 'J': return ((FakeMethodHandle)adapter).fake_invoke_J4(mh, a0, a1, a2, a3);
-+ case 'F': return ((FakeMethodHandle)adapter).fake_invoke_F4(mh, a0, a1, a2, a3);
-+ case 'D': return ((FakeMethodHandle)adapter).fake_invoke_D4(mh, a0, a1, a2, a3);
-+ case 'V': ((FakeMethodHandle)adapter).fake_invoke_V4(mh, a0, a1, a2, a3);
-+ }
-+ return null;
-+ }
-+ }
-+
-+ static class L5 extends MethodHandleInvoker {
-+ public L5(MethodType type, MethodHandle adapter) { super(type, adapter); }
-+ @Override public Object invoke_5(MethodHandle mh, Object a0, Object a1, Object a2, Object a3, Object a4) {
-+ checkType(mh);
-+ switch (rtypec) {
-+ case 'L': return ((FakeMethodHandle)adapter).fake_invoke_L5(mh, a0, a1, a2, a3, a4);
-+ default: return wrap(((FakeMethodHandle)adapter).fake_invoke_I5(mh, a0, a1, a2, a3, a4));
-+ case 'J': return ((FakeMethodHandle)adapter).fake_invoke_J5(mh, a0, a1, a2, a3, a4);
-+ case 'F': return ((FakeMethodHandle)adapter).fake_invoke_F5(mh, a0, a1, a2, a3, a4);
-+ case 'D': return ((FakeMethodHandle)adapter).fake_invoke_D5(mh, a0, a1, a2, a3, a4);
-+ case 'V': ((FakeMethodHandle)adapter).fake_invoke_V5(mh, a0, a1, a2, a3, a4);
-+ }
-+ return null;
-+ }
-+ }
-+
-+ private static Class<?>[] L_CLASSES
-+ = { L0.class, L1.class, L2.class, L3.class, L4.class, L5.class };
-+ static { ARGUMENT_MAX = L_CLASSES.length + 1; }
-+
-+ public static MethodHandleInvoker make(MethodType type) {
-+ MethodHandleInvoker inv = null;
-+ synchronized (invokers) {
-+ inv = invokers.get(type);
-+ }
-+ if (inv != null) return inv;
-+ inv = makeNew(type);
-+ synchronized (invokers) {
-+ MethodHandleInvoker inv2 = invokers.get(type);
-+ if (inv2 == null)
-+ invokers.put(type, inv);
-+ else
-+ inv = inv2;
-+ }
-+ System.out.println("new invoker: "+inv);
-+ return inv;
-+ }
-+
-+ static MethodType approxType(MethodType exactType) {
-+ int len = exactType.parameterCount();
-+ if (len > ARGUMENT_MAX)
-+ throw new IllegalArgumentException("too many arguments for invoker: "+exactType);
-+ // The JVM can insert casts and unboxing for us in a native adapter.
-+ MethodType approxType = MethodType.makeGeneric(len);
-+ // But the return type must be exact, except for subword types.
-+ // Convert subwords to int, since the JVM an narrow them back down.
-+ Class<?> rtype = exactType.returnType();
-+ switch (Wrappers.basicTypeChar(rtype)) {
-+ case 'L':
-+ rtype = Object.class; break;
-+ case 'Z': case 'B': case 'S': case 'C':
-+ rtype = int.class; break;
-+ }
-+ approxType = approxType.changeReturnType(rtype);
-+ return approxType;
-+ }
-+
-+ private static MethodHandleInvoker makeNew(MethodType exactType) {
-+ MethodHandleInvoker inv = null;
-+ Exception ex1 = null;
-+ MethodType approxType = approxType(exactType);
-+ MethodHandle adapter = makeAdapter(exactType, approxType);
-+ Class<? extends MethodHandleInvoker> template = null;
-+ Class<? extends MethodHandleInvoker> instance = null;
-+ Constructor<? extends MethodHandleInvoker> constr = null;
-+ template = L_CLASSES[approxType.parameterCount()].asSubclass(MethodHandleInvoker.class);
-+ {
-+ try {
-+ instance = expandTemplate(template, approxType, exactType);
-+ // When we get rid of the fakery, it will be just
-+ // constr = template.getConstructor
-+ constr = instance.getConstructor(MethodType.class, MethodHandle.class);
-+ inv = constr.newInstance(exactType, adapter);
-+ } catch (IOException ex) {
-+ ex1 = ex;
-+ } catch (InvalidConstantPoolFormatException ex) {
-+ ex1 = ex;
-+ } catch (InstantiationException ex) {
-+ ex1 = ex;
-+ } catch (IllegalAccessException ex) {
-+ ex1 = ex;
-+ } catch (NoSuchMethodException ex) {
-+ ex1 = ex;
-+ } catch (IllegalArgumentException ex) {
-+ ex1 = ex;
-+ } catch (InvocationTargetException ex) {
-+ ex1 = ex;
-+ }
-+ }
-+ if (inv == null) {
-+ printex(ex1);
-+ throw new InternalError();
-+ }
-+ return inv;
-+ }
-+ private static void printex(Exception ex) {
-+ System.out.println("*** Unexpected exception in "+MethodHandleInvoker.class);
-+ System.out.println(ex);
-+ ex.printStackTrace(System.out);
-+ }
-+
-+ private static final AnonymousClassLoader LOADER
-+ = new AnonymousClassLoader(MethodHandleInvoker.class);
-+
-+ private static String utf8Name(Class<?> cls) {
-+ return cls.getName().replace('.', '/');
-+ }
-+
-+ private static class TemplateExpander extends ConstantPoolVisitor {
-+ ConstantPoolParser cp;
-+ ConstantPoolPatch patch;
-+
-+ // Pairs of strings to be rewritten:
-+ String fakeMHName = utf8Name(FakeMethodHandle.class);
-+ String realMHName = utf8Name(MethodHandle.class);
-+ boolean didMHName;
-+
-+ String fakeInvokeName, realInvokeName = "invoke";
-+ boolean didInvokeName;
-+
-+ @Override
-+ public void visitUTF8(int index, byte tag, String utf8) {
-+ String orig = utf8;
-+ if (utf8.equals(fakeMHName)) {
-+ utf8 = realMHName; didMHName = true;
-+ }
-+ if (utf8.equals(fakeInvokeName)) {
-+ utf8 = realInvokeName; didInvokeName = true;
-+ }
-+ if ((Object)utf8 != orig)
-+ patch.putUTF8(index, utf8);
-+ }
-+
-+ public TemplateExpander(Class<? extends MethodHandleInvoker> template,
-+ MethodType approxType, MethodType exactType)
-+ throws IOException, InvalidConstantPoolFormatException {
-+ // construct a descriptor of something like:
-+ // int fake_invoke_I2(MethodHandle, Object, Object);
-+ fakeInvokeName = FMHInvokeName(approxType);
-+ cp = new ConstantPoolParser(template);
-+ patch = cp.createPatch();
-+ cp.parse(this);
-+ if (!(didMHName && didInvokeName))
-+ throw new RuntimeException("utf8 rewrites failed: "
-+ +(!didMHName?"":fakeMHName)+(!didInvokeName?"":fakeInvokeName));
-+ }
-+ }
-+
-+ static final IdentityHashMap<MethodType,MethodHandleInvoker> invokers
-+ = new IdentityHashMap<MethodType, MethodHandleInvoker>();
-+
-+ private static Class<? extends MethodHandleInvoker>
-+ expandTemplate(Class<? extends MethodHandleInvoker> template,
-+ MethodType approxType, MethodType exactType)
-+ throws IOException, InvalidConstantPoolFormatException {
-+ TemplateExpander tex = new TemplateExpander(template, approxType, exactType);
-+ return LOADER.loadClass(tex.patch).asSubclass(MethodHandleInvoker.class);
-+ }
-+
-+ /** Throw this if a bad entry point is taken. */
-+ protected RuntimeException wrongType(MethodHandle mh) {
-+ return new WrongMethodTypeException("wrong call type for "+mh+
-+ " should be "+exactType+" in "+this);
-+ }
-+ protected void checkType(MethodHandle mh) {
-+ if (mh.type() != exactType)
-+ throw wrongType(mh);
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/util/VerifyAccess.java b/src/share/classes/impl/java/dyn/util/VerifyAccess.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/VerifyAccess.java
-@@ -0,0 +1,135 @@
-+/*
-+ * 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 impl.java.dyn.util;
-+
-+import impl.java.dyn.MemberName;
-+import java.lang.reflect.Method;
-+import java.lang.reflect.Modifier;
-+import java.util.Arrays;
-+
-+/**
-+ * This class centralizes information about the JVM's linkage access control.
-+ * @author jrose
-+ */
-+public class VerifyAccess {
-+
-+ private VerifyAccess() { } // cannot instantiate
-+
-+ /**
-+ * Evaluate the JVM linkage rules for access to the given method on behalf of caller.
-+ * Return non-null if and only if the given accessing class has at least partial
-+ * privileges to invoke the given method. The return value {@code Object.class}
-+ * denotes unlimited privileges.
-+ * <p>
-+ * Some circumstances require an additional check on the
-+ * leading parameter (the receiver) of the method, if it is non-static.
-+ * In the case of {@code invokespecial} ({@code doDispatch} is false),
-+ * the leading parameter must be the accessing class or a subclass.
-+ * In the case of a call to a {@code protected} method outside the same
-+ * package, the same constraint applies.
-+ * @param m the proposed callee
-+ * @param doDispatch if false, a non-static m will be invoked as if by {@code invokespecial}
-+ * @param accessingClass the class for which the access check is being made
-+ * @return null if the method is not accessible, else a receiver type constraint, else {@code Object.class}
-+ */
-+ public static Class<?> isAccessible(Class<?> defc, int mods,
-+ boolean doDispatch, Class<?> accessingClass) {
-+ if (!isAccessible(defc, accessingClass))
-+ return null;
-+ Class<?> constraint = Object.class;
-+ if (!doDispatch && !Modifier.isStatic(mods)) {
-+ constraint = accessingClass;
-+ }
-+ if (Modifier.isPublic(mods))
-+ return constraint;
-+ if (Modifier.isPrivate(mods))
-+ return (defc == accessingClass) ? constraint : null;
-+ if (isSamePackage(defc, accessingClass))
-+ return constraint;
-+ if (Modifier.isProtected(mods) && defc.isAssignableFrom(accessingClass))
-+ return constraint;
-+ // else it is private or package scoped, and not close enough
-+ return null;
-+ }
-+
-+ /**
-+ * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
-+ */
-+ public static boolean isAccessible(Class<?> refc, Class<?> accessingClass) {
-+ int mods = refc.getModifiers();
-+ if (Modifier.isPublic(mods))
-+ return true;
-+ if (isSamePackage(accessingClass, refc))
-+ return true;
-+ return false;
-+ }
-+
-+ /**
-+ * Test if two classes have the same class loader and package qualifier.
-+ * @param class1
-+ * @param class2
-+ * @return whether they are in the same package
-+ */
-+ public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
-+ if (class1 == class2)
-+ return true;
-+ if (class1.getClassLoader() != class2.getClassLoader())
-+ return false;
-+ String name1 = class1.getName(), name2 = class2.getName();
-+ int dot = name1.lastIndexOf('.');
-+ if (dot != name2.lastIndexOf('.'))
-+ return false;
-+ for (int i = 0; i < dot; i++) {
-+ if (name1.charAt(i) != name2.charAt(i))
-+ return false;
-+ }
-+ return true;
-+ }
-+
-+ /**
-+ * Test if two classes are defined as part of the same package member (top-level class).
-+ * If this is true, they can share private access with each other.
-+ * @param class1
-+ * @param class2
-+ * @return whether they are identical or nested together
-+ */
-+ public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
-+ if (class1 == class2)
-+ return true;
-+ if (!isSamePackage(class1, class2))
-+ return false;
-+ if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
-+ return false;
-+ return true;
-+ }
-+
-+ private static Class<?> getOutermostEnclosingClass(Class<?> c) {
-+ Class<?> pkgmem = c;
-+ for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
-+ pkgmem = enc;
-+ return pkgmem;
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/util/VerifyType.java b/src/share/classes/impl/java/dyn/util/VerifyType.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/VerifyType.java
-@@ -0,0 +1,140 @@
-+/*
-+ * 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 impl.java.dyn.util;
-+
-+import java.dyn.MethodType;
-+
-+/**
-+ * This class centralizes information about the JVM verifier
-+ * and its requirements about type correctness.
-+ * @author jrose
-+ */
-+public class VerifyType {
-+
-+ private VerifyType() { } // cannot instantiate
-+
-+ /**
-+ * True if a value can be stacked as the source type and unstacked as the
-+ * destination type, without violating the JVM's type consistency.
-+ *
-+ * @param call the type of a stacked value
-+ * @param recv the type by which we'd like to treat it
-+ * @return whether the retyping can be done without motion or reformatting
-+ */
-+ public static boolean isNullConversion(Class<?> src, Class<?> dst) {
-+ if (src == dst) return true;
-+ // Verifier allows any interface to be treated as Object:
-+ if (dst.isInterface()) dst = Object.class;
-+ if (src.isInterface()) src = Object.class;
-+ if (src == dst) return true; // check again
-+ if (dst == void.class) return true; // drop any return value
-+ if (!src.isPrimitive()) return dst.isAssignableFrom(src);
-+ // Verifier allows an int to carry byte, short, char, or even boolean:
-+ if (dst == int.class) return Wrappers.isSubwordOrInt(src);
-+ return false;
-+ }
-+
-+ /**
-+ * True if a method handle can receive a call under a slightly different
-+ * method type, without moving or reformatting any stack elements.
-+ *
-+ * @param call the type of call being made
-+ * @param recv the type of the method handle receiving the call
-+ * @return whether the retyping can be done without motion or reformatting
-+ */
-+ public static boolean isNullConversion(MethodType call, MethodType recv) {
-+ if (call == recv) return true;
-+ int len = call.parameterCount();
-+ if (len != recv.parameterCount()) return false;
-+ for (int i = 0; i < len; i++)
-+ if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
-+ return false;
-+ return isNullConversion(recv.returnType(), call.returnType());
-+ }
-+
-+ /**
-+ * Determine if the JVM verifier allows a value of type call to be
-+ * passed to a formal parameter (or return variable) of type recv.
-+ * Returns 1 if the verifier allows the types to match without conversion.
-+ * Returns -1 if the types can be made to match by a JVM-supported adapter.
-+ * Cases supported are:
-+ * <ul><li>checkcast
-+ * </li><li>conversion between any two integral types (but not floats)
-+ * </li><li>unboxing from a wrapper to its corresponding primitive type
-+ * </li><li>conversion in either direction between float and double
-+ * </li></ul>
-+ * (Autoboxing is not supported here; it must be done via Java code.)
-+ * Returns 0 otherwise.
-+ */
-+ public static int canPassUnchecked(Class<?> src, Class<?> dst) {
-+ if (src == dst)
-+ return 1;
-+
-+ if (dst.isPrimitive()) {
-+ if (dst == void.class)
-+ // Return anything to a caller expecting void.
-+ return 1;
-+ if (src == void.class)
-+ return 0; // void-to-something?
-+ if (!src.isPrimitive())
-+ // Cannot pass a reference to any primitive type (exc. void).
-+ return 0;
-+ boolean swt = Wrappers.isSubwordOrInt(src);
-+ boolean dwt = Wrappers.isSubwordOrInt(dst);
-+ if (swt && dwt) {
-+ if (Wrappers.bitWidth(src) >= Wrappers.bitWidth(dst))
-+ return -1; // truncation may be required
-+ if (!Wrappers.isSigned(dst) && Wrappers.isSigned(src))
-+ return -1; // sign elimination may be required
-+ }
-+ if (src == float.class || dst == float.class) {
-+ if (src == double.class || dst == double.class)
-+ return -1; // floating conversion may be required
-+ else
-+ return 0; // other primitive conversions NYI
-+ } else {
-+ // all fixed-point conversions are supported
-+ return 0;
-+ }
-+ } else if (src.isPrimitive()) {
-+ // Cannot pass a primitive to any reference type.
-+ // (Maybe allow null.class?)
-+ return 0;
-+ }
-+
-+ // Handle reference types in the rest of the block:
-+
-+ // The verifier treats interfaces exactly like Object.
-+ if (dst.isInterface()) dst = Object.class;
-+ //if (call.isInterface()) call = Object.class;
-+ if (dst == Object.class)
-+ // pass any reference to object or an arb. interface
-+ return 1;
-+ // else it's a definite "maybe" (cast is required)
-+ return -1;
-+ }
-+
-+}
-diff --git a/src/share/classes/impl/java/dyn/util/Wrappers.java b/src/share/classes/impl/java/dyn/util/Wrappers.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/Wrappers.java
-@@ -0,0 +1,272 @@
-+/*
-+ * 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 impl.java.dyn.util;
-+
-+import java.util.HashMap;
-+
-+public class Wrappers {
-+
-+ private Wrappers() { } // cannot instantiate
-+
-+ /** If {@code type} is a primitive type, return the corresponding
-+ * wrapper type, else return {@code type} unchanged.
-+ */
-+ public static <T> Class<T> asWrapperType(Class<T> type) {
-+ if (!type.isPrimitive()) {
-+ return type;
-+ }
-+ if (wrappers.isEmpty()) {
-+ fillWrappers();
-+ }
-+ Object[] memo = wrappers.get(type);
-+ assert (memo != null);
-+ return (Class<T>) memo[0]; // unchecked warning is OK here
-+ }
-+
-+ /** If {@code type} is a wrapper type, return the corresponding
-+ * primitive type, else return {@code type} unchanged.
-+ */
-+ public static <T> Class<T> asPrimitiveType(Class<T> type) {
-+ if (type.isPrimitive()) {
-+ return type;
-+ }
-+ if (wrappers.isEmpty()) {
-+ fillWrappers();
-+ }
-+ Object[] memo = wrappers.get(type);
-+ if (memo == null) {
-+ return type;
-+ }
-+ return (Class<T>) memo[1]; // unchecked warning is OK here
-+ }
-+
-+ public static boolean isWrapperType(Class<?> type) {
-+ return asPrimitiveType(type) != type;
-+ }
-+
-+ public static boolean isPrimitiveType(Class<?> type) {
-+ return type.isPrimitive();
-+ }
-+
-+ public static char basicTypeChar(Class<?> type) {
-+ if (!type.isPrimitive()) {
-+ return 'L';
-+ }
-+ if (wrappers.isEmpty()) {
-+ fillWrappers();
-+ }
-+ Object[] memo = wrappers.get(type);
-+ assert (memo != null);
-+ return (char) (Character) memo[2];
-+ }
-+
-+ static final String PRIMITIVE_BITS_TABLE = "LZBCSFIZZDJ";
-+ // "--01234 78"
-+
-+ /** Return the number of bits in the given type, or zero for refs. */
-+ public static int bitWidth(Class<?> type) {
-+ return bitWidth(basicTypeChar(type));
-+ }
-+
-+ /** Return the number of bits in the given basic type, or zero for refs. */
-+ public static int bitWidth(char c) {
-+ int i = PRIMITIVE_BITS_TABLE.indexOf(c);
-+ if (i < 0) throw new IllegalArgumentException("not a basic type char: "+c);
-+ i -= 2;
-+ switch (i) {
-+ case -2: return 0; // L
-+ case -1: return 1; // Z
-+ case 0: return 8; // B
-+ default: return (i + (i & 1)) * 8;
-+ }
-+ }
-+
-+ static final String PRIMITIVE_SIGN_TABLE = "JZICSZB";
-+ // "SuSuS S"
-+ /** Return whether the given type is a signed integral type. */
-+ public static boolean isSigned(Class<?> type) {
-+ return isSigned(basicTypeChar(type));
-+ }
-+
-+ /** Return whether the given type is a signed integral type. */
-+ public static boolean isSigned(char c) {
-+ int i = PRIMITIVE_SIGN_TABLE.indexOf(c);
-+ return (i & 1) == 0;
-+ }
-+
-+ /** Return whether the given type is a unsigned integral type. */
-+ public static boolean isUnsigned(Class<?> type) {
-+ return isUnsigned(basicTypeChar(type));
-+ }
-+
-+ /** Return whether the given type is a unsigned integral type. */
-+ public static boolean isUnsigned(char c) {
-+ int i = PRIMITIVE_SIGN_TABLE.indexOf(c);
-+ return (i & 0x11) == 1;
-+ }
-+
-+ /** Return whether the given type is an integral type. */
-+ public static boolean isIntegral(Class<?> type) {
-+ return isIntegral(basicTypeChar(type));
-+ }
-+
-+ /** Return whether the given type is an integral type. */
-+ public static boolean isIntegral(char c) {
-+ int i = PRIMITIVE_SIGN_TABLE.indexOf(c);
-+ return i >= 0;
-+ }
-+
-+ /** Report if the type is one of int, boolean, byte, char, or short. */
-+ public static boolean isSubwordOrInt(Class<?> type) {
-+ return isSubwordOrInt(basicTypeChar(type));
-+ }
-+
-+ /** Report if the type char is one of "IZBCS". */
-+ public static boolean isSubwordOrInt(char c) {
-+ return PRIMITIVE_SIGN_TABLE.indexOf(c) > 0;
-+ }
-+
-+ /** Return whether the given type is a floating primitive type. */
-+ public static boolean isFloating(Class<?> type) {
-+ return isFloating(basicTypeChar(type));
-+ }
-+
-+ /** Return whether the given type is a floating primitive type. */
-+ public static boolean isFloating(char c) {
-+ return c == 'F' || c == 'D';
-+ }
-+
-+ /** Return the primitive type that corresponds to the given bytecode
-+ * signature character. Return {@code Object.class} for the character
-+ * 'L', and null for any non-signature character or '['.
-+ */
-+ public static Class<?> basicTypeFromChar(char c) {
-+ if (c == 'L') {
-+ return Object.class;
-+ }
-+// if (c == '[') {
-+// return Object[].class;
-+// }
-+ if (wrappers.isEmpty()) {
-+ fillWrappers();
-+ }
-+ Object[] memo = wrappers.get((Character)c);
-+ if (memo == null)
-+ return null; // random junk character
-+ return (Class<?>) memo[1];
-+ }
-+
-+ public static Object zeroValue(Class<?> type) {
-+ if (!type.isPrimitive()) {
-+ return null;
-+ }
-+ if (wrappers.isEmpty()) {
-+ fillWrappers();
-+ }
-+ Object[] memo = wrappers.get(type);
-+ assert (memo != null);
-+ return memo[3];
-+ }
-+
-+ public static <T> T wrap(Object x, Class<T> numClass) {
-+ if (wrappers.isEmpty()) {
-+ fillWrappers();
-+ }
-+ Object[] memo = wrappers.get(numClass);
-+ if (memo == null) return numClass.cast(x); // no change
-+ Class<T> wrapType = (Class<T>) memo[0]; // unchecked warning is OK here
-+ return wrapType.cast(wrap(x, (Character) memo[2]));
-+ }
-+ public static Object wrap(Object x, char c) {
-+ Number xn = numberValue(x);
-+ switch (c) {
-+ case 'I': return Integer.valueOf(xn.intValue());
-+ case 'J': return Long.valueOf(xn.longValue());
-+ case 'F': return Float.valueOf(xn.floatValue());
-+ case 'D': return Double.valueOf(xn.doubleValue());
-+ case 'S': return Short.valueOf((short) xn.intValue());
-+ case 'B': return Byte.valueOf((byte) xn.intValue());
-+ case 'C': return Character.valueOf((char) xn.intValue());
-+ case 'Z': return Boolean.valueOf(boolValue(xn.longValue()));
-+ case 'V': return null;
-+ }
-+ return xn;
-+ }
-+
-+ private static Number numberValue(Object x) {
-+ if (x instanceof Number) return (Number)x;
-+ if (x instanceof Character) return (int)(Character)x;
-+ if (x instanceof Boolean) return (Boolean)x ? 1 : 0;
-+ // Remaining allowed case of void: Must be a null reference.
-+ return (Number)x;
-+ }
-+ private static boolean boolValue(long bits) {
-+ bits &= 1; // simple 31-bit zero extension
-+ return (bits != 0);
-+ }
-+
-+ private static final HashMap<Object, Object[]> wrappers
-+ = new HashMap<Object, Object[]>(20);
-+
-+ private static void fillWrappers() {
-+ Object[][] memos = {
-+ {Boolean.class, Boolean.TYPE, 'Z', (Boolean) false},
-+ {Character.class, Character.TYPE, 'C', (Character) '\000'},
-+ {Byte.class, Byte.TYPE, 'B', (Byte) (byte) 0},
-+ {Short.class, Short.TYPE, 'S', (Short) (short) 0},
-+ {Integer.class, Integer.TYPE, 'I', (Integer) 0},
-+ {Long.class, Long.TYPE, 'J', (Long) 0L},
-+ {Float.class, Float.TYPE, 'F', (Float) 0.0F},
-+ {Double.class, Double.TYPE, 'D', (Double) 0.0},
-+ {Void.class, Void.TYPE, 'V', null}
-+ };
-+ for (Object[] memo : memos) {
-+ wrappers.put(memo[0], memo);
-+ wrappers.put(memo[1], memo);
-+ wrappers.put(memo[2], memo);
-+ }
-+ }
-+
-+ // TO DO: Put these into a unit test.
-+ private static Class<Integer> PTYPE = int.class, WTYPE = Integer.class;
-+ static {
-+ assert(PTYPE != WTYPE);
-+ assert(asPrimitiveType(PTYPE) == PTYPE);
-+ assert(asPrimitiveType(WTYPE) == PTYPE);
-+ assert( asWrapperType(PTYPE) == WTYPE);
-+ assert( asWrapperType(WTYPE) == WTYPE);
-+
-+ assert(bitWidth(String.class) == 0);
-+ assert(bitWidth(Integer.class) == 0);
-+ assert(bitWidth(int.class) == 32);
-+ assert(bitWidth(char.class) == 16);
-+ assert(bitWidth(short.class) == 16);
-+ assert(bitWidth(byte.class) == 8);
-+ assert(bitWidth(boolean.class) == 1);
-+ assert(bitWidth(double.class) == 64);
-+ assert(bitWidth(float.class) == 32);
-+ }
-+}
-diff --git a/src/share/classes/impl/java/dyn/util/package-info.java b/src/share/classes/impl/java/dyn/util/package-info.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/classes/impl/java/dyn/util/package-info.java
-@@ -0,0 +1,31 @@
-+/*
-+ * 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.
-+ */
-+
-+/**
-+ * Extra support for using JSR 292 RI, package java.dyn.
-+ * @author jrose
-+ */
-+
-+package impl.java.dyn.util;
diff --git a/src/share/classes/java/dyn/MethodHandle.java b/src/share/classes/java/dyn/MethodHandle.java
new file mode 100644
--- /dev/null
@@ -3854,7 +128,7 @@ new file mode 100644
+package java.dyn;
+
+//import java.dyn.emu.*;
-+import impl.java.dyn.*;
++import sun.dyn.*;
+
+/**
+ * A method handle is a typed reference to the entry point of a method.
@@ -3987,20 +261,20 @@ new file mode 100644
+
+package java.dyn;
+
-+import impl.java.dyn.Access;
-+import impl.java.dyn.MemberName;
-+import impl.java.dyn.MethodHandleImpl;
-+import impl.java.dyn.util.MethodHandleInvoker;
-+import impl.java.dyn.util.VerifyAccess;
-+import impl.java.dyn.util.Wrappers;
++import sun.dyn.Access;
++import sun.dyn.MemberName;
++import sun.dyn.MethodHandleImpl;
++import sun.dyn.util.MethodHandleInvoker;
++import sun.dyn.util.VerifyAccess;
++import sun.dyn.util.Wrappers;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import sun.reflect.Reflection;
-+import static impl.java.dyn.MemberName.newIllegalArgumentException;
-+import static impl.java.dyn.MemberName.newNoAccessException;
++import static sun.dyn.MemberName.newIllegalArgumentException;
++import static sun.dyn.MemberName.newNoAccessException;
+
+/**
+ * Fundamental operations and utilities for MethodHandle.
@@ -5037,9 +1311,9 @@ new file mode 100644
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
-+import impl.java.dyn.*;
-+import impl.java.dyn.util.BytecodeSignature;
-+import static impl.java.dyn.MemberName.newIllegalArgumentException;
++import sun.dyn.*;
++import sun.dyn.util.BytecodeSignature;
++import static sun.dyn.MemberName.newIllegalArgumentException;
+
+/**
+ * Run-time token used to match call sites with method handles.
@@ -5574,7 +1848,7 @@ new file mode 100644
+
+package java.dyn;
+
-+import impl.java.dyn.util.Wrappers;
++import sun.dyn.util.Wrappers;
+
+/**
+ * Shared information for a group of method types, which differ
@@ -5977,3 +2251,3725 @@ new file mode 100644
+ */
+
+package java.dyn;
+diff --git a/src/share/classes/sun/dyn/Access.java b/src/share/classes/sun/dyn/Access.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/sun/dyn/Access.java
+@@ -0,0 +1,93 @@
++/*
++ * 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 sun.dyn;
++
++import java.dyn.MethodHandles;
++import sun.reflect.Reflection;
++
++/**
++ * Access control to this package.
++ * Classes in other packages can attempt to acquire the access token,
++ * but will fail if they are not recognized as friends.
++ * Certain methods in this package, although public, require a non-null
++ * access token in order to proceed; they act like package-private methods.
++ * @author jrose
++ */
++
++public class Access {
++ private Access() { }
++
++ /**
++ * The heart of this pattern: The list of classes which are
++ * permitted to acquire the access token, and become honorary
++ * members of this package.
++ */
++ static private final String[] FRIENDS = {
++ "java.dyn.", "sun.dyn."
++ };
++
++ /**
++ * The following object is NOT public. That's the point of the pattern.
++ * It is package-private, so that any member of this package
++ * can acquire the access token, and give it away to trusted friends.
++ */
++ static final Access TOKEN = new Access();
++
++ /**
++ * @return Access.TOKEN, if the caller is a friend of this package
++ */
++ public static Access getToken() {
++ Class<?> callc = Reflection.getCallerClass(2);
++ if (callc.getClassLoader() == Access.class.getClassLoader()) {
++ String callcName = callc.getName();
++ for (String friend : FRIENDS) {
++ if (callcName.startsWith(friend))
++ return TOKEN;
++ }
++ }
++ throw new IllegalAccessError("bad caller: " + callc);
++ }
++
++ /**
++ * Throw an IllegalAccessError if the caller does not possess
++ * the Access.TOKEN.
++ * @param must be Access.TOKEN
++ */
++ public static void check(Access token) {
++ if (token == null)
++ fail();
++ // else it must be the unique Access.TOKEN
++ assert(token == Access.TOKEN);
++ }
++ private static void fail() {
++ Class<?> callc = Reflection.getCallerClass(3);
++ throw new IllegalAccessError("bad caller: " + callc);
++ }
++
++ static {
++ //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
++ }
++}
+diff --git a/src/share/classes/sun/dyn/AdapterMethodHandle.java b/src/share/classes/sun/dyn/AdapterMethodHandle.java
+new file mode 100644
+--- /dev/null
++++ b/src/share/classes/sun/dyn/AdapterMethodHandle.java
+@@ -0,0 +1,596 @@
++/*
++ * 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 sun.dyn;
++
++import sun.dyn.util.VerifyType;
++import sun.dyn.util.Wrappers;
++import java.dyn.*;
++import java.util.ArrayList;
++import java.util.Arrays;
++import java.util.List;
++import static sun.dyn.MethodHandleNatives.Constants.*;
++import static sun.dyn.MethodHandleImpl.newIllegalArgumentException;
++
++/**
++ * This method handle performs simple conversion or checking of a single argument.
++ * @author jrose
++ */
++public class AdapterMethodHandle extends BoundMethodHandle {
++
++ //MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
++ //Object argument; // parameter to the conversion if needed
++ //int vmargslot; // which argument slot is affected
++ private final int conversion; // the type of conversion: RETYPE_ONLY, etc.
++
++ // Constructors in this class *must* be package scoped or private.
++ private AdapterMethodHandle(MethodHandle target, MethodType newType,
++ long conv, Object convArg) {
++ super(newType, convArg, newType.parameterSlot(convArgPos(conv)));
++ this.conversion = convCode(conv);
++ if (MethodHandleNatives.JVM_SUPPORT) {
++ // JVM might update VM-specific bits of conversion (ignore)
++ MethodHandleNatives.init(this, target, convArgPos(conv));
++ }
++ }
++ private AdapterMethodHandle(MethodHandle target, MethodType newType,
++ long conv) {
++ this(target, newType, conv, null);
++ }
++
++ private static final Access IMPL_TOKEN = Access.getToken();
++
++ // TO DO: When adapting another MH with a null conversion, clone
++ // the target and change its type, instead of adding another layer.
++
++ /** Can a JVM-level adapter directly implement the proposed
++ * argument conversions, as if by MethodHandles.convertArguments?
++ */
++ public static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
++ // same number of args, of course
++ int len = newType.parameterCount();
++ if (len != oldType.parameterCount())
++ return false;
++
++ // Check return type. (Not much can be done with it.)
++ Class<?> exp = newType.returnType();
++ Class<?> ret = oldType.returnType();
++ if (!VerifyType.isNullConversion(ret, exp))
++ return false;
++
++ // Check args pairwise.
++ for (int i = 0; i < len; i++) {
++ Class<?> src = newType.parameterType(i); // source type
++ Class<?> dst = oldType.parameterType(i); // destination type
++ if (!canConvertArgument(src, dst))
++ return false;
++ }
++
++ return true;
++ }
++
++ /** Can a JVM-level adapter directly implement the proposed
++ * argument conversion, as if by MethodHandles.convertArguments?
++ */
++ public static boolean canConvertArgument(Class<?> src, Class<?> dst) {
++ // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
++ // so we don't need to repeat so much decision making.
++ if (VerifyType.isNullConversion(src, dst)) {
++ return true;
++ } else if (src.isPrimitive()) {
++ if (dst.isPrimitive())
++ return canPrimCast(src, dst);
++ else
++ return canBoxArgument(src, dst);
++ } else {
++ if (dst.isPrimitive())
++ return canUnboxArgument(src, dst);
++ else
++ return true; // any two refs can be interconverted
++ }
++ }
++
++ /**
++ * Create a JVM-level adapter method handle to conform the given method
++ * handle to the similar newType, using only pairwise argument conversions.
++ * For each argument, convert incoming argument to the exact type needed.
++ * Only null conversions are allowed on the return value (until
++ * the JVM supports ricochet adapters).
++ * The argument conversions allowed are casting, unboxing,
++ * integral widening or narrowing, and floating point widening or narrowing.
++ * @param token access check
++ * @param newType required call type
++ * @param target original method handle
++ * @return an adapter to the original handle with the desired new type,
++ * or the original target if the types are already identical
++ * @throws IllegalArgumentException if the adaptation cannot be made
++ * directly by a JVM-level adapter, without help from Java code
++ */
++ public static MethodHandle makePairwiseConvert(Access token,
++ MethodType newType, MethodHandle target) {
++ Access.check(token);
++ MethodType oldType = target.type();
++ if (newType == oldType) return target;
++
++ // caller responsibility:
++ assert(canPairwiseConvert(newType, oldType));
++
++ // Find last non-trivial conversion (if any).
++ int lastConv = newType.parameterCount()-1;
++ while (lastConv >= 0) {
++ Class<?> src = newType.parameterType(lastConv); // source type
++ Class<?> dst = oldType.parameterType(lastConv); // destination type
++ if (VerifyType.isNullConversion(src, dst)) {
++ --lastConv;
++ } else {
++ break;
++ }
++ }
++ // Now build a chain of one or more adapters.
++ MethodHandle adapter = target;
++ MethodType midType = oldType.changeReturnType(newType.returnType());
++ for (int i = 0; i <= lastConv; i++) {
++ Class<?> src = newType.parameterType(i); // source type
++ Class<?> dst = midType.parameterType(i); // destination type
++ if (VerifyType.isNullConversion(src, dst)) {
++ // do nothing: difference is trivial
++ continue;
++ }
++ // Work the current type backward toward the desired caller type:
++ if (i != lastConv) {
++ midType = midType.changeParameterType(i, src);
++ } else {
++ // When doing the last (or only) real conversion,
++ // force all remaining null conversions to happen also.
++ assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
++ midType = newType;
++ }
++
++ // Tricky case analysis follows.
++ // It parallels canConvertArgument() above.
++ if (src.isPrimitive()) {
++ if (dst.isPrimitive()) {
++ adapter = makePrimCast(token, midType, adapter, i, dst);
++ } else {
++ adapter = makeBoxArgument(token, midType, adapter, i, dst);
++ }
++ } else {
++ if (dst.isPrimitive()) {
++ // Caller has boxed a primitive. Unbox it for the target.
++ // The box type must correspond exactly to the primitive type.
++ // This is simpler than the powerful set of widening
++ // conversions supported by reflect.Method.invoke.
++ // Those conversions require a big nest of if/then/else logic,
++ // which we prefer to make a user responsibility.
++ adapter = makeUnboxArgument(token, midType, adapter, i, dst);
++ } else {
++ // Simple reference conversion.
++ // Note: Do not check for a class hierarchy relation
++ // between src and dst. In all cases a 'null' argument
++ // will pass the cast conversion.
++ adapter = makeCheckCast(token, midType, adapter, i, dst);
++ }
++ }
++ assert(adapter.type() == midType);
++ }
++ if (adapter.type() != newType) {
++ // Only trivial conversions remain.
++ adapter = makeRetypeOnly(IMPL_TOKEN, newType, adapter);
++ // Actually, that's because there were no non-trivial ones:
++ assert(lastConv == -1);
++ }
++ assert(adapter.type() == newType);
++ return adapter;
++ }
++
++ /**
++ * Create a JVM-level adapter method handle to permute the arguments
++ * of the given method.
++ * @param token access check
++ * @param newType required call type
++ * @param target original method handle
++ * @param argumentMap for each target argument, position of its source in newType
++ * @return an adapter to the original handle with the desired new type,
++ * or the original target if the types are already identical
++ * and the permutation is null
++ * @throws IllegalArgumentException if the adaptation cannot be made
++ * directly by a JVM-level adapter, without help from Java code
++ */
++ public static MethodHandle makePermutation(Access token,
++ MethodType newType, MethodHandle target,
++ int[] argumentMap) {
++ MethodType oldType = target.type();
++ boolean nullPermutation = true;
++ for (int i = 0; i < argumentMap.length; i++) {
++ int pos = argumentMap[i];
++ if (pos != i)
++ nullPermutation = false;
++ if (pos < 0 || pos >= newType.parameterCount()) {
++ argumentMap = new int[0]; break;
++ }
++ }
++ if (argumentMap.length != oldType.parameterCount())
++ throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
++ if (nullPermutation)
++ return makePairwiseConvert(token, newType, target); // well, that was easy
++
++ // Check return type. (Not much can be done with it.)
++ Class<?> exp = newType.returnType();
++ Class<?> ret = oldType.returnType();
++ if (!VerifyType.isNullConversion(ret, exp))
++ throw newIllegalArgumentException("bad return conversion for "+newType);
++
++ // See if the argument types match up.
++ for (int i = 0; i < argumentMap.length; i++) {
++ int j = argumentMap[i];
++ Class<?> src = newType.parameterType(j);
++ Class<?> dst = oldType.parameterType(i);
++ if (!VerifyType.isNullConversion(src, dst))
++ throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
++ }
++
++ // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
++ // A workable greedy algorithm is as follows:
++ // Drop unused outgoing arguments (right to left: shallowest first).
++ // Duplicate doubly-used outgoing arguments (left to right: deepest first).
++ // Then the remaining problem is a true argument permutation.
++ // Marshal the outgoing arguments as required from left to right.
++ // That is, find the deepest outgoing stack position that does not yet
++ // have the correct argument value, and correct at least that position
++ // by swapping or rotating in the misplaced value (from a shallower place).
++ // If the misplaced value is followed by one or more consecutive values
++ // (also misplaced) issue a rotation which brings as many as possible
++ // into position. Otherwise make progress with either a swap or a
++ // rotation. Prefer the swap as cheaper, but do not use it if it
++ // breaks a slot pair. Prefer the rotation over the swap if it would
++ // preserve more consecutive values shallower than the target position.
++ // When more than one rotation will work (because the required value
++ // is already adjacent to the target position), then use a rotation
++ // which moves the old value in the target position adjacent to
++ // one of its consecutive values. Also, prefer shorter rotation
++ // spans, since they use fewer memory cycles for shuffling.
++
++ throw new UnsupportedOperationException("NYI");
++ }
++
++ private static byte basicType(Class<?> type) {
++ if (type == null) return T_VOID;