--- a/meth.proj.patch Thu Jan 29 14:18:20 2009 -0800
+++ b/meth.proj.patch Thu Jan 29 14:18:23 2009 -0800
@@ -224,7 +224,7 @@ new file mode 100644
new file mode 100644
--- /dev/null
+++ b/src/share/projects/meth/build.xml
-@@ -0,0 +1,141 @@
+@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
@@ -232,12 +232,6 @@ new file mode 100644
+<project name="MethodHandle" default="default" basedir=".">
+ <description>Builds, tests, and runs the project MethodHandle.</description>
+ <import file="nbproject/build-impl.xml"/>
-+
-+<!-- For some reason, the run.jvmargs property does not expand from this file.
-+ It must be placed in nbproject/project.properties as follows:
-+ run.jvmargs=-Xbootclasspath/a:${build.classes.dir}:${local.junit.jar}
-+ -->
-+ <property name="--broken--run.jvmargs" value="-Xbootclasspath/a:${build.classes.dir}:${local.junit.jar}"/>
+
+ <property name="javadoc.includes" value="java/dyn/*.java"/>
+
@@ -273,37 +267,6 @@ new file mode 100644
+ </target>
+
+
-+<!-- FOR TRACING:
-+ <target name="-init-macrodef-junit">
-+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
-+ <attribute default="${includes}" name="includes"/>
-+ <attribute default="${excludes}" name="excludes"/>
-+ <attribute default="**" name="testincludes"/>
-+ <sequential>
-+ <echo message="junit jvmargs: ${run.jvmargs}"/>
-+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${platform.java}" showoutput="true"
-+ >
-+ <batchtest todir="${build.test.results.dir}">
-+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-+ <filename name="@{testincludes}"/>
-+ </fileset>
-+ </batchtest>
-+ <classpath>
-+ <path path="${run.test.classpath}"/>
-+ </classpath>
-+ <syspropertyset>
-+ <propertyref prefix="test-sys-prop."/>
-+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
-+ </syspropertyset>
-+ <formatter type="brief" usefile="false"/>
-+ <formatter type="xml"/>
-+ <jvmarg line="${run.jvmargs}"/>
-+ </junit>
-+ </sequential>
-+ </macrodef>
-+ </target>
-+-->
-+
+ <!--
+
+ There exist several targets which are by default empty and which can be
@@ -370,7 +333,7 @@ new file mode 100644
new file mode 100644
--- /dev/null
+++ b/src/share/projects/meth/nbproject/project.properties
-@@ -0,0 +1,74 @@
+@@ -0,0 +1,80 @@
+application.args=
+application.title=MethodHandle
+application.vendor=jrose
@@ -399,7 +362,7 @@ new file mode 100644
+javac.classpath=\
+ ${reference.AnonymousClass.jar}
+# Space-separated list of extra javac options
-+javac.compilerargs=-Xlint:unchecked
++javac.compilerargs=-Xlint:unchecked -J-Xbootclasspath/p:${reference.langtools-javac.jar} -XDinvokedynamic
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
@@ -419,6 +382,7 @@ new file mode 100644
+javadoc.version=false
+javadoc.windowtitle=
+jnlp.codebase.type=local
++jnlp.codebase.url=file:/Users/jrose/Projects/MethodHandle/dist/
+jnlp.descriptor=application
+jnlp.enabled=false
+jnlp.offline-allowed=false
@@ -426,6 +390,9 @@ new file mode 100644
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=JDK_1.6
++# ref http://ant.apache.org/manual/CoreTasks/javac.html (OpenJDK Notes)
++project.langtools=../langtools
++reference.langtools-javac.jar=${project.langtools}/dist/bootstrap/lib/javac.jar
+project.AnonymousClass=../AnonymousClass
+reference.AnonymousClass.jar=${project.AnonymousClass}/dist/AnonymousClass.jar
+run.classpath=\
@@ -441,15 +408,17 @@ new file mode 100644
+source.encoding=UTF-8
+# One or both refs probably need fixing:
+file.reference.projects=${env.HOME}/Projects
-+#file.reference.davinci.sources.jdk=${file.reference.projects}/davinci/sources/jdk
-+src.src.dir=src
++file.reference.davinci.sources.jdk=${file.reference.projects}/davinci/sources/jdk
++src.src.dir=${file.reference.davinci.sources.jdk}/src/share/classes
++src.src2.dir=src
+test.src.dir=test
+project.license=openjdk
++davinci.patch.name=meth
diff --git a/src/share/projects/meth/nbproject/project.xml b/src/share/projects/meth/nbproject/project.xml
new file mode 100644
--- /dev/null
+++ b/src/share/projects/meth/nbproject/project.xml
-@@ -0,0 +1,27 @@
+@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
@@ -459,7 +428,8 @@ new file mode 100644
+ <minimum-ant-version>1.6.5</minimum-ant-version>
+ <explicit-platform explicit-source-supported="true"/>
+ <source-roots>
-+ <root id="src.src.dir" name="Source Packages"/>
++ <root id="src.src.dir" name="JDK Source Packages"/>
++ <root id="src.src2.dir" name="Local Sources"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
@@ -477,6416 +447,6 @@ new file mode 100644
+ </references>
+ </configuration>
+</project>
-diff --git a/src/share/projects/meth/src/impl/java/dyn/Access.java b/src/share/projects/meth/src/impl/java/dyn/Access.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/AdapterMethodHandle.java b/src/share/projects/meth/src/impl/java/dyn/AdapterMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/impl/java/dyn/AdapterMethodHandle.java
-@@ -0,0 +1,541 @@
-+/*
-+ * 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.
-+
-+ /**
-+ * 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 makePairwiseConversion(Access token,
-+ MethodType newType, MethodHandle target) {
-+ Access.check(token);
-+ int len = newType.parameterCount();
-+ MethodType oldType = target.type();
-+ if (newType == oldType) return target;
-+ if (len != oldType.parameterCount())
-+ throw newIllegalArgumentException("wrong number of arguments in "+newType);
-+
-+ // 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);
-+
-+ // Find last non-trivial conversion.
-+ int lastConv = len-1;
-+ while (lastConv >= 0) {
-+ Class<?> src = newType.parameterType(lastConv); // source type
-+ Class<?> dst = oldType.parameterType(lastConv); // destination type
-+ if (src == dst || VerifyType.isNullConversion(src, dst)) {
-+ --lastConv;
-+ } else {
-+ break;
-+ }
-+ }
-+ // Now build a chain of one or more adapters.
-+ MethodHandle adapter = target;
-+ MethodType midType = oldType.changeReturnType(exp);
-+ for (int i = 0; i <= lastConv; i++) {
-+ Class<?> src = newType.parameterType(i); // source type
-+ Class<?> dst = midType.parameterType(i); // destination type
-+ if (src == dst || 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.
-+ boolean srcPrim = src.isPrimitive();
-+ boolean dstPrim = dst.isPrimitive();
-+ if (!srcPrim && !dstPrim && canCheckCast(src, dst)) {
-+ // 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);
-+ } else if (srcPrim && dstPrim && canPrimCast(src, dst)) {
-+ // Convert a primitive to a primitive, if the JVM supports it.
-+ adapter = makePrimCast(token, midType, adapter, i, dst);
-+ } else if (!srcPrim && dstPrim && canUnboxArgument(src, dst)) {
-+ // 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 {
-+ throw newIllegalArgumentException("bad argument #"+i+" conversion in "+newType);
-+ }
-+ 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 makePairwiseConversion(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 == (convOp & CONV_OP_MASK));
-+ assert(convOp >= CHECK_CAST && convOp <= PRIM_TO_REF);
-+ long stackMove = type2size(dest) - type2size(src);
-+ return ((long) argnum << 32 |
-+ (long) convOp |
-+ (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 == (convOp & CONV_OP_MASK));
-+ assert(convOp >= SWAP_ARGS && convOp <= SPREAD_ARGS);
-+ byte src = 0, dest = 0;
-+ if (convOp >= COLLECT_ARGS && convOp <= SPREAD_ARGS)
-+ src = dest = T_OBJECT;
-+ return ((long) argnum << 32 |
-+ (long) convOp |
-+ (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 == (convOp & CONV_OP_MASK));
-+ assert(convOp == RETYPE_ONLY);
-+ return (long) convOp; // 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(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(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(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(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);
-+ }
-+
-+ // TO DO: makeBoxArgument, 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(DROP_ARGS, dropArgPos, +dropSlotCount);
-+ return new AdapterMethodHandle(target, newType, dropSlotCount, conv);
-+ }
-+
-+ // TO DO: makeCollectArguments, makeSpreadArguments, makeFlyby, makeRicochet
-+}
-diff --git a/src/share/projects/meth/src/impl/java/dyn/BoundMethodHandle.java b/src/share/projects/meth/src/impl/java/dyn/BoundMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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().deleteParameterType(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().deleteParameterType(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/projects/meth/src/impl/java/dyn/CallSiteImpl.java b/src/share/projects/meth/src/impl/java/dyn/CallSiteImpl.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/impl/java/dyn/CallSiteImpl.java
-@@ -0,0 +1,60 @@
-+/*
-+ * 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 CallSite privately created by the JVM at every invokedynamic instruction.
-+ * @author jrose
-+ */
-+class CallSiteImpl extends CallSite {
-+ // Fields used only by the JVM. Do not use or change.
-+ Object vmref;
-+ long vmdata;
-+
-+ private CallSiteImpl(Class<?> caller, String name, MethodType type) {
-+ super(caller, name, type);
-+ }
-+
-+ @Override
-+ public void setTarget(MethodHandle mh) {
-+ checkTarget(mh);
-+ if (MethodHandleNatives.JVM_SUPPORT)
-+ MethodHandleNatives.linkCallSite(this, (MethodHandle) mh);
-+ else
-+ super.setTarget(mh);
-+ }
-+
-+ // this is the up-call from the JVM:
-+ static CallSiteImpl makeSite(Class<?> caller, String name, MethodType type,
-+ long vmdata) {
-+ CallSiteImpl site = new CallSiteImpl(caller, name, type);
-+ site.vmdata = vmdata;
-+ System.out.println("DynCallSite: "+site);
-+ return site;
-+ }
-+}
-diff --git a/src/share/projects/meth/src/impl/java/dyn/DirectMethodHandle.java b/src/share/projects/meth/src/impl/java/dyn/DirectMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/JavaMethodHandle.java b/src/share/projects/meth/src/impl/java/dyn/JavaMethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/MemberName.java b/src/share/projects/meth/src/impl/java/dyn/MemberName.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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.Signatures;
-+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 Signatures.unparse(getMethodType());
-+ else
-+ return Signatures.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 = Signatures.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/projects/meth/src/impl/java/dyn/MethodHandleImpl.java b/src/share/projects/meth/src/impl/java/dyn/MethodHandleImpl.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/impl/java/dyn/MethodHandleImpl.java
-@@ -0,0 +1,266 @@
-+/*
-+ * 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 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,
-+ MethodType oldType,
-+ String permutationOrNull) {
-+ Access.check(token);
-+ throw new UnsupportedOperationException("Not yet implemented");
-+ }
-+
-+ 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 checkArguments(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/projects/meth/src/impl/java/dyn/MethodHandleNatives.java b/src/share/projects/meth/src/impl/java/dyn/MethodHandleNatives.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/impl/java/dyn/MethodHandleNatives.java
-@@ -0,0 +1,240 @@
-+/*
-+ * 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
-+ }
-+ JVM_SUPPORT = JVM_SUPPORT_;
-+ JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
-+ JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
-+ if (!JVM_SUPPORT)
-+ System.out.println("Warning: Running with JVM_SUPPORT=false");
-+ }
-+
-+ // 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 enum AdapterKind in vm/prims/methodHandles.hpp.
-+ */
-+ static final int
-+ RETYPE_ONLY = 0x000, // no argument changes; straight retype
-+ CHECK_CAST = 0x100, // ref-to-ref conversion; requires a Class argument
-+ PRIM_TO_PRIM = 0x200, // converts from one primitive to another
-+ REF_TO_PRIM = 0x300, // unboxes a wrapper to produce a primitive
-+ PRIM_TO_REF = 0x400, // boxes a primitive into a wrapper (NYI)
-+ SWAP_ARGS = 0x500, // swap arguments (vminfo is 2nd arg)
-+ ROT_ARGS = 0x600, // rotate arguments (vminfo is displaced arg)
-+ DUP_ARGS = 0x700, // duplicates one or more arguments (at TOS)
-+ DROP_ARGS = 0x800, // remove one or more argument slots
-+ COLLECT_ARGS = 0x900, // combine one or more arguments into a varargs (NYI)
-+ SPREAD_ARGS = 0xA00, // expand in place a varargs array (of known size)
-+ FLYBY = 0xB00, // operate first on reified argument list (NYI)
-+ RICOCHET = 0xC00; // run an adapter chain on the return value (NYI)
-+ static final int
-+ CONV_OP_MASK = 0xF00, // byte 3 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 3 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/projects/meth/src/impl/java/dyn/package-info.java b/src/share/projects/meth/src/impl/java/dyn/package-info.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/util/MethodHandleInvoker.java b/src/share/projects/meth/src/impl/java/dyn/util/MethodHandleInvoker.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/impl/java/dyn/util/MethodHandleInvoker.java
-@@ -0,0 +1,455 @@
-+/*
-+ * 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.makePairwiseConversion(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;
-+ if (approxType.isVarArgs()) 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 || exactType.isVarArgs())
-+ 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/projects/meth/src/impl/java/dyn/util/Signatures.java b/src/share/projects/meth/src/impl/java/dyn/util/Signatures.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/impl/java/dyn/util/Signatures.java
-@@ -0,0 +1,133 @@
-+/*
-+ * 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;
-+
-+public class Signatures {
-+
-+ private Signatures() { } // cannot instantiate
-+
-+ public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
-+ return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
-+ }
-+
-+ public 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/projects/meth/src/impl/java/dyn/util/VerifyAccess.java b/src/share/projects/meth/src/impl/java/dyn/util/VerifyAccess.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/util/VerifyType.java b/src/share/projects/meth/src/impl/java/dyn/util/VerifyType.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/util/Wrappers.java b/src/share/projects/meth/src/impl/java/dyn/util/Wrappers.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/impl/java/dyn/util/package-info.java b/src/share/projects/meth/src/impl/java/dyn/util/package-info.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/java/dyn/CallSite.java b/src/share/projects/meth/src/java/dyn/CallSite.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/java/dyn/CallSite.java
-@@ -0,0 +1,116 @@
-+/*
-+ * 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;
-+
-+/**
-+ * 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.
-+ * @return the current linkage state of the call site
-+ */
-+ public MethodHandle getTarget() {
-+ return target;
-+ }
-+
-+ /**
-+ * Link or relink the call site, by setting its target method.
-+ * @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 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.
-+ * @return method name specified by the call site
-+ */
-+ public String name() {
-+ return name;
-+ }
-+
-+ /*
-+ * Report the result and parameter types, derived from the invocation descriptor, and resolved
-+ * against the calling class's class loader.
-+ * 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/projects/meth/src/java/dyn/Dynamic.java b/src/share/projects/meth/src/java/dyn/Dynamic.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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.<void>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/projects/meth/src/java/dyn/InvokeDynamicBootstrapError.java b/src/share/projects/meth/src/java/dyn/InvokeDynamicBootstrapError.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/java/dyn/Linkage.java b/src/share/projects/meth/src/java/dyn/Linkage.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/java/dyn/Linkage.java
-@@ -0,0 +1,211 @@
-+/*
-+ * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * This code is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 only, as
-+ * published by the Free Software Foundation. Sun designates this
-+ * particular file as subject to the "Classpath" exception as provided
-+ * by Sun in the LICENSE file that accompanied this code.
-+ *
-+ * This code is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+ * version 2 for more details (a copy is included in the LICENSE file that
-+ * accompanied this code).
-+ *
-+ * You should have received a copy of the GNU General Public License version
-+ * 2 along with this work; if not, write to the Free Software Foundation,
-+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-+ * CA 95054 USA or visit www.sun.com if you need additional information or
-+ * have any questions.
-+ */
-+
-+package java.dyn;
-+
-+import impl.java.dyn.util.MethodHandleInvoker;
-+import java.util.WeakHashMap;
-+import sun.reflect.Reflection;
-+
-+/**
-+ * Static methods which control the linkage of invokedynamic call sites.
-+ * @author John Rose, JSR 292 EG
-+ */
-+public class Linkage {
-+ private Linkage() {} // do not instantiate
-+
-+ /**
-+ * Register a bootstrap method for use for a given caller class.
-+ * The method handle must be of a type equivalent to {@link Linkage#bootstrapInvokeDynamic}.
-+ * <p>
-+ * The operation will fail with an exception if any of the following conditions hold:
-+ * <ul>
-+ * <li>The caller of this method is in a different package than the {@code callerClass},
-+ * and there is a security manager, and its {@code checkPermission} call throws
-+ * when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass).
-+ * <li>The given class already has a bootstrap method, either from an embedded
-+ * {@code BootstrapInvokeDynamic} classfile attribute, or from a previous
-+ * call to this method.
-+ * <li>The given class is already fully initialized.
-+ * <li>The given class is in the process of initialization, in another thread.
-+ * </ul>
-+ * Because of these rules, a class may install its own bootstrap method in
-+ * a static initializer.
-+ */
-+ public static
-+ void registerBootstrapMethod(Class callerClass, MethodHandle mh) {
-+ Class callc = Reflection.getCallerClass(2);
-+ checkPackagePrivilege(callc, callerClass, "registerBootstrapMethod");
-+ if (mh != null && mh.type() != BOOTSTRAP_METHOD_TYPE)
-+ throw new WrongMethodTypeException(mh.type().toString());
-+ synchronized (bootstrapMethods) {
-+ if (bootstrapMethods.containsKey(callerClass))
-+ throw new IllegalStateException("bootstrap method already declared in "+callerClass);
-+ bootstrapMethods.put(callerClass, mh);
-+ }
-+ }
-+
-+ /**
-+ * Report the bootstrap method registered for a given class.
-+ * Returns null if the class has never yet registered a bootstrap method,
-+ * or if the class has explicitly registered a null bootstrap method.
-+ * Only callers privileged to set the bootstrap method may inquire
-+ * about it, because a bootstrap method is potentially a back-door entry
-+ * points to its class.
-+ */
-+ public static
-+ MethodHandle getBootstrapMethod(Class callerClass) {
-+ Class callc = Reflection.getCallerClass(2);
-+ checkPackagePrivilege(callc, callerClass, "registerBootstrapMethod");
-+ synchronized (bootstrapMethods) {
-+ return bootstrapMethods.get(callerClass);
-+ }
-+ }
-+
-+ /** The type of any bootstrap method is (CallSite,Object...)Object.
-+ * The varargs marker is required.
-+ */
-+ public static final MethodType BOOTSTRAP_METHOD_TYPE
-+ = MethodType.make(Object.class,
-+ CallSite.class, Object[].class).changeVarArgs(true);
-+
-+ private static MethodHandleInvoker bootstrapMethodInvoker;
-+
-+ private static final WeakHashMap<Class, MethodHandle> bootstrapMethods =
-+ new WeakHashMap<Class, MethodHandle>();
-+
-+ /** Determine if the caller class has declared or registered its own bootstrap method.
-+ * If so, delegate this call to it. Otherwise, throw an IncompatibleClassChangeError.
-+ */
-+ public static
-+ Object bootstrapInvokeDynamic(CallSite site, Object... receiverAndArguments) {
-+ Class callerClass = site.callerClass();
-+ MethodHandle mh;
-+ synchronized (bootstrapMethods) {
-+ mh = bootstrapMethods.get(callerClass);
-+ }
-+ if (mh == null)
-+ throw new IllegalStateException("no bootstrap method declared in "+callerClass);
-+
-+ System.out.println(site+": calling bootstrap "+mh);
-+ if (bootstrapMethodInvoker == null)
-+ bootstrapMethodInvoker = MethodHandleInvoker.make(BOOTSTRAP_METHOD_TYPE);
-+ return bootstrapMethodInvoker.invoke(mh, site, receiverAndArguments);
-+ }
-+
-+ /**
-+ * Invalidate all <code>invokedynamic</code> call sites everywhere.
-+ * <p>
-+ * When this method returns, every <code>invokedynamic</code> instruction
-+ * will invoke its bootstrap method on next call.
-+ * <p>
-+ * It is unspecified whether call sites already known to the Java
-+ * code will continue to be associated with <code>invokedynamic</code>
-+ * instructions. If any call site is still so associated, its
-+ * {@link CallSite#getTarget()} method is guaranteed to return null
-+ * the invalidation operation completes.
-+ * <p>
-+ * Invalidation operations are likely to be slow. Use them sparingly.
-+ */
-+ public static
-+ Object invalidateAll() {
-+ SecurityManager security = System.getSecurityManager();
-+ if (security != null) {
-+ security.checkPermission(new LinkagePermission("invalidateAll"));
-+ }
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ /**
-+ * Invalidate all <code>invokedynamic</code> call sites associated
-+ * with the given class.
-+ * (These are exactly those sites which report the given class
-+ * via the {@link CallSite#callerClass()} method.)
-+ * <p>
-+ * When this method returns, every matching <code>invokedynamic</code>
-+ * instruction will invoke its bootstrap method on next call.
-+ * <p>
-+ * For additional semantics of call site invalidation,
-+ * see {@link #invalidateAll()}.
-+ */
-+ public static
-+ Object invalidateCallerClass(Class<?> callerClass) {
-+ SecurityManager security = System.getSecurityManager();
-+ if (security != null) {
-+ security.checkPermission(new LinkagePermission("invalidateAll", callerClass));
-+ }
-+ throw new UnsupportedOperationException("NYI");
-+ }
-+
-+ /**
-+ * Ensure the requesting class have privileges to perform invokedynamic
-+ * linkage operations on subjectClass. True if requestingClass is
-+ * null (meaning the request originates from the JVM) or if the
-+ * classes are in the same package and have consistent class loaders.
-+ * (The subject class loader must be identical with or be a child of
-+ * the requesting class loader.)
-+ * @param requestingClass
-+ * @param subjectClass
-+ * @return
-+ */
-+ static void checkPackagePrivilege(Class requestingClass, Class subjectClass,
-+ String permissionName) {
-+ if (requestingClass == null) return;
-+ if (requestingClass == subjectClass) return;
-+ SecurityManager security = System.getSecurityManager();
-+ if (security == null) return; // open season
-+ ClassLoader rcl = requestingClass.getClassLoader();
-+ ClassLoader scl = subjectClass.getClassLoader();
-+ if (isParent(rcl, scl)) {
-+ String rn = requestingClass.getName();
-+ if (rn.startsWith("java.dyn.")) return;
-+ String sn = subjectClass.getName();
-+ if (samePackage(rn, sn)) return;
-+ }
-+ security.checkPermission(new LinkagePermission(permissionName, requestingClass));
-+ }
-+
-+ static
-+ MethodHandle findBootstrapMethod(Class callerClass, Class searchBootstrapClass) {
-+ if (searchBootstrapClass != null) throw new UnsupportedOperationException("NYI");
-+ MethodHandle mh = getBootstrapMethod(callerClass);
-+ System.out.println("reporting bootstrap method to JVM: "+mh);
-+ return mh;
-+ }
-+
-+ private static boolean isParent(ClassLoader rcl, ClassLoader scl) {
-+ while (scl != null && scl != rcl)
-+ scl = scl.getParent();
-+ return (scl == rcl);
-+ }
-+
-+ private static boolean samePackage(String rn, String sn) {
-+ assert((rn.indexOf('/') & sn.indexOf('/')) < 0); // no bytecode names
-+ int lastDot = rn.lastIndexOf('.');
-+ if (lastDot != sn.lastIndexOf('.')) return false;
-+ return rn.startsWith(sn.substring(0, lastDot+1));
-+ }
-+
-+}
-diff --git a/src/share/projects/meth/src/java/dyn/LinkagePermission.java b/src/share/projects/meth/src/java/dyn/LinkagePermission.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/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/projects/meth/src/java/dyn/MethodHandle.java b/src/share/projects/meth/src/java/dyn/MethodHandle.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/java/dyn/MethodHandle.java
-@@ -0,0 +1,129 @@
-+/*
-+ * 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.dyn.emu.*;
-+import impl.java.dyn.*;
-+
-+/**
-+ * A method handle is a typed reference to the entry point of a method.
-+ * <p>
-+ * Method handles are strongly typed according to signature.
-+ * They are not distinguished by method name or enclosing class.
-+ * A method handle must be invoked under a signature which exactly matches
-+ * the method handle's own type.
-+ * <p>
-+ * Every method handle confesses its type via the <code>type</code> accessor.
-+ * The structure of this type is a series of classes, one of which is
-+ * the return type of the method (or <code>void.class</code> if none).
-+ * <p>
-+ * Every method handle appears as an object containing a method named
-+ * <code>invoke</code>, whose signature exactly matches
-+ * the method handle's type.
-+ * A normal Java method call (using the <code>invokevirtual</code> instruction)
-+ * can invoke this method from Java source code (if language support is present).
-+ * <p>
-+ * Every call to a method handle specifies an intended method type,
-+ * which must exactly match the type of the method handle.
-+ * (The type is specified in the <code>invokevirtual</code> instruction,
-+ * via a {@code CONSTANT_NameAndType} constant pool entry.)
-+ * The call looks within the receiver object for a method
-+ * named <code>invoke</code> of the intended method type.
-+ * The call fails with a {@link WrongMethodTypeException}
-+ * if the method does not exist, even if there is an <code>invoke</code>
-+ * method of a closely similar signature.
-+ * <p>
-+ * A method handle is an unrestricted capability to call a method.
-+ * A method handle can be formed on a non-public method by a class
-+ * that has access to that method; the resulting handle can be used
-+ * in any place by any caller who receives a reference to it. Thus, access
-+ * checking is performed when the method handle is created, not
-+ * (as in reflection) every time it is called. Handles to non-public
-+ * methods, or in non-public classes, should generally be kept secret.
-+ * They should not be passed to untrusted code.
-+ * <p>
-+ * Bytecode in an extended JVM can directly call a method handle's
-+ * <code>invoke</code> from an <code>invokevirtual</code> instruction.
-+ * The receiver class type must be <code>MethodHandle</code> and the method name
-+ * must be <code>invoke</code>. The signature of the invocation
-+ * (after resolving symbolic type names) must exactly match the method type
-+ * of the target method.
-+ * <p>
-+ * Bytecode in an extended JVM can directly obtain a method handle
-+ * for any accessible method from a <code>ldc</code> instruction
-+ * which refers to a <code>CONSTANT_Methodref</code> or
-+ * <code>CONSTANT_InterfaceMethodref</code> constant pool entry.
-+ * <p>
-+ * All JVMs can also use a reflective API called <code>MethodHandles</code>
-+ * for creating and calling method handles.
-+ * <p>
-+ * A method reference may refer either to a static or non-static method.
-+ * In the non-static case, the method handle type includes an explicit
-+ * receiver argument, prepended before any other arguments.
-+ * In the method handle's type, the initial receiver argument is typed
-+ * according to the class under which the method was initially requested.
-+ * (E.g., if a non-static method handle is obtained via <code>ldc</code>,
-+ * the type of the receiver is the class named in the constant pool entry.)
-+ * <p>
-+ * When a method handle to a virtual method is invoked, the method is
-+ * always looked up in the receiver (that is, the first argument).
-+ * <p>
-+ * A non-virtual method handles to a specific virtual method implementation
-+ * can also be created. These do not perform virtual lookup based on
-+ * receiver type. Such a method handle simulates the effect of
-+ * an <code>invokespecial</code> instruction to the same method.
-+ *
-+ * @see MethodType
-+ * @see MethodHandles
-+ * @author John Rose, JSR 292 EG
-+ */
-+public class MethodHandle extends MethodHandleImpl {
-+ // interface MethodHandle<T extends MethodType<R,A...>>
-+ // { T type(); <R,A...> public R invoke(A...); }
-+
-+ final private MethodType type;
-+
-+ /**
-+ * Report the type of this method handle.
-+ * Every invocation of this method handle must exactly match this type.
-+ * @return the method handle type
-+ */
-+ public MethodType type() {
-+ return type;
-+ }
-+
-+ /**
-+ * The constructor for MethodHandle may only be called by privileged code.
-+ * Subclasses may be in other packages, but must possess
-+ * a token which they obtained from MH with a security check.
-+ * @param token non-null object which proves access permission
-+ * @param type type (permanently assigned) of the new method handle
-+ */
-+ protected MethodHandle(Access token, MethodType type) {
-+ super(token);
-+ this.type = type;
-+ }
-+}
-diff --git a/src/share/projects/meth/src/java/dyn/MethodHandles.java b/src/share/projects/meth/src/java/dyn/MethodHandles.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/java/dyn/MethodHandles.java
-@@ -0,0 +1,940 @@
-+/*
-+ * 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.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 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;
-+
-+/**
-+ * Fundamental operations and utilities for MethodHandle.
-+ * <p>
-+ * <em>API Note:</em> The matching of method types in this API cannot
-+ * be completely checked by Java's generic type system for three reasons:
-+ * <ol>
-+ * <li>Method types range over all possible arities,
-+ * from no arguments to an arbitrary number of arguments.
-+ * Generics are not variadic, and so cannot represent this.</li>
-+ * <li>Method types can specify arguments of primitive types,
-+ * which Java generic types cannot range over.</li>
-+ * <li>Method types can optionally specify varargs (ellipsis).</li>
-+ * </ol>
-+ * @author John Rose, JSR 292 EG
-+ */
-+public class MethodHandles {
-+
-+ private MethodHandles() { } // do not instantiate
-+
-+ private static final Access IMPL_TOKEN = Access.getToken();
-+ private static final MemberName.Factory IMPL_LOOKUP = MemberName.getFactory(IMPL_TOKEN);
-+
-+ //// Method handle creation from ordinary methods.
-+
-+ /**
-+ * Produce a method handle for a static method.
-+ * The type of the method handle will be that of the method.
-+ * The method and all its argument types must be accessible to the caller.
-+ * If the method's class has not yet been initialized, that is done
-+ * immediately, before the method handle is returned.
-+ * @param defc the class from which the method is accessed
-+ * @param name the name of the method
-+ * @param type the type of the method
-+ * @return the desired method handle, or null if no such method exists
-+ * @exception SecurityException <em>TBD</em>
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, caller);
-+ checkStatic(true, method, caller);
-+ return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, caller);
-+ }
-+
-+ private static void checkStatic(boolean wantStatic, MemberName m, Class<?> caller) {
-+ if (wantStatic != m.isStatic()) {
-+ String message = wantStatic ? "expected a static method" : "expected a non-static method";
-+ throw newNoAccessException(message, m, caller);
-+ }
-+ }
-+
-+ /**
-+ * Produce a method handle for a virtual method.
-+ * The type of the method handle will be that of the method,
-+ * with the receiver type ({@code defc}) prepended.
-+ * The method and all its argument types must be accessible to the caller.
-+ * <p>
-+ * When called, the handle will treat the first argument as a receiver
-+ * and dispatch on the receiver's type to determine which method
-+ * implementation to enter.
-+ * (The dispatching action is identical with that performed by an
-+ * {@code invokevirtual} or {@code invokeinterface} instruction.)
-+ * @param defc the class or interface from which the method is accessed
-+ * @param name the name of the method
-+ * @param type the type of the method, with the receiver argument omitted
-+ * @return the desired method handle, or null if no such method exists
-+ * @exception SecurityException <em>TBD</em>
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type), true, caller);
-+ checkStatic(false, method, caller);
-+ return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, caller);
-+ }
-+
-+ /**
-+ * Produce an early-bound method handle for a virtual method,
-+ * or a handle for a constructor, as if called from an {@code invokespecial}
-+ * instruction from {@code caller}.
-+ * The type of the method handle will be that of the method or constructor,
-+ * with a suitably restricted receiver type (such as {@code caller}) prepended.
-+ * The method or constructor and all its argument types must be accessible
-+ * to the caller.
-+ * <p>
-+ * When called, the handle will treat the first argument as a receiver,
-+ * but will not dispatch on the receiver's type.
-+ * (This direct invocation action is identical with that performed by an
-+ * {@code invokespecial} instruction.)
-+ * <p>
-+ * If the explicitly specified caller class is not identical with the actual
-+ * caller of {@code findSpecial}, a security check TBD is performed.
-+ * @param defc the class or interface from which the method is accessed
-+ * @param name the name of the method, or "<init>" for a constructor
-+ * @param type the type of the method, with the receiver argument omitted
-+ * @param specialCaller the proposed calling class to perform the {@code invokespecial}
-+ * @return the desired method handle, or null if no such method exists
-+ * @exception SecurityException <em>TBD</em>
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
-+ Class<?> specialCaller) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ checkSpecialCaller(specialCaller, caller);
-+ MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
-+ checkStatic(false, method, caller);
-+ if (name.equals("<init>")) {
-+ if (defc != specialCaller)
-+ throw newNoAccessException("constructor must be local to caller", method, caller);
-+ } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
-+ throw newNoAccessException("method must be in a superclass of caller", method, caller);
-+ }
-+ return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
-+ }
-+
-+ /**
-+ * Produce an early-bound method handle for a non-static method.
-+ * The receiver must have a supertype {@code defc} in which a method
-+ * of the given name and type is accessible to the caller.
-+ * The method and all its argument types must be accessible to the caller.
-+ * The type of the method handle will be that of the method.
-+ * The given receiver will be bound into the method handle.
-+ * <p>
-+ * Equivalent to the following expression:
-+ * <code>
-+ * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
-+ * </code>
-+ * @param receiver the object from which the method is accessed
-+ * @param name the name of the method
-+ * @param type the type of the method, with the receiver argument omitted
-+ * @return the desired method handle, or null if no such method exists
-+ * @exception SecurityException <em>TBD</em>
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
-+ MemberName reference = new MemberName(rcvc, name, type);
-+ MemberName method = IMPL_LOOKUP.resolveOrFail(reference, true, caller);
-+ checkStatic(false, method, caller);
-+ MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, caller);
-+ MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
-+ if (bmh == null)
-+ throw newNoAccessException(method, caller);
-+ return bmh;
-+ }
-+
-+ /**
-+ * Make a direct method handle to <i>m</i>, if the current caller has permission.
-+ * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
-+ * If <i>m</i> is virtual, overriding is respected on every call.
-+ * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
-+ * The type of the method handle will be that of the method,
-+ * with the receiver type prepended (but only if it is non-static).
-+ * If the method's {@code accessible} flag is not set,
-+ * access checking is performed immediately on behalf of the caller.
-+ * If <i>m</i> is not public, do not share the resulting handle with untrusted callers.
-+ * @param m the reflected method
-+ * @return a method handle which can invoke the reflected method
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle unreflect(Method m) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ return unreflect(new MemberName(m), m.isAccessible(), true, caller);
-+ }
-+
-+ /**
-+ * Produce a method handle for a reflected method.
-+ * It will bypass checks for overriding methods on the receiver,
-+ * as if by the {@code invokespecial} instruction.
-+ * The type of the method handle will be that of the method,
-+ * with the receiver type prepended.
-+ * If the method's {@code accessible} flag is not set,
-+ * access checking is performed immediately on behalf of the caller,
-+ * as if {@code invokespecial} instruction were being linked.
-+ * @param m the reflected method
-+ * @return a method handle which can invoke the reflected method
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ checkSpecialCaller(specialCaller, caller);
-+ MemberName mname = new MemberName(m);
-+ checkStatic(false, mname, caller);
-+ return unreflect(mname, m.isAccessible(), false, specialCaller);
-+ }
-+
-+// /**
-+// * Produce a method handle for a reflected constructor.
-+// * It will allow direct access to the constructor,
-+// * as if by the {@code invokespecial} instruction.
-+// * The type of the method handle will be that of the method,
-+// * with the receiver type prepended.
-+// * If the constructor's {@code accessible} flag is not set,
-+// * access checking is performed immediately on behalf of the caller,
-+// * as if {@code invokespecial} instruction were being linked.
-+// * @param ctor the reflected constructor
-+// * @param specialCaller the proposed calling class to perform the {@code invokespecial}
-+// * @return a method handle which can invoke the reflected constructor
-+// * @exception NoAccessException if access checking fails
-+// */
-+// public static
-+// MethodHandle unreflectSpecial(Constructor ctor, Class<?> specialCaller) throws NoAccessException {
-+// Class<?> caller = Reflection.getCallerClass(2);
-+// checkSpecialCaller(specialCaller, caller);
-+// MemberName m = new MemberName(ctor);
-+// checkStatic(false, m, caller);
-+// return unreflect(m, ctor.isAccessible(), false, specialCaller);
-+// }
-+
-+ private static
-+ void checkSpecialCaller(Class<?> specialCaller, Class<?> caller) {
-+ if (caller != null && !VerifyAccess.isSamePackageMember(specialCaller, caller))
-+ throw newNoAccessException("no private access", new MemberName(specialCaller), caller);
-+ }
-+
-+ // Helper for creating handles on reflected methods and constructors.
-+ private static
-+ MethodHandle unreflect(MemberName m, boolean isAccessible, boolean doDispatch, Class<?> caller) {
-+ MethodType mtype = m.getInvocationType();
-+ Class<?> defc = m.getDeclaringClass();
-+ int mods = m.getModifiers();
-+ if (m.isStatic()) {
-+ if (!isAccessible &&
-+ VerifyAccess.isAccessible(defc, mods, false, caller) == null)
-+ throw newNoAccessException(m, caller);
-+ } else {
-+ Class<?> constraint;
-+ if (isAccessible) {
-+ // abbreviated access check for "unlocked" method
-+ constraint = doDispatch ? defc : caller;
-+ } else {
-+ constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, caller);
-+ }
-+ if (constraint != defc && !constraint.isAssignableFrom(defc)) {
-+ if (!defc.isAssignableFrom(constraint))
-+ throw newNoAccessException("receiver must be in caller class", m, caller);
-+ mtype = mtype.changeParameterType(0, constraint);
-+ }
-+ }
-+ return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, caller);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle giving read access to a reflected field.
-+ * The type of the method handle will have a return type of the field's
-+ * value type. Its sole argument will be the field's containing class
-+ * (but only if it is non-static).
-+ * If the method's {@code accessible} flag is not set,
-+ * access checking is performed immediately on behalf of the caller.
-+ * @param f the reflected field
-+ * @return a method handle which can load values from the reflected field
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle unreflectGetter(Field f) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, (Class)caller);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle giving write access to a reflected field.
-+ * The type of the method handle will have a void return type.
-+ * Its last argument will be the field's value type.
-+ * Its other argument will be the field's containing class
-+ * (but only if it is non-static).
-+ * If the method's {@code accessible} flag is not set,
-+ * access checking is performed immediately on behalf of the caller.
-+ * @param f the reflected field
-+ * @return a method handle which can store values into the reflected field
-+ * @exception NoAccessException if access checking fails
-+ */
-+ public static
-+ MethodHandle unreflectSetter(Field f) throws NoAccessException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, (Class)caller);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle giving read access to elements of an array.
-+ * The type of the method handle will have a return type of the array's
-+ * element type. Its first argument will be the array type,
-+ * and the second will be {@code int}.
-+ * @param arrayClass an array type
-+ * @return a method handle which can load values from the given array type
-+ * @throws IllegalArgumentException if arrayClass is not an array type
-+ */
-+ public static
-+ MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false, (Class)caller);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle giving write access to elements of an array.
-+ * The type of the method handle will have a void return type.
-+ * Its last argument will be the array's element type.
-+ * The first and second arguments will be the array type and int.
-+ * @return a method handle which can store values into the array type
-+ * @throws IllegalArgumentException if arrayClass is not an array type
-+ */
-+ public static
-+ MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
-+ Class<?> caller = Reflection.getCallerClass(2);
-+ return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true, (Class)caller);
-+ }
-+
-+
-+ /// method handle invocation (reflective style)
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Call the {@code invoke} method of a given method handle.
-+ * The given arguments must exactly match the parameter types of the method handle.
-+ * <em>TBD: Fill in the details.</em>
-+ * No conversions are performed except reference casting and unboxing of primitives.
-+ * @param target method handle to invoke
-+ * @param arguments arguments to pass to the target (with any primitives wrapped)
-+ * @return the result of the method (with any primitive wrapped)
-+ */
-+ public static
-+ Object invoke(MethodHandle target, Object... arguments) {
-+ // TO DO: Remove this checking logic; must be part of the invoker anyway.
-+ int length = arguments.length;
-+ MethodType type = target.type();
-+ if (type.parameterCount() != length)
-+ throw new WrongMethodTypeException("wrong number of arguments");
-+ for (int i = 0; i < length; i++) {
-+ Object argument = arguments[i];
-+ Class<?> ptype = type.parameterType(i);
-+ if (ptype.isPrimitive()) {
-+ argument.getClass(); // provoke NPE if null
-+ ptype = Wrappers.asWrapperType(ptype);
-+ } else if (ptype.isInterface()) {
-+ ptype = Object.class; // no check
-+ }
-+ if (ptype != Object.class) {
-+ ptype.cast(argument);
-+ }
-+ }
-+ // End of checking logic.
-+ return MethodHandleInvoker.make(target.type()).invoke(target, arguments);
-+ }
-+
-+ /**
-+ * <em>WORK IN PROGRESS:</em>
-+ * Perform value checking, exactly as if for an adapted method handle.
-+ * It is assumed that the given value is either null, of type T0,
-+ * or (if T0 is primitive) of the wrapper type corresponding to T0.
-+ * The following checks and conversions are made:
-+ * <ul>
-+ * <li>If T0 and T1 are references, then a cast to T1 is applied.
-+ * (The types do not need to be related in any particular way.)
-+ * <li>If T0 and T1 are primitives, then a widening or narrowing
-+ * conversion is applied, if one exists.
-+ * <li>If T0 is a primitive and T1 a reference, and
-+ * T0 has a wrapper type TW, a boxing conversion to TW is applied,
-+ * possibly followed by a reference conversion.
-+ * T1 must be TW or a supertype.
-+ * <li>If T0 is a reference and T1 a primitive, and
-+ * T1 has a wrapper type TW, an unboxing conversion is applied,
-+ * possibly preceded by a reference conversion.
-+ * T0 must be TW or a supertype.
-+ * <li>If T1 is void, the return value is discarded
-+ * <li>If T0 is void and T1 a reference, a null value is introduced.
-+ * <li>If T0 is void and T1 a primitive, a zero value is introduced.
-+ * </ul>
-+ * If the value is discarded, null will be returned.
-+ * @param valueType
-+ * @param value
-+ * @return the value, converted if necessary
-+ * @throws java.lang.ClassCastException if a cast fails
-+ */
-+ static
-+ Object checkValue(Class<?> T0, Class<?> T1, Object value)
-+ throws ClassCastException
-+ {
-+ if (T0 == T1) {
-+ // no conversion needed
-+ return value;
-+ }
-+ boolean prim0 = T0.isPrimitive(), prim1 = T1.isPrimitive();
-+ Class<?> TW;
-+ if (!prim0) {
-+ if (!prim1) {
-+ return T1.cast(T0.cast(value));
-+ }
-+ // convert reference to primitive by unboxing
-+ TW = Wrappers.asWrapperType(T0);
-+ return T1.cast(TW.cast(value));
-+ }
-+ if (!prim1) {
-+ // convert primitive to reference type by boxing
-+ TW = Wrappers.asWrapperType(T1);
-+ return TW.cast(T0.cast(value));
-+ }
-+ // convert primitive to primitive; this requires a real value change
-+ if (value == null)
-+ return Wrappers.zeroValue(T1);
-+ // convert non-Number primitives to Integer:
-+ if (value instanceof Character) {
-+ char ch = (char) (Character) value;
-+ value = Integer.valueOf(ch);
-+ if (T1 == Integer.class)
-+ return value;
-+ } else if (value instanceof Boolean) {
-+ boolean z = (boolean) (Boolean) value;
-+ value = Integer.valueOf(z ? 1 : 0);
-+ if (T1 == Integer.class)
-+ return value;
-+ }
-+ Number numval = (Number) value;
-+ switch (Wrappers.basicTypeChar(T1)) {
-+ case 'Z': return (numval.intValue() != 0);
-+ case 'B': return numval.byteValue();
-+ case 'C': return (char) numval.intValue();
-+ case 'S': return numval.shortValue();
-+ case 'I': return numval.intValue();
-+ case 'J': return numval.longValue();
-+ case 'F': return numval.floatValue();
-+ case 'D': return numval.doubleValue();
-+ }
-+ return null;
-+ }
-+
-+ static
-+ Object checkValue(Class<?> T1, Object value)
-+ throws ClassCastException
-+ {
-+ Class<?> T0;
-+ if (value == null)
-+ T0 = Object.class;
-+ else
-+ T0 = value.getClass();
-+ return checkValue(T0, T1, value);
-+ }
-+
-+ /// method handle modification (creation from other method handles)
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which adapts the type of the
-+ * given method handle to a new type, by pairwise argument conversion,
-+ * and/or varargs conversion.
-+ * The original type and new type must have the same number of
-+ * arguments, or else one or both them the must be varargs types.
-+ * The resulting method handle is guaranteed to confess a type
-+ * which is equal to the desired new type, with any varargs property erased.
-+ * <p>
-+ * If the original type and new type are equal, returns target.
-+ * <p>
-+ * The following conversions are applied as needed both to
-+ * arguments and return types. Let T0 and T1 be the differing
-+ * new and old parameter types (or old and new return types)
-+ * for corresponding values passed by the new and old method types.
-+ * <p>
-+ * If an ordinary (non-varargs) parameter of the new type is
-+ * to be boxed in a varargs parameter of the old type of type T1[],
-+ * then T1 is the element type of the varargs array.
-+ * Otherwise, if a varargs parameter of the new type of type T0[]
-+ * is to be spread into one or more outgoing old type parameters,
-+ * then T0 is the element type of the
-+ * If the new type is varargs and the old type is not, the varargs
-+ * argument will be checked and must be a non-null array of exactly
-+ * the right length. If there are no parameters in the old type
-+ * corresponding to the new varargs parameter, the varargs argument
-+ * is also allowed to be null.
-+ * <p>
-+ * Given those types T0, T1, one of the following conversions is applied
-+ * if possible:
-+ * <ul>
-+ * <li>If T0 and T1 are references, then a cast to T2 is applied,
-+ * where T2 is Object if T1 is an interface, else T1.
-+ * (The types do not need to be related in any particular way.
-+ * The treatment of interfaces follows the usage of the bytecode verifier.)
-+ * <li>If T0 and T1 are primitives, then a Java casting
-+ * conversion (JLS 5.5) is applied, if one exists.
-+ * <li>If T0 and T1 are primitives and one is boolean,
-+ * the boolean is treated as a one-bit unsigned integer.
-+ * (This treatment follows the usage of the bytecode verifier.)
-+ * A conversion from another primitive type behaves as if
-+ * it first converts to byte, and then masks all but the low bit.
-+ * <li>If T0 is a primitive and T1 a reference, a boxing
-+ * conversion is applied if one exists, possibly followed by
-+ * an reference conversion to a superclass.
-+ * T1 must be a wrapper class or a supertype of one.
-+ * If T1 is a wrapper class, T0 is converted if necessary
-+ * to T1's primitive type by one of the preceding conversions.
-+ * Otherwise, T0 is boxed, and its wrapper converted to T1.
-+ * <li>If T0 is a reference and T1 a primitive, an unboxing
-+ * conversion is applied if one exists, possibly preceded by
-+ * a reference conversion to a wrapper class.
-+ * T0 must be a wrapper class or a supertype of one.
-+ * If T0 is a wrapper class, its primitive value is converted
-+ * if necessary to T1 by one of the preceding conversions.
-+ * Otherwise, T0 is converted directly to the wrapper type for T1,
-+ * which is then unboxed.
-+ * <li>If T1 is void, any returned value is discarded
-+ * <li>If T0 is void and T1 a reference, a null value is introduced.
-+ * <li>If T0 is void and T1 a primitive, a zero value is introduced.
-+ * </ul>
-+ * @param target the method handle to invoke after arguments are retyped
-+ * @param newType the expected type of the new method handle
-+ * @return a method handle which delegates to {@code target} after performing
-+ * any necessary argument conversions, and arranges for any
-+ * necessary return value conversions
-+ */
-+ public static
-+ MethodHandle convertArguments(MethodHandle target, MethodType newType) {
-+ MethodType oldType = target.type();
-+ if (oldType.equals(newType))
-+ return target;
-+ return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
-+ newType, target.type(), null);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which adapts the calling sequence of the
-+ * given method handle to a new type, by reordering the arguments.
-+ * Duplication and omission is allowed.
-+ * The resulting method handle is guaranteed to confess a type
-+ * which is equal to the desired new type.
-+ * <p>
-+ * The given permutation string controls the reordering.
-+ * The characters of the string are treated as small integers.
-+ * All the characters must be in the range zero (i.e., '\0') to
-+ * the number of incoming arguments (the parameter count of the new type).
-+ * The length of the string must be equal to the number of outgoing
-+ * parameters (the parameter count of the original method handle's type).
-+ * If the n-th character of the string denotes the integer k,
-+ * then the n-th incoming argument becomes the k-th outgoing argument.
-+ * <p>
-+ * Pairwise conversions are applied as needed to arguments and return
-+ * values, as with {@link #convertArguments}.
-+ * @param target the method handle to invoke after arguments are reordered
-+ * @param newType the expected type of the new method handle
-+ * @param permutation a string which controls the reordering
-+ * @return a method handle which delegates to {@code target} after performing
-+ * any necessary argument motion and conversions, and arranges for any
-+ * necessary return value conversions
-+ */
-+ public static
-+ MethodHandle permuteArguments(MethodHandle target, MethodType newType, String permutation) {
-+ MethodType oldType = target.type();
-+ return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
-+ newType, target.type(),
-+ permutation);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which adapts the type of the
-+ * given method handle to a new type, by spreading the final argument.
-+ * The resulting method handle is guaranteed to confess a type
-+ * which is equal to the desired new type.
-+ * <p>
-+ * The final parameter type of the new type must be an array type T[].
-+ * This is the type of what is called the <i>spread</i> argument.
-+ * All other arguments of the new type are called <i>ordinary</i> arguments.
-+ * <p>
-+ * The ordinary arguments of the new type are pairwise converted
-+ * to the initial parameter types of the old type, according to the
-+ * rules in {@link #convertArguments}.
-+ * Any additional arguments in the old type
-+ * are converted from the array element type T,
-+ * again according to the rules in {@link #convertArguments}.
-+ * The return value is converted according likewise.
-+ * <p>
-+ * The call verifies that the spread argument is in fact an array
-+ * of exactly the type length, i.e., the excess number of
-+ * arguments in the old type over the ordinary arguments in the new type.
-+ * If there are no excess arguments, the spread argument is also
-+ * allowed to be null.
-+ * @param target the method handle to invoke after the argument is prepended
-+ * @param newType the expected type of the new method handle
-+ * @return a new method handle which spreads its final argument,
-+ * before calling the original method handle
-+ */
-+ public static
-+ MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
-+ MethodType oldType = target.type();
-+ int inargs = newType.parameterCount();
-+ int outargs = oldType.parameterCount();
-+ int spreadPos = inargs - 1;
-+ int numSpread = (outargs - spreadPos);
-+ if (spreadPos < 0 || numSpread < 0)
-+ throw newIllegalArgumentException("wrong number of arguments");
-+ newType = newType.changeVarArgs(true);
-+ return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, newType, oldType, null);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which adapts the type of the
-+ * given method handle to a new type, by collecting a series of
-+ * trailing arguments into an array.
-+ * The resulting method handle is guaranteed to confess a type
-+ * which is equal to the desired new type.
-+ * <p>
-+ * This method is inverse to {@link #spreadArguments}.
-+ * The final parameter type of the old type must be an array type T[],
-+ * which is the type of what is called the <i>spread</i> argument.
-+ * The trailing arguments of the new type which correspond to
-+ * the spread argument are all converted to type T and collected
-+ * into an array before the original method is called.
-+ * @param target the method handle to invoke after the argument is prepended
-+ * @param newType the expected type of the new method handle
-+ * @return a new method handle which collects some trailings argument
-+ * into an array, before calling the original method handle
-+ */
-+ public static
-+ MethodHandle collectArguments(MethodHandle target, MethodType newType) {
-+ MethodType oldType = target.type();
-+ int inargs = newType.parameterCount();
-+ int outargs = oldType.parameterCount();
-+ int collectPos = outargs - 1;
-+ int numCollect = (inargs - collectPos);
-+ if (collectPos < 0 || numCollect < 0)
-+ throw newIllegalArgumentException("wrong number of arguments");
-+ oldType = oldType.changeVarArgs(true);
-+ return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, newType, oldType, null);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which calls the original method handle,
-+ * after inserting the given argument as the first argument.
-+ * The type of the new method handle will drop the first argument
-+ * type from the original handle's type.
-+ * <p>
-+ * Equivalent to {@code insertArgument(target, value, 0)}.
-+ */
-+ public static
-+ MethodHandle insertArgument(MethodHandle target, Object value) {
-+ return insertArgument(target, value, 0);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which calls the original method handle,
-+ * after appending the given argument as the final argument.
-+ * The type of the new method handle will drop the last argument
-+ * type from the original handle's type.
-+ * <p>
-+ * Equivalent to {@code insertArgument(target, value, N)},
-+ * where <i>N</i> is the number of arguments to <i>target</i>.
-+ */
-+ public static
-+ MethodHandle appendArgument(MethodHandle target, Object value) {
-+ return insertArgument(target, value, target.type().parameterCount());
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which calls the original method handle,
-+ * after inserting the given argument at the given position.
-+ * The type of the new method handle will drop the corresponding argument
-+ * type from the original handle's type.
-+ * <p>
-+ * The given argument object must match the dropped argument type.
-+ * If the dropped argument type is a primitive, the argument object
-+ * must be a wrapper, and is unboxed to produce the primitive.
-+ * <p>
-+ * The <i>pos</i> may range between zero and <i>N</i> (inclusively),
-+ * where <i>N</i> is the number of argument types in <i>target</i>,
-+ * meaning to insert the new argument as the first or last (respectively),
-+ * or somewhere in between.
-+ * @param target the method handle to invoke after the argument is inserted
-+ * @param value the argument to insert
-+ * @param pos where to insert the argument (zero for the first)
-+ * @return a new method handle which inserts an additional argument,
-+ * before calling the original method handle
-+ */
-+ public static
-+ MethodHandle insertArgument(MethodHandle target, Object value, int pos) {
-+ MethodType oldType = target.type();
-+ ArrayList<Class<?>> ptypes =
-+ new ArrayList<Class<?>>(oldType.parameterList());
-+ int outargs = oldType.parameterCount();
-+ int inargs = outargs - 1;
-+ if (pos < 0 || pos >= outargs)
-+ throw newIllegalArgumentException("no argument type to append");
-+ Class<?> valueType = ptypes.remove(pos);
-+ value = checkValue(valueType, value);
-+ if (pos == 0 && !valueType.isPrimitive()) {
-+ // At least for now, make bound method handles a special case.
-+ // This lets us get by with minimal JVM support, at the expense
-+ // of generating signature-specific adapters as Java bytecodes.
-+ MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
-+ if (bmh != null) return bmh;
-+ // else fall through to general adapter machinery
-+ }
-+ return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Produce a method handle which calls the original method handle,
-+ * after dropping the given argument(s) at the given position.
-+ * The type of the new method handle will insert the given argument
-+ * type(s), at that position, into the original handle's type.
-+ * <p>
-+ * The <i>pos</i> may range between zero and <i>N-1</i>,
-+ * where <i>N</i> is the number of argument types in <i>target</i>,
-+ * meaning to drop the first or last argument (respectively),
-+ * or an argument somewhere in between.
-+ * @param target the method handle to invoke after the argument is dropped
-+ * @param valueTypes the type(s) of the argument to drop
-+ * @param pos which argument to drop (zero for the first)
-+ * @return a new method handle which drops an argument of the given type,
-+ * before calling the original method handle
-+ */
-+ public static
-+ MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
-+ if (valueTypes.length == 0) return target;
-+ MethodType oldType = target.type();
-+ int outargs = oldType.parameterCount();
-+ int inargs = outargs + valueTypes.length;
-+ if (pos < 0 || pos >= inargs)
-+ throw newIllegalArgumentException("no argument type to remove");
-+ ArrayList<Class<?>> ptypes =
-+ new ArrayList<Class<?>>(oldType.parameterList());
-+ ptypes.addAll(pos, Arrays.asList(valueTypes));
-+ MethodType newType = MethodType.make(oldType.returnType(), ptypes);
-+ return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Make a method handle which adapts a target method handle,
-+ * by guarding it with a test, a boolean-valued method handle.
-+ * If the guard fails, a fallback handle is called instead.
-+ * All three method handles must have the same corresponding
-+ * argument and return types, except that the return type
-+ * of the test must be boolean.
-+ * <p> Here is pseudocode for the resulting adapter:
-+ * <blockquote><pre>
-+ * signature T(A...);
-+ * boolean test(A...);
-+ * T target(A...);
-+ * T fallback(A...);
-+ * T adapter(A... a) {
-+ * if (test(a...))
-+ * return target(a...);
-+ * else
-+ * return fallback(a...);
-+ * }
-+ * </pre></blockquote>
-+ * @param test method handle used for test, must return boolean
-+ * @param target method handle to call if test passes
-+ * @param fallback method handle to call if test fails
-+ * @return method handle which incorporates the specified if/then/else logic
-+ * @throws IllegalArgumentException if {@code test} does not return boolean,
-+ * or if all three method types do not match (with the return
-+ * type of {@code test} changed to match that of {@code target}).
-+ */
-+ public static
-+ MethodHandle guardWithTest(MethodHandle test,
-+ MethodHandle target,
-+ MethodHandle fallback) {
-+ if (target.type() != fallback.type())
-+ throw newIllegalArgumentException("target and fallback types do not match");
-+ if (target.type().changeReturnType(boolean.class) != test.type())
-+ throw newIllegalArgumentException("target and test types do not match");
-+ /* {
-+ MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
-+ return z ? t : f;
-+ }
-+ MethodHandle choose = findVirtual(MethodHandles.class, "choose",
-+ MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
-+ choose = appendArgument(choose, target);
-+ choose = appendArgument(choose, fallback);
-+ choose = combineArguments(choose, test);
-+ MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
-+ return checkArguments(invoke, choose, 0);
-+ } */
-+ return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
-+ }
-+
-+ /**
-+ * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
-+ * Adapt a target method handle {@code target} by first checking its arguments,
-+ * and then calling the target.
-+ * The check is performed by a second method handle, the {@code checker}.
-+ * After this, control passes to the target method handle, with the same
-+ * arguments.
-+ * <p>
-+ * The return value of the checker is inserted into the argument list
-+ * for {@code target} at the indicated position {@code pos}, if it is non-negative.
-+ * Except for this inserted argument (if any), the argument types of
-+ * the target {@code target} and the {@code checker} must be identical.
-+ * <p>
-+ * The checker handle must have the same argument types as the
-+ * target handle, but must return {@link MethodHandle} instead of
-+ * the ultimate return type. The returned method handle, in turn,
-+ * is required to have exactly the given final method type.
-+ * <p> Here is pseudocode for the resulting adapter:
-+ * <blockquote><pre>
-+ * signature V(A[pos]..., B...);
-+ * signature T(A[pos]..., V, B...);
-+ * T target(A... a, V, B... b);
-+ * U checker(A..., B...);
-+ * T adapter(A... a, B... b) {
-+ * V v = checker(a..., b...);
-+ * return target(a..., v, b...);
-+ * }
-+ * </pre></blockquote>
-+ * @param target the method handle to invoke after arguments are checked
-+ * @param checker method handle to call initially on the incoming arguments
-+ * @param pos where the return value of {@code checker} is to
-+ * be inserted as an argument to {@code target}
-+ * @return method handle which incorporates the specified dispatch logic
-+ * @throws IllegalArgumentException if {@code checker} does not itself
-+ * return either void or the {@code pos}-th argument of {@code target},
-+ * or does not have the same argument types as {@code target}
-+ * (minus the inserted argument)
-+ */
-+ public static
-+ MethodHandle checkArguments(MethodHandle target, MethodHandle checker, int pos) {
-+ MethodType mhType = target.type();
-+ Class<?> checkType = checker.type().returnType();
-+ MethodType incomingArgs;
-+ if (pos < 0) {
-+ // No inserted argument; target & checker must have same argument types.
-+ incomingArgs = mhType;
-+ if (!incomingArgs.changeReturnType(checkType).equals(checker.type()))
-+ throw newIllegalArgumentException("target and checker types do not match");
-+ } else {
-+ // Inserted argument.
-+ if (pos >= mhType.parameterCount()
-+ || mhType.parameterType(pos) != checkType)
-+ throw newIllegalArgumentException("inserted checker argument does not match target");
-+ incomingArgs = mhType.deleteParameterType(pos);
-+ }
-+ if (!incomingArgs.changeReturnType(checkType).equals(checker.type())) {
-+ throw newIllegalArgumentException("target and checker types do not match");
-+ }
-+ return MethodHandleImpl.checkArguments(IMPL_TOKEN, target, checker, pos);
-+ }
-+
-+ /// standard method handles
-+
-+ /**
-+ * Identity function.
-+ * @param x an arbitrary reference value
-+ * @return the same value x
-+ */
-+ /*public*/ static <T>
-+ T identity(T x) {
-+ return x;
-+ }
-+
-+ /**
-+ * A method handle for {@link #identity}
-+ */
-+ /*public*/ static
-+ MethodHandle identityMethod() {
-+ if (IDENTITY == null)
-+ IDENTITY = findStatic(MethodHandle.class, "identity", IDENTITY_TYPE);
-+ return IDENTITY;
-+ }
-+ private static
-+ MethodHandle IDENTITY;
-+ private static final
-+ MethodType IDENTITY_TYPE = MethodType.make(Object.class, Object.class);
-+
-+ /**
-+ * Empty function.
-+ */
-+ /*public*/ static
-+ void empty() {
-+ }
-+
-+ /**
-+ * A method handle for {@link #empty}
-+ */
-+ /*public*/ static
-+ MethodHandle emptyMethod() {
-+ if (EMPTY == null)
-+ EMPTY = findStatic(MethodHandle.class, "empty", EMPTY_TYPE);
-+ return EMPTY;
-+ }
-+ private static
-+ MethodHandle EMPTY;
-+ private static final
-+ MethodType EMPTY_TYPE = MethodType.make(void.class);
-+}
-diff --git a/src/share/projects/meth/src/java/dyn/MethodType.java b/src/share/projects/meth/src/java/dyn/MethodType.java
-new file mode 100644
---- /dev/null
-+++ b/src/share/projects/meth/src/java/dyn/MethodType.java
-@@ -0,0 +1,579 @@
-+/*
-+ * 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.util.Arrays;
-+import java.util.Collections;
-+import java.util.HashMap;
-+import java.util.List;
-+import impl.java.dyn.*;
-+import impl.java.dyn.util.Signatures;
-+import static impl.java.dyn.MemberName.newIllegalArgumentException;
-+
-+/**
-+ * Run-time token used to match call sites with method handles.
-+ * The structure is a return type accompanied by any number of parameter types.
-+ * The types (primitive, void, and reference) are represented by Class objects.
-+ * All instances of <code>MethodType</code> are immutable.
-+ * Two instances are completely interchangeable if they compare equal.
-+ * Equality depends exactly on the return and parameter types, plus the varargs bit.
-+ * <p>
-+ * This type can be created only by factory methods, which manage interning.
-+ *
-+ * @author John Rose, JSR 292 EG
-+ */
-+public final
-+class MethodType {
-+ final Class<?> rtype;
-+ final Class<?>[] ptypes;
-+ MethodTypeForm form; // erased form, plus cached data about primitives
-+ MethodType wrapAlt; // alternative wrapped/unwrapped version
-+
-+ private static final Access IMPL_TOKEN = Access.getToken();
-+
-+ private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean varargs) {
-+ checkRtype(rtype);
-+ checkPtypes(ptypes);
-+ this.rtype = rtype;
-+ this.ptypes = ptypes;
-+ if (!varargs) {
-+ this.form = MethodTypeForm.FAKE[0];
-+ } else {
-+ this.form = MethodTypeForm.FAKE[1];
-+ checkVarargs(ptypes);
-+ }
-+ assert(this.isVarArgs() == varargs);
-+ }
-+
-+ private void checkRtype(Class<?> rtype) {
-+ rtype.equals(rtype); // null check
-+ }
-+ private void checkPtypes(Class<?>[] ptypes) {
-+ for (Class<?> ptype : ptypes) {
-+ ptype.equals(ptype); // null check
-+ if (ptype == void.class)
-+ throw newIllegalArgumentException("void parameter: "+this);
-+ }
-+ }
-+ private void checkVarargs(Class<?>[] ptypes) {
-+ if (ptypes.length == 0 || !ptypes[ptypes.length-1].isArray())
-+ throw newIllegalArgumentException("not varargs: "+this);
-+ }
-+
-+ static final HashMap<MethodType,MethodType> internTable
-+ = new HashMap<MethodType, MethodType>();
-+
-+ static final Class<?>[] NO_PTYPES = {};
-+
-+ /** Find or create an instance of the given method type.
-+ * @param rtype the return type
-+ * @param ptypes the parameter types
-+ * @return the interned method type with the given parts
-+ * @throws NullPointerException if rtype or any ptype is null
-+ * @throws IllegalArgumentException if any of the ptypes is void,
-+ */
-+ public static
-+ MethodType make(Class<?> rtype, Class<?>[] ptypes) {
-+ return makeImpl(rtype, ptypes, false, false);
-+ }
-+
-+ /** Find or create an instance of the given method type.
-+ * @param rtype the return type
-+ * @param ptypes the parameter types
-+ * @param varargs whether the method type will be varargs
-+ * @return the interned method type with the given parts
-+ * @throws NullPointerException if rtype or any ptype is null
-+ * @throws IllegalArgumentException if any of the ptypes is void,
-+ * or if varargs is true and the last parameter type is not an array
-+ */
-+ public static
-+ MethodType make(Class<?> rtype, Class<?>[] ptypes, boolean varargs) {
-+ return makeImpl(rtype, ptypes, varargs, false);
-+ }
-+
-+ /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. */
-+ public static
-+ MethodType make(Class<?> rtype, List<Class<?>> ptypes) {
-+ return makeImpl(rtype, ptypes.toArray(NO_PTYPES), false, true);
-+ }
-+
-+ /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
-+ * The leading parameter type is prepended to the remaining array.
-+ */
-+ public static
-+ MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
-+ Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
-+ ptypes1[0] = ptype0;
-+ System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
-+ return makeImpl(rtype, ptypes1, false, true);
-+ }
-+
-+ /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
-+ * The resulting method has no parameter types.
-+ */
-+ public static
-+ MethodType make(Class<?> rtype) {
-+ return makeImpl(rtype, NO_PTYPES, false, true);
-+ }
-+
-+ /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
-+ * The resulting method has the single given parameter type.
-+ */
-+ public static
-+ MethodType make(Class<?> rtype, Class<?> ptype0) {
-+ return makeImpl(rtype, new Class<?>[]{ ptype0 }, false, true);
-+ }
-+
-+ /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
-+ * The resulting method has the same parameter types as {@code ptypes},
-+ * and the specified return type.
-+ */
-+ public static
-+ MethodType make(Class<?> rtype, MethodType ptypes) {
-+ return makeImpl(rtype, ptypes.ptypes, false, true);
-+ }
-+
-+ /**
-+ * Sole factory method to find or create an interned method type.
-+ * @param rtype desired return type
-+ * @param ptypes desired parameter types
-+ * @param varargs whether the method type will be varargs
-+ * @param trusted whether the ptypes can be used without cloning
-+ * @return the unique method type of the desired structure
-+ */
-+ static
-+ MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean varargs, boolean trusted) {
-+ if (ptypes == null || ptypes.length == 0) {
-+ ptypes = NO_PTYPES; trusted = true;
-+ }
-+ MethodType mt1 = new MethodType(rtype, ptypes, varargs);
-+ MethodType mt0;
-+ synchronized (internTable) {
-+ mt0 = internTable.get(mt1);
-+ if (mt0 != null)
-+ return mt0;
-+ }
-+ if (!trusted)
-+