--- /dev/null	2009-01-20 02:47:23.000000000 -0800
+++ new/src/share/projects/meth/src/impl/java/dyn/MethodHandleImpl.java	2009-01-20 02:47:22.000000000 -0800
@@ -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);
+    }
+}
