Merge
authorxdono
Thu, 07 May 2009 12:26:22 -0700
changeset 120839d93fb6926c
parent 1207 86d2541a9ba2
parent 1194 9ba256e2e5c1
child 1210 7ec6857812d2
Merge
     1.1 --- a/make/docs/CORE_PKGS.gmk	Thu May 07 10:31:32 2009 -0700
     1.2 +++ b/make/docs/CORE_PKGS.gmk	Thu May 07 12:26:22 2009 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  #
     1.5 -# Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 +# Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
     1.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8  #
     1.9  # This code is free software; you can redistribute it and/or modify it
    1.10 @@ -55,6 +55,7 @@
    1.11  # This is a list of regular expressions. So foo.* matches "foo" and "foo.bar".
    1.12  #
    1.13  ACTIVE_JSR_PKGS= \
    1.14 +  java.dyn \
    1.15    java.sql  \
    1.16    javax.activation  \
    1.17    javax.annotation.*  \
     2.1 --- a/make/java/Makefile	Thu May 07 10:31:32 2009 -0700
     2.2 +++ b/make/java/Makefile	Thu May 07 12:26:22 2009 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  #
     2.5 -# Copyright 1995-2006 Sun Microsystems, Inc.  All Rights Reserved.
     2.6 +# Copyright 1995-2009 Sun Microsystems, Inc.  All Rights Reserved.
     2.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8  #
     2.9  # This code is free software; you can redistribute it and/or modify it
    2.10 @@ -39,7 +39,7 @@
    2.11  # Others
    2.12  #    Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk
    2.13  SUBDIRS += security npt java_crw_demo java_hprof_demo \
    2.14 -	    math awt util text applet net nio \
    2.15 +	    math awt util text applet net nio dyn \
    2.16  	    sql rmi jar beans logging management instrument
    2.17  
    2.18  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/make/java/dyn/Makefile	Thu May 07 12:26:22 2009 -0700
     3.3 @@ -0,0 +1,44 @@
     3.4 +#
     3.5 +# Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     3.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 +#
     3.8 +# This code is free software; you can redistribute it and/or modify it
     3.9 +# under the terms of the GNU General Public License version 2 only, as
    3.10 +# published by the Free Software Foundation.  Sun designates this
    3.11 +# particular file as subject to the "Classpath" exception as provided
    3.12 +# by Sun in the LICENSE file that accompanied this code.
    3.13 +#
    3.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 +# version 2 for more details (a copy is included in the LICENSE file that
    3.18 +# accompanied this code).
    3.19 +#
    3.20 +# You should have received a copy of the GNU General Public License version
    3.21 +# 2 along with this work; if not, write to the Free Software Foundation,
    3.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 +#
    3.24 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    3.25 +# CA 95054 USA or visit www.sun.com if you need additional information or
    3.26 +# have any questions.
    3.27 +#
    3.28 +
    3.29 +BUILDDIR = ../..
    3.30 +
    3.31 +PACKAGE = java.dyn
    3.32 +PRODUCT = java
    3.33 +include $(BUILDDIR)/common/Defs.gmk
    3.34 +
    3.35 +AUTO_FILES_JAVA_DIRS = java/dyn sun/dyn
    3.36 +
    3.37 +# The sources built here use new language syntax to generate
    3.38 +# method handle calls.  Let's be sure we are using that format.
    3.39 +#LANGUAGE_VERSION = -source 7
    3.40 +#CLASS_VERSION = -target 7
    3.41 +
    3.42 +# Actually, it will be less disruptive to compile with the same
    3.43 +# -target option as the rest of the system, and just turn on
    3.44 +# the specific compiler option we need here:
    3.45 +OTHER_JAVACFLAGS = -XDinvokedynamic
    3.46 +
    3.47 +include $(BUILDDIR)/common/Classes.gmk
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/share/classes/java/dyn/CallSite.java	Thu May 07 12:26:22 2009 -0700
     4.3 @@ -0,0 +1,201 @@
     4.4 +/*
     4.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Sun designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Sun in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    4.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    4.26 + * have any questions.
    4.27 + */
    4.28 +
    4.29 +package java.dyn;
    4.30 +
    4.31 +import sun.dyn.util.BytecodeName;
    4.32 +
    4.33 +/**
    4.34 + * An <code>invokedynamic</code> call site, as reified to the bootstrap method.
    4.35 + * Every instance of a call site corresponds to a distinct instance
    4.36 + * of the <code>invokedynamic</code> instruction.
    4.37 + * Call sites have state, one reference word, called the <code>target</code>,
    4.38 + * and typed as a {@link MethodHandle}.  When this state is null (as it is
    4.39 + * initially) the call site is in the unlinked state.  Otherwise, it is said
    4.40 + * to be linked to its target.
    4.41 + * <p>
    4.42 + * When an unlinked call site is executed, a bootstrap routine is called
    4.43 + * to finish the execution of the call site, and optionally to link
    4.44 + * the call site.
    4.45 + * <p>
    4.46 + * @author John Rose, JSR 292 EG
    4.47 + */
    4.48 +public class CallSite {
    4.49 +    // Fields used only by the JVM.  Do not use or change.
    4.50 +    private Object vmmethod;
    4.51 +    int callerMID, callerBCI;  // supplied by the JVM
    4.52 +
    4.53 +    MethodHandle target;
    4.54 +    final Object caller;  // usually a class
    4.55 +    final String name;
    4.56 +    final MethodType type;
    4.57 +
    4.58 +    public CallSite(Object caller, String name, MethodType type) {
    4.59 +        this.caller = caller;
    4.60 +        this.name = name;
    4.61 +        this.type = type;
    4.62 +    }
    4.63 +
    4.64 +    private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) {
    4.65 +        site.callerMID = callerMID;
    4.66 +        site.callerBCI = callerBCI;
    4.67 +        if (site.target == null)
    4.68 +            site.setTarget(site.initialTarget());
    4.69 +    }
    4.70 +
    4.71 +    /**
    4.72 +     * Just after a call site is created by a bootstrap method handle,
    4.73 +     * if the target has not been initialized by the factory method itself,
    4.74 +     * the method {@code initialTarget} is called to produce an initial
    4.75 +     * non-null target.  (Live call sites must never have null targets.)
    4.76 +     * <p>
    4.77 +     * If the bootstrap method itself does not initialize the call site,
    4.78 +     * this method must be overridden, because it just raises an
    4.79 +     * {@code InvokeDynamicBootstrapError}.
    4.80 +     */
    4.81 +    protected MethodHandle initialTarget() {
    4.82 +        throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+this);
    4.83 +    }
    4.84 +
    4.85 +    /**
    4.86 +     * Report the current linkage state of the call site.  (This is mutable.)
    4.87 +     * The value is null if and only if the call site is currently unlinked.
    4.88 +     * When a linked call site is invoked, the target method is used directly.
    4.89 +     * When an unlinked call site is invoked, its bootstrap method receives
    4.90 +     * the call, as if via {@link Linkage#bootstrapInvokeDynamic}.
    4.91 +     * <p>
    4.92 +     * The interactions of {@code getTarget} with memory are the same
    4.93 +     * as of a read from an ordinary variable, such as an array element or a
    4.94 +     * non-volatile, non-final field.
    4.95 +     * <p>
    4.96 +     * In particular, the current thread may choose to reuse the result
    4.97 +     * of a previous read of the target from memory, and may fail to see
    4.98 +     * a recent update to the target by another thread.
    4.99 +     * @return the current linkage state of the call site
   4.100 +     * @see #setTarget
   4.101 +     */
   4.102 +    public MethodHandle getTarget() {
   4.103 +        return target;
   4.104 +    }
   4.105 +
   4.106 +    /**
   4.107 +     * Link or relink the call site, by setting its target method.
   4.108 +     * <p>
   4.109 +     * The interactions of {@code setTarget} with memory are the same
   4.110 +     * as of a write to an ordinary variable, such as an array element or a
   4.111 +     * non-volatile, non-final field.
   4.112 +     * <p>
   4.113 +     * In particular, unrelated threads may fail to see the updated target
   4.114 +     * until they perform a read from memory.
   4.115 +     * Stronger guarantees can be created by putting appropriate operations
   4.116 +     * into the bootstrap method and/or the target methods used
   4.117 +     * at any given call site.
   4.118 +     * @param target the new target, or null if it is to be unlinked
   4.119 +     * @throws WrongMethodTypeException if the new target is not null
   4.120 +     *         and has a method type that differs from the call site's {@link #type}
   4.121 +     */
   4.122 +    public void setTarget(MethodHandle target) {
   4.123 +        checkTarget(target);
   4.124 +        this.target = target;
   4.125 +    }
   4.126 +
   4.127 +    protected void checkTarget(MethodHandle target) {
   4.128 +        if (!canSetTarget(target))
   4.129 +            throw new WrongMethodTypeException(String.valueOf(target));
   4.130 +    }
   4.131 +
   4.132 +    protected boolean canSetTarget(MethodHandle target) {
   4.133 +        return (target != null && target.type() == type());
   4.134 +    }
   4.135 +
   4.136 +    /**
   4.137 +     * Report the class containing the call site.
   4.138 +     * This is immutable static context.
   4.139 +     * @return class containing the call site
   4.140 +     */
   4.141 +    public Class<?> callerClass() {
   4.142 +        return (Class) caller;
   4.143 +    }
   4.144 +
   4.145 +    /**
   4.146 +     * Report the method name specified in the {@code invokedynamic} instruction.
   4.147 +     * This is immutable static context.
   4.148 +     * <p>
   4.149 +     * Note that the name is a JVM bytecode name, and as such can be any
   4.150 +     * non-empty string, as long as it does not contain certain "dangerous"
   4.151 +     * characters such as slash {@code '/'} and dot {@code '.'}.
   4.152 +     * See the Java Virtual Machine specification for more details.
   4.153 +     * <p>
   4.154 +     * Application such as a language runtimes may need to encode
   4.155 +     * arbitrary program element names and other configuration information
   4.156 +     * into the name.  A standard convention for doing this is
   4.157 +     * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
   4.158 +     * @return method name specified by the call site
   4.159 +     */
   4.160 +    public String name() {
   4.161 +        return name;
   4.162 +    }
   4.163 +
   4.164 +    /**
   4.165 +     * Report the method name specified in the {@code invokedynamic} instruction,
   4.166 +     * as a series of components, individually demangled according to
   4.167 +     * the standard convention
   4.168 +     * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
   4.169 +     * <p>
   4.170 +     * Non-empty runs of characters between dangerous characters are demangled.
   4.171 +     * Each component is either a completely arbitrary demangled string,
   4.172 +     * or else a character constant for a punctuation character, typically ':'.
   4.173 +     * (In principle, the character can be any dangerous character that the
   4.174 +     * JVM lets through in a method name, such as '$' or ']'.
   4.175 +     * Runtime implementors are encouraged to use colon ':' for building
   4.176 +     * structured names.)
   4.177 +     * <p>
   4.178 +     * In the common case where the name contains no dangerous characters,
   4.179 +     * the result is an array whose only element array is the demangled
   4.180 +     * name at the call site.  Such a demangled name can be any sequence
   4.181 +     * of any number of any unicode characters.
   4.182 +     * @return method name components specified by the call site
   4.183 +     */
   4.184 +    public Object[] nameComponents() {
   4.185 +        return BytecodeName.parseBytecodeName(name);
   4.186 +    }
   4.187 +
   4.188 +    /**
   4.189 +     * Report the resolved result and parameter types of this call site,
   4.190 +     * which are derived from its bytecode-level invocation descriptor.
   4.191 +     * The types are packaged into a {@link MethodType}.
   4.192 +     * Any linked target of this call site must be exactly this method type.
   4.193 +     * This is immutable static context.
   4.194 +     * @return method type specified by the call site
   4.195 +     */
   4.196 +    public MethodType type() {
   4.197 +        return type;
   4.198 +    }
   4.199 +
   4.200 +    @Override
   4.201 +    public String toString() {
   4.202 +        return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]";
   4.203 +    }
   4.204 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/share/classes/java/dyn/InvokeDynamic.java	Thu May 07 12:26:22 2009 -0700
     5.3 @@ -0,0 +1,39 @@
     5.4 +/*
     5.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Sun designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Sun in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    5.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    5.26 + * have any questions.
    5.27 + */
    5.28 +
    5.29 +package java.dyn;
    5.30 +
    5.31 +/**
    5.32 + * Syntactic marker interface to request javac to emit an {@code invokedynamic} instruction.
    5.33 + * <p>
    5.34 + * This type has no particular meaning as a class or interface supertype, and can never be instantiated.
    5.35 + * Logically, it denotes a source of all dynamically typed methods.
    5.36 + * @author John Rose, JSR 292 EG
    5.37 + */
    5.38 +public final class InvokeDynamic {
    5.39 +    private InvokeDynamic() { throw new InternalError(); }  // do not instantiate
    5.40 +
    5.41 +    // no statically defined static methods
    5.42 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Thu May 07 12:26:22 2009 -0700
     6.3 @@ -0,0 +1,55 @@
     6.4 +/*
     6.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Sun designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Sun in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    6.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    6.26 + * have any questions.
    6.27 + */
    6.28 +
    6.29 +package java.dyn;
    6.30 +
    6.31 +/**
    6.32 + * Thrown to indicate that an {@code invokedynamic} instruction has
    6.33 + * failed to find its bootstrap method, or the bootstrap method has
    6.34 + * failed to provide a call site with a non-null target.
    6.35 + * <p>
    6.36 + * The boostrap method must have been declared during a class's initialization
    6.37 + * by a call to {@link Linkage#registerBootstrapMethod}.
    6.38 + *
    6.39 + * @author John Rose, JSR 292 EG
    6.40 + */
    6.41 +public class InvokeDynamicBootstrapError extends LinkageError {
    6.42 +    /**
    6.43 +     * Constructs a {@code InvokeDynamicBootstrapError} with no detail message.
    6.44 +     */
    6.45 +    public InvokeDynamicBootstrapError() {
    6.46 +        super();
    6.47 +    }
    6.48 +
    6.49 +    /**
    6.50 +     * Constructs a {@code InvokeDynamicBootstrapError} with the specified
    6.51 +     * detail message.
    6.52 +     *
    6.53 +     * @param s the detail message.
    6.54 +     */
    6.55 +    public InvokeDynamicBootstrapError(String s) {
    6.56 +        super(s);
    6.57 +    }
    6.58 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/share/classes/java/dyn/JavaMethodHandle.java	Thu May 07 12:26:22 2009 -0700
     7.3 @@ -0,0 +1,83 @@
     7.4 +/*
     7.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.  Sun designates this
    7.11 + * particular file as subject to the "Classpath" exception as provided
    7.12 + * by Sun in the LICENSE file that accompanied this code.
    7.13 + *
    7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 + * version 2 for more details (a copy is included in the LICENSE file that
    7.18 + * accompanied this code).
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License version
    7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 + *
    7.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    7.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    7.26 + * have any questions.
    7.27 + */
    7.28 +
    7.29 +package java.dyn;
    7.30 +
    7.31 +/**
    7.32 + * A Java method handle extends the basic method handle type with additional
    7.33 + * programmer defined methods and fields.
    7.34 + * Its behavior as a method handle is determined at instance creation time,
    7.35 + * by providing the new instance with an "entry point" method handle
    7.36 + * to handle calls.  This entry point must accept a leading argument
    7.37 + * whose type is the Java method handle itself or a supertype, and the
    7.38 + * entry point is always called with the Java method handle itself as
    7.39 + * the first argument.  This is similar to ordinary virtual methods, which also
    7.40 + * accept the receiver object {@code this} as an implicit leading argument.
    7.41 + * The {@code MethodType} of the Java method handle is the same as that
    7.42 + * of the entry point method handle, with the leading parameter type
    7.43 + * omitted.
    7.44 + * <p>
    7.45 + * Here is an example of usage:
    7.46 + * <p><blockquote><pre>
    7.47 + *     class Greeter extends JavaMethodHandle {
    7.48 + *         public void run() { System.out.println("hello, "+greetee); }
    7.49 + *         private final String greetee;
    7.50 + *         Greeter(String greetee) {
    7.51 + *             super(RUN);
    7.52 + *             this.greetee = greetee;
    7.53 + *         }
    7.54 + *         // the entry point function is computed once:
    7.55 + *         private static final MethodHandle RUN
    7.56 + *             = MethodHandles.findVirtual(MyMethodHandle.class, "run",
    7.57 + *                   MethodType.make(void.class));
    7.58 + *     }
    7.59 + *     Greeter greeter = new Greeter("world");
    7.60 + *     greeter.run();  // prints "hello, world"
    7.61 + *     MethodHandle mh = greeter;
    7.62 + *     mh.invoke();  // also prints "hello, world"
    7.63 + * </pre></blockquote>
    7.64 + * <p>
    7.65 + * In this example, the method {@code run} provides the entry point.
    7.66 + * The entry point need not be a constant value; it may be independently
    7.67 + * computed in each call to the constructor.  The entry point does not
    7.68 + * even need to be a method on the Java method handle class, though
    7.69 + * that is the typical case.
    7.70 + * @see MethodHandle
    7.71 + * @author John Rose, JSR 292 EG
    7.72 + */
    7.73 +public abstract class JavaMethodHandle
    7.74 +        // Note: This is an implementation inheritance hack, and will be removed
    7.75 +        // with a JVM change which moves the required hidden behavior onto this class.
    7.76 +        extends sun.dyn.BoundMethodHandle
    7.77 +{
    7.78 +    /**
    7.79 +     * When creating a, pass in {@code entryPoint}, any method handle which
    7.80 +     * can take the current object
    7.81 +     * @param entryPoint
    7.82 +     */
    7.83 +    protected JavaMethodHandle(MethodHandle entryPoint) {
    7.84 +        super(entryPoint, 0);
    7.85 +    }
    7.86 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/share/classes/java/dyn/Linkage.java	Thu May 07 12:26:22 2009 -0700
     8.3 @@ -0,0 +1,199 @@
     8.4 +/*
     8.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.  Sun designates this
    8.11 + * particular file as subject to the "Classpath" exception as provided
    8.12 + * by Sun in the LICENSE file that accompanied this code.
    8.13 + *
    8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.17 + * version 2 for more details (a copy is included in the LICENSE file that
    8.18 + * accompanied this code).
    8.19 + *
    8.20 + * You should have received a copy of the GNU General Public License version
    8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.23 + *
    8.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    8.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    8.26 + * have any questions.
    8.27 + */
    8.28 +
    8.29 +package java.dyn;
    8.30 +
    8.31 +import java.util.WeakHashMap;
    8.32 +import sun.reflect.Reflection;
    8.33 +import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege;
    8.34 +
    8.35 +/**
    8.36 + * Static methods which control the linkage of invokedynamic call sites.
    8.37 + * @author John Rose, JSR 292 EG
    8.38 + */
    8.39 +public class Linkage {
    8.40 +    private Linkage() {}  // do not instantiate
    8.41 +
    8.42 +    /**
    8.43 +     * Register a bootstrap method for use for a given caller class.
    8.44 +     * The method handle must be of a type equivalent to {@link Linkage#makeCallSite}.
    8.45 +     * <p>
    8.46 +     * The operation will fail with an exception if any of the following conditions hold:
    8.47 +     * <ul>
    8.48 +     * <li>The caller of this method is in a different package than the {@code callerClass},
    8.49 +     *     and there is a security manager, and its {@code checkPermission} call throws
    8.50 +     *     when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass).
    8.51 +     * <li>The given class already has a bootstrap method, either from an embedded
    8.52 +     *     {@code BootstrapInvokeDynamic} classfile attribute, or from a previous
    8.53 +     *     call to this method.
    8.54 +     * <li>The given class is already fully initialized.
    8.55 +     * <li>The given class is in the process of initialization, in another thread.
    8.56 +     * </ul>
    8.57 +     * Because of these rules, a class may install its own bootstrap method in
    8.58 +     * a static initializer.
    8.59 +     */
    8.60 +    public static
    8.61 +    void registerBootstrapMethod(Class callerClass, MethodHandle mh) {
    8.62 +        Class callc = Reflection.getCallerClass(2);
    8.63 +        checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
    8.64 +        checkBSM(mh);
    8.65 +        synchronized (bootstrapMethods) {
    8.66 +            if (bootstrapMethods.containsKey(callerClass))
    8.67 +                throw new IllegalStateException("bootstrap method already declared in "+callerClass);
    8.68 +            bootstrapMethods.put(callerClass, mh);
    8.69 +        }
    8.70 +    }
    8.71 +
    8.72 +    static void checkBSM(MethodHandle mh) {
    8.73 +        if (mh == null)  throw new IllegalArgumentException("null bootstrap method");
    8.74 +        if (mh.type() == OLD_BOOTSTRAP_METHOD_TYPE) // FIXME: delete at EDR/PFD
    8.75 +            throw new WrongMethodTypeException("bootstrap method must be a CallSite factory");
    8.76 +        if (mh.type() != BOOTSTRAP_METHOD_TYPE)
    8.77 +            throw new WrongMethodTypeException(mh.toString());
    8.78 +    }
    8.79 +
    8.80 +    /**
    8.81 +     * Simplified version of registerBootstrapMethod for self-registration,
    8.82 +     * to be called from a static initializer.
    8.83 +     * Finds a static method of type (CallSite, Object[]) -> Object in the
    8.84 +     * given class, and installs it on the caller.
    8.85 +     * @throws IllegalArgumentException if there is no such method
    8.86 +     */
    8.87 +    public static
    8.88 +    void registerBootstrapMethod(Class<?> runtime, String name) {
    8.89 +        Class callc = Reflection.getCallerClass(2);
    8.90 +        MethodHandle bootstrapMethod =
    8.91 +            MethodHandles.findStaticFrom(callc, runtime, name, BOOTSTRAP_METHOD_TYPE);
    8.92 +        // FIXME: exception processing wrong here
    8.93 +        checkBSM(bootstrapMethod);
    8.94 +        Linkage.registerBootstrapMethod(callc, bootstrapMethod);
    8.95 +    }
    8.96 +
    8.97 +    /**
    8.98 +     * Simplified version of registerBootstrapMethod for self-registration,
    8.99 +     * to be called from a static initializer.
   8.100 +     * Finds a static method of type (CallSite, Object[]) -> Object in the
   8.101 +     * caller's class, and installs it on the caller.
   8.102 +     * @throws IllegalArgumentException if there is no such method
   8.103 +     */
   8.104 +    public static
   8.105 +    void registerBootstrapMethod(String name) {
   8.106 +        Class callc = Reflection.getCallerClass(2);
   8.107 +        MethodHandle bootstrapMethod =
   8.108 +            MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE);
   8.109 +        // FIXME: exception processing wrong here
   8.110 +        checkBSM(bootstrapMethod);
   8.111 +        Linkage.registerBootstrapMethod(callc, bootstrapMethod);
   8.112 +    }
   8.113 +
   8.114 +    /**
   8.115 +     * Report the bootstrap method registered for a given class.
   8.116 +     * Returns null if the class has never yet registered a bootstrap method,
   8.117 +     * or if the class has explicitly registered a null bootstrap method.
   8.118 +     * Only callers privileged to set the bootstrap method may inquire
   8.119 +     * about it, because a bootstrap method is potentially a back-door entry
   8.120 +     * point into its class.
   8.121 +     */
   8.122 +    public static
   8.123 +    MethodHandle getBootstrapMethod(Class callerClass) {
   8.124 +        Class callc = Reflection.getCallerClass(2);
   8.125 +        checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
   8.126 +        synchronized (bootstrapMethods) {
   8.127 +            return bootstrapMethods.get(callerClass);
   8.128 +        }
   8.129 +    }
   8.130 +
   8.131 +    /** The type of any bootstrap method is a three-argument method
   8.132 +     * {@code (Class<?>, String, MethodType)} returning a {@code CallSite}.
   8.133 +     */
   8.134 +    public static final MethodType BOOTSTRAP_METHOD_TYPE
   8.135 +            = MethodType.make(CallSite.class,
   8.136 +                              Class.class, String.class, MethodType.class);
   8.137 +
   8.138 +    private static final MethodType OLD_BOOTSTRAP_METHOD_TYPE
   8.139 +            = MethodType.make(Object.class,
   8.140 +                              CallSite.class, Object[].class);
   8.141 +
   8.142 +    private static final WeakHashMap<Class, MethodHandle> bootstrapMethods =
   8.143 +            new WeakHashMap<Class, MethodHandle>();
   8.144 +
   8.145 +    /**
   8.146 +     * Invalidate all <code>invokedynamic</code> call sites everywhere.
   8.147 +     * <p>
   8.148 +     * When this method returns, every <code>invokedynamic</code> instruction
   8.149 +     * will invoke its bootstrap method on next call.
   8.150 +     * <p>
   8.151 +     * It is unspecified whether call sites already known to the Java
   8.152 +     * code will continue to be associated with <code>invokedynamic</code>
   8.153 +     * instructions.  If any call site is still so associated, its
   8.154 +     * {@link CallSite#getTarget()} method is guaranteed to return null
   8.155 +     * the invalidation operation completes.
   8.156 +     * <p>
   8.157 +     * Invalidation operations are likely to be slow.  Use them sparingly.
   8.158 +     */
   8.159 +    public static
   8.160 +    Object invalidateAll() {
   8.161 +        SecurityManager security = System.getSecurityManager();
   8.162 +        if (security != null) {
   8.163 +            security.checkPermission(new LinkagePermission("invalidateAll"));
   8.164 +        }
   8.165 +        throw new UnsupportedOperationException("NYI");
   8.166 +    }
   8.167 +
   8.168 +    /**
   8.169 +     * Invalidate all <code>invokedynamic</code> call sites associated
   8.170 +     * with the given class.
   8.171 +     * (These are exactly those sites which report the given class
   8.172 +     * via the {@link CallSite#callerClass()} method.)
   8.173 +     * <p>
   8.174 +     * When this method returns, every matching <code>invokedynamic</code>
   8.175 +     * instruction will invoke its bootstrap method on next call.
   8.176 +     * <p>
   8.177 +     * For additional semantics of call site invalidation,
   8.178 +     * see {@link #invalidateAll()}.
   8.179 +     */
   8.180 +    public static
   8.181 +    Object invalidateCallerClass(Class<?> callerClass) {
   8.182 +        SecurityManager security = System.getSecurityManager();
   8.183 +        if (security != null) {
   8.184 +            security.checkPermission(new LinkagePermission("invalidateAll", callerClass));
   8.185 +        }
   8.186 +        throw new UnsupportedOperationException("NYI");
   8.187 +    }
   8.188 +
   8.189 +    private static Object doNotBootstrap(CallSite site, Object... arguments) {
   8.190 +        throw new UnsupportedOperationException("call site must not have null target: "+site);
   8.191 +    }
   8.192 +
   8.193 +    private static final MethodHandle DO_NOT_BOOTSTRAP =
   8.194 +            MethodHandles.Lookup.IMPL_LOOKUP.findStatic(Linkage.class, "doNotBootstrap",
   8.195 +                OLD_BOOTSTRAP_METHOD_TYPE);
   8.196 +
   8.197 +    // Up-call from the JVM.  Obsolete.  FIXME: Delete from VM then from here.
   8.198 +    static
   8.199 +    MethodHandle findBootstrapMethod(Class callerClass, Class searchBootstrapClass) {
   8.200 +        return DO_NOT_BOOTSTRAP;
   8.201 +    }
   8.202 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/share/classes/java/dyn/LinkagePermission.java	Thu May 07 12:26:22 2009 -0700
     9.3 @@ -0,0 +1,111 @@
     9.4 +/*
     9.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Sun designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Sun in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    9.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    9.26 + * have any questions.
    9.27 + */
    9.28 +
    9.29 +package java.dyn;
    9.30 +
    9.31 +import java.security.*;
    9.32 +import java.util.Enumeration;
    9.33 +import java.util.Hashtable;
    9.34 +import java.util.StringTokenizer;
    9.35 +
    9.36 +/**
    9.37 + * This class is for runtime permissions. A RuntimePermission
    9.38 + * contains a name (also referred to as a "target name") but
    9.39 + * no actions list; you either have the named permission
    9.40 + * or you don't.
    9.41 + *
    9.42 + * <P>
    9.43 + * The target name is the name of the runtime permission (see below). The
    9.44 + * naming convention follows the  hierarchical property naming convention.
    9.45 + * Also, an asterisk
    9.46 + * may appear at the end of the name, following a ".", or by itself, to
    9.47 + * signify a wildcard match. For example: "loadLibrary.*" or "*" is valid,
    9.48 + * "*loadLibrary" or "a*b" is not valid.
    9.49 + * <P>
    9.50 + * The following table lists all the possible RuntimePermission target names,
    9.51 + * and for each provides a description of what the permission allows
    9.52 + * and a discussion of the risks of granting code the permission.
    9.53 + * <P>
    9.54 + *
    9.55 + * <table border=1 cellpadding=5 summary="permission target name,
    9.56 + *  what the target allows,and associated risks">
    9.57 + * <tr>
    9.58 + * <th>Permission Target Name</th>
    9.59 + * <th>What the Permission Allows</th>
    9.60 + * <th>Risks of Allowing this Permission</th>
    9.61 + * </tr>
    9.62 + *
    9.63 + * <tr>
    9.64 + *   <td>registerBootstrapMethod.{class name}</td>
    9.65 + *   <td>Specifying a bootstrap method for invokedynamic, within a class of the given name</td>
    9.66 + *   <td>An attacker could attempt to attach a bootstrap method to a class which
    9.67 + *       has just been loaded, thus gaining control of its invokedynamic calls.</td>
    9.68 + * </tr>
    9.69 + *
    9.70 + * <tr>
    9.71 + *   <td>invalidateAll</td>
    9.72 + *   <td>Force the relinking of invokedynamic call sites everywhere.</td>
    9.73 + *   <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>
    9.74 + * </tr>
    9.75 + *
    9.76 + *
    9.77 + * <tr>
    9.78 + *   <td>invalidateCallerClass.{class name}</td>
    9.79 + *   <td>Force the relinking of invokedynamic call sites in the given class.</td>
    9.80 + *   <td>See {@code invalidateAll}.</td>
    9.81 + * </tr>
    9.82 + * </table>
    9.83 + *
    9.84 + * @see java.security.BasicPermission
    9.85 + * @see java.lang.SecurityManager
    9.86 + *
    9.87 + * @author John Rose, JSR 292 EG
    9.88 + */
    9.89 +
    9.90 +public final class LinkagePermission extends BasicPermission {
    9.91 +    /**
    9.92 +     * Create a new LinkagePermission with the given name.
    9.93 +     * The name is the symbolic name of the LinkagePermission, such as
    9.94 +     * "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk
    9.95 +     * may appear at the end of the name, following a ".", or by itself, to
    9.96 +     * signify a wildcard match.
    9.97 +     *
    9.98 +     * @param name the name of the LinkagePermission
    9.99 +     */
   9.100 +    public LinkagePermission(String name) {
   9.101 +        super(name);
   9.102 +    }
   9.103 +
   9.104 +    /**
   9.105 +     * Create a new LinkagePermission with the given name on the given class.
   9.106 +     * Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}.
   9.107 +     *
   9.108 +     * @param name the name of the LinkagePermission
   9.109 +     * @param clazz the class affected by the permission
   9.110 +     */
   9.111 +    public LinkagePermission(String name, Class<?> clazz) {
   9.112 +        super(name + "." + clazz.getName());
   9.113 +    }
   9.114 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/share/classes/java/dyn/MethodHandle.java	Thu May 07 12:26:22 2009 -0700
    10.3 @@ -0,0 +1,135 @@
    10.4 +/*
    10.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Sun designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Sun in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   10.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   10.26 + * have any questions.
   10.27 + */
   10.28 +
   10.29 +package java.dyn;
   10.30 +
   10.31 +//import sun.dyn.*;
   10.32 +
   10.33 +import sun.dyn.Access;
   10.34 +import sun.dyn.MethodHandleImpl;
   10.35 +
   10.36 +/**
   10.37 + * A method handle is a typed reference to the entry point of a method.
   10.38 + * <p>
   10.39 + * Method handles are strongly typed according to signature.
   10.40 + * They are not distinguished by method name or enclosing class.
   10.41 + * A method handle must be invoked under a signature which exactly matches
   10.42 + * the method handle's own type.
   10.43 + * <p>
   10.44 + * Every method handle confesses its type via the <code>type</code> accessor.
   10.45 + * The structure of this type is a series of classes, one of which is
   10.46 + * the return type of the method (or <code>void.class</code> if none).
   10.47 + * <p>
   10.48 + * Every method handle appears as an object containing a method named
   10.49 + * <code>invoke</code>, whose signature exactly matches
   10.50 + * the method handle's type.
   10.51 + * A normal Java method call (using the <code>invokevirtual</code> instruction)
   10.52 + * can invoke this method from Java source code (if language support is present).
   10.53 + * <p>
   10.54 + * Every call to a method handle specifies an intended method type,
   10.55 + * which must exactly match the type of the method handle.
   10.56 + * (The type is specified in the <code>invokevirtual</code> instruction,
   10.57 + * via a {@code CONSTANT_NameAndType} constant pool entry.)
   10.58 + * The call looks within the receiver object for a method
   10.59 + * named <code>invoke</code> of the intended method type.
   10.60 + * The call fails with a {@link WrongMethodTypeException}
   10.61 + * if the method does not exist, even if there is an <code>invoke</code>
   10.62 + * method of a closely similar signature.
   10.63 + * <p>
   10.64 + * A method handle is an unrestricted capability to call a method.
   10.65 + * A method handle can be formed on a non-public method by a class
   10.66 + * that has access to that method; the resulting handle can be used
   10.67 + * in any place by any caller who receives a reference to it.  Thus, access
   10.68 + * checking is performed when the method handle is created, not
   10.69 + * (as in reflection) every time it is called.  Handles to non-public
   10.70 + * methods, or in non-public classes, should generally be kept secret.
   10.71 + * They should not be passed to untrusted code.
   10.72 + * <p>
   10.73 + * Bytecode in an extended JVM can directly call a method handle's
   10.74 + * <code>invoke</code> from an <code>invokevirtual</code> instruction.
   10.75 + * The receiver class type must be <code>MethodHandle</code> and the method name
   10.76 + * must be <code>invoke</code>.  The signature of the invocation
   10.77 + * (after resolving symbolic type names) must exactly match the method type
   10.78 + * of the target method.
   10.79 + * <p>
   10.80 + * Bytecode in an extended JVM can directly obtain a method handle
   10.81 + * for any accessible method from a <code>ldc</code> instruction
   10.82 + * which refers to a <code>CONSTANT_Methodref</code> or
   10.83 + * <code>CONSTANT_InterfaceMethodref</code> constant pool entry.
   10.84 + * <p>
   10.85 + * All JVMs can also use a reflective API called <code>MethodHandles</code>
   10.86 + * for creating and calling method handles.
   10.87 + * <p>
   10.88 + * A method reference may refer either to a static or non-static method.
   10.89 + * In the non-static case, the method handle type includes an explicit
   10.90 + * receiver argument, prepended before any other arguments.
   10.91 + * In the method handle's type, the initial receiver argument is typed
   10.92 + * according to the class under which the method was initially requested.
   10.93 + * (E.g., if a non-static method handle is obtained via <code>ldc</code>,
   10.94 + * the type of the receiver is the class named in the constant pool entry.)
   10.95 + * <p>
   10.96 + * When a method handle to a virtual method is invoked, the method is
   10.97 + * always looked up in the receiver (that is, the first argument).
   10.98 + * <p>
   10.99 + * A non-virtual method handles to a specific virtual method implementation
  10.100 + * can also be created.  These do not perform virtual lookup based on
  10.101 + * receiver type.  Such a method handle simulates the effect of
  10.102 + * an <code>invokespecial</code> instruction to the same method.
  10.103 + *
  10.104 + * @see MethodType
  10.105 + * @see MethodHandles
  10.106 + * @author John Rose, JSR 292 EG
  10.107 + */
  10.108 +public abstract class MethodHandle
  10.109 +        // Note: This is an implementation inheritance hack, and will be removed
  10.110 +        // with a JVM change which moves the required hidden state onto this class.
  10.111 +        extends MethodHandleImpl
  10.112 +{
  10.113 +    // interface MethodHandle<T extends MethodType<R,A...>>
  10.114 +    // { T type(); <R,A...> public R invoke(A...); }
  10.115 +
  10.116 +    final private MethodType type;
  10.117 +
  10.118 +    /**
  10.119 +     * Report the type of this method handle.
  10.120 +     * Every invocation of this method handle must exactly match this type.
  10.121 +     * @return the method handle type
  10.122 +     */
  10.123 +    public MethodType type() {
  10.124 +        return type;
  10.125 +    }
  10.126 +
  10.127 +    /**
  10.128 +     * The constructor for MethodHandle may only be called by privileged code.
  10.129 +     * Subclasses may be in other packages, but must possess
  10.130 +     * a token which they obtained from MH with a security check.
  10.131 +     * @param token non-null object which proves access permission
  10.132 +     * @param type type (permanently assigned) of the new method handle
  10.133 +     */
  10.134 +    protected MethodHandle(Access token, MethodType type) {
  10.135 +        super(token);
  10.136 +        this.type = type;
  10.137 +    }
  10.138 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/share/classes/java/dyn/MethodHandles.java	Thu May 07 12:26:22 2009 -0700
    11.3 @@ -0,0 +1,1092 @@
    11.4 +/*
    11.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Sun designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Sun in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   11.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   11.26 + * have any questions.
   11.27 + */
   11.28 +
   11.29 +package java.dyn;
   11.30 +
   11.31 +import java.lang.reflect.Constructor;
   11.32 +import sun.dyn.Access;
   11.33 +import sun.dyn.MemberName;
   11.34 +import sun.dyn.MethodHandleImpl;
   11.35 +import sun.dyn.util.VerifyAccess;
   11.36 +import sun.dyn.util.Wrapper;
   11.37 +import java.lang.reflect.Field;
   11.38 +import java.lang.reflect.Method;
   11.39 +import java.lang.reflect.Modifier;
   11.40 +import java.util.ArrayList;
   11.41 +import java.util.Arrays;
   11.42 +import sun.dyn.Invokers;
   11.43 +import sun.dyn.MethodTypeImpl;
   11.44 +import sun.reflect.Reflection;
   11.45 +import static sun.dyn.MemberName.newIllegalArgumentException;
   11.46 +import static sun.dyn.MemberName.newNoAccessException;
   11.47 +
   11.48 +/**
   11.49 + * Fundamental operations and utilities for MethodHandle.
   11.50 + * <p>
   11.51 + * <em>API Note:</em>  The matching of method types in this API cannot
   11.52 + * be completely checked by Java's generic type system for three reasons:
   11.53 + * <ol>
   11.54 + * <li>Method types range over all possible arities,
   11.55 + * from no arguments to an arbitrary number of arguments.
   11.56 + * Generics are not variadic, and so cannot represent this.</li>
   11.57 + * <li>Method types can specify arguments of primitive types,
   11.58 + * which Java generic types cannot range over.</li>
   11.59 + * <li>Method types can optionally specify varargs (ellipsis).</li>
   11.60 + * </ol>
   11.61 + * @author John Rose, JSR 292 EG
   11.62 + */
   11.63 +public class MethodHandles {
   11.64 +
   11.65 +    private MethodHandles() { }  // do not instantiate
   11.66 +
   11.67 +    private static final Access IMPL_TOKEN = Access.getToken();
   11.68 +    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
   11.69 +    static { MethodHandleImpl.initStatics(); }
   11.70 +    // See IMPL_LOOKUP below.
   11.71 +
   11.72 +    //// Method handle creation from ordinary methods.
   11.73 +
   11.74 +    public static Lookup lookup() {
   11.75 +        return new Lookup();
   11.76 +    }
   11.77 +
   11.78 +    /**
   11.79 +     * A factory object for creating method handles, when the creation
   11.80 +     * requires access checking.  Method handles do not perform
   11.81 +     * access checks when they are called; this is a major difference
   11.82 +     * from reflective {@link Method}, which performs access checking
   11.83 +     * against every caller, on every call.  Method handle access
   11.84 +     * restrictions are enforced when a method handle is created.
   11.85 +     * The caller class against which those restrictions are enforced
   11.86 +     * is known as the "lookup class".  {@link Lookup} embodies an
   11.87 +     * authenticated lookup class, and can be used to create any number
   11.88 +     * of access-checked method handles, all checked against a single
   11.89 +     * lookup class.
   11.90 +     * <p>
   11.91 +     * A class which needs to create method handles will call
   11.92 +     * {@code MethodHandles.lookup()} to create a factory for itself.
   11.93 +     * It may then use this factory to create method handles on
   11.94 +     * all of its methods, including private ones.
   11.95 +     * It may also delegate the lookup (e.g., to a metaobject protocol)
   11.96 +     * by passing the {@code Lookup} object to other code.
   11.97 +     * If this other code creates method handles, they will be access
   11.98 +     * checked against the original lookup class, and not with any higher
   11.99 +     * privileges.
  11.100 +     * <p>
  11.101 +     * Note that access checks only apply to named and reflected methods.
  11.102 +     * Other method handle creation methods, such as {@link #convertArguments},
  11.103 +     * do not require any access checks, and can be done independently
  11.104 +     * of any lookup class.
  11.105 +     * <p>
  11.106 +     * <em>A note about error conditions:<em>  A lookup can fail, because
  11.107 +     * the containing class is not accessible to the lookup class, or
  11.108 +     * because the desired class member is missing, or because the
  11.109 +     * desired class member is not accessible to the lookup class.
  11.110 +     * It can also fail if a security manager is installed and refuses
  11.111 +     * access.  In any of these cases, an exception will be
  11.112 +     * thrown from the attempted lookup.
  11.113 +     * In general, the conditions under which a method handle may be
  11.114 +     * created for a method M are exactly as restrictive as the conditions
  11.115 +     * under which the lookup class could have compiled a call to M.
  11.116 +     */
  11.117 +    public static final
  11.118 +    class Lookup {
  11.119 +        private final Class<?> lookupClass;
  11.120 +
  11.121 +        /** Which class is performing the lookup?  It is this class against
  11.122 +         *  which checks are performed for visibility and access permissions.
  11.123 +         *  <p>
  11.124 +         *  This value is null if and only if this lookup is {@link #PUBLIC_LOOKUP}.
  11.125 +         */
  11.126 +        public Class<?> lookupClass() {
  11.127 +            return lookupClass;
  11.128 +        }
  11.129 +
  11.130 +        /** Embody the current class (the lookupClass) as a lookup class
  11.131 +         * for method handle creation.
  11.132 +         * Must be called by from a method in this package,
  11.133 +         * which in turn is called by a method not in this package.
  11.134 +         * Also, don't make it private, lest javac interpose
  11.135 +         * an access$N method.
  11.136 +         */
  11.137 +        Lookup() {
  11.138 +            Class caller = getCallerClassAtEntryPoint();
  11.139 +            // make sure we haven't accidentally picked up this class:
  11.140 +            checkUnprivilegedlookupClass(caller);
  11.141 +            this.lookupClass = caller;
  11.142 +        }
  11.143 +
  11.144 +        private Lookup(Class<?> lookupClass) {
  11.145 +            this.lookupClass = lookupClass;
  11.146 +        }
  11.147 +
  11.148 +        /** Version of lookup which is trusted minimally.
  11.149 +         *  It can only be used to create method handles to
  11.150 +         *  publicly accessible members.
  11.151 +         */
  11.152 +        public static final Lookup PUBLIC_LOOKUP = new Lookup(null);
  11.153 +
  11.154 +        /** Package-private version of lookup which is trusted. */
  11.155 +        static final Lookup IMPL_LOOKUP = new Lookup(Access.class);
  11.156 +        static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
  11.157 +
  11.158 +        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
  11.159 +            if (lookupClass == null ||
  11.160 +                lookupClass == Access.class ||
  11.161 +                lookupClass.getName().startsWith("java.dyn."))
  11.162 +                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
  11.163 +        }
  11.164 +
  11.165 +        @Override
  11.166 +        public String toString() {
  11.167 +            if (lookupClass == null)
  11.168 +                return "public";
  11.169 +            return lookupClass.getName();
  11.170 +        }
  11.171 +
  11.172 +        // call this from an entry point method in Lookup with extraFrames=0.
  11.173 +        private static Class<?> getCallerClassAtEntryPoint() {
  11.174 +            final int CALLER_DEPTH = 4;
  11.175 +            // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
  11.176 +            // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
  11.177 +            // Note:  This should be the only use of getCallerClass in this file.
  11.178 +            return Reflection.getCallerClass(CALLER_DEPTH);
  11.179 +        }
  11.180 +
  11.181 +        /**
  11.182 +         * Produce a method handle for a static method.
  11.183 +         * The type of the method handle will be that of the method.
  11.184 +         * The method and all its argument types must be accessible to the lookup class.
  11.185 +         * If the method's class has not yet been initialized, that is done
  11.186 +         * immediately, before the method handle is returned.
  11.187 +         * @param defc the class from which the method is accessed
  11.188 +         * @param name the name of the method
  11.189 +         * @param type the type of the method
  11.190 +         * @return the desired method handle
  11.191 +         * @exception SecurityException <em>TBD</em>
  11.192 +         * @exception NoAccessException if the method does not exist or access checking fails
  11.193 +         */
  11.194 +        public
  11.195 +        MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
  11.196 +            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
  11.197 +            checkStatic(true, method, lookupClass);
  11.198 +            //throw NoSuchMethodException
  11.199 +            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
  11.200 +        }
  11.201 +
  11.202 +        /**
  11.203 +         * Produce a method handle for a virtual method.
  11.204 +         * The type of the method handle will be that of the method,
  11.205 +         * with the receiver type ({@code defc}) prepended.
  11.206 +         * The method and all its argument types must be accessible to the lookup class.
  11.207 +         * <p>
  11.208 +         * When called, the handle will treat the first argument as a receiver
  11.209 +         * and dispatch on the receiver's type to determine which method
  11.210 +         * implementation to enter.
  11.211 +         * (The dispatching action is identical with that performed by an
  11.212 +         * {@code invokevirtual} or {@code invokeinterface} instruction.)
  11.213 +         * @param defc the class or interface from which the method is accessed
  11.214 +         * @param name the name of the method
  11.215 +         * @param type the type of the method, with the receiver argument omitted
  11.216 +         * @return the desired method handle
  11.217 +         * @exception SecurityException <em>TBD</em>
  11.218 +         * @exception NoAccessException if the method does not exist or access checking fails
  11.219 +         */
  11.220 +        public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
  11.221 +            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass);
  11.222 +            checkStatic(false, method, lookupClass);
  11.223 +            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
  11.224 +        }
  11.225 +
  11.226 +        /**
  11.227 +         * Produce an early-bound method handle for a virtual method,
  11.228 +         * or a handle for a constructor, as if called from an {@code invokespecial}
  11.229 +         * instruction from {@code caller}.
  11.230 +         * The type of the method handle will be that of the method or constructor,
  11.231 +         * with a suitably restricted receiver type (such as {@code caller}) prepended.
  11.232 +         * The method or constructor and all its argument types must be accessible
  11.233 +         * to the caller.
  11.234 +         * <p>
  11.235 +         * When called, the handle will treat the first argument as a receiver,
  11.236 +         * but will not dispatch on the receiver's type.
  11.237 +         * (This direct invocation action is identical with that performed by an
  11.238 +         * {@code invokespecial} instruction.)
  11.239 +         * <p>
  11.240 +         * If the explicitly specified caller class is not identical with the
  11.241 +         * lookup class, a security check TBD is performed.
  11.242 +         * @param defc the class or interface from which the method is accessed
  11.243 +         * @param name the name of the method, or "<init>" for a constructor
  11.244 +         * @param type the type of the method, with the receiver argument omitted
  11.245 +         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
  11.246 +         * @return the desired method handle
  11.247 +         * @exception SecurityException <em>TBD</em>
  11.248 +         * @exception NoAccessException if the method does not exist or access checking fails
  11.249 +         */
  11.250 +        public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
  11.251 +                                        Class<?> specialCaller) throws NoAccessException {
  11.252 +            checkSpecialCaller(specialCaller, lookupClass);
  11.253 +            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
  11.254 +            checkStatic(false, method, lookupClass);
  11.255 +            if (name.equals("<init>")) {
  11.256 +                if (defc != specialCaller)
  11.257 +                    throw newNoAccessException("constructor must be local to lookup class", method, lookupClass);
  11.258 +            } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
  11.259 +                throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
  11.260 +            }
  11.261 +            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
  11.262 +        }
  11.263 +
  11.264 +        /**
  11.265 +         * Produce an early-bound method handle for a non-static method.
  11.266 +         * The receiver must have a supertype {@code defc} in which a method
  11.267 +         * of the given name and type is accessible to the lookup class.
  11.268 +         * The method and all its argument types must be accessible to the lookup class.
  11.269 +         * The type of the method handle will be that of the method.
  11.270 +         * The given receiver will be bound into the method handle.
  11.271 +         * <p>
  11.272 +         * Equivalent to the following expression:
  11.273 +         * <code>
  11.274 +         * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
  11.275 +         * </code>
  11.276 +         * @param receiver the object from which the method is accessed
  11.277 +         * @param name the name of the method
  11.278 +         * @param type the type of the method, with the receiver argument omitted
  11.279 +         * @return the desired method handle
  11.280 +         * @exception SecurityException <em>TBD</em>
  11.281 +         * @exception NoAccessException if the method does not exist or access checking fails
  11.282 +         */
  11.283 +        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
  11.284 +            Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
  11.285 +            MemberName reference = new MemberName(rcvc, name, type);
  11.286 +            MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass);
  11.287 +            checkStatic(false, method, lookupClass);
  11.288 +            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
  11.289 +            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
  11.290 +            if (bmh == null)
  11.291 +                throw newNoAccessException(method, lookupClass);
  11.292 +            return bmh;
  11.293 +        }
  11.294 +
  11.295 +        /**
  11.296 +         * Make a direct method handle to <i>m</i>, if the lookup class has permission.
  11.297 +         * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
  11.298 +         * If <i>m</i> is virtual, overriding is respected on every call.
  11.299 +         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
  11.300 +         * The type of the method handle will be that of the method,
  11.301 +         * with the receiver type prepended (but only if it is non-static).
  11.302 +         * If the method's {@code accessible} flag is not set,
  11.303 +         * access checking is performed immediately on behalf of the lookup class.
  11.304 +         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
  11.305 +         * @param m the reflected method
  11.306 +         * @return a method handle which can invoke the reflected method
  11.307 +         * @exception NoAccessException if access checking fails
  11.308 +         */
  11.309 +        public MethodHandle unreflect(Method m) throws NoAccessException {
  11.310 +            return unreflectImpl(new MemberName(m), m.isAccessible(), true, lookupClass);
  11.311 +        }
  11.312 +
  11.313 +        /**
  11.314 +         * Produce a method handle for a reflected method.
  11.315 +         * It will bypass checks for overriding methods on the receiver,
  11.316 +         * as if by the {@code invokespecial} instruction.
  11.317 +         * The type of the method handle will be that of the method,
  11.318 +         * with the receiver type prepended.
  11.319 +         * If the method's {@code accessible} flag is not set,
  11.320 +         * access checking is performed immediately on behalf of the lookup class,
  11.321 +         * as if {@code invokespecial} instruction were being linked.
  11.322 +         * @param m the reflected method
  11.323 +         * @return a method handle which can invoke the reflected method
  11.324 +         * @exception NoAccessException if access checking fails
  11.325 +         */
  11.326 +        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
  11.327 +            checkSpecialCaller(specialCaller, lookupClass);
  11.328 +            MemberName mname = new MemberName(m);
  11.329 +            checkStatic(false, mname, lookupClass);
  11.330 +            return unreflectImpl(mname, m.isAccessible(), false, specialCaller);
  11.331 +        }
  11.332 +
  11.333 +        /**
  11.334 +         * Produce a method handle for a reflected constructor.
  11.335 +         * The type of the method handle will be that of the constructor.
  11.336 +         * The method handle will perform a {@code newInstance} operation,
  11.337 +         * creating a new instance of the constructor's class on the
  11.338 +         * arguments passed to the method handle.
  11.339 +         * <p>
  11.340 +         * If the constructor's {@code accessible} flag is not set,
  11.341 +         * access checking is performed immediately on behalf of the lookup class,
  11.342 +         * as if {@code invokespecial} instruction were being linked.
  11.343 +         * @param ctor the reflected constructor
  11.344 +         * @return a method handle which can invoke the reflected constructor
  11.345 +         * @exception NoAccessException if access checking fails
  11.346 +         */
  11.347 +        public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
  11.348 +            MemberName m = new MemberName(ctor);
  11.349 +            return unreflectImpl(m, ctor.isAccessible(), false, lookupClass);
  11.350 +        }
  11.351 +
  11.352 +        /**
  11.353 +         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.354 +         * Produce a method handle giving read access to a reflected field.
  11.355 +         * The type of the method handle will have a return type of the field's
  11.356 +         * value type.  Its sole argument will be the field's containing class
  11.357 +         * (but only if it is non-static).
  11.358 +         * If the method's {@code accessible} flag is not set,
  11.359 +         * access checking is performed immediately on behalf of the lookup class.
  11.360 +         * @param f the reflected field
  11.361 +         * @return a method handle which can load values from the reflected field
  11.362 +         * @exception NoAccessException if access checking fails
  11.363 +         */
  11.364 +        public MethodHandle unreflectGetter(Field f) throws NoAccessException {
  11.365 +            return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, lookupClass);
  11.366 +        }
  11.367 +
  11.368 +        /**
  11.369 +         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.370 +         * Produce a method handle giving write access to a reflected field.
  11.371 +         * The type of the method handle will have a void return type.
  11.372 +         * Its last argument will be the field's value type.
  11.373 +         * Its other argument will be the field's containing class
  11.374 +         * (but only if it is non-static).
  11.375 +         * If the method's {@code accessible} flag is not set,
  11.376 +         * access checking is performed immediately on behalf of the lookup class.
  11.377 +         * @param f the reflected field
  11.378 +         * @return a method handle which can store values into the reflected field
  11.379 +         * @exception NoAccessException if access checking fails
  11.380 +         */
  11.381 +        public MethodHandle unreflectSetter(Field f) throws NoAccessException {
  11.382 +            return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, lookupClass);
  11.383 +        }
  11.384 +
  11.385 +    }
  11.386 +
  11.387 +    static /*must not be public*/
  11.388 +    MethodHandle findStaticFrom(Class<?> lookupClass,
  11.389 +                                Class<?> defc, String name, MethodType type) throws NoAccessException {
  11.390 +        MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
  11.391 +        checkStatic(true, method, lookupClass);
  11.392 +        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
  11.393 +    }
  11.394 +
  11.395 +    static void checkStatic(boolean wantStatic, MemberName m, Class<?> lookupClass) {
  11.396 +        if (wantStatic != m.isStatic()) {
  11.397 +            String message = wantStatic ? "expected a static method" : "expected a non-static method";
  11.398 +            throw newNoAccessException(message, m, lookupClass);
  11.399 +        }
  11.400 +    }
  11.401 +
  11.402 +    static void checkSpecialCaller(Class<?> specialCaller, Class<?> lookupClass) {
  11.403 +        if (lookupClass == Lookup.IMPL_LOOKUP.lookupClass())
  11.404 +            return;  // privileged action
  11.405 +        if (lookupClass == null ||  // public-only access
  11.406 +            !VerifyAccess.isSamePackageMember(specialCaller, lookupClass))
  11.407 +            throw newNoAccessException("no private access", new MemberName(specialCaller), lookupClass);
  11.408 +    }
  11.409 +
  11.410 +    // Helper for creating handles on reflected methods and constructors.
  11.411 +    static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
  11.412 +                                      boolean doDispatch, Class<?> lookupClass) {
  11.413 +        MethodType mtype = m.getInvocationType();
  11.414 +        Class<?> defc = m.getDeclaringClass();
  11.415 +        int mods = m.getModifiers();
  11.416 +        if (m.isStatic()) {
  11.417 +            if (!isAccessible &&
  11.418 +                    VerifyAccess.isAccessible(defc, mods, false, lookupClass) == null)
  11.419 +                throw newNoAccessException(m, lookupClass);
  11.420 +        } else {
  11.421 +            Class<?> constraint;
  11.422 +            if (isAccessible) {
  11.423 +                // abbreviated access check for "unlocked" method
  11.424 +                constraint = doDispatch ? defc : lookupClass;
  11.425 +            } else {
  11.426 +                constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, lookupClass);
  11.427 +            }
  11.428 +            if (constraint != defc && !constraint.isAssignableFrom(defc)) {
  11.429 +                if (!defc.isAssignableFrom(constraint))
  11.430 +                    throw newNoAccessException("receiver must be in caller class", m, lookupClass);
  11.431 +                mtype = mtype.changeParameterType(0, constraint);
  11.432 +            }
  11.433 +        }
  11.434 +        return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookupClass);
  11.435 +    }
  11.436 +
  11.437 +    /**
  11.438 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.439 +     * Produce a method handle giving read access to elements of an array.
  11.440 +     * The type of the method handle will have a return type of the array's
  11.441 +     * element type.  Its first argument will be the array type,
  11.442 +     * and the second will be {@code int}.
  11.443 +     * @param arrayClass an array type
  11.444 +     * @return a method handle which can load values from the given array type
  11.445 +     * @throws  IllegalArgumentException if arrayClass is not an array type
  11.446 +     */
  11.447 +    public static
  11.448 +    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
  11.449 +        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false);
  11.450 +    }
  11.451 +
  11.452 +    /**
  11.453 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.454 +     * Produce a method handle giving write access to elements of an array.
  11.455 +     * The type of the method handle will have a void return type.
  11.456 +     * Its last argument will be the array's element type.
  11.457 +     * The first and second arguments will be the array type and int.
  11.458 +     * @return a method handle which can store values into the array type
  11.459 +     * @throws IllegalArgumentException if arrayClass is not an array type
  11.460 +     */
  11.461 +    public static
  11.462 +    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
  11.463 +        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
  11.464 +    }
  11.465 +
  11.466 +
  11.467 +    /// method handle invocation (reflective style)
  11.468 +
  11.469 +    /**
  11.470 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.471 +     * Call the {@code invoke} method of a given method handle,
  11.472 +     * with arguments that exactly match the parameter types of the method handle.
  11.473 +     * The length of the arguments array must equal the parameter count
  11.474 +     * of the target's type.
  11.475 +     * The arguments array is spread into separate arguments, and
  11.476 +     * basic reference and unboxing conversions are applied.
  11.477 +     * <p>
  11.478 +     * In order to match the type of the target, the following argument
  11.479 +     * conversions are applied as necessary:
  11.480 +     * <ul>
  11.481 +     * <li>reference casting
  11.482 +     * <li>unboxing
  11.483 +     * </ul>
  11.484 +     * The following conversions are not applied:
  11.485 +     * <ul>
  11.486 +     * <li>primitive conversions (e.g., {@code byte} to {@code int}
  11.487 +     * <li>varargs conversions other than the initial spread
  11.488 +     * <li>any application-specific conversions (e.g., string to number)
  11.489 +     * </ul>
  11.490 +     * The result returned by the call is boxed if it is a primitive,
  11.491 +     * or forced to null if the return type is void.
  11.492 +     * <p>
  11.493 +     * This call is a convenience method for the following code:
  11.494 +     * <pre>
  11.495 +     *   MethodHandle invoker = MethodHandles.genericInvoker(target.type(), 0, true);
  11.496 +     *   Object result = invoker.invoke(arguments);
  11.497 +     * </pre>
  11.498 +     * @param target the method handle to invoke
  11.499 +     * @param arguments the arguments to pass to the target
  11.500 +     * @return the result returned by the target
  11.501 +     */
  11.502 +    public static
  11.503 +    Object invoke(MethodHandle target, Object... arguments) {
  11.504 +        int argc = arguments == null ? 0 : arguments.length;
  11.505 +        MethodType type = target.type();
  11.506 +        if (argc <= 4) {
  11.507 +            MethodHandle invoker = invokers(type).genericInvoker();
  11.508 +            switch (argc) {
  11.509 +                case 0:  return invoker.<Object>invoke(target);
  11.510 +                case 1:  return invoker.<Object>invoke(target,
  11.511 +                                    arguments[0]);
  11.512 +                case 2:  return invoker.<Object>invoke(target,
  11.513 +                                    arguments[0], arguments[1]);
  11.514 +                case 3:  return invoker.<Object>invoke(target,
  11.515 +                                    arguments[0], arguments[1], arguments[2]);
  11.516 +                case 4:  return invoker.<Object>invoke(target,
  11.517 +                                    arguments[0], arguments[1], arguments[2], arguments[3]);
  11.518 +            }
  11.519 +        }
  11.520 +        MethodHandle invoker = invokers(type).varargsInvoker();
  11.521 +        return invoker.<Object>invoke(target, arguments);
  11.522 +    }
  11.523 +
  11.524 +    public static
  11.525 +    Object invoke_0(MethodHandle target) {
  11.526 +        MethodHandle invoker = invokers(target.type()).genericInvoker();
  11.527 +        return invoker.<Object>invoke(target);
  11.528 +    }
  11.529 +    public static
  11.530 +    Object invoke_1(MethodHandle target, Object a0) {
  11.531 +        MethodHandle invoker = invokers(target.type()).genericInvoker();
  11.532 +        return invoker.<Object>invoke(target, a0);
  11.533 +    }
  11.534 +    public static
  11.535 +    Object invoke_2(MethodHandle target, Object a0, Object a1) {
  11.536 +        MethodHandle invoker = invokers(target.type()).genericInvoker();
  11.537 +        return invoker.<Object>invoke(target, a0, a1);
  11.538 +    }
  11.539 +    public static
  11.540 +    Object invoke_3(MethodHandle target, Object a0, Object a1, Object a2) {
  11.541 +        MethodHandle invoker = invokers(target.type()).genericInvoker();
  11.542 +        return invoker.<Object>invoke(target, a0, a1, a2);
  11.543 +    }
  11.544 +    public static
  11.545 +    Object invoke_4(MethodHandle target, Object a0, Object a1, Object a2, Object a3) {
  11.546 +        MethodHandle invoker = invokers(target.type()).genericInvoker();
  11.547 +        return invoker.<Object>invoke(target, a0, a1, a2, a3);
  11.548 +    }
  11.549 +
  11.550 +    /**
  11.551 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.552 +     * Give a method handle which will invoke any method handle of the
  11.553 +     * given type on a standard set of {@code Object} type arguments.
  11.554 +     * The the resulting invoker will be a method handle with the following
  11.555 +     * arguments:
  11.556 +     * <ul>
  11.557 +     * <li>a single {@code MethodHandle} target
  11.558 +     * <li>zero or more {@code Object} values
  11.559 +     * <li>an optional {@code Object[]} array containing more arguments
  11.560 +     * </ul>
  11.561 +     * The invoker will spread the varargs array (if present), apply
  11.562 +     * reference casts as necessary, and unbox primitive arguments.
  11.563 +     * The return value of the invoker will be an {@code Object} reference,
  11.564 +     * boxing a primitive value if the original type returns a primitive,
  11.565 +     * and always null if the original type returns void.
  11.566 +     * <p>
  11.567 +     * This is a convenience method equivalent to the following code:
  11.568 +     * <pre>
  11.569 +     * MethodHandle invoker = exactInvoker(type);
  11.570 +     * MethodType genericType = MethodType.makeGeneric(objectArgCount, varargs);
  11.571 +     * genericType = genericType.insertParameterType(0, MethodHandle.class);
  11.572 +     * if (!varargs)
  11.573 +     *     return convertArguments(invoker, genericType);
  11.574 +     * else
  11.575 +     *     return spreadArguments(invoker, genericType);
  11.576 +     * </pre>
  11.577 +     * @param type the desired target type
  11.578 +     * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
  11.579 +     * @param varargs if true, the invoker will accept a final {@code Object[]} argument
  11.580 +     * @return a method handle suitable for invoking any method handle of the given type
  11.581 +     */
  11.582 +    static public
  11.583 +    MethodHandle genericInvoker(MethodType type, int objectArgCount, boolean varargs) {
  11.584 +        return invokers(type).genericInvoker();
  11.585 +    }
  11.586 +
  11.587 +    /**
  11.588 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.589 +     * Give a method handle which will take a invoke any method handle of the
  11.590 +     * given type.  The resulting invoker will have a type which is
  11.591 +     * exactly equal to the desired type, except that it will accept
  11.592 +     * an additional leading argument of type {@code MethodHandle}.
  11.593 +     * <p>
  11.594 +     * This is a convenience method equivalent to the following code:
  11.595 +     * <pre>
  11.596 +     *     MethodHandles.lookup().findVirtual(MethodHandle.class, "invoke", type);
  11.597 +     * </pre>
  11.598 +     * @param type the desired target type
  11.599 +     * @return a method handle suitable for invoking any method handle of the given type
  11.600 +     */
  11.601 +    static public
  11.602 +    MethodHandle exactInvoker(MethodType type) {
  11.603 +        return invokers(type).exactInvoker();
  11.604 +    }
  11.605 +
  11.606 +    static private Invokers invokers(MethodType type) {
  11.607 +        return MethodTypeImpl.invokers(IMPL_TOKEN, type);
  11.608 +    }
  11.609 +
  11.610 +    /**
  11.611 +     * <em>WORK IN PROGRESS:</em>
  11.612 +     * Perform value checking, exactly as if for an adapted method handle.
  11.613 +     * It is assumed that the given value is either null, of type T0,
  11.614 +     * or (if T0 is primitive) of the wrapper type corresponding to T0.
  11.615 +     * The following checks and conversions are made:
  11.616 +     * <ul>
  11.617 +     * <li>If T0 and T1 are references, then a cast to T1 is applied.
  11.618 +     *     (The types do not need to be related in any particular way.)
  11.619 +     * <li>If T0 and T1 are primitives, then a widening or narrowing
  11.620 +     *     conversion is applied, if one exists.
  11.621 +     * <li>If T0 is a primitive and T1 a reference, and
  11.622 +     *     T0 has a wrapper type TW, a boxing conversion to TW is applied,
  11.623 +     *     possibly followed by a reference conversion.
  11.624 +     *     T1 must be TW or a supertype.
  11.625 +     * <li>If T0 is a reference and T1 a primitive, and
  11.626 +     *     T1 has a wrapper type TW, an unboxing conversion is applied,
  11.627 +     *     possibly preceded by a reference conversion.
  11.628 +     *     T0 must be TW or a supertype.
  11.629 +     * <li>If T1 is void, the return value is discarded
  11.630 +     * <li>If T0 is void and T1 a reference, a null value is introduced.
  11.631 +     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
  11.632 +     * </ul>
  11.633 +     * If the value is discarded, null will be returned.
  11.634 +     * @param valueType
  11.635 +     * @param value
  11.636 +     * @return the value, converted if necessary
  11.637 +     * @throws java.lang.ClassCastException if a cast fails
  11.638 +     */
  11.639 +    static
  11.640 +    <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
  11.641 +       throws ClassCastException
  11.642 +    {
  11.643 +        if (t0 == t1) {
  11.644 +            // no conversion needed; just reassert the same type
  11.645 +            if (t0.isPrimitive())
  11.646 +                return Wrapper.asPrimitiveType(t1).cast(value);
  11.647 +            else
  11.648 +                return Wrapper.OBJECT.cast(value, t1);
  11.649 +        }
  11.650 +        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
  11.651 +        if (!prim0) {
  11.652 +            // check contract with caller
  11.653 +            Wrapper.OBJECT.cast(value, t0);
  11.654 +            if (!prim1) {
  11.655 +                return Wrapper.OBJECT.cast(value, t1);
  11.656 +            }
  11.657 +            // convert reference to primitive by unboxing
  11.658 +            Wrapper w1 = Wrapper.forPrimitiveType(t1);
  11.659 +            return w1.cast(value, t1);
  11.660 +        }
  11.661 +        // check contract with caller:
  11.662 +        Wrapper.asWrapperType(t0).cast(value);
  11.663 +        Wrapper w1 = Wrapper.forPrimitiveType(t1);
  11.664 +        return w1.cast(value, t1);
  11.665 +    }
  11.666 +
  11.667 +    static
  11.668 +    Object checkValue(Class<?> T1, Object value)
  11.669 +       throws ClassCastException
  11.670 +    {
  11.671 +        Class<?> T0;
  11.672 +        if (value == null)
  11.673 +            T0 = Object.class;
  11.674 +        else
  11.675 +            T0 = value.getClass();
  11.676 +        return checkValue(T0, T1, value);
  11.677 +    }
  11.678 +
  11.679 +    /// method handle modification (creation from other method handles)
  11.680 +
  11.681 +    /**
  11.682 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.683 +     * Produce a method handle which adapts the type of the
  11.684 +     * given method handle to a new type, by pairwise argument conversion,
  11.685 +     * and/or varargs conversion.
  11.686 +     * The original type and new type must have the same number of
  11.687 +     * arguments, or else one or both them the must be varargs types.
  11.688 +     * The resulting method handle is guaranteed to confess a type
  11.689 +     * which is equal to the desired new type, with any varargs property erased.
  11.690 +     * <p>
  11.691 +     * If the original type and new type are equal, returns target.
  11.692 +     * <p>
  11.693 +     * The following conversions are applied as needed both to
  11.694 +     * arguments and return types.  Let T0 and T1 be the differing
  11.695 +     * new and old parameter types (or old and new return types)
  11.696 +     * for corresponding values passed by the new and old method types.
  11.697 +     * <p>
  11.698 +     * If an ordinary (non-varargs) parameter of the new type is
  11.699 +     * to be boxed in a varargs parameter of the old type of type T1[],
  11.700 +     * then T1 is the element type of the varargs array.
  11.701 +     * Otherwise, if a varargs parameter of the new type of type T0[]
  11.702 +     * is to be spread into one or more outgoing old type parameters,
  11.703 +     * then T0 is the element type of the
  11.704 +     * If the new type is varargs and the old type is not, the varargs
  11.705 +     * argument will be checked and must be a non-null array of exactly
  11.706 +     * the right length.  If there are no parameters in the old type
  11.707 +     * corresponding to the new varargs parameter, the varargs argument
  11.708 +     * is also allowed to be null.
  11.709 +     * <p>
  11.710 +     * Given those types T0, T1, one of the following conversions is applied
  11.711 +     * if possible:
  11.712 +     * <ul>
  11.713 +     * <li>If T0 and T1 are references, then a cast to T2 is applied,
  11.714 +     *     where T2 is Object if T1 is an interface, else T1.
  11.715 +     *     (The types do not need to be related in any particular way.
  11.716 +     *     The treatment of interfaces follows the usage of the bytecode verifier.)
  11.717 +     * <li>If T0 and T1 are primitives, then a Java casting
  11.718 +     *     conversion (JLS 5.5) is applied, if one exists.
  11.719 +     * <li>If T0 and T1 are primitives and one is boolean,
  11.720 +     *     the boolean is treated as a one-bit unsigned integer.
  11.721 +     *     (This treatment follows the usage of the bytecode verifier.)
  11.722 +     *     A conversion from another primitive type behaves as if
  11.723 +     *     it first converts to byte, and then masks all but the low bit.
  11.724 +     * <li>If T0 is a primitive and T1 a reference, a boxing
  11.725 +     *     conversion is applied if one exists, possibly followed by
  11.726 +     *     an reference conversion to a superclass.
  11.727 +     *     T1 must be a wrapper class or a supertype of one.
  11.728 +     *     If T1 is a wrapper class, T0 is converted if necessary
  11.729 +     *     to T1's primitive type by one of the preceding conversions.
  11.730 +     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
  11.731 +     * <li>If T0 is a reference and T1 a primitive, an unboxing
  11.732 +     *     conversion is applied if one exists, possibly preceded by
  11.733 +     *     a reference conversion to a wrapper class.
  11.734 +     *     T0 must be a wrapper class or a supertype of one.
  11.735 +     *     If T0 is a wrapper class, its primitive value is converted
  11.736 +     *     if necessary to T1 by one of the preceding conversions.
  11.737 +     *     Otherwise, T0 is converted directly to the wrapper type for T1,
  11.738 +     *     which is then unboxed.
  11.739 +     * <li>If T1 is void, any returned value is discarded
  11.740 +     * <li>If T0 is void and T1 a reference, a null value is introduced.
  11.741 +     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
  11.742 +     * </ul>
  11.743 +     * @param target the method handle to invoke after arguments are retyped
  11.744 +     * @param newType the expected type of the new method handle
  11.745 +     * @return a method handle which delegates to {@code target} after performing
  11.746 +     *           any necessary argument conversions, and arranges for any
  11.747 +     *           necessary return value conversions
  11.748 +     * @throws WrongMethodTypeException if the conversion cannot be made
  11.749 +     */
  11.750 +    public static
  11.751 +    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
  11.752 +        MethodType oldType = target.type();
  11.753 +        if (oldType.equals(newType))
  11.754 +            return target;
  11.755 +        MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
  11.756 +                                                 newType, oldType, null);
  11.757 +        if (res == null)
  11.758 +            throw newIllegalArgumentException("cannot convert to "+newType+": "+target);
  11.759 +        return res;
  11.760 +    }
  11.761 +
  11.762 +    /**
  11.763 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.764 +     * Produce a method handle which adapts the calling sequence of the
  11.765 +     * given method handle to a new type, by reordering the arguments.
  11.766 +     * The resulting method handle is guaranteed to confess a type
  11.767 +     * which is equal to the desired new type.
  11.768 +     * <p>
  11.769 +     * The given array controls the reordering.
  11.770 +     * Call {@code #I} the number of incoming parameters (the value
  11.771 +     * {@code newType.parameterCount()}, and call {@code #O} the number
  11.772 +     * of outgoing parameters (the value {@code target.type().parameterCount()}).
  11.773 +     * Then the length of the reordering array must be {@code #O},
  11.774 +     * and each element must be a non-negative number less than {@code #I}.
  11.775 +     * For every {@code N} less than {@code #O}, the {@code N}-th
  11.776 +     * outgoing argument will be taken from the {@code I}-th incoming
  11.777 +     * argument, where {@code I} is {@code reorder[N]}.
  11.778 +     * <p>
  11.779 +     * The reordering array need not specify an actual permutation.
  11.780 +     * An incoming argument will be duplicated if its index appears
  11.781 +     * more than once in the array, and an incoming argument will be dropped
  11.782 +     * if its index does not appear in the array.
  11.783 +     * <p>
  11.784 +     * Pairwise conversions are applied as needed to arguments and return
  11.785 +     * values, as with {@link #convertArguments}.
  11.786 +     * @param target the method handle to invoke after arguments are reordered
  11.787 +     * @param newType the expected type of the new method handle
  11.788 +     * @param reorder a string which controls the reordering
  11.789 +     * @return a method handle which delegates to {@code target} after performing
  11.790 +     *           any necessary argument motion and conversions, and arranges for any
  11.791 +     *           necessary return value conversions
  11.792 +     */
  11.793 +    public static
  11.794 +    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) {
  11.795 +        MethodType oldType = target.type();
  11.796 +        checkReorder(reorder, newType, oldType);
  11.797 +        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
  11.798 +                                                 newType, oldType,
  11.799 +                                                 reorder);
  11.800 +    }
  11.801 +
  11.802 +    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
  11.803 +        if (reorder.length == oldType.parameterCount()) {
  11.804 +            int limit = newType.parameterCount();
  11.805 +            boolean bad = false;
  11.806 +            for (int i : reorder) {
  11.807 +                if (i < 0 || i >= limit) {
  11.808 +                    bad = true; break;
  11.809 +                }
  11.810 +            }
  11.811 +            if (!bad)  return;
  11.812 +        }
  11.813 +        throw newIllegalArgumentException("bad reorder array");
  11.814 +    }
  11.815 +
  11.816 +    /**
  11.817 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.818 +     * Produce a method handle which adapts the type of the
  11.819 +     * given method handle to a new type, by spreading the final argument.
  11.820 +     * The resulting method handle is guaranteed to confess a type
  11.821 +     * which is equal to the desired new type.
  11.822 +     * <p>
  11.823 +     * The final parameter type of the new type must be an array type T[].
  11.824 +     * This is the type of what is called the <i>spread</i> argument.
  11.825 +     * All other arguments of the new type are called <i>ordinary</i> arguments.
  11.826 +     * <p>
  11.827 +     * The ordinary arguments of the new type are pairwise converted
  11.828 +     * to the initial parameter types of the old type, according to the
  11.829 +     * rules in {@link #convertArguments}.
  11.830 +     * Any additional arguments in the old type
  11.831 +     * are converted from the array element type T,
  11.832 +     * again according to the rules in {@link #convertArguments}.
  11.833 +     * The return value is converted according likewise.
  11.834 +     * <p>
  11.835 +     * The call verifies that the spread argument is in fact an array
  11.836 +     * of exactly the type length, i.e., the excess number of
  11.837 +     * arguments in the old type over the ordinary arguments in the new type.
  11.838 +     * If there are no excess arguments, the spread argument is also
  11.839 +     * allowed to be null.
  11.840 +     * @param target the method handle to invoke after the argument is prepended
  11.841 +     * @param newType the expected type of the new method handle
  11.842 +     * @return a new method handle which spreads its final argument,
  11.843 +     *         before calling the original method handle
  11.844 +     */
  11.845 +    public static
  11.846 +    MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
  11.847 +        MethodType oldType = target.type();
  11.848 +        int inargs  = newType.parameterCount();
  11.849 +        int outargs = oldType.parameterCount();
  11.850 +        int spreadPos = inargs - 1;
  11.851 +        int numSpread = (outargs - spreadPos);
  11.852 +        MethodHandle res = null;
  11.853 +        if (spreadPos >= 0 && numSpread >= 0) {
  11.854 +            res = MethodHandleImpl.spreadArguments(IMPL_TOKEN, target, newType, spreadPos);
  11.855 +        }
  11.856 +        if (res == null) {
  11.857 +            throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
  11.858 +        }
  11.859 +        return res;
  11.860 +    }
  11.861 +
  11.862 +    /**
  11.863 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.864 +     * Produce a method handle which adapts the type of the
  11.865 +     * given method handle to a new type, by collecting a series of
  11.866 +     * trailing arguments into an array.
  11.867 +     * The resulting method handle is guaranteed to confess a type
  11.868 +     * which is equal to the desired new type.
  11.869 +     * <p>
  11.870 +     * This method is inverse to {@link #spreadArguments}.
  11.871 +     * The final parameter type of the old type must be an array type T[],
  11.872 +     * which is the type of what is called the <i>spread</i> argument.
  11.873 +     * The trailing arguments of the new type which correspond to
  11.874 +     * the spread argument are all converted to type T and collected
  11.875 +     * into an array before the original method is called.
  11.876 +     * <p>
  11.877 +     * ISSUE: Unify this with combineArguments.  CollectArguments
  11.878 +     * is combineArguments with (a) new Object[]{...} as a combiner,
  11.879 +     * and (b) the combined arguments dropped, in favor of the combined result.
  11.880 +     * @param target the method handle to invoke after the argument is prepended
  11.881 +     * @param newType the expected type of the new method handle
  11.882 +     * @return a new method handle which collects some trailings argument
  11.883 +     *         into an array, before calling the original method handle
  11.884 +     */
  11.885 +    public static
  11.886 +    MethodHandle collectArguments(MethodHandle target, MethodType newType) {
  11.887 +        MethodType oldType = target.type();
  11.888 +        int inargs  = newType.parameterCount();
  11.889 +        int outargs = oldType.parameterCount();
  11.890 +        int collectPos = outargs - 1;
  11.891 +        int numCollect = (inargs - collectPos);
  11.892 +        if (collectPos < 0 || numCollect < 0)
  11.893 +            throw newIllegalArgumentException("wrong number of arguments");
  11.894 +        return MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos);
  11.895 +    }
  11.896 +
  11.897 +    /**
  11.898 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.899 +     * Produce a method handle which calls the original method handle,
  11.900 +     * after inserting the given argument at the given position.
  11.901 +     * The type of the new method handle will drop the corresponding argument
  11.902 +     * type from the original handle's type.
  11.903 +     * <p>
  11.904 +     * The given argument object must match the dropped argument type.
  11.905 +     * If the dropped argument type is a primitive, the argument object
  11.906 +     * must be a wrapper, and is unboxed to produce the primitive.
  11.907 +     * <p>
  11.908 +     * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
  11.909 +     * where <i>N</i> is the number of argument types in <i>target</i>,
  11.910 +     * meaning to insert the new argument as the first or last (respectively),
  11.911 +     * or somewhere in between.
  11.912 +     * @param target the method handle to invoke after the argument is inserted
  11.913 +     * @param pos where to insert the argument (zero for the first)
  11.914 +     * @param value the argument to insert
  11.915 +     * @return a new method handle which inserts an additional argument,
  11.916 +     *         before calling the original method handle
  11.917 +     */
  11.918 +    public static
  11.919 +    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
  11.920 +        MethodType oldType = target.type();
  11.921 +        ArrayList<Class<?>> ptypes =
  11.922 +                new ArrayList<Class<?>>(oldType.parameterList());
  11.923 +        int outargs = oldType.parameterCount();
  11.924 +        int inargs  = outargs - 1;
  11.925 +        if (pos < 0 || pos >= outargs)
  11.926 +            throw newIllegalArgumentException("no argument type to append");
  11.927 +        Class<?> valueType = ptypes.remove(pos);
  11.928 +        value = checkValue(valueType, value);
  11.929 +        if (pos == 0 && !valueType.isPrimitive()) {
  11.930 +            // At least for now, make bound method handles a special case.
  11.931 +            // This lets us get by with minimal JVM support, at the expense
  11.932 +            // of generating signature-specific adapters as Java bytecodes.
  11.933 +            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
  11.934 +            if (bmh != null)  return bmh;
  11.935 +            // else fall through to general adapter machinery
  11.936 +        }
  11.937 +        return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
  11.938 +    }
  11.939 +
  11.940 +    /**
  11.941 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.942 +     * Produce a method handle which calls the original method handle,
  11.943 +     * after dropping the given argument(s) at the given position.
  11.944 +     * The type of the new method handle will insert the given argument
  11.945 +     * type(s), at that position, into the original handle's type.
  11.946 +     * <p>
  11.947 +     * The <i>pos</i> may range between zero and <i>N-1</i>,
  11.948 +     * where <i>N</i> is the number of argument types in <i>target</i>,
  11.949 +     * meaning to drop the first or last argument (respectively),
  11.950 +     * or an argument somewhere in between.
  11.951 +     * @param target the method handle to invoke after the argument is dropped
  11.952 +     * @param valueTypes the type(s) of the argument to drop
  11.953 +     * @param pos which argument to drop (zero for the first)
  11.954 +     * @return a new method handle which drops an argument of the given type,
  11.955 +     *         before calling the original method handle
  11.956 +     */
  11.957 +    public static
  11.958 +    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
  11.959 +        if (valueTypes.length == 0)  return target;
  11.960 +        MethodType oldType = target.type();
  11.961 +        int outargs = oldType.parameterCount();
  11.962 +        int inargs  = outargs + valueTypes.length;
  11.963 +        if (pos < 0 || pos >= inargs)
  11.964 +            throw newIllegalArgumentException("no argument type to remove");
  11.965 +        ArrayList<Class<?>> ptypes =
  11.966 +                new ArrayList<Class<?>>(oldType.parameterList());
  11.967 +        ptypes.addAll(pos, Arrays.asList(valueTypes));
  11.968 +        MethodType newType = MethodType.make(oldType.returnType(), ptypes);
  11.969 +        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
  11.970 +    }
  11.971 +
  11.972 +    /**
  11.973 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  11.974 +     * Make a method handle which adapts a target method handle,
  11.975 +     * by guarding it with a test, a boolean-valued method handle.
  11.976 +     * If the guard fails, a fallback handle is called instead.
  11.977 +     * All three method handles must have the same corresponding
  11.978 +     * argument and return types, except that the return type
  11.979 +     * of the test must be boolean.
  11.980 +     * <p> Here is pseudocode for the resulting adapter:
  11.981 +     * <blockquote><pre>
  11.982 +     * signature T(A...);
  11.983 +     * boolean test(A...);
  11.984 +     * T target(A...);
  11.985 +     * T fallback(A...);
  11.986 +     * T adapter(A... a) {
  11.987 +     *   if (test(a...))
  11.988 +     *     return target(a...);
  11.989 +     *   else
  11.990 +     *     return fallback(a...);
  11.991 +     * }
  11.992 +     * </pre></blockquote>
  11.993 +     * @param test method handle used for test, must return boolean
  11.994 +     * @param target method handle to call if test passes
  11.995 +     * @param fallback method handle to call if test fails
  11.996 +     * @return method handle which incorporates the specified if/then/else logic
  11.997 +     * @throws IllegalArgumentException if {@code test} does not return boolean,
  11.998 +     *          or if all three method types do not match (with the return
  11.999 +     *          type of {@code test} changed to match that of {@code target}).
 11.1000 +     */
 11.1001 +    public static
 11.1002 +    MethodHandle guardWithTest(MethodHandle test,
 11.1003 +                               MethodHandle target,
 11.1004 +                               MethodHandle fallback) {
 11.1005 +        if (target.type() != fallback.type())
 11.1006 +            throw newIllegalArgumentException("target and fallback types do not match");
 11.1007 +        if (target.type().changeReturnType(boolean.class) != test.type())
 11.1008 +            throw newIllegalArgumentException("target and test types do not match");
 11.1009 +        /* {
 11.1010 +            MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
 11.1011 +            static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
 11.1012 +                return z ? t : f;
 11.1013 +            }
 11.1014 +            static MethodHandle compose(MethodHandle f, MethodHandle g) {
 11.1015 +                Class<?> initargs = g.type().parameterArray();
 11.1016 +                f = dropArguments(f, 1, initargs);  // ignore 2nd copy of args
 11.1017 +                return combineArguments(f, g);
 11.1018 +            }
 11.1019 +            // choose = \z.(z ? target : fallback)
 11.1020 +            MethodHandle choose = findVirtual(MethodHandles.class, "choose",
 11.1021 +                    MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
 11.1022 +            choose = appendArgument(choose, target);
 11.1023 +            choose = appendArgument(choose, fallback);
 11.1024 +            MethodHandle dispatch = compose(choose, test);
 11.1025 +            // dispatch = \(a...).(test(a...) ? target : fallback)
 11.1026 +            return combineArguments(invoke, dispatch, 0);
 11.1027 +            // return \(a...).((test(a...) ? target : fallback).invoke(a...))
 11.1028 +        } */
 11.1029 +        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
 11.1030 +    }
 11.1031 +
 11.1032 +    /**
 11.1033 +     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
 11.1034 +     * Adapt a target method handle {@code target} by first processing
 11.1035 +     * its arguments, and then calling the target.
 11.1036 +     * The initial processing is performed by a second method handle, the {@code combiner}.
 11.1037 +     * After this, control passes to the {@code target}, with the same arguments.
 11.1038 +     * <p>
 11.1039 +     * The return value of the {@code combiner} is inserted into the argument list
 11.1040 +     * for the {@code target} at the indicated position {@code pos}, if it is non-negative.
 11.1041 +     * Except for this inserted argument (if any), the argument types of
 11.1042 +     * the target {@code target} and the {@code combiner} must be identical.
 11.1043 +     * <p>
 11.1044 +     * (Note that {@link #dropArguments} can be used to remove any arguments
 11.1045 +     * that either the {@code combiner} or {@code target} does not wish to receive.)
 11.1046 +     * <p>
 11.1047 +     * The combiner handle must have the same argument types as the
 11.1048 +     * target handle, but must return {@link MethodHandle} instead of
 11.1049 +     * the ultimate return type.  The returned method handle, in turn,
 11.1050 +     * is required to have exactly the given final method type.
 11.1051 +     * <p> Here is pseudocode for the resulting adapter:
 11.1052 +     * <blockquote><pre>
 11.1053 +     * signature V(A[pos]..., B...);
 11.1054 +     * signature T(A[pos]..., V, B...);
 11.1055 +     * T target(A... a, V v, B... b);
 11.1056 +     * V combiner(A..., B...);
 11.1057 +     * T adapter(A... a, B... b) {
 11.1058 +     *   V v = combiner(a..., b...);
 11.1059 +     *   return target(a..., v, b...);
 11.1060 +     * }
 11.1061 +     * </pre></blockquote>
 11.1062 +     * @param target the method handle to invoke after arguments are combined
 11.1063 +     * @param pos where the return value of {@code combiner} is to
 11.1064 +     *          be inserted as an argument to {@code target}
 11.1065 +     * @param combiner method handle to call initially on the incoming arguments
 11.1066 +     * @return method handle which incorporates the specified dispatch logic
 11.1067 +     * @throws IllegalArgumentException if {@code combiner} does not itself
 11.1068 +     *          return either void or the {@code pos}-th argument of {@code target},
 11.1069 +     *          or does not have the same argument types as {@code target}
 11.1070 +     *          (minus the inserted argument)
 11.1071 +     */
 11.1072 +    public static
 11.1073 +    MethodHandle combineArguments(MethodHandle target, int pos, MethodHandle combiner) {
 11.1074 +        MethodType mhType = target.type();
 11.1075 +        Class<?> combineType = combiner.type().returnType();
 11.1076 +        MethodType incomingArgs;
 11.1077 +        if (pos < 0) {
 11.1078 +            // No inserted argument; target & combiner must have same argument types.
 11.1079 +            incomingArgs = mhType;
 11.1080 +            if (!incomingArgs.changeReturnType(combineType).equals(combiner.type()))
 11.1081 +                throw newIllegalArgumentException("target and combiner types do not match");
 11.1082 +        } else {
 11.1083 +            // Inserted argument.
 11.1084 +            if (pos >= mhType.parameterCount()
 11.1085 +                || mhType.parameterType(pos) != combineType)
 11.1086 +                throw newIllegalArgumentException("inserted combiner argument does not match target");
 11.1087 +            incomingArgs = mhType.dropParameterType(pos);
 11.1088 +        }
 11.1089 +        if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) {
 11.1090 +            throw newIllegalArgumentException("target and combiner types do not match");
 11.1091 +        }
 11.1092 +        return MethodHandleImpl.combineArguments(IMPL_TOKEN, target, combiner, pos);
 11.1093 +    }
 11.1094 +
 11.1095 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/share/classes/java/dyn/MethodType.java	Thu May 07 12:26:22 2009 -0700
    12.3 @@ -0,0 +1,575 @@
    12.4 +/*
    12.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.  Sun designates this
   12.11 + * particular file as subject to the "Classpath" exception as provided
   12.12 + * by Sun in the LICENSE file that accompanied this code.
   12.13 + *
   12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.17 + * version 2 for more details (a copy is included in the LICENSE file that
   12.18 + * accompanied this code).
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License version
   12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.23 + *
   12.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   12.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   12.26 + * have any questions.
   12.27 + */
   12.28 +
   12.29 +package java.dyn;
   12.30 +
   12.31 +import java.util.Arrays;
   12.32 +import java.util.Collections;
   12.33 +import java.util.HashMap;
   12.34 +import java.util.List;
   12.35 +import sun.dyn.Access;
   12.36 +import sun.dyn.Invokers;
   12.37 +import sun.dyn.MethodTypeImpl;
   12.38 +import sun.dyn.util.BytecodeSignature;
   12.39 +import static sun.dyn.MemberName.newIllegalArgumentException;
   12.40 +
   12.41 +/**
   12.42 + * Run-time token used to match call sites with method handles.
   12.43 + * The structure is a return type accompanied by any number of parameter types.
   12.44 + * The types (primitive, void, and reference) are represented by Class objects.
   12.45 + * All instances of <code>MethodType</code> are immutable.
   12.46 + * Two instances are completely interchangeable if they compare equal.
   12.47 + * Equality depends exactly on the return and parameter types.
   12.48 + * <p>
   12.49 + * This type can be created only by factory methods, which manage interning.
   12.50 + *
   12.51 + * @author John Rose, JSR 292 EG
   12.52 + */
   12.53 +public final
   12.54 +class MethodType {
   12.55 +    private final Class<?>   rtype;
   12.56 +    private final Class<?>[] ptypes;
   12.57 +    private MethodTypeForm form; // erased form, plus cached data about primitives
   12.58 +    private MethodType wrapAlt;  // alternative wrapped/unwrapped version
   12.59 +    private Invokers invokers;   // cache of handy higher-order adapters
   12.60 +
   12.61 +    private static final Access IMPL_TOKEN = Access.getToken();
   12.62 +
   12.63 +    // share a cache with a friend in this package
   12.64 +    Invokers getInvokers() { return invokers; }
   12.65 +    void setInvokers(Invokers inv) { invokers = inv; }
   12.66 +
   12.67 +    static {
   12.68 +        // This hack allows the implementation package special access to
   12.69 +        // the internals of MethodType.  In particular, the Form has all sorts
   12.70 +        // of cached information useful to the implementation code.
   12.71 +        MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() {
   12.72 +            public Class<?>[] ptypes(MethodType mt)        { return mt.ptypes; }
   12.73 +            public MethodTypeImpl form(MethodType mt)      { return mt.form; }
   12.74 +            public void setForm(MethodType mt, MethodTypeImpl form) {
   12.75 +                assert(mt.form == null);
   12.76 +                mt.form = (MethodTypeForm) form;
   12.77 +            }
   12.78 +            public MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   12.79 +                return MethodType.makeImpl(rtype, ptypes, trusted);
   12.80 +            }
   12.81 +            public MethodTypeImpl newMethodTypeForm(MethodType mt) {
   12.82 +                return new MethodTypeForm(mt);
   12.83 +            }
   12.84 +            public Invokers getInvokers(MethodType mt)    { return mt.invokers; }
   12.85 +            public void setInvokers(MethodType mt, Invokers inv) { mt.invokers = inv; }
   12.86 +        });
   12.87 +    }
   12.88 +
   12.89 +    private MethodType(Class<?> rtype, Class<?>[] ptypes) {
   12.90 +        checkRtype(rtype);
   12.91 +        checkPtypes(ptypes);
   12.92 +        this.rtype = rtype;
   12.93 +        this.ptypes = ptypes;
   12.94 +    }
   12.95 +
   12.96 +    private void checkRtype(Class<?> rtype) {
   12.97 +        rtype.equals(rtype);  // null check
   12.98 +    }
   12.99 +    private void checkPtypes(Class<?>[] ptypes) {
  12.100 +        for (Class<?> ptype : ptypes) {
  12.101 +            ptype.equals(ptype);  // null check
  12.102 +            if (ptype == void.class)
  12.103 +                throw newIllegalArgumentException("void parameter: "+this);
  12.104 +        }
  12.105 +    }
  12.106 +
  12.107 +    static final HashMap<MethodType,MethodType> internTable
  12.108 +            = new HashMap<MethodType, MethodType>();
  12.109 +
  12.110 +    static final Class<?>[] NO_PTYPES = {};
  12.111 +
  12.112 +    /** Find or create an instance of the given method type.
  12.113 +     * @param rtype  the return type
  12.114 +     * @param ptypes the parameter types
  12.115 +     * @return the interned method type with the given parts
  12.116 +     * @throws NullPointerException if rtype or any ptype is null
  12.117 +     * @throws IllegalArgumentException if any of the ptypes is void
  12.118 +     */
  12.119 +    public static
  12.120 +    MethodType make(Class<?> rtype, Class<?>[] ptypes) {
  12.121 +        return makeImpl(rtype, ptypes, false);
  12.122 +    }
  12.123 +
  12.124 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. */
  12.125 +    public static
  12.126 +    MethodType make(Class<?> rtype, List<? extends Class<?>> ptypes) {
  12.127 +        return makeImpl(rtype, ptypes.toArray(NO_PTYPES), true);
  12.128 +    }
  12.129 +
  12.130 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.131 +     *  The leading parameter type is prepended to the remaining array.
  12.132 +     */
  12.133 +    public static
  12.134 +    MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
  12.135 +        Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
  12.136 +        ptypes1[0] = ptype0;
  12.137 +        System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
  12.138 +        return makeImpl(rtype, ptypes1, true);
  12.139 +    }
  12.140 +
  12.141 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.142 +     *  The resulting method has no parameter types.
  12.143 +     */
  12.144 +    public static
  12.145 +    MethodType make(Class<?> rtype) {
  12.146 +        return makeImpl(rtype, NO_PTYPES, true);
  12.147 +    }
  12.148 +
  12.149 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.150 +     *  The resulting method has the single given parameter type.
  12.151 +     */
  12.152 +    public static
  12.153 +    MethodType make(Class<?> rtype, Class<?> ptype0) {
  12.154 +        return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
  12.155 +    }
  12.156 +
  12.157 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.158 +     *  The resulting method has the same parameter types as {@code ptypes},
  12.159 +     *  and the specified return type.
  12.160 +     */
  12.161 +    public static
  12.162 +    MethodType make(Class<?> rtype, MethodType ptypes) {
  12.163 +        return makeImpl(rtype, ptypes.ptypes, true);
  12.164 +    }
  12.165 +
  12.166 +    /**
  12.167 +     * Sole factory method to find or create an interned method type.
  12.168 +     * @param rtype desired return type
  12.169 +     * @param ptypes desired parameter types
  12.170 +     * @param trusted whether the ptypes can be used without cloning
  12.171 +     * @return the unique method type of the desired structure
  12.172 +     */
  12.173 +    private static
  12.174 +    MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
  12.175 +        if (ptypes == null || ptypes.length == 0) {
  12.176 +            ptypes = NO_PTYPES; trusted = true;
  12.177 +        }
  12.178 +        MethodType mt1 = new MethodType(rtype, ptypes);
  12.179 +        MethodType mt0;
  12.180 +        synchronized (internTable) {
  12.181 +            mt0 = internTable.get(mt1);
  12.182 +            if (mt0 != null)
  12.183 +                return mt0;
  12.184 +        }
  12.185 +        if (!trusted)
  12.186 +            // defensively copy the array passed in by the user
  12.187 +            mt1 = new MethodType(rtype, ptypes.clone());
  12.188 +        // promote the object to the Real Thing, and reprobe
  12.189 +        MethodTypeImpl.initForm(IMPL_TOKEN, mt1);
  12.190 +        synchronized (internTable) {
  12.191 +            mt0 = internTable.get(mt1);
  12.192 +            if (mt0 != null)
  12.193 +                return mt0;
  12.194 +            internTable.put(mt1, mt1);
  12.195 +        }
  12.196 +        return mt1;
  12.197 +    }
  12.198 +
  12.199 +    // Entry point from JVM.  TODO: Change the name & signature.
  12.200 +    private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes,
  12.201 +            boolean ignore1, boolean ignore2) {
  12.202 +        return makeImpl(rtype, ptypes, true);
  12.203 +    }
  12.204 +
  12.205 +    private static final MethodType[] objectOnlyTypes = new MethodType[20];
  12.206 +
  12.207 +    /**
  12.208 +     * Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
  12.209 +     * All parameters and the return type will be Object, except the final varargs parameter if any.
  12.210 +     * @param objectArgCount number of parameters (excluding the varargs parameter if any)
  12.211 +     * @param varargs whether there will be a varargs parameter, of type Object[]
  12.212 +     * @return a totally generic method type, given only its count of parameters and varargs
  12.213 +     * @see #makeGeneric(int)
  12.214 +     */
  12.215 +    public static
  12.216 +    MethodType makeGeneric(int objectArgCount, boolean varargs) {
  12.217 +        MethodType mt;
  12.218 +        int ivarargs = (!varargs ? 0 : 1);
  12.219 +        int ootIndex = objectArgCount*2 + ivarargs;
  12.220 +        if (ootIndex < objectOnlyTypes.length) {
  12.221 +            mt = objectOnlyTypes[ootIndex];
  12.222 +            if (mt != null)  return mt;
  12.223 +        }
  12.224 +        Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
  12.225 +        Arrays.fill(ptypes, Object.class);
  12.226 +        if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
  12.227 +        mt = makeImpl(Object.class, ptypes, true);
  12.228 +        if (ootIndex < objectOnlyTypes.length) {
  12.229 +            objectOnlyTypes[ootIndex] = mt;     // cache it here also!
  12.230 +        }
  12.231 +        return mt;
  12.232 +    }
  12.233 +
  12.234 +    /**
  12.235 +     * All parameters and the return type will be Object.
  12.236 +     * @param objectArgCount number of parameters
  12.237 +     * @return a totally generic method type, given only its count of parameters
  12.238 +     * @see #makeGeneric(int, boolean)
  12.239 +     */
  12.240 +    public static
  12.241 +    MethodType makeGeneric(int objectArgCount) {
  12.242 +        return makeGeneric(objectArgCount, false);
  12.243 +    }
  12.244 +
  12.245 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
  12.246 +     * @param num    the index (zero-based) of the parameter type to change
  12.247 +     * @param nptype a new parameter type to replace the old one with
  12.248 +     * @return the same type, except with the selected parameter changed
  12.249 +     */
  12.250 +    public MethodType changeParameterType(int num, Class<?> nptype) {
  12.251 +        if (parameterType(num) == nptype)  return this;
  12.252 +        Class<?>[] nptypes = ptypes.clone();
  12.253 +        nptypes[num] = nptype;
  12.254 +        return makeImpl(rtype, nptypes, true);
  12.255 +    }
  12.256 +
  12.257 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
  12.258 +     * @param num    the position (zero-based) of the inserted parameter type
  12.259 +     * @param nptype a new parameter type to insert into the parameter list
  12.260 +     * @return the same type, except with the selected parameter inserted
  12.261 +     */
  12.262 +    public MethodType insertParameterType(int num, Class<?> nptype) {
  12.263 +        int len = ptypes.length;
  12.264 +        Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1);
  12.265 +        System.arraycopy(nptypes, num, nptypes, num+1, len-num);
  12.266 +        nptypes[num] = nptype;
  12.267 +        return makeImpl(rtype, nptypes, true);
  12.268 +    }
  12.269 +
  12.270 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
  12.271 +     * @param num    the index (zero-based) of the parameter type to remove
  12.272 +     * @return the same type, except with the selected parameter removed
  12.273 +     */
  12.274 +    public MethodType dropParameterType(int num) {
  12.275 +        int len = ptypes.length;
  12.276 +        Class<?>[] nptypes;
  12.277 +        if (num == 0) {
  12.278 +            nptypes = Arrays.copyOfRange(ptypes, 1, len);
  12.279 +        } else {
  12.280 +            nptypes = Arrays.copyOfRange(ptypes, 0, len-1);
  12.281 +            System.arraycopy(ptypes, num+1, nptypes, num, (len-1)-num);
  12.282 +        }
  12.283 +        return makeImpl(rtype, nptypes, true);
  12.284 +    }
  12.285 +
  12.286 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}.
  12.287 +     * @param nrtype a return parameter type to replace the old one with
  12.288 +     * @return the same type, except with the return type change
  12.289 +     */
  12.290 +    public MethodType changeReturnType(Class<?> nrtype) {
  12.291 +        if (returnType() == nrtype)  return this;
  12.292 +        return makeImpl(nrtype, ptypes, true);
  12.293 +    }
  12.294 +
  12.295 +    /** Convenience method.
  12.296 +     * Report if this type contains a primitive argument or return value.
  12.297 +     * @return true if any of the types are primitives
  12.298 +     */
  12.299 +    public boolean hasPrimitives() {
  12.300 +        return form.hasPrimitives();
  12.301 +    }
  12.302 +
  12.303 +    /** Convenience method.
  12.304 +     * Report if this type contains a wrapper argument or return value.
  12.305 +     * Wrappers are types which box primitive values, such as {@link Integer}.
  12.306 +     * @return true if any of the types are wrappers
  12.307 +     */
  12.308 +    public boolean hasWrappers() {
  12.309 +        return unwrap() != this;
  12.310 +    }
  12.311 +
  12.312 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.313 +     * Erase all reference types to Object.
  12.314 +     * @return a version of the original type with all reference types replaced
  12.315 +     */
  12.316 +    public MethodType erase() {
  12.317 +        return form.erasedType();
  12.318 +    }
  12.319 +
  12.320 +    /** Convenience method for {@link #makeGeneric(int)}.
  12.321 +     * Convert all types, both reference and primitive, to Object.
  12.322 +     * @return a version of the original type with all types replaced
  12.323 +     */
  12.324 +    public MethodType generic() {
  12.325 +        return makeGeneric(parameterCount());
  12.326 +    }
  12.327 +
  12.328 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.329 +     * Convert all primitive types to their corresponding wrapper types.
  12.330 +     * A {@code void} return type is changed to the type {@code java.lang.Void}.
  12.331 +     * @return a version of the original type with all primitive types replaced
  12.332 +     */
  12.333 +    public MethodType wrap() {
  12.334 +        return hasPrimitives() ? wrapWithPrims(this) : this;
  12.335 +    }
  12.336 +
  12.337 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.338 +     * Convert all wrapper types to their corresponding primitive types.
  12.339 +     * A return type of {@java.lang.Void} is changed to {@code void}.
  12.340 +     * @return a version of the original type with all wrapper types replaced
  12.341 +     */
  12.342 +    public MethodType unwrap() {
  12.343 +        MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
  12.344 +        return unwrapWithNoPrims(noprims);
  12.345 +    }
  12.346 +
  12.347 +    private static MethodType wrapWithPrims(MethodType pt) {
  12.348 +        assert(pt.hasPrimitives());
  12.349 +        MethodType wt = pt.wrapAlt;
  12.350 +        if (wt == null) {
  12.351 +            // fill in lazily
  12.352 +            wt = MethodTypeImpl.canonicalize(pt, MethodTypeImpl.WRAP, MethodTypeImpl.WRAP);
  12.353 +            assert(wt != null);
  12.354 +            pt.wrapAlt = wt;
  12.355 +        }
  12.356 +        return wt;
  12.357 +    }
  12.358 +
  12.359 +    private static MethodType unwrapWithNoPrims(MethodType wt) {
  12.360 +        assert(!wt.hasPrimitives());
  12.361 +        MethodType uwt = wt.wrapAlt;
  12.362 +        if (uwt == null) {
  12.363 +            // fill in lazily
  12.364 +            uwt = MethodTypeImpl.canonicalize(wt, MethodTypeImpl.UNWRAP, MethodTypeImpl.UNWRAP);
  12.365 +            if (uwt == null)
  12.366 +                uwt = wt;    // type has no wrappers or prims at all
  12.367 +            wt.wrapAlt = uwt;
  12.368 +        }
  12.369 +        return uwt;
  12.370 +    }
  12.371 +
  12.372 +    /** @param num the index (zero-based) of the desired parameter type
  12.373 +     *  @return the selected parameter type
  12.374 +     */
  12.375 +    public Class<?> parameterType(int num) {
  12.376 +        return ptypes[num];
  12.377 +    }
  12.378 +    /** @return the number of parameter types */
  12.379 +    public int parameterCount() {
  12.380 +        return ptypes.length;
  12.381 +    }
  12.382 +    /** @return the return type */
  12.383 +    public Class<?> returnType() {
  12.384 +        return rtype;
  12.385 +    }
  12.386 +
  12.387 +    /**
  12.388 +     * Convenience method to present the arguments as a list.
  12.389 +     * @return the parameter types (as an immutable list)
  12.390 +     */
  12.391 +    public List<Class<?>> parameterList() {
  12.392 +        return Collections.unmodifiableList(Arrays.asList(ptypes));
  12.393 +    }
  12.394 +
  12.395 +    /**
  12.396 +     * Convenience method to present the arguments as an array.
  12.397 +     * @return the parameter types (as a fresh copy if necessary)
  12.398 +     */
  12.399 +    public Class<?>[] parameterArray() {
  12.400 +        return ptypes.clone();
  12.401 +    }
  12.402 +
  12.403 +    /**
  12.404 +     * Compares the specified object with this type for equality.
  12.405 +     * That is, it returns <tt>true</tt> if and only if the specified object
  12.406 +     * is also a method type with exactly the same parameters and return type.
  12.407 +     * @param x object to compare
  12.408 +     * @see Object#equals(Object)
  12.409 +     */
  12.410 +    @Override
  12.411 +    public boolean equals(Object x) {
  12.412 +        return this == x || x instanceof MethodType && equals((MethodType)x);
  12.413 +    }
  12.414 +
  12.415 +    private boolean equals(MethodType that) {
  12.416 +        return this.rtype == that.rtype
  12.417 +            && Arrays.equals(this.ptypes, that.ptypes);
  12.418 +    }
  12.419 +
  12.420 +    /**
  12.421 +     * Returns the hash code value for this method type.
  12.422 +     * It is defined to be the same as the hashcode of a List
  12.423 +     * whose elements are the return type followed by the
  12.424 +     * parameter types.
  12.425 +     * @return the hash code value for this method type
  12.426 +     * @see Object#hashCode()
  12.427 +     * @see #equals(Object)
  12.428 +     * @see List#hashCode()
  12.429 +     */
  12.430 +    @Override
  12.431 +    public int hashCode() {
  12.432 +      int hashCode = 31 + rtype.hashCode();
  12.433 +      for (Class<?> ptype : ptypes)
  12.434 +          hashCode = 31*hashCode + ptype.hashCode();
  12.435 +      return hashCode;
  12.436 +    }
  12.437 +
  12.438 +    /**
  12.439 +     * The string representation of a method type is a
  12.440 +     * parenthesis enclosed, comma separated list of type names,
  12.441 +     * followed immediately by the return type.
  12.442 +     * <p>
  12.443 +     * If a type name is array, it the base type followed
  12.444 +     * by [], rather than the Class.getName of the array type.
  12.445 +     */
  12.446 +    @Override
  12.447 +    public String toString() {
  12.448 +        StringBuilder sb = new StringBuilder();
  12.449 +        sb.append("(");
  12.450 +        for (int i = 0; i < ptypes.length; i++) {
  12.451 +            if (i > 0)  sb.append(",");
  12.452 +            putName(sb, ptypes[i]);
  12.453 +        }
  12.454 +        sb.append(")");
  12.455 +        putName(sb, rtype);
  12.456 +        return sb.toString();
  12.457 +    }
  12.458 +
  12.459 +    static void putName(StringBuilder sb, Class<?> cls) {
  12.460 +        int brackets = 0;
  12.461 +        while (cls.isArray()) {
  12.462 +            cls = cls.getComponentType();
  12.463 +            brackets++;
  12.464 +        }
  12.465 +        String n = cls.getName();
  12.466 +        /*
  12.467 +        if (n.startsWith("java.lang.")) {
  12.468 +            String nb = n.substring("java.lang.".length());
  12.469 +            if (nb.indexOf('.') < 0)  n = nb;
  12.470 +        } else if (n.indexOf('.') < 0) {
  12.471 +            n = "."+n;          // anonymous package
  12.472 +        }
  12.473 +        */
  12.474 +        sb.append(n);
  12.475 +        while (brackets > 0) {
  12.476 +            sb.append("[]");
  12.477 +            brackets--;
  12.478 +        }
  12.479 +    }
  12.480 +
  12.481 +    /// Queries which have to do with the bytecode architecture
  12.482 +
  12.483 +    /** The number of JVM stack slots required to invoke a method
  12.484 +     * of this type.  Note that (for historic reasons) the JVM requires
  12.485 +     * a second stack slot to pass long and double arguments.
  12.486 +     * So this method returns {@link #parameterCount()} plus the
  12.487 +     * number of long and double parameters (if any).
  12.488 +     * <p>
  12.489 +     * This method is included for the benfit of applications that must
  12.490 +     * generate bytecodes that process method handles and invokedynamic.
  12.491 +     * @return the number of JVM stack slots for this type's parameters
  12.492 +     */
  12.493 +    public int parameterSlotCount() {
  12.494 +        return form.parameterSlotCount();
  12.495 +    }
  12.496 +
  12.497 +    /** Number of JVM stack slots which carry all parameters after
  12.498 +     * the given position, which must be in the range of 0 to
  12.499 +     * {@code parameterCount} inclusive.  Successive parameters are
  12.500 +     * more shallowly stacked, and parameters are indexed in the bytecodes
  12.501 +     * according to their trailing edge.  Thus, to obtain the depth
  12.502 +     * in the outgoing call stack of parameter {@code N}, obtain
  12.503 +     * the {@code parameterSlotDepth} of its trailing edge
  12.504 +     * at position {@code N+1}.
  12.505 +     * <p>
  12.506 +     * Parameters of type {@code long} and {@code double} occupy
  12.507 +     * two stack slots (for historical reasons) and all others occupy one.
  12.508 +     * Therefore, the number returned is the number of arguments
  12.509 +     * <em>including</em> and <em>after</em> the given parameter,
  12.510 +     * <em>plus</em> the number of long or double arguments
  12.511 +     * at or after after the argument for the given parameter.
  12.512 +     * <p>
  12.513 +     * This method is included for the benfit of applications that must
  12.514 +     * generate bytecodes that process method handles and invokedynamic.
  12.515 +     * @param num an index (zero-based, inclusive) within the parameter types
  12.516 +     * @return the index of the (shallowest) JVM stack slot transmitting the
  12.517 +     *         given parameter
  12.518 +     */
  12.519 +    public int parameterSlotDepth(int num) {
  12.520 +        if (num < 0 || num > ptypes.length)
  12.521 +            parameterType(num);  // force a range check
  12.522 +        return form.parameterToArgSlot(num-1);
  12.523 +    }
  12.524 +
  12.525 +    /** The number of JVM stack slots required to receive a return value
  12.526 +     * from a method of this type.
  12.527 +     * If the {@link #returnType() return type} is void, it will be zero,
  12.528 +     * else if the return type is long or double, it will be two, else one.
  12.529 +     * <p>
  12.530 +     * This method is included for the benfit of applications that must
  12.531 +     * generate bytecodes that process method handles and invokedynamic.
  12.532 +     * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
  12.533 +     */
  12.534 +    public int returnSlotCount() {
  12.535 +        return form.returnSlotCount();
  12.536 +    }
  12.537 +
  12.538 +    /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}.
  12.539 +     * Find or create an instance (interned) of the given method type.
  12.540 +     * Any class or interface name embedded in the signature string
  12.541 +     * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
  12.542 +     * on the given loader (or if it is null, on the system class loader).
  12.543 +     * <p>
  12.544 +     * Note that it is possible to build method types which cannot be
  12.545 +     * constructed by this method, because their component types are
  12.546 +     * not all reachable from a common class loader.
  12.547 +     * <p>
  12.548 +     * This method is included for the benfit of applications that must
  12.549 +     * generate bytecodes that process method handles and invokedynamic.
  12.550 +     * @param bytecodeSignature a bytecode-level signature string "(T...)T"
  12.551 +     * @param loader the class loader in which to look up the types
  12.552 +     * @return a method type matching the bytecode-level signature
  12.553 +     * @throws IllegalArgumentException if the string is not well-formed
  12.554 +     * @throws TypeNotPresentException if a named type cannot be found
  12.555 +     */
  12.556 +    public static MethodType fromBytecodeString(String bytecodeSignature, ClassLoader loader)
  12.557 +        throws IllegalArgumentException, TypeNotPresentException
  12.558 +    {
  12.559 +        List<Class<?>> types = BytecodeSignature.parseMethod(bytecodeSignature, loader);
  12.560 +        Class<?> rtype = types.remove(types.size() - 1);
  12.561 +        Class<?>[] ptypes = types.toArray(NO_PTYPES);
  12.562 +        return makeImpl(rtype, ptypes, true);
  12.563 +    }
  12.564 +
  12.565 +    /**
  12.566 +     * Create a bytecode signature representation of the type.
  12.567 +     * Note that this is not a strict inverse of
  12.568 +     * <p>
  12.569 +     * This method is included for the benfit of applications that must
  12.570 +     * generate bytecodes that process method handles and invokedynamic.
  12.571 +     * {@link #fromBytecodeString(java.lang.String, java.lang.ClassLoader)},
  12.572 +     * because the latter requires a suitable class loader argument.
  12.573 +     * @return the bytecode signature representation
  12.574 +     */
  12.575 +    public String toBytecodeString() {
  12.576 +        return BytecodeSignature.unparse(this);
  12.577 +    }
  12.578 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/share/classes/java/dyn/MethodTypeForm.java	Thu May 07 12:26:22 2009 -0700
    13.3 @@ -0,0 +1,39 @@
    13.4 +/*
    13.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.  Sun designates this
   13.11 + * particular file as subject to the "Classpath" exception as provided
   13.12 + * by Sun in the LICENSE file that accompanied this code.
   13.13 + *
   13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 + * version 2 for more details (a copy is included in the LICENSE file that
   13.18 + * accompanied this code).
   13.19 + *
   13.20 + * You should have received a copy of the GNU General Public License version
   13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 + *
   13.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   13.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   13.26 + * have any questions.
   13.27 + */
   13.28 +
   13.29 +package java.dyn;
   13.30 +
   13.31 +/**
   13.32 + * TO DO:  Temporary shim; remove after refactoring effects are complete in JVM.
   13.33 + * @author John Rose
   13.34 + */
   13.35 +import sun.dyn.MethodTypeImpl;
   13.36 +
   13.37 +class MethodTypeForm extends MethodTypeImpl {
   13.38 +
   13.39 +    MethodTypeForm(MethodType erasedType) {
   13.40 +        super(erasedType);
   13.41 +    }
   13.42 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/share/classes/java/dyn/NoAccessException.java	Thu May 07 12:26:22 2009 -0700
    14.3 @@ -0,0 +1,75 @@
    14.4 +/*
    14.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.  Sun designates this
   14.11 + * particular file as subject to the "Classpath" exception as provided
   14.12 + * by Sun in the LICENSE file that accompanied this code.
   14.13 + *
   14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.17 + * version 2 for more details (a copy is included in the LICENSE file that
   14.18 + * accompanied this code).
   14.19 + *
   14.20 + * You should have received a copy of the GNU General Public License version
   14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.23 + *
   14.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   14.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   14.26 + * have any questions.
   14.27 + */
   14.28 +
   14.29 +package java.dyn;
   14.30 +
   14.31 +/**
   14.32 + * Thrown to indicate that a caller has attempted to create a method handle
   14.33 + * which calls a method to which the caller does not have access.
   14.34 + * This unchecked exception is analogous to {@link IllegalAccessException},
   14.35 + * which is a checked exception thrown when reflective invocation fails
   14.36 + * because of an access check.  With method handles, this same access
   14.37 + * checking is performed on behalf of the method handle creator,
   14.38 + * at the time of creation.
   14.39 + * @author John Rose, JSR 292 EG
   14.40 + */
   14.41 +public class NoAccessException extends RuntimeException {
   14.42 +    /**
   14.43 +     * Constructs a {@code NoAccessException} with no detail message.
   14.44 +     */
   14.45 +    public NoAccessException() {
   14.46 +        super();
   14.47 +    }
   14.48 +
   14.49 +    /**
   14.50 +     * Constructs a {@code NoAccessException} with the specified
   14.51 +     * detail message.
   14.52 +     *
   14.53 +     * @param s the detail message
   14.54 +     */
   14.55 +    public NoAccessException(String s) {
   14.56 +        super(s);
   14.57 +    }
   14.58 +
   14.59 +    /**
   14.60 +     * Constructs a {@code NoAccessException} with the specified cause.
   14.61 +     *
   14.62 +     * @param cause the underlying cause of the exception
   14.63 +     */
   14.64 +    public NoAccessException(Throwable cause) {
   14.65 +        super(cause);
   14.66 +    }
   14.67 +
   14.68 +    /**
   14.69 +     * Constructs a {@code NoAccessException} with the specified
   14.70 +     * detail message and cause.
   14.71 +     *
   14.72 +     * @param s the detail message
   14.73 +     * @param cause the underlying cause of the exception
   14.74 +     */
   14.75 +    public NoAccessException(String s, Throwable cause) {
   14.76 +        super(s, cause);
   14.77 +    }
   14.78 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/share/classes/java/dyn/WrongMethodTypeException.java	Thu May 07 12:26:22 2009 -0700
    15.3 @@ -0,0 +1,59 @@
    15.4 +/*
    15.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.7 + *
    15.8 + * This code is free software; you can redistribute it and/or modify it
    15.9 + * under the terms of the GNU General Public License version 2 only, as
   15.10 + * published by the Free Software Foundation.  Sun designates this
   15.11 + * particular file as subject to the "Classpath" exception as provided
   15.12 + * by Sun in the LICENSE file that accompanied this code.
   15.13 + *
   15.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   15.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   15.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15.17 + * version 2 for more details (a copy is included in the LICENSE file that
   15.18 + * accompanied this code).
   15.19 + *
   15.20 + * You should have received a copy of the GNU General Public License version
   15.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   15.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   15.23 + *
   15.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   15.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   15.26 + * have any questions.
   15.27 + */
   15.28 +
   15.29 +package java.dyn;
   15.30 +
   15.31 +/**
   15.32 + * Thrown to indicate that code has attempted to call a method handle
   15.33 + * via the wrong method type.  As with the bytecode representation of
   15.34 + * normal Java method calls, method handle calls are strongly typed
   15.35 + * to a specific signature associated with a call site.
   15.36 + * <p>
   15.37 + * This exception may also be thrown when two method handles are
   15.38 + * composed, and the system detects that their types cannot be
   15.39 + * matched up correctly.  This amounts to an early evaluation
   15.40 + * of the type mismatch, at method handle construction time,
   15.41 + * instead of when the mismatched method handle is called.
   15.42 + *
   15.43 + * @author John Rose, JSR 292 EG
   15.44 + */
   15.45 +public class WrongMethodTypeException extends RuntimeException {
   15.46 +    /**
   15.47 +     * Constructs a {@code WrongMethodTypeException} with no detail message.
   15.48 +     */
   15.49 +    public WrongMethodTypeException() {
   15.50 +        super();
   15.51 +    }
   15.52 +
   15.53 +    /**
   15.54 +     * Constructs a {@code WrongMethodTypeException} with the specified
   15.55 +     * detail message.
   15.56 +     *
   15.57 +     * @param s the detail message.
   15.58 +     */
   15.59 +    public WrongMethodTypeException(String s) {
   15.60 +        super(s);
   15.61 +    }
   15.62 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/share/classes/java/dyn/package-info.java	Thu May 07 12:26:22 2009 -0700
    16.3 @@ -0,0 +1,32 @@
    16.4 +/*
    16.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.  Sun designates this
   16.11 + * particular file as subject to the "Classpath" exception as provided
   16.12 + * by Sun in the LICENSE file that accompanied this code.
   16.13 + *
   16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.17 + * version 2 for more details (a copy is included in the LICENSE file that
   16.18 + * accompanied this code).
   16.19 + *
   16.20 + * You should have received a copy of the GNU General Public License version
   16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.23 + *
   16.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   16.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   16.26 + * have any questions.
   16.27 + */
   16.28 +
   16.29 +/**
   16.30 + * This package contains dynamic language support provided directly by
   16.31 + * the Java core class libraries and virtual machine.
   16.32 + * @author John Rose, JSR 292 EG
   16.33 + */
   16.34 +
   16.35 +package java.dyn;
    17.1 --- a/src/share/classes/java/io/Console.java	Thu May 07 10:31:32 2009 -0700
    17.2 +++ b/src/share/classes/java/io/Console.java	Thu May 07 12:26:22 2009 -0700
    17.3 @@ -503,20 +503,25 @@
    17.4  
    17.5      // Set up JavaIOAccess in SharedSecrets
    17.6      static {
    17.7 -
    17.8 -        // Add a shutdown hook to restore console's echo state should
    17.9 -        // it be necessary.
   17.10 -        sun.misc.SharedSecrets.getJavaLangAccess()
   17.11 -            .registerShutdownHook(0 /* shutdown hook invocation order */,
   17.12 -                new Runnable() {
   17.13 -                    public void run() {
   17.14 -                        try {
   17.15 -                            if (echoOff) {
   17.16 -                                echo(true);
   17.17 -                            }
   17.18 -                        } catch (IOException x) { }
   17.19 -                    }
   17.20 -                });
   17.21 +        try {
   17.22 +            // Add a shutdown hook to restore console's echo state should
   17.23 +            // it be necessary.
   17.24 +            sun.misc.SharedSecrets.getJavaLangAccess()
   17.25 +                .registerShutdownHook(0 /* shutdown hook invocation order */,
   17.26 +                    false /* only register if shutdown is not in progress */,
   17.27 +                    new Runnable() {
   17.28 +                        public void run() {
   17.29 +                            try {
   17.30 +                                if (echoOff) {
   17.31 +                                    echo(true);
   17.32 +                                }
   17.33 +                            } catch (IOException x) { }
   17.34 +                        }
   17.35 +                    });
   17.36 +        } catch (IllegalStateException e) {
   17.37 +            // shutdown is already in progress and console is first used
   17.38 +            // by a shutdown hook
   17.39 +        }
   17.40  
   17.41          sun.misc.SharedSecrets.setJavaIOAccess(new sun.misc.JavaIOAccess() {
   17.42              public Console console() {
    18.1 --- a/src/share/classes/java/io/DeleteOnExitHook.java	Thu May 07 10:31:32 2009 -0700
    18.2 +++ b/src/share/classes/java/io/DeleteOnExitHook.java	Thu May 07 12:26:22 2009 -0700
    18.3 @@ -34,23 +34,31 @@
    18.4   */
    18.5  
    18.6  class DeleteOnExitHook {
    18.7 +    private static LinkedHashSet<String> files = new LinkedHashSet<String>();
    18.8      static {
    18.9 -         sun.misc.SharedSecrets.getJavaLangAccess()
   18.10 -             .registerShutdownHook(2 /* Shutdown hook invocation order */,
   18.11 -                 new Runnable() {
   18.12 -                     public void run() {
   18.13 -                        runHooks();
   18.14 -                     }
   18.15 -                 });
   18.16 +        // DeleteOnExitHook must be the last shutdown hook to be invoked.
   18.17 +        // Application shutdown hooks may add the first file to the
   18.18 +        // delete on exit list and cause the DeleteOnExitHook to be
   18.19 +        // registered during shutdown in progress. So set the
   18.20 +        // registerShutdownInProgress parameter to true.
   18.21 +        sun.misc.SharedSecrets.getJavaLangAccess()
   18.22 +            .registerShutdownHook(2 /* Shutdown hook invocation order */,
   18.23 +                true /* register even if shutdown in progress */,
   18.24 +                new Runnable() {
   18.25 +                    public void run() {
   18.26 +                       runHooks();
   18.27 +                    }
   18.28 +                }
   18.29 +        );
   18.30      }
   18.31  
   18.32 -    private static LinkedHashSet<String> files = new LinkedHashSet<String>();
   18.33 -
   18.34      private DeleteOnExitHook() {}
   18.35  
   18.36      static synchronized void add(String file) {
   18.37 -        if(files == null)
   18.38 +        if(files == null) {
   18.39 +            // DeleteOnExitHook is running. Too late to add a file
   18.40              throw new IllegalStateException("Shutdown in progress");
   18.41 +        }
   18.42  
   18.43          files.add(file);
   18.44      }
    19.1 --- a/src/share/classes/java/lang/ApplicationShutdownHooks.java	Thu May 07 10:31:32 2009 -0700
    19.2 +++ b/src/share/classes/java/lang/ApplicationShutdownHooks.java	Thu May 07 12:26:22 2009 -0700
    19.3 @@ -35,17 +35,26 @@
    19.4   */
    19.5  
    19.6  class ApplicationShutdownHooks {
    19.7 +    /* The set of registered hooks */
    19.8 +    private static IdentityHashMap<Thread, Thread> hooks;
    19.9      static {
   19.10 -        Shutdown.add(1 /* shutdown hook invocation order */,
   19.11 -            new Runnable() {
   19.12 -                public void run() {
   19.13 -                    runHooks();
   19.14 +        try {
   19.15 +            Shutdown.add(1 /* shutdown hook invocation order */,
   19.16 +                false /* not registered if shutdown in progress */,
   19.17 +                new Runnable() {
   19.18 +                    public void run() {
   19.19 +                        runHooks();
   19.20 +                    }
   19.21                  }
   19.22 -            });
   19.23 +            );
   19.24 +            hooks = new IdentityHashMap<Thread, Thread>();
   19.25 +        } catch (IllegalStateException e) {
   19.26 +            // application shutdown hooks cannot be added if
   19.27 +            // shutdown is in progress.
   19.28 +            hooks = null;
   19.29 +        }
   19.30      }
   19.31  
   19.32 -    /* The set of registered hooks */
   19.33 -    private static IdentityHashMap<Thread, Thread> hooks = new IdentityHashMap<Thread, Thread>();
   19.34  
   19.35      private ApplicationShutdownHooks() {}
   19.36  
    20.1 --- a/src/share/classes/java/lang/Shutdown.java	Thu May 07 10:31:32 2009 -0700
    20.2 +++ b/src/share/classes/java/lang/Shutdown.java	Thu May 07 12:26:22 2009 -0700
    20.3 @@ -53,6 +53,9 @@
    20.4      private static final int MAX_SYSTEM_HOOKS = 10;
    20.5      private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];
    20.6  
    20.7 +    // the index of the currently running shutdown hook to the hooks array
    20.8 +    private static int currentRunningHook = 0;
    20.9 +
   20.10      /* The preceding static fields are protected by this lock */
   20.11      private static class Lock { };
   20.12      private static Object lock = new Lock();
   20.13 @@ -68,17 +71,39 @@
   20.14      }
   20.15  
   20.16  
   20.17 -    /* Add a new shutdown hook.  Checks the shutdown state and the hook itself,
   20.18 +    /**
   20.19 +     * Add a new shutdown hook.  Checks the shutdown state and the hook itself,
   20.20       * but does not do any security checks.
   20.21 +     *
   20.22 +     * The registerShutdownInProgress parameter should be false except
   20.23 +     * registering the DeleteOnExitHook since the first file may
   20.24 +     * be added to the delete on exit list by the application shutdown
   20.25 +     * hooks.
   20.26 +     *
   20.27 +     * @params slot  the slot in the shutdown hook array, whose element
   20.28 +     *               will be invoked in order during shutdown
   20.29 +     * @params registerShutdownInProgress true to allow the hook
   20.30 +     *               to be registered even if the shutdown is in progress.
   20.31 +     * @params hook  the hook to be registered
   20.32 +     *
   20.33 +     * @throw IllegalStateException
   20.34 +     *        if registerShutdownInProgress is false and shutdown is in progress; or
   20.35 +     *        if registerShutdownInProgress is true and the shutdown process
   20.36 +     *           already passes the given slot
   20.37       */
   20.38 -    static void add(int slot, Runnable hook) {
   20.39 +    static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
   20.40          synchronized (lock) {
   20.41 -            if (state > RUNNING)
   20.42 -                throw new IllegalStateException("Shutdown in progress");
   20.43 -
   20.44              if (hooks[slot] != null)
   20.45                  throw new InternalError("Shutdown hook at slot " + slot + " already registered");
   20.46  
   20.47 +            if (!registerShutdownInProgress) {
   20.48 +                if (state > RUNNING)
   20.49 +                    throw new IllegalStateException("Shutdown in progress");
   20.50 +            } else {
   20.51 +                if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook))
   20.52 +                    throw new IllegalStateException("Shutdown in progress");
   20.53 +            }
   20.54 +
   20.55              hooks[slot] = hook;
   20.56          }
   20.57      }
   20.58 @@ -86,11 +111,15 @@
   20.59      /* Run all registered shutdown hooks
   20.60       */
   20.61      private static void runHooks() {
   20.62 -        /* We needn't bother acquiring the lock just to read the hooks field,
   20.63 -         * since the hooks can't be modified once shutdown is in progress
   20.64 -         */
   20.65 -        for (Runnable hook : hooks) {
   20.66 +        for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
   20.67              try {
   20.68 +                Runnable hook;
   20.69 +                synchronized (lock) {
   20.70 +                    // acquire the lock to make sure the hook registered during
   20.71 +                    // shutdown is visible here.
   20.72 +                    currentRunningHook = i;
   20.73 +                    hook = hooks[i];
   20.74 +                }
   20.75                  if (hook != null) hook.run();
   20.76              } catch(Throwable t) {
   20.77                  if (t instanceof ThreadDeath) {
    21.1 --- a/src/share/classes/java/lang/System.java	Thu May 07 10:31:32 2009 -0700
    21.2 +++ b/src/share/classes/java/lang/System.java	Thu May 07 12:26:22 2009 -0700
    21.3 @@ -1171,8 +1171,8 @@
    21.4              public void blockedOn(Thread t, Interruptible b) {
    21.5                  t.blockedOn(b);
    21.6              }
    21.7 -            public void registerShutdownHook(int slot, Runnable r) {
    21.8 -                Shutdown.add(slot, r);
    21.9 +            public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
   21.10 +                Shutdown.add(slot, registerShutdownInProgress, hook);
   21.11              }
   21.12          });
   21.13      }
    22.1 --- a/src/share/classes/java/util/zip/ZipFile.java	Thu May 07 10:31:32 2009 -0700
    22.2 +++ b/src/share/classes/java/util/zip/ZipFile.java	Thu May 07 12:26:22 2009 -0700
    22.3 @@ -154,7 +154,7 @@
    22.4       * @param file the ZIP file to be opened for reading
    22.5       * @param mode the mode in which the file is to be opened
    22.6       * @param charset
    22.7 -     *        the {@link java.nio.charset.Charset {@code charset}} to
    22.8 +     *        the {@linkplain java.nio.charset.Charset charset} to
    22.9       *        be used to decode the ZIP entry name and comment that are not
   22.10       *        encoded by using UTF-8 encoding (indicated by entry's general
   22.11       *        purpose flag).
   22.12 @@ -206,7 +206,7 @@
   22.13       *
   22.14       * @param name the name of the zip file
   22.15       * @param charset
   22.16 -     *        the {@link java.nio.charset.Charset {@code charset}} to
   22.17 +     *        the {@linkplain java.nio.charset.Charset charset} to
   22.18       *        be used to decode the ZIP entry name and comment that are not
   22.19       *        encoded by using UTF-8 encoding (indicated by entry's general
   22.20       *        purpose flag).
   22.21 @@ -230,7 +230,7 @@
   22.22       * Opens a ZIP file for reading given the specified File object.
   22.23       * @param file the ZIP file to be opened for reading
   22.24       * @param charset
   22.25 -     *        The {@link java.nio.charset.Charset {@code charset}} to be
   22.26 +     *        The {@linkplain java.nio.charset.Charset charset} to be
   22.27       *        used to decode the ZIP entry name and comment (ignored if
   22.28       *        the <a href="package-summary.html#lang_encoding"> language
   22.29       *        encoding bit</a> of the ZIP entry's general purpose bit
    23.1 --- a/src/share/classes/java/util/zip/ZipInputStream.java	Thu May 07 10:31:32 2009 -0700
    23.2 +++ b/src/share/classes/java/util/zip/ZipInputStream.java	Thu May 07 12:26:22 2009 -0700
    23.3 @@ -84,7 +84,7 @@
    23.4       * @param in the actual input stream
    23.5       *
    23.6       * @param charset
    23.7 -     *        The {@link java.nio.charset.Charset {@code charset}} to be
    23.8 +     *        The {@linkplain java.nio.charset.Charset charset} to be
    23.9       *        used to decode the ZIP entry name (ignored if the
   23.10       *        <a href="package-summary.html#lang_encoding"> language
   23.11       *        encoding bit</a> of the ZIP entry's general purpose bit
    24.1 --- a/src/share/classes/java/util/zip/ZipOutputStream.java	Thu May 07 10:31:32 2009 -0700
    24.2 +++ b/src/share/classes/java/util/zip/ZipOutputStream.java	Thu May 07 12:26:22 2009 -0700
    24.3 @@ -108,7 +108,7 @@
    24.4       *
    24.5       * @param out the actual output stream
    24.6       *
    24.7 -     * @param charset the {@link java.nio.charset.Charset </code>charset<code>}
    24.8 +     * @param charset the {@linkplain java.nio.charset.Charset charset}
    24.9       *                to be used to encode the entry names and comments
   24.10       *
   24.11       * @since 1.7
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/src/share/classes/sun/dyn/Access.java	Thu May 07 12:26:22 2009 -0700
    25.3 @@ -0,0 +1,109 @@
    25.4 +/*
    25.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    25.7 + *
    25.8 + * This code is free software; you can redistribute it and/or modify it
    25.9 + * under the terms of the GNU General Public License version 2 only, as
   25.10 + * published by the Free Software Foundation.  Sun designates this
   25.11 + * particular file as subject to the "Classpath" exception as provided
   25.12 + * by Sun in the LICENSE file that accompanied this code.
   25.13 + *
   25.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   25.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   25.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   25.17 + * version 2 for more details (a copy is included in the LICENSE file that
   25.18 + * accompanied this code).
   25.19 + *
   25.20 + * You should have received a copy of the GNU General Public License version
   25.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   25.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   25.23 + *
   25.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   25.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   25.26 + * have any questions.
   25.27 + */
   25.28 +
   25.29 +package sun.dyn;
   25.30 +
   25.31 +import sun.reflect.Reflection;
   25.32 +
   25.33 +/**
   25.34 + * Access control to this package.
   25.35 + * Classes in other packages can attempt to acquire the access token,
   25.36 + * but will fail if they are not recognized as friends.
   25.37 + * Certain methods in this package, although public, require a non-null
   25.38 + * access token in order to proceed; they act like package-private methods.
   25.39 + * @author jrose
   25.40 + */
   25.41 +
   25.42 +public class Access {
   25.43 +
   25.44 +    private Access() { }
   25.45 +
   25.46 +    /**
   25.47 +     * The heart of this pattern:  The list of classes which are
   25.48 +     * permitted to acquire the access token, and become honorary
   25.49 +     * members of this package.
   25.50 +     */
   25.51 +    private static final String[] FRIENDS = {
   25.52 +        "java.dyn.", "sun.dyn."
   25.53 +    };
   25.54 +
   25.55 +    /**
   25.56 +     * The following object is NOT public.  That's the point of the pattern.
   25.57 +     * It is package-private, so that any member of this package
   25.58 +     * can acquire the access token, and give it away to trusted friends.
   25.59 +     */
   25.60 +    static final Access TOKEN = new Access();
   25.61 +
   25.62 +    /**
   25.63 +     * @return Access.TOKEN, if the caller is a friend of this package
   25.64 +     */
   25.65 +    public static Access getToken() {
   25.66 +        Class<?> callc = Reflection.getCallerClass(2);
   25.67 +        if (isFriend(callc))
   25.68 +            return TOKEN;
   25.69 +        else
   25.70 +            throw new IllegalAccessError("bad caller: " + callc);
   25.71 +    }
   25.72 +
   25.73 +    /** Is the given name the name of a class which could be our friend? */
   25.74 +    public static boolean isFriendName(String name) {
   25.75 +        for (String friend : FRIENDS) {
   25.76 +            if (name.startsWith(friend))
   25.77 +                return true;
   25.78 +        }
   25.79 +        return false;
   25.80 +    }
   25.81 +
   25.82 +    /** Is the given class a friend?  True if {@link #isFriendName},
   25.83 +     *  and the given class also shares a class loader with us.
   25.84 +     */
   25.85 +    public static boolean isFriend(Class<?> c) {
   25.86 +        return isFriendName(c.getName()) && c.getClassLoader() == CLASS_LOADER;
   25.87 +    }
   25.88 +
   25.89 +    private static final ClassLoader CLASS_LOADER = Access.class.getClassLoader();
   25.90 +
   25.91 +    /**
   25.92 +     * Throw an IllegalAccessError if the caller does not possess
   25.93 +     * the Access.TOKEN.
   25.94 +     * @param must be Access.TOKEN
   25.95 +     */
   25.96 +    public static void check(Access token) {
   25.97 +        if (token == null)
   25.98 +            fail();
   25.99 +        // else it must be the unique Access.TOKEN
  25.100 +        assert(token == Access.TOKEN);
  25.101 +    }
  25.102 +    private static void fail() {
  25.103 +        final int CALLER_DEPTH = 3;
  25.104 +        // 0: Reflection.getCC, 1: this.fail, 2: Access.*, 3: caller
  25.105 +        Class<?> callc = Reflection.getCallerClass(CALLER_DEPTH);
  25.106 +        throw new IllegalAccessError("bad caller: " + callc);
  25.107 +    }
  25.108 +
  25.109 +    static {
  25.110 +        //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
  25.111 +    }
  25.112 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/src/share/classes/sun/dyn/AdapterMethodHandle.java	Thu May 07 12:26:22 2009 -0700
    26.3 @@ -0,0 +1,728 @@
    26.4 +/*
    26.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.7 + *
    26.8 + * This code is free software; you can redistribute it and/or modify it
    26.9 + * under the terms of the GNU General Public License version 2 only, as
   26.10 + * published by the Free Software Foundation.  Sun designates this
   26.11 + * particular file as subject to the "Classpath" exception as provided
   26.12 + * by Sun in the LICENSE file that accompanied this code.
   26.13 + *
   26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   26.17 + * version 2 for more details (a copy is included in the LICENSE file that
   26.18 + * accompanied this code).
   26.19 + *
   26.20 + * You should have received a copy of the GNU General Public License version
   26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   26.23 + *
   26.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   26.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   26.26 + * have any questions.
   26.27 + */
   26.28 +
   26.29 +package sun.dyn;
   26.30 +
   26.31 +import sun.dyn.util.VerifyType;
   26.32 +import sun.dyn.util.Wrapper;
   26.33 +import java.dyn.*;
   26.34 +import java.util.Arrays;
   26.35 +import static sun.dyn.MethodHandleNatives.Constants.*;
   26.36 +import static sun.dyn.MethodHandleImpl.newIllegalArgumentException;
   26.37 +
   26.38 +/**
   26.39 + * This method handle performs simple conversion or checking of a single argument.
   26.40 + * @author jrose
   26.41 + */
   26.42 +public class AdapterMethodHandle extends BoundMethodHandle {
   26.43 +
   26.44 +    //MethodHandle vmtarget;   // next AMH or BMH in chain or final DMH
   26.45 +    //Object       argument;   // parameter to the conversion if needed
   26.46 +    //int          vmargslot;  // which argument slot is affected
   26.47 +    private final int conversion;  // the type of conversion: RETYPE_ONLY, etc.
   26.48 +
   26.49 +    // Constructors in this class *must* be package scoped or private.
   26.50 +    private AdapterMethodHandle(MethodHandle target, MethodType newType,
   26.51 +                long conv, Object convArg) {
   26.52 +        super(newType, convArg, newType.parameterSlotDepth(1+convArgPos(conv)));
   26.53 +        this.conversion = convCode(conv);
   26.54 +        if (MethodHandleNatives.JVM_SUPPORT) {
   26.55 +            // JVM might update VM-specific bits of conversion (ignore)
   26.56 +            MethodHandleNatives.init(this, target, convArgPos(conv));
   26.57 +        }
   26.58 +    }
   26.59 +    private AdapterMethodHandle(MethodHandle target, MethodType newType,
   26.60 +                long conv) {
   26.61 +        this(target, newType, conv, null);
   26.62 +    }
   26.63 +
   26.64 +    private static final Access IMPL_TOKEN = Access.getToken();
   26.65 +
   26.66 +    // TO DO:  When adapting another MH with a null conversion, clone
   26.67 +    // the target and change its type, instead of adding another layer.
   26.68 +
   26.69 +    /** Can a JVM-level adapter directly implement the proposed
   26.70 +     *  argument conversions, as if by MethodHandles.convertArguments?
   26.71 +     */
   26.72 +    public static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
   26.73 +        // same number of args, of course
   26.74 +        int len = newType.parameterCount();
   26.75 +        if (len != oldType.parameterCount())
   26.76 +            return false;
   26.77 +
   26.78 +        // Check return type.  (Not much can be done with it.)
   26.79 +        Class<?> exp = newType.returnType();
   26.80 +        Class<?> ret = oldType.returnType();
   26.81 +        if (!VerifyType.isNullConversion(ret, exp))
   26.82 +            return false;
   26.83 +
   26.84 +        // Check args pairwise.
   26.85 +        for (int i = 0; i < len; i++) {
   26.86 +            Class<?> src = newType.parameterType(i); // source type
   26.87 +            Class<?> dst = oldType.parameterType(i); // destination type
   26.88 +            if (!canConvertArgument(src, dst))
   26.89 +                return false;
   26.90 +        }
   26.91 +
   26.92 +        return true;
   26.93 +    }
   26.94 +
   26.95 +    /** Can a JVM-level adapter directly implement the proposed
   26.96 +     *  argument conversion, as if by MethodHandles.convertArguments?
   26.97 +     */
   26.98 +    public static boolean canConvertArgument(Class<?> src, Class<?> dst) {
   26.99 +        // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
  26.100 +        // so we don't need to repeat so much decision making.
  26.101 +        if (VerifyType.isNullConversion(src, dst)) {
  26.102 +            return true;
  26.103 +        } else if (src.isPrimitive()) {
  26.104 +            if (dst.isPrimitive())
  26.105 +                return canPrimCast(src, dst);
  26.106 +            else
  26.107 +                return canBoxArgument(src, dst);
  26.108 +        } else {
  26.109 +            if (dst.isPrimitive())
  26.110 +                return canUnboxArgument(src, dst);
  26.111 +            else
  26.112 +                return true;  // any two refs can be interconverted
  26.113 +        }
  26.114 +    }
  26.115 +
  26.116 +    /**
  26.117 +     * Create a JVM-level adapter method handle to conform the given method
  26.118 +     * handle to the similar newType, using only pairwise argument conversions.
  26.119 +     * For each argument, convert incoming argument to the exact type needed.
  26.120 +     * Only null conversions are allowed on the return value (until
  26.121 +     * the JVM supports ricochet adapters).
  26.122 +     * The argument conversions allowed are casting, unboxing,
  26.123 +     * integral widening or narrowing, and floating point widening or narrowing.
  26.124 +     * @param token access check
  26.125 +     * @param newType required call type
  26.126 +     * @param target original method handle
  26.127 +     * @return an adapter to the original handle with the desired new type,
  26.128 +     *          or the original target if the types are already identical
  26.129 +     *          or null if the adaptation cannot be made
  26.130 +     */
  26.131 +    public static MethodHandle makePairwiseConvert(Access token,
  26.132 +                MethodType newType, MethodHandle target) {
  26.133 +        Access.check(token);
  26.134 +        MethodType oldType = target.type();
  26.135 +        if (newType == oldType)  return target;
  26.136 +
  26.137 +        if (!canPairwiseConvert(newType, oldType))
  26.138 +            return null;
  26.139 +        // (after this point, it is an assertion error to fail to convert)
  26.140 +
  26.141 +        // Find last non-trivial conversion (if any).
  26.142 +        int lastConv = newType.parameterCount()-1;
  26.143 +        while (lastConv >= 0) {
  26.144 +            Class<?> src = newType.parameterType(lastConv); // source type
  26.145 +            Class<?> dst = oldType.parameterType(lastConv); // destination type
  26.146 +            if (VerifyType.isNullConversion(src, dst)) {
  26.147 +                --lastConv;
  26.148 +            } else {
  26.149 +                break;
  26.150 +            }
  26.151 +        }
  26.152 +        // Now build a chain of one or more adapters.
  26.153 +        MethodHandle adapter = target;
  26.154 +        MethodType midType = oldType.changeReturnType(newType.returnType());
  26.155 +        for (int i = 0; i <= lastConv; i++) {
  26.156 +            Class<?> src = newType.parameterType(i); // source type
  26.157 +            Class<?> dst = midType.parameterType(i); // destination type
  26.158 +            if (VerifyType.isNullConversion(src, dst)) {
  26.159 +                // do nothing: difference is trivial
  26.160 +                continue;
  26.161 +            }
  26.162 +            // Work the current type backward toward the desired caller type:
  26.163 +            if (i != lastConv) {
  26.164 +                midType = midType.changeParameterType(i, src);
  26.165 +            } else {
  26.166 +                // When doing the last (or only) real conversion,
  26.167 +                // force all remaining null conversions to happen also.
  26.168 +                assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
  26.169 +                midType = newType;
  26.170 +            }
  26.171 +
  26.172 +            // Tricky case analysis follows.
  26.173 +            // It parallels canConvertArgument() above.
  26.174 +            if (src.isPrimitive()) {
  26.175 +                if (dst.isPrimitive()) {
  26.176 +                    adapter = makePrimCast(token, midType, adapter, i, dst);
  26.177 +                } else {
  26.178 +                    adapter = makeBoxArgument(token, midType, adapter, i, dst);
  26.179 +                }
  26.180 +            } else {
  26.181 +                if (dst.isPrimitive()) {
  26.182 +                    // Caller has boxed a primitive.  Unbox it for the target.
  26.183 +                    // The box type must correspond exactly to the primitive type.
  26.184 +                    // This is simpler than the powerful set of widening
  26.185 +                    // conversions supported by reflect.Method.invoke.
  26.186 +                    // Those conversions require a big nest of if/then/else logic,
  26.187 +                    // which we prefer to make a user responsibility.
  26.188 +                    adapter = makeUnboxArgument(token, midType, adapter, i, dst);
  26.189 +                } else {
  26.190 +                    // Simple reference conversion.
  26.191 +                    // Note:  Do not check for a class hierarchy relation
  26.192 +                    // between src and dst.  In all cases a 'null' argument
  26.193 +                    // will pass the cast conversion.
  26.194 +                    adapter = makeCheckCast(token, midType, adapter, i, dst);
  26.195 +                }
  26.196 +            }
  26.197 +            assert(adapter != null);
  26.198 +            assert(adapter.type() == midType);
  26.199 +        }
  26.200 +        if (adapter.type() != newType) {
  26.201 +            // Only trivial conversions remain.
  26.202 +            adapter = makeRetypeOnly(IMPL_TOKEN, newType, adapter);
  26.203 +            assert(adapter != null);
  26.204 +            // Actually, that's because there were no non-trivial ones:
  26.205 +            assert(lastConv == -1);
  26.206 +        }
  26.207 +        assert(adapter.type() == newType);
  26.208 +        return adapter;
  26.209 +    }
  26.210 +
  26.211 +    /**
  26.212 +     * Create a JVM-level adapter method handle to permute the arguments
  26.213 +     * of the given method.
  26.214 +     * @param token access check
  26.215 +     * @param newType required call type
  26.216 +     * @param target original method handle
  26.217 +     * @param argumentMap for each target argument, position of its source in newType
  26.218 +     * @return an adapter to the original handle with the desired new type,
  26.219 +     *          or the original target if the types are already identical
  26.220 +     *          and the permutation is null
  26.221 +     * @throws IllegalArgumentException if the adaptation cannot be made
  26.222 +     *          directly by a JVM-level adapter, without help from Java code
  26.223 +     */
  26.224 +    public static MethodHandle makePermutation(Access token,
  26.225 +                MethodType newType, MethodHandle target,
  26.226 +                int[] argumentMap) {
  26.227 +        MethodType oldType = target.type();
  26.228 +        boolean nullPermutation = true;
  26.229 +        for (int i = 0; i < argumentMap.length; i++) {
  26.230 +            int pos = argumentMap[i];
  26.231 +            if (pos != i)
  26.232 +                nullPermutation = false;
  26.233 +            if (pos < 0 || pos >= newType.parameterCount()) {
  26.234 +                argumentMap = new int[0]; break;
  26.235 +            }
  26.236 +        }
  26.237 +        if (argumentMap.length != oldType.parameterCount())
  26.238 +            throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
  26.239 +        if (nullPermutation) {
  26.240 +            MethodHandle res = makePairwiseConvert(token, newType, target);
  26.241 +            // well, that was easy
  26.242 +            if (res == null)
  26.243 +                throw newIllegalArgumentException("cannot convert pairwise: "+newType);
  26.244 +            return res;
  26.245 +        }
  26.246 +
  26.247 +        // Check return type.  (Not much can be done with it.)
  26.248 +        Class<?> exp = newType.returnType();
  26.249 +        Class<?> ret = oldType.returnType();
  26.250 +        if (!VerifyType.isNullConversion(ret, exp))
  26.251 +            throw newIllegalArgumentException("bad return conversion for "+newType);
  26.252 +
  26.253 +        // See if the argument types match up.
  26.254 +        for (int i = 0; i < argumentMap.length; i++) {
  26.255 +            int j = argumentMap[i];
  26.256 +            Class<?> src = newType.parameterType(j);
  26.257 +            Class<?> dst = oldType.parameterType(i);
  26.258 +            if (!VerifyType.isNullConversion(src, dst))
  26.259 +                throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
  26.260 +        }
  26.261 +
  26.262 +        // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
  26.263 +        // A workable greedy algorithm is as follows:
  26.264 +        // Drop unused outgoing arguments (right to left: shallowest first).
  26.265 +        // Duplicate doubly-used outgoing arguments (left to right: deepest first).
  26.266 +        // Then the remaining problem is a true argument permutation.
  26.267 +        // Marshal the outgoing arguments as required from left to right.
  26.268 +        // That is, find the deepest outgoing stack position that does not yet
  26.269 +        // have the correct argument value, and correct at least that position
  26.270 +        // by swapping or rotating in the misplaced value (from a shallower place).
  26.271 +        // If the misplaced value is followed by one or more consecutive values
  26.272 +        // (also misplaced)  issue a rotation which brings as many as possible
  26.273 +        // into position.  Otherwise make progress with either a swap or a
  26.274 +        // rotation.  Prefer the swap as cheaper, but do not use it if it
  26.275 +        // breaks a slot pair.  Prefer the rotation over the swap if it would
  26.276 +        // preserve more consecutive values shallower than the target position.
  26.277 +        // When more than one rotation will work (because the required value
  26.278 +        // is already adjacent to the target position), then use a rotation
  26.279 +        // which moves the old value in the target position adjacent to
  26.280 +        // one of its consecutive values.  Also, prefer shorter rotation
  26.281 +        // spans, since they use fewer memory cycles for shuffling.
  26.282 +
  26.283 +        throw new UnsupportedOperationException("NYI");
  26.284 +    }
  26.285 +
  26.286 +    private static byte basicType(Class<?> type) {
  26.287 +        if (type == null)  return T_VOID;
  26.288 +        switch (Wrapper.forBasicType(type)) {
  26.289 +            case BOOLEAN:  return T_BOOLEAN;
  26.290 +            case CHAR:     return T_CHAR;
  26.291 +            case FLOAT:    return T_FLOAT;
  26.292 +            case DOUBLE:   return T_DOUBLE;
  26.293 +            case BYTE:     return T_BYTE;
  26.294 +            case SHORT:    return T_SHORT;
  26.295 +            case INT:      return T_INT;
  26.296 +            case LONG:     return T_LONG;
  26.297 +            case OBJECT:   return T_OBJECT;
  26.298 +            case VOID:     return T_VOID;
  26.299 +        }
  26.300 +        return 99; // T_ILLEGAL or some such
  26.301 +    }
  26.302 +
  26.303 +    /** Number of stack slots for the given type.
  26.304 +     *  Two for T_DOUBLE and T_FLOAT, one for the rest.
  26.305 +     */
  26.306 +    private static int type2size(int type) {
  26.307 +        assert(type >= T_BOOLEAN && type <= T_OBJECT);
  26.308 +        return (type == T_FLOAT || type == T_DOUBLE) ? 2 : 1;
  26.309 +    }
  26.310 +
  26.311 +    /** Construct an adapter conversion descriptor for a single-argument conversion. */
  26.312 +    private static long makeConv(int convOp, int argnum, int src, int dest) {
  26.313 +        assert(src  == (src  & 0xF));
  26.314 +        assert(dest == (dest & 0xF));
  26.315 +        assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
  26.316 +        long stackMove = type2size(dest) - type2size(src);
  26.317 +        return ((long) argnum << 32 |
  26.318 +                (long) convOp << CONV_OP_SHIFT |
  26.319 +                (int)  src    << CONV_SRC_TYPE_SHIFT |
  26.320 +                (int)  dest   << CONV_DEST_TYPE_SHIFT |
  26.321 +                stackMove     << CONV_STACK_MOVE_SHIFT
  26.322 +                );
  26.323 +    }
  26.324 +    private static long makeConv(int convOp, int argnum, int stackMove) {
  26.325 +        assert(convOp >= OP_SWAP_ARGS && convOp <= OP_SPREAD_ARGS);
  26.326 +        byte src = 0, dest = 0;
  26.327 +        if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS)
  26.328 +            src = dest = T_OBJECT;
  26.329 +        return ((long) argnum << 32 |
  26.330 +                (long) convOp << CONV_OP_SHIFT |
  26.331 +                (int)  src    << CONV_SRC_TYPE_SHIFT |
  26.332 +                (int)  dest   << CONV_DEST_TYPE_SHIFT |
  26.333 +                stackMove     << CONV_STACK_MOVE_SHIFT
  26.334 +                );
  26.335 +    }
  26.336 +    private static long makeConv(int convOp) {
  26.337 +        assert(convOp == OP_RETYPE_ONLY);
  26.338 +        return (long) convOp << CONV_OP_SHIFT;   // stackMove, src, dst, argnum all zero
  26.339 +    }
  26.340 +    private static int convCode(long conv) {
  26.341 +        return (int)conv;
  26.342 +    }
  26.343 +    private static int convArgPos(long conv) {
  26.344 +        return (int)(conv >>> 32);
  26.345 +    }
  26.346 +    private static boolean convOpSupported(int convOp) {
  26.347 +        assert(convOp >= 0 && convOp <= CONV_OP_LIMIT);
  26.348 +        return ((1<<convOp) & CONV_OP_IMPLEMENTED_MASK) != 0;
  26.349 +    }
  26.350 +
  26.351 +    /** One of OP_RETYPE_ONLY, etc. */
  26.352 +    int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
  26.353 +
  26.354 +    @Override
  26.355 +    public String toString() {
  26.356 +        return addTypeString(this, "Adapted[" + basicToString(nonAdapter((MethodHandle)vmtarget)) + "]");
  26.357 +    }
  26.358 +
  26.359 +    private static MethodHandle nonAdapter(MethodHandle mh) {
  26.360 +        return (MethodHandle)
  26.361 +            MethodHandleNatives.getTarget(mh, ETF_DIRECT_HANDLE);
  26.362 +    }
  26.363 +
  26.364 +    /* Return one plus the position of the first non-trivial difference
  26.365 +     * between the given types.  This is not a symmetric operation;
  26.366 +     * we are considering adapting the targetType to adapterType.
  26.367 +     * Trivial differences are those which could be ignored by the JVM
  26.368 +     * without subverting the verifier.  Otherwise, adaptable differences
  26.369 +     * are ones for which we could create an adapter to make the type change.
  26.370 +     * Return zero if there are no differences (other than trivial ones).
  26.371 +     * Return 1+N if N is the only adaptable argument difference.
  26.372 +     * Return the -2-N where N is the first of several adaptable
  26.373 +     * argument differences.
  26.374 +     * Return -1 if there there are differences which are not adaptable.
  26.375 +     */
  26.376 +    private static int diffTypes(MethodType adapterType,
  26.377 +                                 MethodType targetType,
  26.378 +                                 boolean raw) {
  26.379 +        int diff;
  26.380 +        diff = diffReturnTypes(adapterType, targetType, raw);
  26.381 +        if (diff != 0)  return diff;
  26.382 +        int nargs = adapterType.parameterCount();
  26.383 +        if (nargs != targetType.parameterCount())
  26.384 +            return -1;
  26.385 +        diff = diffParamTypes(adapterType, 0, targetType, 0, nargs, raw);
  26.386 +        //System.out.println("diff "+adapterType);
  26.387 +        //System.out.println("  "+diff+" "+targetType);
  26.388 +        return diff;
  26.389 +    }
  26.390 +    private static int diffReturnTypes(MethodType adapterType,
  26.391 +                                       MethodType targetType,
  26.392 +                                       boolean raw) {
  26.393 +        Class<?> src = targetType.returnType();
  26.394 +        Class<?> dst = adapterType.returnType();
  26.395 +        if ((!raw
  26.396 +             ? VerifyType.canPassUnchecked(src, dst)
  26.397 +             : VerifyType.canPassRaw(src, dst)
  26.398 +             ) > 0)
  26.399 +            return 0;  // no significant difference
  26.400 +        if (raw && !src.isPrimitive() && !dst.isPrimitive())
  26.401 +            return 0;  // can force a reference return (very carefully!)
  26.402 +        //if (false)  return 1;  // never adaptable!
  26.403 +        return -1;  // some significant difference
  26.404 +    }
  26.405 +    private static int diffParamTypes(MethodType adapterType, int tstart,
  26.406 +                                      MethodType targetType, int astart,
  26.407 +                                      int nargs, boolean raw) {
  26.408 +        assert(nargs >= 0);
  26.409 +        int res = 0;
  26.410 +        for (int i = 0; i < nargs; i++) {
  26.411 +            Class<?> src  = adapterType.parameterType(tstart+i);
  26.412 +            Class<?> dest = targetType.parameterType(astart+i);
  26.413 +            if ((!raw
  26.414 +                 ? VerifyType.canPassUnchecked(src, dest)
  26.415 +                 : VerifyType.canPassRaw(src, dest)
  26.416 +                ) <= 0) {
  26.417 +                // found a difference; is it the only one so far?
  26.418 +                if (res != 0)
  26.419 +                    return -1-res; // return -2-i for prev. i
  26.420 +                res = 1+i;
  26.421 +            }
  26.422 +        }
  26.423 +        return res;
  26.424 +    }
  26.425 +
  26.426 +    /** Can a retyping adapter (alone) validly convert the target to newType? */
  26.427 +    public static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
  26.428 +        return canRetypeOnly(newType, targetType, false);
  26.429 +    }
  26.430 +    /** Can a retyping adapter (alone) convert the target to newType?
  26.431 +     *  It is allowed to widen subword types and void to int, to make bitwise
  26.432 +     *  conversions between float/int and double/long, and to perform unchecked
  26.433 +     *  reference conversions on return.  This last feature requires that the
  26.434 +     *  caller be trusted, and perform explicit cast conversions on return values.
  26.435 +     */
  26.436 +    static boolean canRawRetypeOnly(MethodType newType, MethodType targetType) {
  26.437 +        return canRetypeOnly(newType, targetType, true);
  26.438 +    }
  26.439 +    static boolean canRetypeOnly(MethodType newType, MethodType targetType, boolean raw) {
  26.440 +        if (!convOpSupported(OP_RETYPE_ONLY))  return false;
  26.441 +        int diff = diffTypes(newType, targetType, raw);
  26.442 +        // %%% This assert is too strong.  Factor diff into VerifyType and reconcile.
  26.443 +        assert((diff == 0) == VerifyType.isNullConversion(newType, targetType));
  26.444 +        return diff == 0;
  26.445 +    }
  26.446 +
  26.447 +    /** Factory method:  Performs no conversions; simply retypes the adapter.
  26.448 +     *  Allows unchecked argument conversions pairwise, if they are safe.
  26.449 +     *  Returns null if not possible.
  26.450 +     */
  26.451 +    public static MethodHandle makeRetypeOnly(Access token,
  26.452 +                MethodType newType, MethodHandle target) {
  26.453 +        return makeRetypeOnly(token, newType, target, false);
  26.454 +    }
  26.455 +    public static MethodHandle makeRawRetypeOnly(Access token,
  26.456 +                MethodType newType, MethodHandle target) {
  26.457 +        return makeRetypeOnly(token, newType, target, true);
  26.458 +    }
  26.459 +    static MethodHandle makeRetypeOnly(Access token,
  26.460 +                MethodType newType, MethodHandle target, boolean raw) {
  26.461 +        Access.check(token);
  26.462 +        if (!canRetypeOnly(newType, target.type(), raw))
  26.463 +            return null;
  26.464 +        // TO DO:  clone the target guy, whatever he is, with new type.
  26.465 +        return new AdapterMethodHandle(target, newType, makeConv(OP_RETYPE_ONLY));
  26.466 +    }
  26.467 +
  26.468 +    /** Can a checkcast adapter validly convert the target to newType?
  26.469 +     *  The JVM supports all kind of reference casts, even silly ones.
  26.470 +     */
  26.471 +    public static boolean canCheckCast(MethodType newType, MethodType targetType,
  26.472 +                int arg, Class<?> castType) {
  26.473 +        if (!convOpSupported(OP_CHECK_CAST))  return false;
  26.474 +        Class<?> src = newType.parameterType(arg);
  26.475 +        Class<?> dst = targetType.parameterType(arg);
  26.476 +        if (!canCheckCast(src, castType)
  26.477 +                || !VerifyType.isNullConversion(castType, dst))
  26.478 +            return false;
  26.479 +        int diff = diffTypes(newType, targetType, false);
  26.480 +        return (diff == arg+1);  // arg is sole non-trivial diff
  26.481 +    }
  26.482 +    /** Can an primitive conversion adapter validly convert src to dst? */
  26.483 +    public static boolean canCheckCast(Class<?> src, Class<?> dst) {
  26.484 +        return (!src.isPrimitive() && !dst.isPrimitive());
  26.485 +    }
  26.486 +
  26.487 +    /** Factory method:  Forces a cast at the given argument.
  26.488 +     *  The castType is the target of the cast, and can be any type
  26.489 +     *  with a null conversion to the corresponding target parameter.
  26.490 +     *  Return null if this cannot be done.
  26.491 +     */
  26.492 +    public static MethodHandle makeCheckCast(Access token,
  26.493 +                MethodType newType, MethodHandle target,
  26.494 +                int arg, Class<?> castType) {
  26.495 +        Access.check(token);
  26.496 +        if (!canCheckCast(newType, target.type(), arg, castType))
  26.497 +            return null;
  26.498 +        long conv = makeConv(OP_CHECK_CAST, arg, 0);
  26.499 +        return new AdapterMethodHandle(target, newType, conv, castType);
  26.500 +    }
  26.501 +
  26.502 +    /** Can an primitive conversion adapter validly convert the target to newType?
  26.503 +     *  The JVM currently supports all conversions except those between
  26.504 +     *  floating and integral types.
  26.505 +     */
  26.506 +    public static boolean canPrimCast(MethodType newType, MethodType targetType,
  26.507 +                int arg, Class<?> convType) {
  26.508 +        if (!convOpSupported(OP_PRIM_TO_PRIM))  return false;
  26.509 +        Class<?> src = newType.parameterType(arg);
  26.510 +        Class<?> dst = targetType.parameterType(arg);
  26.511 +        if (!canPrimCast(src, convType)
  26.512 +                || !VerifyType.isNullConversion(convType, dst))
  26.513 +            return false;
  26.514 +        int diff = diffTypes(newType, targetType, false);
  26.515 +        return (diff == arg+1);  // arg is sole non-trivial diff
  26.516 +    }
  26.517 +    /** Can an primitive conversion adapter validly convert src to dst? */
  26.518 +    public static boolean canPrimCast(Class<?> src, Class<?> dst) {
  26.519 +        if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
  26.520 +            return false;
  26.521 +        } else if (Wrapper.forPrimitiveType(dst).isFloating()) {
  26.522 +            // both must be floating types
  26.523 +            return Wrapper.forPrimitiveType(src).isFloating();
  26.524 +        } else {
  26.525 +            // both are integral, and all combinations work fine
  26.526 +            assert(Wrapper.forPrimitiveType(src).isIntegral() &&
  26.527 +                   Wrapper.forPrimitiveType(dst).isIntegral());
  26.528 +            return true;
  26.529 +        }
  26.530 +    }
  26.531 +
  26.532 +    /** Factory method:  Truncate the given argument with zero or sign extension,
  26.533 +     *  and/or convert between single and doubleword versions of integer or float.
  26.534 +     *  The convType is the target of the conversion, and can be any type
  26.535 +     *  with a null conversion to the corresponding target parameter.
  26.536 +     *  Return null if this cannot be done.
  26.537 +     */
  26.538 +    public static MethodHandle makePrimCast(Access token,
  26.539 +                MethodType newType, MethodHandle target,
  26.540 +                int arg, Class<?> convType) {
  26.541 +        Access.check(token);
  26.542 +        MethodType oldType = target.type();
  26.543 +        Class<?> src = newType.parameterType(arg);
  26.544 +        Class<?> dst = oldType.parameterType(arg);
  26.545 +        if (!canPrimCast(newType, oldType, arg, convType))
  26.546 +            return null;
  26.547 +        long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType));
  26.548 +        return new AdapterMethodHandle(target, newType, conv);
  26.549 +    }
  26.550 +
  26.551 +    /** Can an unboxing conversion validly convert src to dst?
  26.552 +     *  The JVM currently supports all kinds of casting and unboxing.
  26.553 +     *  The convType is the unboxed type; it can be either a primitive or wrapper.
  26.554 +     */
  26.555 +    public static boolean canUnboxArgument(MethodType newType, MethodType targetType,
  26.556 +                int arg, Class<?> convType) {
  26.557 +        if (!convOpSupported(OP_REF_TO_PRIM))  return false;
  26.558 +        Class<?> src = newType.parameterType(arg);
  26.559 +        Class<?> dst = targetType.parameterType(arg);
  26.560 +        Class<?> boxType = Wrapper.asWrapperType(convType);
  26.561 +        convType = Wrapper.asPrimitiveType(convType);
  26.562 +        if (!canCheckCast(src, boxType)
  26.563 +                || boxType == convType
  26.564 +                || !VerifyType.isNullConversion(convType, dst))
  26.565 +            return false;
  26.566 +        int diff = diffTypes(newType, targetType, false);
  26.567 +        return (diff == arg+1);  // arg is sole non-trivial diff
  26.568 +    }
  26.569 +    /** Can an primitive unboxing adapter validly convert src to dst? */
  26.570 +    public static boolean canUnboxArgument(Class<?> src, Class<?> dst) {
  26.571 +        return (!src.isPrimitive() && Wrapper.asPrimitiveType(dst).isPrimitive());
  26.572 +    }
  26.573 +
  26.574 +    /** Factory method:  Unbox the given argument.
  26.575 +     *  Return null if this cannot be done.
  26.576 +     */
  26.577 +    public static MethodHandle makeUnboxArgument(Access token,
  26.578 +                MethodType newType, MethodHandle target,
  26.579 +                int arg, Class<?> convType) {
  26.580 +        MethodType oldType = target.type();
  26.581 +        Class<?> src = newType.parameterType(arg);
  26.582 +        Class<?> dst = oldType.parameterType(arg);
  26.583 +        Class<?> boxType = Wrapper.asWrapperType(convType);
  26.584 +        Class<?> primType = Wrapper.asPrimitiveType(convType);
  26.585 +        if (!canUnboxArgument(newType, oldType, arg, convType))
  26.586 +            return null;
  26.587 +        MethodType castDone = newType;
  26.588 +        if (!VerifyType.isNullConversion(src, boxType))
  26.589 +            castDone = newType.changeParameterType(arg, boxType);
  26.590 +        long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
  26.591 +        MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
  26.592 +        if (castDone == newType)
  26.593 +            return adapter;
  26.594 +        return makeCheckCast(token, newType, adapter, arg, boxType);
  26.595 +    }
  26.596 +
  26.597 +    /** Can an primitive boxing adapter validly convert src to dst? */
  26.598 +    public static boolean canBoxArgument(Class<?> src, Class<?> dst) {
  26.599 +        if (!convOpSupported(OP_PRIM_TO_REF))  return false;
  26.600 +        throw new UnsupportedOperationException("NYI");
  26.601 +    }
  26.602 +
  26.603 +    /** Factory method:  Unbox the given argument.
  26.604 +     *  Return null if this cannot be done.
  26.605 +     */
  26.606 +    public static MethodHandle makeBoxArgument(Access token,
  26.607 +                MethodType newType, MethodHandle target,
  26.608 +                int arg, Class<?> convType) {
  26.609 +        // this is difficult to do in the JVM because it must GC
  26.610 +        return null;
  26.611 +    }
  26.612 +
  26.613 +    // TO DO: makeSwapArguments, makeRotateArguments, makeDuplicateArguments
  26.614 +
  26.615 +    /** Can an adapter simply drop arguments to convert the target to newType? */
  26.616 +    public static boolean canDropArguments(MethodType newType, MethodType targetType,
  26.617 +                int dropArgPos, int dropArgCount) {
  26.618 +        if (dropArgCount == 0)
  26.619 +            return canRetypeOnly(newType, targetType);
  26.620 +        if (!convOpSupported(OP_DROP_ARGS))  return false;
  26.621 +        if (diffReturnTypes(newType, targetType, false) != 0)
  26.622 +            return false;
  26.623 +        int nptypes = newType.parameterCount();
  26.624 +        // parameter types must be the same up to the drop point
  26.625 +        if (dropArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, dropArgPos, false) != 0)
  26.626 +            return false;
  26.627 +        int afterPos = dropArgPos + dropArgCount;
  26.628 +        int afterCount = nptypes - afterPos;
  26.629 +        if (dropArgPos < 0 || dropArgPos >= nptypes ||
  26.630 +            dropArgCount < 1 || afterPos > nptypes ||
  26.631 +            targetType.parameterCount() != nptypes - dropArgCount)
  26.632 +            return false;
  26.633 +        // parameter types after the drop point must also be the same
  26.634 +        if (afterCount != 0 && diffParamTypes(newType, afterPos, targetType, dropArgPos, afterCount, false) != 0)
  26.635 +            return false;
  26.636 +        return true;
  26.637 +    }
  26.638 +
  26.639 +    /** Factory method:  Drop selected arguments.
  26.640 +     *  Allow unchecked retyping of remaining arguments, pairwise.
  26.641 +     *  Return null if this is not possible.
  26.642 +     */
  26.643 +    public static MethodHandle makeDropArguments(Access token,
  26.644 +                MethodType newType, MethodHandle target,
  26.645 +                int dropArgPos, int dropArgCount) {
  26.646 +        Access.check(token);
  26.647 +        if (dropArgCount == 0)
  26.648 +            return makeRetypeOnly(IMPL_TOKEN, newType, target);
  26.649 +        MethodType mt = target.type();
  26.650 +        int argCount  = mt.parameterCount();
  26.651 +        if (!canDropArguments(newType, mt, dropArgPos, dropArgCount))
  26.652 +            return null;
  26.653 +        int dropSlotCount, dropSlotPos;
  26.654 +        if (dropArgCount >= argCount) {
  26.655 +            assert(dropArgPos == argCount-1);
  26.656 +            dropSlotPos = 0;
  26.657 +            dropSlotCount = mt.parameterSlotCount();
  26.658 +        } else {
  26.659 +            // arglist: [0: keep... | dpos: drop... | dpos+dcount: keep... ]
  26.660 +            int lastDroppedArg = dropArgPos + dropArgCount - 1;
  26.661 +            int lastKeptArg    = dropArgPos - 1;  // might be -1, which is OK
  26.662 +            dropSlotPos      = mt.parameterSlotDepth(1+lastDroppedArg);
  26.663 +            int lastKeptSlot = mt.parameterSlotDepth(1+lastKeptArg);
  26.664 +            dropSlotCount = lastKeptSlot - dropSlotPos;
  26.665 +            assert(dropSlotCount >= dropArgCount);
  26.666 +        }
  26.667 +        long conv = makeConv(OP_DROP_ARGS, dropArgPos, +dropSlotCount);
  26.668 +        return new AdapterMethodHandle(target, newType, dropSlotCount, conv);
  26.669 +    }
  26.670 +
  26.671 +    /** Can an adapter spread an argument to convert the target to newType? */
  26.672 +    public static boolean canSpreadArguments(MethodType newType, MethodType targetType,
  26.673 +                Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
  26.674 +        if (!convOpSupported(OP_SPREAD_ARGS))  return false;
  26.675 +        if (diffReturnTypes(newType, targetType, false) != 0)
  26.676 +            return false;
  26.677 +        int nptypes = newType.parameterCount();
  26.678 +        // parameter types must be the same up to the spread point
  26.679 +        if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
  26.680 +            return false;
  26.681 +        int afterPos = spreadArgPos + spreadArgCount;
  26.682 +        int afterCount = nptypes - afterPos;
  26.683 +        if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
  26.684 +            spreadArgCount < 0 ||
  26.685 +            targetType.parameterCount() != nptypes - 1 + spreadArgCount)
  26.686 +            return false;
  26.687 +        // parameter types after the spread point must also be the same
  26.688 +        if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0)
  26.689 +            return false;
  26.690 +        // match the array element type to the spread arg types
  26.691 +        Class<?> rawSpreadArgType = newType.parameterType(spreadArgPos);
  26.692 +        if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType))
  26.693 +            return false;
  26.694 +        for (int i = 0; i < spreadArgCount; i++) {
  26.695 +            Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i);
  26.696 +            Class<?> dst = targetType.parameterType(spreadArgPos + i);
  26.697 +            if (src == null || !VerifyType.isNullConversion(src, dst))
  26.698 +                return false;
  26.699 +        }
  26.700 +        return true;
  26.701 +    }
  26.702 +
  26.703 +    /** Factory method:  Spread selected argument. */
  26.704 +    public static MethodHandle makeSpreadArguments(Access token,
  26.705 +                MethodType newType, MethodHandle target,
  26.706 +                Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
  26.707 +        Access.check(token);
  26.708 +        MethodType mt = target.type();
  26.709 +        int argCount  = mt.parameterCount();
  26.710 +        if (!canSpreadArguments(newType, mt, spreadArgType, spreadArgPos, spreadArgCount))
  26.711 +            return null;
  26.712 +        int spreadSlotCount, spreadSlotPos;
  26.713 +        if (spreadArgCount >= argCount) {
  26.714 +            assert(spreadArgPos == argCount-1);
  26.715 +            spreadSlotPos = 0;
  26.716 +            spreadSlotCount = mt.parameterSlotCount();
  26.717 +        } else {
  26.718 +            // arglist: [0: keep... | dpos: spread... | dpos+dcount: keep... ]
  26.719 +            int lastSpreadArg = spreadArgPos + spreadArgCount - 1;
  26.720 +            int lastKeptArg   = spreadArgPos - 1;  // might be -1, which is OK
  26.721 +            spreadSlotPos     = mt.parameterSlotDepth(1+lastSpreadArg);
  26.722 +            int lastKeptSlot  = mt.parameterSlotDepth(1+lastKeptArg);
  26.723 +            spreadSlotCount = lastKeptSlot - spreadSlotPos;
  26.724 +            assert(spreadSlotCount >= spreadArgCount);
  26.725 +        }
  26.726 +        long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, spreadSlotCount);
  26.727 +        return new AdapterMethodHandle(target, newType, conv, spreadArgType);
  26.728 +    }
  26.729 +
  26.730 +    // TO DO: makeCollectArguments, makeFlyby, makeRicochet
  26.731 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/src/share/classes/sun/dyn/BoundMethodHandle.java	Thu May 07 12:26:22 2009 -0700
    27.3 @@ -0,0 +1,180 @@
    27.4 +/*
    27.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.7 + *
    27.8 + * This code is free software; you can redistribute it and/or modify it
    27.9 + * under the terms of the GNU General Public License version 2 only, as
   27.10 + * published by the Free Software Foundation.  Sun designates this
   27.11 + * particular file as subject to the "Classpath" exception as provided
   27.12 + * by Sun in the LICENSE file that accompanied this code.
   27.13 + *
   27.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   27.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   27.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   27.17 + * version 2 for more details (a copy is included in the LICENSE file that
   27.18 + * accompanied this code).
   27.19 + *
   27.20 + * You should have received a copy of the GNU General Public License version
   27.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   27.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   27.23 + *
   27.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   27.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   27.26 + * have any questions.
   27.27 + */
   27.28 +
   27.29 +package sun.dyn;
   27.30 +
   27.31 +import sun.dyn.util.VerifyType;
   27.32 +import sun.dyn.util.Wrapper;
   27.33 +import java.dyn.*;
   27.34 +
   27.35 +/**
   27.36 + * The flavor of method handle which emulates an invoke instruction
   27.37 + * on a predetermined argument.  The JVM dispatches to the correct method
   27.38 + * when the handle is created, not when it is invoked.
   27.39 + * @author jrose
   27.40 + */
   27.41 +public class BoundMethodHandle extends MethodHandle  {
   27.42 +    //MethodHandle vmtarget;           // next BMH or final DMH or methodOop
   27.43 +    private final Object argument;     // argument to insert
   27.44 +    private final int    vmargslot;    // position at which it is inserted
   27.45 +
   27.46 +    // Constructors in this class *must* be package scoped or private.
   27.47 +
   27.48 +    /** Bind a direct MH to its receiver (or first ref. argument).
   27.49 +     *  The JVM will pre-dispatch the MH if it is not already static.
   27.50 +     */
   27.51 +    BoundMethodHandle(DirectMethodHandle mh, Object argument) {
   27.52 +        super(Access.TOKEN, mh.type().dropParameterType(0));
   27.53 +        // check the type now, once for all:
   27.54 +        this.argument = checkReferenceArgument(argument, mh, 0);
   27.55 +        this.vmargslot = this.type().parameterSlotCount();
   27.56 +        if (MethodHandleNatives.JVM_SUPPORT) {
   27.57 +            this.vmtarget = null;  // maybe updated by JVM
   27.58 +            MethodHandleNatives.init(this, mh, 0);
   27.59 +        } else {
   27.60 +            this.vmtarget = mh;
   27.61 +        }
   27.62 +     }
   27.63 +
   27.64 +    private static final int REF_ARG = 0, PRIM_ARG = 1, SELF_ARG = 2;
   27.65 +
   27.66 +    /** Insert an argument into an arbitrary method handle.
   27.67 +     *  If argnum is zero, inserts the first argument, etc.
   27.68 +     *  The argument type must be a reference.
   27.69 +     */
   27.70 +    BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
   27.71 +        this(mh, argument, argnum, mh.type().parameterType(argnum).isPrimitive() ? PRIM_ARG : REF_ARG);
   27.72 +    }
   27.73 +
   27.74 +    /** Insert an argument into an arbitrary method handle.
   27.75 +     *  If argnum is zero, inserts the first argument, etc.
   27.76 +     */
   27.77 +    BoundMethodHandle(MethodHandle mh, Object argument, int argnum, int whichArg) {
   27.78 +        super(Access.TOKEN, mh.type().dropParameterType(argnum));
   27.79 +        if (whichArg == PRIM_ARG)
   27.80 +            this.argument = bindPrimitiveArgument(argument, mh, argnum);
   27.81 +        else {
   27.82 +            if (whichArg == SELF_ARG)  argument = this;
   27.83 +            this.argument = checkReferenceArgument(argument, mh, argnum);
   27.84 +        }
   27.85 +        this.vmargslot = this.type().parameterSlotDepth(argnum);
   27.86 +        if (MethodHandleNatives.JVM_SUPPORT) {
   27.87 +            this.vmtarget = null;  // maybe updated by JVM
   27.88 +            MethodHandleNatives.init(this, mh, argnum);
   27.89 +        } else {
   27.90 +            this.vmtarget = mh;
   27.91 +        }
   27.92 +    }
   27.93 +
   27.94 +    /** For the AdapterMethodHandle subclass.
   27.95 +     */
   27.96 +    BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
   27.97 +        super(Access.TOKEN, type);
   27.98 +        this.argument = argument;
   27.99 +        this.vmargslot = vmargslot;
  27.100 +        assert(this.getClass() == AdapterMethodHandle.class);
  27.101 +    }
  27.102 +
  27.103 +    /** Initialize the current object as a method handle, binding it
  27.104 +     *  as the {@code argnum}th argument of the method handle {@code entryPoint}.
  27.105 +     *  The invocation type of the resulting method handle will be the
  27.106 +     *  same as {@code entryPoint},  except that the {@code argnum}th argument
  27.107 +     *  type will be dropped.
  27.108 +     */
  27.109 +    public BoundMethodHandle(MethodHandle entryPoint, int argnum) {
  27.110 +        this(entryPoint, null, argnum, SELF_ARG);
  27.111 +
  27.112 +        // Note:  If the conversion fails, perhaps because of a bad entryPoint,
  27.113 +        // the MethodHandle.type field will not be filled in, and therefore
  27.114 +        // no MH.invoke call will ever succeed.  The caller may retain a pointer
  27.115 +        // to the broken method handle, but no harm can be done with it.
  27.116 +    }
  27.117 +
  27.118 +    /** Initialize the current object as a method handle, binding it
  27.119 +     *  as the first argument of the method handle {@code entryPoint}.
  27.120 +     *  The invocation type of the resulting method handle will be the
  27.121 +     *  same as {@code entryPoint},  except that the first argument
  27.122 +     *  type will be dropped.
  27.123 +     */
  27.124 +    public BoundMethodHandle(MethodHandle entryPoint) {
  27.125 +        this(entryPoint, null, 0, SELF_ARG);
  27.126 +    }
  27.127 +
  27.128 +    /** Make sure the given {@code argument} can be used as {@code argnum}-th
  27.129 +     *  parameter of the given method handle {@code mh}, which must be a reference.
  27.130 +     *  <p>
  27.131 +     *  If this fails, throw a suitable {@code WrongMethodTypeException},
  27.132 +     *  which will prevent the creation of an illegally typed bound
  27.133 +     *  method handle.
  27.134 +     */
  27.135 +    final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
  27.136 +        Class<?> ptype = mh.type().parameterType(argnum);
  27.137 +        if (ptype.isPrimitive()) {
  27.138 +            // fail
  27.139 +        } else if (argument == null) {
  27.140 +            return null;
  27.141 +        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
  27.142 +            return argument;
  27.143 +        }
  27.144 +        throw badBoundArgumentException(argument, mh, argnum);
  27.145 +    }
  27.146 +
  27.147 +    /** Make sure the given {@code argument} can be used as {@code argnum}-th
  27.148 +     *  parameter of the given method handle {@code mh}, which must be a primitive.
  27.149 +     *  <p>
  27.150 +     *  If this fails, throw a suitable {@code WrongMethodTypeException},
  27.151 +     *  which will prevent the creation of an illegally typed bound
  27.152 +     *  method handle.
  27.153 +     */
  27.154 +    final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
  27.155 +        Class<?> ptype = mh.type().parameterType(argnum);
  27.156 +        Wrapper  wrap = Wrapper.forPrimitiveType(ptype);
  27.157 +        Object   zero  = wrap.zero();
  27.158 +        if (zero == null) {
  27.159 +            // fail
  27.160 +        } else if (argument == null) {
  27.161 +            if (ptype != int.class && wrap.isSubwordOrInt())
  27.162 +                return Integer.valueOf(0);
  27.163 +            else
  27.164 +                return zero;
  27.165 +        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
  27.166 +            if (ptype != int.class && wrap.isSubwordOrInt())
  27.167 +                return Wrapper.INT.wrap(argument);
  27.168 +            else
  27.169 +                return argument;
  27.170 +        }
  27.171 +        throw badBoundArgumentException(argument, mh, argnum);
  27.172 +    }
  27.173 +
  27.174 +    final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
  27.175 +        String atype = (argument == null) ? "null" : argument.getClass().toString();
  27.176 +        return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
  27.177 +    }
  27.178 +
  27.179 +    @Override
  27.180 +    public String toString() {
  27.181 +        return "Bound[" + super.toString() + "]";
  27.182 +    }
  27.183 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/share/classes/sun/dyn/CallSiteImpl.java	Thu May 07 12:26:22 2009 -0700
    28.3 @@ -0,0 +1,70 @@
    28.4 +/*
    28.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.7 + *
    28.8 + * This code is free software; you can redistribute it and/or modify it
    28.9 + * under the terms of the GNU General Public License version 2 only, as
   28.10 + * published by the Free Software Foundation.  Sun designates this
   28.11 + * particular file as subject to the "Classpath" exception as provided
   28.12 + * by Sun in the LICENSE file that accompanied this code.
   28.13 + *
   28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.17 + * version 2 for more details (a copy is included in the LICENSE file that
   28.18 + * accompanied this code).
   28.19 + *
   28.20 + * You should have received a copy of the GNU General Public License version
   28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.23 + *
   28.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   28.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   28.26 + * have any questions.
   28.27 + */
   28.28 +
   28.29 +package sun.dyn;
   28.30 +
   28.31 +import java.dyn.*;
   28.32 +
   28.33 +/**
   28.34 + * The CallSite privately created by the JVM at every invokedynamic instruction.
   28.35 + * @author jrose
   28.36 + */
   28.37 +class CallSiteImpl extends CallSite {
   28.38 +    // Fields used only by the JVM.  Do not use or change.
   28.39 +    private Object vmmethod;
   28.40 +
   28.41 +    // Values supplied by the JVM:
   28.42 +    int callerMID, callerBCI;
   28.43 +
   28.44 +    private CallSiteImpl(Class<?> caller, String name, MethodType type) {
   28.45 +        super(caller, name, type);
   28.46 +    }
   28.47 +
   28.48 +    @Override
   28.49 +    public void setTarget(MethodHandle mh) {
   28.50 +        checkTarget(mh);
   28.51 +        if (MethodHandleNatives.JVM_SUPPORT)
   28.52 +            MethodHandleNatives.linkCallSite(this, (MethodHandle) mh);
   28.53 +        else
   28.54 +            super.setTarget(mh);
   28.55 +    }
   28.56 +
   28.57 +    private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
   28.58 +            MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite",
   28.59 +                MethodType.make(void.class, CallSite.class, int.class, int.class));
   28.60 +
   28.61 +    // this is the up-call from the JVM:
   28.62 +    static CallSite makeSite(Class<?> caller, String name, MethodType type,
   28.63 +                             int callerMID, int callerBCI) {
   28.64 +        MethodHandle bsm = Linkage.getBootstrapMethod(caller);
   28.65 +        if (bsm == null)
   28.66 +            throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller);
   28.67 +        CallSite site = bsm.<CallSite>invoke(caller, name, type);
   28.68 +        if (site == null)
   28.69 +            throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller);
   28.70 +        PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI);
   28.71 +        return site;
   28.72 +    }
   28.73 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/src/share/classes/sun/dyn/DirectMethodHandle.java	Thu May 07 12:26:22 2009 -0700
    29.3 @@ -0,0 +1,56 @@
    29.4 +/*
    29.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.  Sun designates this
   29.11 + * particular file as subject to the "Classpath" exception as provided
   29.12 + * by Sun in the LICENSE file that accompanied this code.
   29.13 + *
   29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.17 + * version 2 for more details (a copy is included in the LICENSE file that
   29.18 + * accompanied this code).
   29.19 + *
   29.20 + * You should have received a copy of the GNU General Public License version
   29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.23 + *
   29.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   29.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   29.26 + * have any questions.
   29.27 + */
   29.28 +
   29.29 +package sun.dyn;
   29.30 +
   29.31 +import java.dyn.*;
   29.32 +import static sun.dyn.MethodHandleNatives.Constants.*;
   29.33 +
   29.34 +/**
   29.35 + * The flavor of method handle which emulates invokespecial or invokestatic.
   29.36 + * @author jrose
   29.37 + */
   29.38 +class DirectMethodHandle extends MethodHandle {
   29.39 +    //inherited oop    vmtarget;    // methodOop or virtual class/interface oop
   29.40 +    private final int  vmindex;     // method index within class or interface
   29.41 +    { vmindex = VM_INDEX_UNINITIALIZED; }  // JVM may change this
   29.42 +
   29.43 +    // Constructors in this class *must* be package scoped or private.
   29.44 +    DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) {
   29.45 +        super(Access.TOKEN, mtype);
   29.46 +
   29.47 +        assert(m.isMethod() || !doDispatch && m.isConstructor());
   29.48 +        if (!m.isResolved())
   29.49 +            throw new InternalError();
   29.50 +
   29.51 +        // Null check and replace privilege token (as passed to JVM) with null.
   29.52 +        if (lookupClass.equals(Access.class))  lookupClass = null;
   29.53 +        MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
   29.54 +    }
   29.55 +
   29.56 +    boolean isValid() {
   29.57 +        return (vmindex != VM_INDEX_UNINITIALIZED);
   29.58 +    }
   29.59 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/src/share/classes/sun/dyn/FilterGeneric.java	Thu May 07 12:26:22 2009 -0700
    30.3 @@ -0,0 +1,338 @@
    30.4 +/*
    30.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 + *
    30.8 + * This code is free software; you can redistribute it and/or modify it
    30.9 + * under the terms of the GNU General Public License version 2 only, as
   30.10 + * published by the Free Software Foundation.  Sun designates this
   30.11 + * particular file as subject to the "Classpath" exception as provided
   30.12 + * by Sun in the LICENSE file that accompanied this code.
   30.13 + *
   30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.17 + * version 2 for more details (a copy is included in the LICENSE file that
   30.18 + * accompanied this code).
   30.19 + *
   30.20 + * You should have received a copy of the GNU General Public License version
   30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.22 + * Inc., 51 Franklin Sf, tifth Floor, Boston, MA 02110-1301 USA.
   30.23 + *
   30.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   30.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   30.26 + * have any questions.
   30.27 + */
   30.28 +
   30.29 +package sun.dyn;
   30.30 +
   30.31 +import java.dyn.JavaMethodHandle;
   30.32 +import java.dyn.MethodHandle;
   30.33 +import java.dyn.MethodType;
   30.34 +import java.dyn.NoAccessException;
   30.35 +import java.lang.reflect.Constructor;
   30.36 +import java.lang.reflect.InvocationTargetException;
   30.37 +
   30.38 +/**
   30.39 + * "Flyby adapters" which apply arbitrary conversions to arguments
   30.40 + * on the way to a ultimate target.
   30.41 + * For simplicity, these are all generically typed.
   30.42 + * @author jrose
   30.43 + */
   30.44 +class FilterGeneric {
   30.45 +    // type for the outgoing call (will be generic)
   30.46 +    private final MethodType targetType;
   30.47 +    // position of (first) argument to participate in filtering
   30.48 +    private final short argumentPosition;
   30.49 +    // number of arguments to participate in filtering
   30.50 +    private final short argumentCount;
   30.51 +    // how the result interacts with the filtered arguments: Prepend, Append, Replace, Discard
   30.52 +    private final char replaceMode;
   30.53 +    // prototype adapter (clone and customize for each new target & conversion!)
   30.54 +    private final Adapter adapter;
   30.55 +    // entry point for adapter (Adapter mh, a...) => ...
   30.56 +    private final MethodHandle entryPoint;
   30.57 +    // more of them (loosely cached)
   30.58 +    private FilterGeneric variations;
   30.59 +
   30.60 +    /** Compute and cache information common to all unboxing adapters
   30.61 +     *  that can call out to targets of the erasure-family of the given erased type.
   30.62 +     */
   30.63 +    // TO DO: Make this private.
   30.64 +    FilterGeneric(MethodType targetType, short argumentPosition, short argumentCount, char replaceMode) {
   30.65 +        if (argumentCount == 0) {
   30.66 +            if (replaceMode == 'P' || replaceMode == 'A')  replaceMode = 'R';
   30.67 +            if (replaceMode == 'I')  argumentPosition = 0;
   30.68 +        }
   30.69 +        this.targetType = targetType;
   30.70 +        this.argumentPosition = argumentPosition;
   30.71 +        this.argumentCount = argumentCount;
   30.72 +        this.replaceMode = replaceMode;
   30.73 +        validate(targetType, argumentPosition, argumentCount, replaceMode);
   30.74 +        Adapter ad = findAdapter(targetType, argumentPosition, argumentCount, replaceMode, filterType());
   30.75 +        if (ad == null)
   30.76 +            ad = buildAdapterFromBytecodes(targetType, argumentPosition, argumentCount, replaceMode, filterType());
   30.77 +        this.adapter = ad;
   30.78 +        this.entryPoint = ad.prototypeEntryPoint();
   30.79 +    }
   30.80 +
   30.81 +    Adapter makeInstance(MethodHandle filter, MethodHandle target) {
   30.82 +        return adapter.makeInstance(entryPoint, filter, target);
   30.83 +    }
   30.84 +
   30.85 +    /** Build an adapter of the given generic type, which invokes typedTarget
   30.86 +     *  on the incoming arguments, after unboxing as necessary.
   30.87 +     *  The return value is boxed if necessary.
   30.88 +     * @param genericType  the required type of the result
   30.89 +     * @param typedTarget the target
   30.90 +     * @return an adapter method handle
   30.91 +     */
   30.92 +    public static MethodHandle make(MethodHandle target, int pos, MethodHandle filter) {
   30.93 +        return FilterGeneric.of(target.type(), (short)pos, (short)1, 'R').makeInstance(filter, target);
   30.94 +    }
   30.95 +
   30.96 +    /** Return the adapter information for this type's erasure. */
   30.97 +    static FilterGeneric of(MethodType type, short ap, short ac, char mode) {
   30.98 +        if (type.generic() != type)
   30.99 +            throw new IllegalArgumentException("must be generic: "+type);
  30.100 +        validate(type, ap, ac, mode);
  30.101 +        MethodTypeImpl form = MethodTypeImpl.of(type);
  30.102 +        FilterGeneric filterGen = form.filterGeneric;
  30.103 +        if (filterGen == null)
  30.104 +            form.filterGeneric = filterGen = new FilterGeneric(type, (short)0, (short)1, 'R');
  30.105 +        return find(filterGen, ap, ac, mode);
  30.106 +    }
  30.107 +
  30.108 +    static FilterGeneric find(FilterGeneric gen, short ap, short ac, char mode) {
  30.109 +        for (;;) {
  30.110 +            if (gen.argumentPosition == ap &&
  30.111 +                gen.argumentCount == ac &&
  30.112 +                gen.replaceMode == mode) {
  30.113 +                return gen;
  30.114 +            }
  30.115 +            FilterGeneric gen2 = gen.variations;
  30.116 +            if (gen2 == null)  break;
  30.117 +            gen = gen2;
  30.118 +        }
  30.119 +        FilterGeneric gen2 = new FilterGeneric(gen.targetType, ap, ac, mode);
  30.120 +        gen.variations = gen2;  // OK if this smashes another cached chain
  30.121 +        return gen2;
  30.122 +    }
  30.123 +
  30.124 +    private static void validate(MethodType type, short ap, short ac, char mode) {
  30.125 +        int endpos = ap + ac;
  30.126 +        switch (mode) {
  30.127 +            case 'P': case 'A': case 'R': case 'D':
  30.128 +                if (ap >= 0 && ac >= 0 &&
  30.129 +                        endpos >= 0 && endpos <= type.parameterCount())
  30.130 +                    return;
  30.131 +            default:
  30.132 +                throw new InternalError("configuration "+patternName(ap, ac, mode));
  30.133 +        }
  30.134 +    }
  30.135 +
  30.136 +    public String toString() {
  30.137 +        return "FilterGeneric/"+patternName()+targetType;
  30.138 +    }
  30.139 +
  30.140 +    String patternName() {
  30.141 +        return patternName(argumentPosition, argumentCount, replaceMode);
  30.142 +    }
  30.143 +
  30.144 +    static String patternName(short ap, short ac, char mode) {
  30.145 +        return ""+mode+ap+(ac>1?"_"+ac:"");
  30.146 +    }
  30.147 +
  30.148 +    Class<?> filterType() {
  30.149 +        return Object.class;  // result of filter operation; an uninteresting type
  30.150 +    }
  30.151 +
  30.152 +    static MethodType targetType(MethodType entryType, short ap, short ac, char mode,
  30.153 +                                 Class<?> arg) {
  30.154 +        MethodType type = entryType;
  30.155 +        int pos = ap;
  30.156 +        switch (mode) {
  30.157 +            case 'A':
  30.158 +                pos += ac;
  30.159 +            case 'P':
  30.160 +                type = type.insertParameterType(pos, arg);
  30.161 +                break;
  30.162 +            case 'I':
  30.163 +                for (int i = 1; i < ac; i++)
  30.164 +                    type = type.dropParameterType(pos);
  30.165 +                assert(type.parameterType(pos) == arg);
  30.166 +                break;
  30.167 +            case 'D':
  30.168 +                break;
  30.169 +        }
  30.170 +        return type;
  30.171 +    }
  30.172 +
  30.173 +    static MethodType entryType(MethodType targetType, short ap, short ac, char mode,
  30.174 +                                Class<?> arg) {
  30.175 +        MethodType type = targetType;
  30.176 +        int pos = ap;
  30.177 +        switch (mode) {
  30.178 +            case 'A':
  30.179 +                pos += ac;
  30.180 +            case 'P':
  30.181 +                type = type.dropParameterType(pos);
  30.182 +                break;
  30.183 +            case 'I':
  30.184 +                for (int i = 1; i < ac; i++)
  30.185 +                    type = type.insertParameterType(pos, arg);
  30.186 +                assert(type.parameterType(pos) == arg);
  30.187 +                break;
  30.188 +            case 'D':
  30.189 +                break;
  30.190 +        }
  30.191 +        return type;
  30.192 +    }
  30.193 +
  30.194 +    /* Create an adapter that handles spreading calls for the given type. */
  30.195 +    static Adapter findAdapter(MethodType targetType, short ap, short ac, char mode, Class<?> arg) {
  30.196 +        MethodType entryType = entryType(targetType, ap, ac, mode, arg);
  30.197 +        int argc = targetType.parameterCount();
  30.198 +        String pname = patternName(ap, ac, mode);
  30.199 +        String cname0 = "F"+argc;
  30.200 +        String cname1 = "F"+argc+mode;
  30.201 +        String cname2 = "F"+argc+pname;
  30.202 +        String[] cnames = { cname0, cname1, cname1+"X", cname2 };
  30.203 +        String iname = "invoke_"+pname;
  30.204 +        // e.g., F5R; invoke_R3
  30.205 +        for (String cname : cnames) {
  30.206 +            Class<? extends Adapter> acls = Adapter.findSubClass(cname);
  30.207 +            if (acls == null)  continue;
  30.208 +            // see if it has the required invoke method
  30.209 +            MethodHandle entryPoint = null;
  30.210 +            try {
  30.211 +                entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
  30.212 +            } catch (NoAccessException ex) {
  30.213 +            }
  30.214 +            if (entryPoint == null)  continue;
  30.215 +            Constructor<? extends Adapter> ctor = null;
  30.216 +            try {
  30.217 +                ctor = acls.getDeclaredConstructor(MethodHandle.class);
  30.218 +            } catch (NoSuchMethodException ex) {
  30.219 +            } catch (SecurityException ex) {
  30.220 +            }
  30.221 +            if (ctor == null)  continue;
  30.222 +            try {
  30.223 +                // Produce an instance configured as a prototype.
  30.224 +                return ctor.newInstance(entryPoint);
  30.225 +            } catch (IllegalArgumentException ex) {
  30.226 +            } catch (InvocationTargetException ex) {
  30.227 +            } catch (InstantiationException ex) {
  30.228 +            } catch (IllegalAccessException ex) {
  30.229 +            }
  30.230 +        }
  30.231 +        return null;
  30.232 +    }
  30.233 +
  30.234 +    static Adapter buildAdapterFromBytecodes(MethodType targetType, short ap, short ac, char mode, Class<?> arg) {
  30.235 +        throw new UnsupportedOperationException("NYI");
  30.236 +    }
  30.237 +
  30.238 +    /**
  30.239 +     * This adapter takes some untyped arguments, and returns an untyped result.
  30.240 +     * Internally, it applies the invoker to the target, which causes the
  30.241 +     * objects to be unboxed; the result is a raw type in L/I/J/F/D.
  30.242 +     * This result is passed to convert, which is responsible for
  30.243 +     * converting the raw result into a boxed object.
  30.244 +     * The invoker is kept separate from the target because it can be
  30.245 +     * generated once per type erasure family, and reused across adapters.
  30.246 +     */
  30.247 +    static abstract class Adapter extends JavaMethodHandle {
  30.248 +        protected final MethodHandle filter;
  30.249 +        protected final MethodHandle target;
  30.250 +
  30.251 +        protected boolean isPrototype() { return target == null; }
  30.252 +        protected Adapter(MethodHandle entryPoint) {
  30.253 +            this(entryPoint, entryPoint, null);
  30.254 +            assert(isPrototype());
  30.255 +        }
  30.256 +        protected MethodHandle prototypeEntryPoint() {
  30.257 +            if (!isPrototype())  throw new InternalError();
  30.258 +            return filter;
  30.259 +        }
  30.260 +
  30.261 +        protected Adapter(MethodHandle entryPoint,
  30.262 +                          MethodHandle filter, MethodHandle target) {
  30.263 +            super(entryPoint);
  30.264 +            this.filter = filter;
  30.265 +            this.target = target;
  30.266 +        }
  30.267 +
  30.268 +        /** Make a copy of self, with new fields. */
  30.269 +        protected abstract Adapter makeInstance(MethodHandle entryPoint,
  30.270 +                MethodHandle filter, MethodHandle target);
  30.271 +        // { return new ThisType(entryPoint, filter, target); }
  30.272 +
  30.273 +        static private final String CLASS_PREFIX; // "sun.dyn.FilterGeneric$"
  30.274 +        static {
  30.275 +            String aname = Adapter.class.getName();
  30.276 +            String sname = Adapter.class.getSimpleName();
  30.277 +            if (!aname.endsWith(sname))  throw new InternalError();
  30.278 +            CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
  30.279 +        }
  30.280 +        /** Find a sibing class of Adapter. */
  30.281 +        static Class<? extends Adapter> findSubClass(String name) {
  30.282 +            String cname = Adapter.CLASS_PREFIX + name;
  30.283 +            try {
  30.284 +                return Class.forName(cname).asSubclass(Adapter.class);
  30.285 +            } catch (ClassNotFoundException ex) {
  30.286 +                return null;
  30.287 +            } catch (ClassCastException ex) {
  30.288 +                return null;
  30.289 +            }
  30.290 +        }
  30.291 +    }
  30.292 +
  30.293 +    //* generated classes follow this pattern:
  30.294 +    static class F1RX extends Adapter {
  30.295 +        protected F1RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  30.296 +        protected F1RX(MethodHandle e, MethodHandle f, MethodHandle t)
  30.297 +                        { super(e, f, t); }
  30.298 +        protected F1RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
  30.299 +                        { return new F1RX(e, f, t); }
  30.300 +        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
  30.301 +        protected Object target(Object a0) { return target.<Object>invoke(a0); }
  30.302 +        protected Object invoke_R0(Object a0) { return target(filter(a0)); }
  30.303 +    }
  30.304 +    static class F2RX extends Adapter {
  30.305 +        protected F2RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  30.306 +        protected F2RX(MethodHandle e, MethodHandle f, MethodHandle t)
  30.307 +                        { super(e, f, t); }
  30.308 +        protected F2RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
  30.309 +                        { return new F2RX(e, f, t); }
  30.310 +        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
  30.311 +        protected Object target(Object a0, Object a1) { return target.<Object>invoke(a0, a1); }
  30.312 +        protected Object invoke_R0(Object a0, Object a1) { return target(filter(a0), a1); }
  30.313 +        protected Object invoke_R1(Object a0, Object a1) { return target(a0, filter(a1)); }
  30.314 +    }
  30.315 +    static class F3RX extends Adapter {
  30.316 +        protected F3RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  30.317 +        protected F3RX(MethodHandle e, MethodHandle f, MethodHandle t)
  30.318 +                        { super(e, f, t); }
  30.319 +        protected F3RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
  30.320 +                        { return new F3RX(e, f, t); }
  30.321 +        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
  30.322 +        protected Object target(Object a0, Object a1, Object a2) { return target.<Object>invoke(a0, a1, a2); }
  30.323 +        protected Object invoke_R0(Object a0, Object a1, Object a2) { return target(filter(a0), a1, a2); }
  30.324 +        protected Object invoke_R1(Object a0, Object a1, Object a2) { return target(a0, filter(a1), a2); }
  30.325 +        protected Object invoke_R2(Object a0, Object a1, Object a2) { return target(a0, a1, filter(a2)); }
  30.326 +    }
  30.327 +    static class F4RX extends Adapter {
  30.328 +        protected F4RX(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  30.329 +        protected F4RX(MethodHandle e, MethodHandle f, MethodHandle t)
  30.330 +                        { super(e, f, t); }
  30.331 +        protected F4RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
  30.332 +                        { return new F4RX(e, f, t); }
  30.333 +        protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
  30.334 +        protected Object target(Object a0, Object a1, Object a2, Object a3) { return target.<Object>invoke(a0, a1, a2, a3); }
  30.335 +        protected Object invoke_R0(Object a0, Object a1, Object a2, Object a3) { return target(filter(a0), a1, a2, a3); }
  30.336 +        protected Object invoke_R1(Object a0, Object a1, Object a2, Object a3) { return target(a0, filter(a1), a2, a3); }
  30.337 +        protected Object invoke_R2(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, filter(a2), a3); }
  30.338 +        protected Object invoke_R3(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, filter(a3)); }
  30.339 +    }
  30.340 +    // */
  30.341 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/src/share/classes/sun/dyn/FilterOneArgument.java	Thu May 07 12:26:22 2009 -0700
    31.3 @@ -0,0 +1,73 @@
    31.4 +/*
    31.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.  Sun designates this
   31.11 + * particular file as subject to the "Classpath" exception as provided
   31.12 + * by Sun in the LICENSE file that accompanied this code.
   31.13 + *
   31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.17 + * version 2 for more details (a copy is included in the LICENSE file that
   31.18 + * accompanied this code).
   31.19 + *
   31.20 + * You should have received a copy of the GNU General Public License version
   31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.23 + *
   31.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   31.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   31.26 + * have any questions.
   31.27 + */
   31.28 +
   31.29 +package sun.dyn;
   31.30 +
   31.31 +import java.dyn.JavaMethodHandle;
   31.32 +import java.dyn.MethodHandle;
   31.33 +import java.dyn.MethodHandles;
   31.34 +import java.dyn.MethodType;
   31.35 +
   31.36 +/**
   31.37 + * Unary function composition, useful for many small plumbing jobs.
   31.38 + * The invoke method takes a single reference argument, and returns a reference
   31.39 + * Internally, it first calls the {@code filter} method on the argument,
   31.40 + * Making up the difference between the raw method type and the
   31.41 + * final method type is the responsibility of a JVM-level adapter.
   31.42 + * @author jrose
   31.43 + */
   31.44 +public class FilterOneArgument extends JavaMethodHandle {
   31.45 +    protected final MethodHandle filter;  // Object -> Object
   31.46 +    protected final MethodHandle target;  // Object -> Object
   31.47 +
   31.48 +    protected Object entryPoint(Object argument) {
   31.49 +        Object filteredArgument = filter.<Object>invoke(argument);
   31.50 +        return target.<Object>invoke(filteredArgument);
   31.51 +    }
   31.52 +
   31.53 +    private static final MethodHandle entryPoint =
   31.54 +        MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "entryPoint", MethodType.makeGeneric(1));
   31.55 +
   31.56 +    protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
   31.57 +        super(entryPoint);
   31.58 +        this.filter = filter;
   31.59 +        this.target = target;
   31.60 +    }
   31.61 +
   31.62 +    public static MethodHandle make(MethodHandle filter, MethodHandle target) {
   31.63 +        if (filter == null)  return target;
   31.64 +        if (target == null)  return filter;
   31.65 +        return new FilterOneArgument(filter, target);
   31.66 +    }
   31.67 +
   31.68 +    public String toString() {
   31.69 +        return filter + "|>" + target;
   31.70 +    }
   31.71 +
   31.72 +//    MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
   31.73 +//        MethodHandle filter = make(filter1, filter2);
   31.74 +//        return make(filter, target);
   31.75 +//    }
   31.76 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/src/share/classes/sun/dyn/FromGeneric.java	Thu May 07 12:26:22 2009 -0700
    32.3 @@ -0,0 +1,627 @@
    32.4 +/*
    32.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.  Sun designates this
   32.11 + * particular file as subject to the "Classpath" exception as provided
   32.12 + * by Sun in the LICENSE file that accompanied this code.
   32.13 + *
   32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.17 + * version 2 for more details (a copy is included in the LICENSE file that
   32.18 + * accompanied this code).
   32.19 + *
   32.20 + * You should have received a copy of the GNU General Public License version
   32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.23 + *
   32.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   32.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   32.26 + * have any questions.
   32.27 + */
   32.28 +
   32.29 +package sun.dyn;
   32.30 +
   32.31 +import java.dyn.JavaMethodHandle;
   32.32 +import java.dyn.MethodHandle;
   32.33 +import java.dyn.MethodHandles;
   32.34 +import java.dyn.MethodType;
   32.35 +import java.dyn.NoAccessException;
   32.36 +import java.lang.reflect.Constructor;
   32.37 +import java.lang.reflect.InvocationTargetException;
   32.38 +import sun.dyn.util.ValueConversions;
   32.39 +import sun.dyn.util.Wrapper;
   32.40 +
   32.41 +/**
   32.42 + * Adapters which mediate between incoming calls which are not generic
   32.43 + * and outgoing calls which are.  Any call can be represented generically
   32.44 + * boxing up its arguments, and (on return) unboxing the return value.
   32.45 + * <p>
   32.46 + * A call is "generic" (in MethodHandle terms) if its MethodType features
   32.47 + * only Object arguments.  A non-generic call therefore features
   32.48 + * primitives and/or reference types other than Object.
   32.49 + * An adapter has types for its incoming and outgoing calls.
   32.50 + * The incoming call type is simply determined by the adapter's type
   32.51 + * (the MethodType it presents to callers).  The outgoing call type
   32.52 + * is determined by the adapter's target (a MethodHandle that the adapter
   32.53 + * either binds internally or else takes as a leading argument).
   32.54 + * (To stretch the term, adapter-like method handles may have multiple
   32.55 + * targets or be polymorphic across multiple call types.)
   32.56 + * <p>
   32.57 + * This adapter can sometimes be more directly implemented
   32.58 + * by the JVM's built-in OP_SPREAD_ARGS adapter.
   32.59 + * @author jrose
   32.60 + */
   32.61 +class FromGeneric {
   32.62 +    // type for the outgoing call (may have primitives, etc.)
   32.63 +    private final MethodType targetType;
   32.64 +    // type of the outgoing call internal to the adapter
   32.65 +    private final MethodType internalType;
   32.66 +    // prototype adapter (clone and customize for each new target!)
   32.67 +    private final Adapter adapter;
   32.68 +    // entry point for adapter (Adapter mh, a...) => ...
   32.69 +    private final MethodHandle entryPoint;
   32.70 +    // unboxing invoker of type (MH, Object**N) => raw return value
   32.71 +    // it makes up the difference of internalType => targetType
   32.72 +    private final MethodHandle unboxingInvoker;
   32.73 +    // conversion which boxes a the target's raw return value
   32.74 +    private final MethodHandle returnConversion;
   32.75 +
   32.76 +    /** Compute and cache information common to all unboxing adapters
   32.77 +     *  that can call out to targets of the erasure-family of the given erased type.
   32.78 +     */
   32.79 +    private FromGeneric(MethodType targetType) {
   32.80 +        this.targetType = targetType;
   32.81 +        MethodType internalType0;
   32.82 +        // the target invoker will generally need casts on reference arguments
   32.83 +        Adapter ad = findAdapter(internalType0 = targetType.erase());
   32.84 +        if (ad != null) {
   32.85 +            // Immediate hit to exactly the adapter we want,
   32.86 +            // with no monkeying around with primitive types.
   32.87 +            this.internalType = internalType0;
   32.88 +            this.adapter = ad;
   32.89 +            this.entryPoint = ad.prototypeEntryPoint();
   32.90 +            this.returnConversion = computeReturnConversion(targetType, internalType0);
   32.91 +            this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
   32.92 +            return;
   32.93 +        }
   32.94 +
   32.95 +        // outgoing primitive arguments will be wrapped; unwrap them
   32.96 +        MethodType primsAsObj = MethodTypeImpl.of(targetType).primArgsAsBoxes();
   32.97 +        MethodType objArgsRawRet = MethodTypeImpl.of(primsAsObj).primsAsInts();
   32.98 +        if (objArgsRawRet != targetType)
   32.99 +            ad = findAdapter(internalType0 = objArgsRawRet);
  32.100 +        if (ad == null) {
  32.101 +            ad = buildAdapterFromBytecodes(internalType0 = targetType);
  32.102 +        }
  32.103 +        this.internalType = internalType0;
  32.104 +        this.adapter = ad;
  32.105 +        MethodType tepType = targetType.insertParameterType(0, adapter.getClass());
  32.106 +        this.entryPoint = ad.prototypeEntryPoint();
  32.107 +        this.returnConversion = computeReturnConversion(targetType, internalType0);
  32.108 +        this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
  32.109 +    }
  32.110 +
  32.111 +    /**
  32.112 +     * The typed target will be called according to targetType.
  32.113 +     * The adapter code will in fact see the raw result from internalType,
  32.114 +     * and must box it into an object.  Produce a converter for this.
  32.115 +     */
  32.116 +    private static MethodHandle computeReturnConversion(
  32.117 +            MethodType targetType, MethodType internalType) {
  32.118 +        Class<?> tret = targetType.returnType();
  32.119 +        Class<?> iret = internalType.returnType();
  32.120 +        Wrapper wrap = Wrapper.forBasicType(tret);
  32.121 +        if (!iret.isPrimitive()) {
  32.122 +            assert(iret == Object.class);
  32.123 +            return ValueConversions.identity();
  32.124 +        } else if (wrap.primitiveType() == iret) {
  32.125 +            return ValueConversions.box(wrap, false);
  32.126 +        } else {
  32.127 +            assert(tret == double.class ? iret == long.class : iret == int.class);
  32.128 +            return ValueConversions.boxRaw(wrap, false);
  32.129 +        }
  32.130 +    }
  32.131 +
  32.132 +    /**
  32.133 +     * The typed target will need an exact invocation point; provide it here.
  32.134 +     * The adapter will possibly need to make a slightly different call,
  32.135 +     * so adapt the invoker.  This way, the logic for making up the
  32.136 +     * difference between what the adapter can call and what the target
  32.137 +     * needs can be cached once per type.
  32.138 +     */
  32.139 +    private static MethodHandle computeUnboxingInvoker(
  32.140 +            MethodType targetType, MethodType internalType) {
  32.141 +        // All the adapters we have here have reference-untyped internal calls.
  32.142 +        assert(internalType == internalType.erase());
  32.143 +        MethodHandle invoker = MethodHandles.exactInvoker(targetType);
  32.144 +        // cast all narrow reference types, unbox all primitive arguments:
  32.145 +        MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
  32.146 +        MethodHandle fixArgs = AdapterMethodHandle.convertArguments(Access.TOKEN,
  32.147 +                                 invoker, Invokers.invokerType(fixArgsType),
  32.148 +                                 invoker.type(), null);
  32.149 +        if (fixArgs == null)
  32.150 +            throw new InternalError("bad fixArgs");
  32.151 +        // reinterpret the calling sequence as raw:
  32.152 +        MethodHandle retyper = AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN,
  32.153 +                                        Invokers.invokerType(internalType), fixArgs);
  32.154 +        if (retyper == null)
  32.155 +            throw new InternalError("bad retyper");
  32.156 +        return retyper;
  32.157 +    }
  32.158 +
  32.159 +    Adapter makeInstance(MethodHandle typedTarget) {
  32.160 +        MethodType type = typedTarget.type();
  32.161 +        if (type == targetType) {
  32.162 +            return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
  32.163 +        }
  32.164 +        // my erased-type is not exactly the same as the desired type
  32.165 +        assert(type.erase() == targetType);  // else we are busted
  32.166 +        MethodHandle invoker = computeUnboxingInvoker(type, internalType);
  32.167 +        return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
  32.168 +    }
  32.169 +
  32.170 +    /** Build an adapter of the given generic type, which invokes typedTarget
  32.171 +     *  on the incoming arguments, after unboxing as necessary.
  32.172 +     *  The return value is boxed if necessary.
  32.173 +     * @param genericType  the required type of the result
  32.174 +     * @param typedTarget the target
  32.175 +     * @return an adapter method handle
  32.176 +     */
  32.177 +    public static MethodHandle make(MethodHandle typedTarget) {
  32.178 +        MethodType type = typedTarget.type();
  32.179 +        if (type == type.generic())  return typedTarget;
  32.180 +        return FromGeneric.of(type).makeInstance(typedTarget);
  32.181 +    }
  32.182 +
  32.183 +    /** Return the adapter information for this type's erasure. */
  32.184 +    static FromGeneric of(MethodType type) {
  32.185 +        MethodTypeImpl form = MethodTypeImpl.of(type);
  32.186 +        FromGeneric fromGen = form.fromGeneric;
  32.187 +        if (fromGen == null)
  32.188 +            form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
  32.189 +        return fromGen;
  32.190 +    }
  32.191 +
  32.192 +    public String toString() {
  32.193 +        return "FromGeneric"+targetType;
  32.194 +    }
  32.195 +
  32.196 +    /* Create an adapter that handles spreading calls for the given type. */
  32.197 +    static Adapter findAdapter(MethodType internalType) {
  32.198 +        MethodType entryType = internalType.generic();
  32.199 +        MethodTypeImpl form = MethodTypeImpl.of(internalType);
  32.200 +        Class<?> rtype = internalType.returnType();
  32.201 +        int argc = form.parameterCount();
  32.202 +        int lac = form.longPrimitiveParameterCount();
  32.203 +        int iac = form.primitiveParameterCount() - lac;
  32.204 +        String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
  32.205 +        String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
  32.206 +        String cname0 = rawReturn + argc;
  32.207 +        String cname1 = "A"       + argc;
  32.208 +        String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
  32.209 +        String iname = "invoke_"+cname0+intsAndLongs;
  32.210 +        // e.g., D5I2, D5, L5I2, L5; invoke_D5
  32.211 +        for (String cname : cnames) {
  32.212 +            Class<? extends Adapter> acls = Adapter.findSubClass(cname);
  32.213 +            if (acls == null)  continue;
  32.214 +            // see if it has the required invoke method
  32.215 +            MethodHandle entryPoint = null;
  32.216 +            try {
  32.217 +                entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
  32.218 +            } catch (NoAccessException ex) {
  32.219 +            }
  32.220 +            if (entryPoint == null)  continue;
  32.221 +            Constructor<? extends Adapter> ctor = null;
  32.222 +            try {
  32.223 +                ctor = acls.getDeclaredConstructor(MethodHandle.class);
  32.224 +            } catch (NoSuchMethodException ex) {
  32.225 +            } catch (SecurityException ex) {
  32.226 +            }
  32.227 +            if (ctor == null)  continue;
  32.228 +            try {
  32.229 +                // Produce an instance configured as a prototype.
  32.230 +                return ctor.newInstance(entryPoint);
  32.231 +            } catch (IllegalArgumentException ex) {
  32.232 +            } catch (InvocationTargetException ex) {
  32.233 +            } catch (InstantiationException ex) {
  32.234 +            } catch (IllegalAccessException ex) {
  32.235 +            }
  32.236 +        }
  32.237 +        return null;
  32.238 +    }
  32.239 +
  32.240 +    static Adapter buildAdapterFromBytecodes(MethodType internalType) {
  32.241 +        throw new UnsupportedOperationException("NYI");
  32.242 +    }
  32.243 +
  32.244 +    /**
  32.245 +     * This adapter takes some untyped arguments, and returns an untyped result.
  32.246 +     * Internally, it applies the invoker to the target, which causes the
  32.247 +     * objects to be unboxed; the result is a raw type in L/I/J/F/D.
  32.248 +     * This result is passed to convert, which is responsible for
  32.249 +     * converting the raw result into a boxed object.
  32.250 +     * The invoker is kept separate from the target because it can be
  32.251 +     * generated once per type erasure family, and reused across adapters.
  32.252 +     */
  32.253 +    static abstract class Adapter extends JavaMethodHandle {
  32.254 +        /*
  32.255 +         * class X<<R,int N>> extends Adapter {
  32.256 +         *   (MH, Object**N)=>raw(R) invoker;
  32.257 +         *   (any**N)=>R target;
  32.258 +         *   raw(R)=>Object convert;
  32.259 +         *   Object invoke(Object**N a) = convert(invoker(target, a...))
  32.260 +         * }
  32.261 +         */
  32.262 +        protected final MethodHandle invoker;  // (MH, Object**N) => raw(R)
  32.263 +        protected final MethodHandle convert;  // raw(R) => Object
  32.264 +        protected final MethodHandle target;   // (any**N) => R
  32.265 +
  32.266 +        protected boolean isPrototype() { return target == null; }
  32.267 +        protected Adapter(MethodHandle entryPoint) {
  32.268 +            this(entryPoint, null, entryPoint, null);
  32.269 +            assert(isPrototype());
  32.270 +        }
  32.271 +        protected MethodHandle prototypeEntryPoint() {
  32.272 +            if (!isPrototype())  throw new InternalError();
  32.273 +            return convert;
  32.274 +        }
  32.275 +
  32.276 +        protected Adapter(MethodHandle entryPoint,
  32.277 +                          MethodHandle invoker, MethodHandle convert, MethodHandle target) {
  32.278 +            super(entryPoint);
  32.279 +            this.invoker = invoker;
  32.280 +            this.convert = convert;
  32.281 +            this.target  = target;
  32.282 +        }
  32.283 +
  32.284 +        /** Make a copy of self, with new fields. */
  32.285 +        protected abstract Adapter makeInstance(MethodHandle entryPoint,
  32.286 +                MethodHandle invoker, MethodHandle convert, MethodHandle target);
  32.287 +        // { return new ThisType(entryPoint, convert, target); }
  32.288 +
  32.289 +        /// Conversions on the value returned from the target.
  32.290 +        protected Object convert_L(Object result) { return convert.<Object>invoke(result); }
  32.291 +        protected Object convert_I(int    result) { return convert.<Object>invoke(result); }
  32.292 +        protected Object convert_J(long   result) { return convert.<Object>invoke(result); }
  32.293 +        protected Object convert_F(float  result) { return convert.<Object>invoke(result); }
  32.294 +        protected Object convert_D(double result) { return convert.<Object>invoke(result); }
  32.295 +
  32.296 +        static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$"
  32.297 +        static {
  32.298 +            String aname = Adapter.class.getName();
  32.299 +            String sname = Adapter.class.getSimpleName();
  32.300 +            if (!aname.endsWith(sname))  throw new InternalError();
  32.301 +            CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
  32.302 +        }
  32.303 +        /** Find a sibing class of Adapter. */
  32.304 +        static Class<? extends Adapter> findSubClass(String name) {
  32.305 +            String cname = Adapter.CLASS_PREFIX + name;
  32.306 +            try {
  32.307 +                return Class.forName(cname).asSubclass(Adapter.class);
  32.308 +            } catch (ClassNotFoundException ex) {
  32.309 +                return null;
  32.310 +            } catch (ClassCastException ex) {
  32.311 +                return null;
  32.312 +            }
  32.313 +        }
  32.314 +    }
  32.315 +
  32.316 +    /* generated classes follow this pattern:
  32.317 +    static class xA2 extends Adapter {
  32.318 +        protected xA2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.319 +        protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.320 +                        { super(e, i, c, t); }
  32.321 +        protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.322 +                        { return new xA2(e, i, c, t); }
  32.323 +        protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
  32.324 +        protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.<int   >invoke(target, a0, a1)); }
  32.325 +        protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.<long  >invoke(target, a0, a1)); }
  32.326 +        protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.<float >invoke(target, a0, a1)); }
  32.327 +        protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.<double>invoke(target, a0, a1)); }
  32.328 +    }
  32.329 +    // */
  32.330 +
  32.331 +/*
  32.332 +: SHELL; n=FromGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
  32.333 +//{{{
  32.334 +import java.util.*;
  32.335 +class genclasses {
  32.336 +    static String[] TYPES = { "Object", "int   ", "long  ", "float ", "double" };
  32.337 +    static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
  32.338 +    static String[][] TEMPLATES = { {
  32.339 +        "@for@ arity=0..10  rcat<=4 nrefs<=99 nints=0   nlongs=0",
  32.340 +        "    //@each-cat@",
  32.341 +        "    static class @cat@ extends Adapter {",
  32.342 +        "        protected @cat@(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype",
  32.343 +        "        protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
  32.344 +        "                        { super(e, i, c, t); }",
  32.345 +        "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
  32.346 +        "                        { return new @cat@(e, i, c, t); }",
  32.347 +        "        //@each-R@",
  32.348 +        "        protected Object invoke_@catN@(@Tvav@) { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }",
  32.349 +        "        //@end-R@",
  32.350 +        "    }",
  32.351 +    } };
  32.352 +    static final String NEWLINE_INDENT = "\n                ";
  32.353 +    enum VAR {
  32.354 +        cat, catN, R, Rc, av, Tvav, Ovav;
  32.355 +        public final String pattern = "@"+toString().replace('_','.')+"@";
  32.356 +        public String binding;
  32.357 +        static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
  32.358 +            int nargs = nrefs + nints + nlongs;
  32.359 +            if (topLevel)
  32.360 +                VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
  32.361 +            VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
  32.362 +            VAR.R.binding = TYPES[rcat];
  32.363 +            VAR.Rc.binding = TCHARS[rcat];
  32.364 +            String[] Tv = new String[nargs];
  32.365 +            String[] av = new String[nargs];
  32.366 +            String[] Tvav = new String[nargs];
  32.367 +            String[] Ovav = new String[nargs];
  32.368 +            for (int i = 0; i < nargs; i++) {
  32.369 +                int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
  32.370 +                Tv[i] = TYPES[tcat];
  32.371 +                av[i] = arg(i);
  32.372 +                Tvav[i] = param(Tv[i], av[i]);
  32.373 +                Ovav[i] = param("Object", av[i]);
  32.374 +            }
  32.375 +            VAR.av.binding = comma(", ", av);
  32.376 +            VAR.Tvav.binding = comma(Tvav);
  32.377 +            VAR.Ovav.binding = comma(Ovav);
  32.378 +        }
  32.379 +        static String arg(int i) { return "a"+i; }
  32.380 +        static String param(String t, String a) { return t+" "+a; }
  32.381 +        static String comma(String[] v) { return comma("", v); }
  32.382 +        static String comma(String sep, String[] v) {
  32.383 +            if (v.length == 0)  return "";
  32.384 +            String res = sep+v[0];
  32.385 +            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
  32.386 +            return res;
  32.387 +        }
  32.388 +        static String transform(String string) {
  32.389 +            for (VAR var : values())
  32.390 +                string = string.replaceAll(var.pattern, var.binding);
  32.391 +            return string;
  32.392 +        }
  32.393 +    }
  32.394 +    static String[] stringsIn(String[] strings, int beg, int end) {
  32.395 +        return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
  32.396 +    }
  32.397 +    static String[] stringsBefore(String[] strings, int pos) {
  32.398 +        return stringsIn(strings, 0, pos);
  32.399 +    }
  32.400 +    static String[] stringsAfter(String[] strings, int pos) {
  32.401 +        return stringsIn(strings, pos, strings.length);
  32.402 +    }
  32.403 +    static int indexAfter(String[] strings, int pos, String tag) {
  32.404 +        return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
  32.405 +    }
  32.406 +    static int indexBefore(String[] strings, int pos, String tag) {
  32.407 +        for (int i = pos, end = strings.length; ; i++) {
  32.408 +            if (i == end || strings[i].endsWith(tag))  return i;
  32.409 +        }
  32.410 +    }
  32.411 +    static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
  32.412 +    static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
  32.413 +    static HashSet<String> done = new HashSet<String>();
  32.414 +    public static void main(String... av) {
  32.415 +        for (String[] template : TEMPLATES) {
  32.416 +            int forLinesLimit = indexBefore(template, 0, "@each-cat@");
  32.417 +            String[] forLines = stringsBefore(template, forLinesLimit);
  32.418 +            template = stringsAfter(template, forLinesLimit);
  32.419 +            for (String forLine : forLines)
  32.420 +                expandTemplate(forLine, template);
  32.421 +        }
  32.422 +    }
  32.423 +    static void expandTemplate(String forLine, String[] template) {
  32.424 +        String[] params = forLine.split("[^0-9]+");
  32.425 +        if (params[0].length() == 0)  params = stringsAfter(params, 1);
  32.426 +        System.out.println("//params="+Arrays.asList(params));
  32.427 +        int pcur = 0;
  32.428 +        MIN_ARITY = Integer.valueOf(params[pcur++]);
  32.429 +        MAX_ARITY = Integer.valueOf(params[pcur++]);
  32.430 +        MAX_RCAT  = Integer.valueOf(params[pcur++]);
  32.431 +        MAX_REFS  = Integer.valueOf(params[pcur++]);
  32.432 +        MAX_INTS  = Integer.valueOf(params[pcur++]);
  32.433 +        MAX_LONGS = Integer.valueOf(params[pcur++]);
  32.434 +        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
  32.435 +        if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
  32.436 +        ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
  32.437 +        ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
  32.438 +        for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
  32.439 +            for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
  32.440 +                expandTemplate(template, true, rcat, nargs, 0, 0);
  32.441 +                if (ALL_ARG_TYPES)  break;
  32.442 +                expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
  32.443 +                if (ALL_RETURN_TYPES)  break;
  32.444 +            }
  32.445 +        }
  32.446 +    }
  32.447 +    static String catstr(int rcat, int nrefs, int nints, int nlongs) {
  32.448 +        int nargs = nrefs + nints + nlongs;
  32.449 +        String cat = TCHARS[rcat] + nargs;
  32.450 +        if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
  32.451 +        return cat;
  32.452 +    }
  32.453 +    static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
  32.454 +        for (int isLong = 0; isLong <= 1; isLong++) {
  32.455 +            for (int nprims = 1; nprims <= nargs; nprims++) {
  32.456 +                int nrefs = nargs - nprims;
  32.457 +                int nints = ((1-isLong) * nprims);
  32.458 +                int nlongs = (isLong * nprims);
  32.459 +                expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
  32.460 +            }
  32.461 +        }
  32.462 +    }
  32.463 +    static void expandTemplate(String[] template, boolean topLevel,
  32.464 +                               int rcat, int nrefs, int nints, int nlongs) {
  32.465 +        int nargs = nrefs + nints + nlongs;
  32.466 +        if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
  32.467 +        VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
  32.468 +        if (topLevel && !done.add(VAR.cat.binding)) {
  32.469 +            System.out.println("    //repeat "+VAR.cat.binding);
  32.470 +            return;
  32.471 +        }
  32.472 +        for (int i = 0; i < template.length; i++) {
  32.473 +            String line = template[i];
  32.474 +            if (line.endsWith("@each-cat@")) {
  32.475 +                // ignore
  32.476 +            } else if (line.endsWith("@each-R@")) {
  32.477 +                int blockEnd = indexAfter(template, i, "@end-R@");
  32.478 +                String[] block = stringsIn(template, i+1, blockEnd-1);
  32.479 +                for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
  32.480 +                    expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
  32.481 +                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
  32.482 +                i = blockEnd-1; continue;
  32.483 +            } else if (line.endsWith("@each-Tv@")) {
  32.484 +                int blockEnd = indexAfter(template, i, "@end-Tv@");
  32.485 +                String[] block = stringsIn(template, i+1, blockEnd-1);
  32.486 +                expandTemplate(block, false, rcat, nrefs, nints, nlongs);
  32.487 +                expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
  32.488 +                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
  32.489 +                i = blockEnd-1; continue;
  32.490 +            } else {
  32.491 +                System.out.println(VAR.transform(line));
  32.492 +            }
  32.493 +        }
  32.494 +    }
  32.495 +}
  32.496 +//}}} */
  32.497 +//params=[0, 10, 4, 99, 0, 0]
  32.498 +    static class A0 extends Adapter {
  32.499 +        protected A0(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.500 +        protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.501 +                        { super(e, i, c, t); }
  32.502 +        protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.503 +                        { return new A0(e, i, c, t); }
  32.504 +        protected Object invoke_L0() { return convert_L(invoker.<Object>invoke(target)); }
  32.505 +        protected Object invoke_I0() { return convert_I(invoker.<int   >invoke(target)); }
  32.506 +        protected Object invoke_J0() { return convert_J(invoker.<long  >invoke(target)); }
  32.507 +        protected Object invoke_F0() { return convert_F(invoker.<float >invoke(target)); }
  32.508 +        protected Object invoke_D0() { return convert_D(invoker.<double>invoke(target)); }
  32.509 +    }
  32.510 +    static class A1 extends Adapter {
  32.511 +        protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.512 +        protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.513 +                        { super(e, i, c, t); }
  32.514 +        protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.515 +                        { return new A1(e, i, c, t); }
  32.516 +        protected Object invoke_L1(Object a0) { return convert_L(invoker.<Object>invoke(target, a0)); }
  32.517 +        protected Object invoke_I1(Object a0) { return convert_I(invoker.<int   >invoke(target, a0)); }
  32.518 +        protected Object invoke_J1(Object a0) { return convert_J(invoker.<long  >invoke(target, a0)); }
  32.519 +        protected Object invoke_F1(Object a0) { return convert_F(invoker.<float >invoke(target, a0)); }
  32.520 +        protected Object invoke_D1(Object a0) { return convert_D(invoker.<double>invoke(target, a0)); }
  32.521 +    }
  32.522 +    static class A2 extends Adapter {
  32.523 +        protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.524 +        protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.525 +                        { super(e, i, c, t); }
  32.526 +        protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.527 +                        { return new A2(e, i, c, t); }
  32.528 +        protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
  32.529 +        protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.<int   >invoke(target, a0, a1)); }
  32.530 +        protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.<long  >invoke(target, a0, a1)); }
  32.531 +        protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.<float >invoke(target, a0, a1)); }
  32.532 +        protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.<double>invoke(target, a0, a1)); }
  32.533 +    }
  32.534 +    static class A3 extends Adapter {
  32.535 +        protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.536 +        protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.537 +                        { super(e, i, c, t); }
  32.538 +        protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.539 +                        { return new A3(e, i, c, t); }
  32.540 +        protected Object invoke_L3(Object a0, Object a1, Object a2) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2)); }
  32.541 +        protected Object invoke_I3(Object a0, Object a1, Object a2) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2)); }
  32.542 +        protected Object invoke_J3(Object a0, Object a1, Object a2) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2)); }
  32.543 +        protected Object invoke_F3(Object a0, Object a1, Object a2) { return convert_F(invoker.<float >invoke(target, a0, a1, a2)); }
  32.544 +        protected Object invoke_D3(Object a0, Object a1, Object a2) { return convert_D(invoker.<double>invoke(target, a0, a1, a2)); }
  32.545 +    }
  32.546 +    static class A4 extends Adapter {
  32.547 +        protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.548 +        protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.549 +                        { super(e, i, c, t); }
  32.550 +        protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.551 +                        { return new A4(e, i, c, t); }
  32.552 +        protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3)); }
  32.553 +        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3)); }
  32.554 +        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3)); }
  32.555 +        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3)); }
  32.556 +        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3)); }
  32.557 +    }
  32.558 +    static class A5 extends Adapter {
  32.559 +        protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.560 +        protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.561 +                        { super(e, i, c, t); }
  32.562 +        protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.563 +                        { return new A5(e, i, c, t); }
  32.564 +        protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4)); }
  32.565 +        protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4)); }
  32.566 +        protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4)); }
  32.567 +        protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4)); }
  32.568 +        protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4)); }
  32.569 +    }
  32.570 +    static class A6 extends Adapter {
  32.571 +        protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.572 +        protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.573 +                        { super(e, i, c, t); }
  32.574 +        protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.575 +                        { return new A6(e, i, c, t); }
  32.576 +        protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5)); }
  32.577 +        protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5)); }
  32.578 +        protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5)); }
  32.579 +        protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5)); }
  32.580 +        protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5)); }
  32.581 +    }
  32.582 +    static class A7 extends Adapter {
  32.583 +        protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.584 +        protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.585 +                        { super(e, i, c, t); }
  32.586 +        protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.587 +                        { return new A7(e, i, c, t); }
  32.588 +        protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
  32.589 +        protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
  32.590 +        protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
  32.591 +        protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
  32.592 +        protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
  32.593 +    }
  32.594 +    static class A8 extends Adapter {
  32.595 +        protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.596 +        protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.597 +                        { super(e, i, c, t); }
  32.598 +        protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.599 +                        { return new A8(e, i, c, t); }
  32.600 +        protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  32.601 +        protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  32.602 +        protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  32.603 +        protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  32.604 +        protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
  32.605 +    }
  32.606 +    static class A9 extends Adapter {
  32.607 +        protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.608 +        protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.609 +                        { super(e, i, c, t); }
  32.610 +        protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.611 +                        { return new A9(e, i, c, t); }
  32.612 +        protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  32.613 +        protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  32.614 +        protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  32.615 +        protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  32.616 +        protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  32.617 +    }
  32.618 +    static class A10 extends Adapter {
  32.619 +        protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  32.620 +        protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.621 +                        { super(e, i, c, t); }
  32.622 +        protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
  32.623 +                        { return new A10(e, i, c, t); }
  32.624 +        protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  32.625 +        protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_I(invoker.<int   >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  32.626 +        protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_J(invoker.<long  >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  32.627 +        protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  32.628 +        protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  32.629 +    }
  32.630 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/src/share/classes/sun/dyn/Invokers.java	Thu May 07 12:26:22 2009 -0700
    33.3 @@ -0,0 +1,86 @@
    33.4 +/*
    33.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + *
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.  Sun designates this
   33.11 + * particular file as subject to the "Classpath" exception as provided
   33.12 + * by Sun in the LICENSE file that accompanied this code.
   33.13 + *
   33.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.17 + * version 2 for more details (a copy is included in the LICENSE file that
   33.18 + * accompanied this code).
   33.19 + *
   33.20 + * You should have received a copy of the GNU General Public License version
   33.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.23 + *
   33.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   33.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   33.26 + * have any questions.
   33.27 + */
   33.28 +
   33.29 +package sun.dyn;
   33.30 +
   33.31 +import java.dyn.MethodHandle;
   33.32 +import java.dyn.MethodHandles;
   33.33 +import java.dyn.MethodType;
   33.34 +
   33.35 +
   33.36 +/**
   33.37 + * Construction and caching of often-used invokers.
   33.38 + * @author jrose
   33.39 + */
   33.40 +public class Invokers {
   33.41 +    // exact type (sans leading taget MH) for the outgoing call
   33.42 +    private final MethodType targetType;
   33.43 +
   33.44 +    // exact invoker for the outgoing call
   33.45 +    private /*lazy*/ MethodHandle exactInvoker;
   33.46 +
   33.47 +    // generic (untyped) invoker for the outgoing call
   33.48 +    private /*lazy*/ MethodHandle genericInvoker;
   33.49 +
   33.50 +    /** Compute and cache information common to all collecting adapters
   33.51 +     *  that implement members of the erasure-family of the given erased type.
   33.52 +     */
   33.53 +    public Invokers(Access token, MethodType targetType) {
   33.54 +        Access.check(token);
   33.55 +        this.targetType = targetType;
   33.56 +    }
   33.57 +
   33.58 +    public static MethodType invokerType(MethodType targetType) {
   33.59 +        return targetType.insertParameterType(0, MethodHandle.class);
   33.60 +    }
   33.61 +
   33.62 +    public MethodHandle exactInvoker() {
   33.63 +        MethodHandle invoker = exactInvoker;
   33.64 +        if (invoker != null)  return invoker;
   33.65 +        invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
   33.66 +        if (invoker == null)  throw new InternalError("JVM cannot find invoker for "+targetType);
   33.67 +        assert(invokerType(targetType) == invoker.type());
   33.68 +        exactInvoker = invoker;
   33.69 +        return invoker;
   33.70 +    }
   33.71 +
   33.72 +    public MethodHandle genericInvoker() {
   33.73 +        MethodHandle invoker1 = exactInvoker();
   33.74 +        MethodHandle invoker = genericInvoker;
   33.75 +        if (invoker != null)  return invoker;
   33.76 +        MethodType genericType = targetType.generic();
   33.77 +        invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType));
   33.78 +        genericInvoker = invoker;
   33.79 +        return invoker;
   33.80 +    }
   33.81 +
   33.82 +    public MethodHandle varargsInvoker() {
   33.83 +        throw new UnsupportedOperationException("NYI");
   33.84 +    }
   33.85 +
   33.86 +    public String toString() {
   33.87 +        return "Invokers"+targetType;
   33.88 +    }
   33.89 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/src/share/classes/sun/dyn/MemberName.java	Thu May 07 12:26:22 2009 -0700
    34.3 @@ -0,0 +1,552 @@
    34.4 +/*
    34.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 + *
    34.8 + * This code is free software; you can redistribute it and/or modify it
    34.9 + * under the terms of the GNU General Public License version 2 only, as
   34.10 + * published by the Free Software Foundation.  Sun designates this
   34.11 + * particular file as subject to the "Classpath" exception as provided
   34.12 + * by Sun in the LICENSE file that accompanied this code.
   34.13 + *
   34.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   34.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.17 + * version 2 for more details (a copy is included in the LICENSE file that
   34.18 + * accompanied this code).
   34.19 + *
   34.20 + * You should have received a copy of the GNU General Public License version
   34.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   34.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.23 + *
   34.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   34.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   34.26 + * have any questions.
   34.27 + */
   34.28 +
   34.29 +package sun.dyn;
   34.30 +
   34.31 +import sun.dyn.util.BytecodeSignature;
   34.32 +import java.dyn.*;
   34.33 +import java.lang.reflect.Constructor;
   34.34 +import java.lang.reflect.Field;
   34.35 +import java.lang.reflect.Method;
   34.36 +import java.lang.reflect.Member;
   34.37 +import java.lang.reflect.Modifier;
   34.38 +import java.util.ArrayList;
   34.39 +import java.util.Collections;
   34.40 +import java.util.Iterator;
   34.41 +import java.util.List;
   34.42 +import static sun.dyn.MethodHandleNatives.Constants.*;
   34.43 +
   34.44 +/**
   34.45 + * Compact information which fully characterizes a method or field reference.
   34.46 + * When resolved, it includes a direct pointer to JVM metadata.
   34.47 + * This representation is stateless and only decriptive.
   34.48 + * It provides no private information and no capability to use the member.
   34.49 + * <p>
   34.50 + * By contrast, a java.lang.reflect.Method contains fuller information
   34.51 + * about the internals of a method (except its bytecodes) and also
   34.52 + * allows invocation.  A MemberName is much lighter than a reflect.Method,
   34.53 + * since it contains about 7 fields to Method's 16 (plus its sub-arrays),
   34.54 + * and those seven fields omit much of the information in Method.
   34.55 + * @author jrose
   34.56 + */
   34.57 +public final class MemberName implements Member, Cloneable {
   34.58 +    private Class<?>   clazz;       // class in which the method is defined
   34.59 +    private String     name;        // may be null if not yet materialized
   34.60 +    private Object     type;        // may be null if not yet materialized
   34.61 +    private int        flags;       // modifier bits; see reflect.Modifier
   34.62 +
   34.63 +    private Object     vmtarget;    // VM-specific target value
   34.64 +    private int        vmindex;     // method index within class or interface
   34.65 +
   34.66 +    { vmindex = VM_INDEX_UNINITIALIZED; }
   34.67 +
   34.68 +    public Class<?> getDeclaringClass() {
   34.69 +        if (clazz == null && isResolved()) {
   34.70 +            expandFromVM();
   34.71 +        }
   34.72 +        return clazz;
   34.73 +    }
   34.74 +
   34.75 +    public ClassLoader getClassLoader() {
   34.76 +        return clazz.getClassLoader();
   34.77 +    }
   34.78 +
   34.79 +    public String getName() {
   34.80 +        if (name == null) {
   34.81 +            expandFromVM();
   34.82 +            if (name == null)  return null;
   34.83 +        }
   34.84 +        return name;
   34.85 +    }
   34.86 +
   34.87 +    public MethodType getMethodType() {
   34.88 +        if (type == null) {
   34.89 +            expandFromVM();
   34.90 +            if (type == null)  return null;
   34.91 +        }
   34.92 +        if (!isInvocable())
   34.93 +            throw newIllegalArgumentException("not invocable, no method type");
   34.94 +        if (type instanceof MethodType) {
   34.95 +            return (MethodType) type;
   34.96 +        }
   34.97 +        if (type instanceof String) {
   34.98 +            String sig = (String) type;
   34.99 +            MethodType res = MethodType.fromBytecodeString(sig, getClassLoader());
  34.100 +            this.type = res;
  34.101 +            return res;
  34.102 +        }
  34.103 +        if (type instanceof Object[]) {
  34.104 +            Object[] typeInfo = (Object[]) type;
  34.105 +            Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
  34.106 +            Class<?> rtype = (Class<?>) typeInfo[0];
  34.107 +            MethodType res = MethodType.make(rtype, ptypes);
  34.108 +            this.type = res;
  34.109 +            return res;
  34.110 +        }
  34.111 +        throw new InternalError("bad method type "+type);
  34.112 +    }
  34.113 +
  34.114 +    public MethodType getInvocationType() {
  34.115 +        MethodType itype = getMethodType();
  34.116 +        if (!isStatic())
  34.117 +            itype = itype.insertParameterType(0, clazz);
  34.118 +        return itype;
  34.119 +    }
  34.120 +
  34.121 +    public Class<?>[] getParameterTypes() {
  34.122 +        return getMethodType().parameterArray();
  34.123 +    }
  34.124 +
  34.125 +    public Class<?> getReturnType() {
  34.126 +        return getMethodType().returnType();
  34.127 +    }
  34.128 +
  34.129 +    public Class<?> getFieldType() {
  34.130 +        if (type == null) {
  34.131 +            expandFromVM();
  34.132 +            if (type == null)  return null;
  34.133 +        }
  34.134 +        if (isInvocable())
  34.135 +            throw newIllegalArgumentException("not a field or nested class, no simple type");
  34.136 +        if (type instanceof Class<?>) {
  34.137 +            return (Class<?>) type;
  34.138 +        }
  34.139 +        if (type instanceof String) {
  34.140 +            String sig = (String) type;
  34.141 +            MethodType mtype = MethodType.fromBytecodeString("()"+sig, getClassLoader());
  34.142 +            Class<?> res = mtype.returnType();
  34.143 +            this.type = res;
  34.144 +            return res;
  34.145 +        }
  34.146 +        throw new InternalError("bad field type "+type);
  34.147 +    }
  34.148 +
  34.149 +    public Object getType() {
  34.150 +        return (isInvocable() ? getMethodType() : getFieldType());
  34.151 +    }
  34.152 +
  34.153 +    public String getSignature() {
  34.154 +        if (type == null) {
  34.155 +            expandFromVM();
  34.156 +            if (type == null)  return null;
  34.157 +        }
  34.158 +        if (type instanceof String)
  34.159 +            return (String) type;
  34.160 +        if (isInvocable())
  34.161 +            return BytecodeSignature.unparse(getMethodType());
  34.162 +        else
  34.163 +            return BytecodeSignature.unparse(getFieldType());
  34.164 +    }
  34.165 +
  34.166 +    public int getModifiers() {
  34.167 +        return (flags & RECOGNIZED_MODIFIERS);
  34.168 +    }
  34.169 +
  34.170 +    private void setFlags(int flags) {
  34.171 +        this.flags = flags;
  34.172 +        assert(testAnyFlags(ALL_KINDS));
  34.173 +    }
  34.174 +
  34.175 +    private boolean testFlags(int mask, int value) {
  34.176 +        return (flags & mask) == value;
  34.177 +    }
  34.178 +    private boolean testAllFlags(int mask) {
  34.179 +        return testFlags(mask, mask);
  34.180 +    }
  34.181 +    private boolean testAnyFlags(int mask) {
  34.182 +        return !testFlags(mask, 0);
  34.183 +    }
  34.184 +
  34.185 +    public boolean isStatic() {
  34.186 +        return Modifier.isStatic(flags);
  34.187 +    }
  34.188 +    public boolean isPublic() {
  34.189 +        return Modifier.isPublic(flags);
  34.190 +    }
  34.191 +    public boolean isPrivate() {
  34.192 +        return Modifier.isPrivate(flags);
  34.193 +    }
  34.194 +    public boolean isProtected() {
  34.195 +        return Modifier.isProtected(flags);
  34.196 +    }
  34.197 +    public boolean isFinal() {
  34.198 +        return Modifier.isFinal(flags);
  34.199 +    }
  34.200 +    public boolean isAbstract() {
  34.201 +        return Modifier.isAbstract(flags);
  34.202 +    }
  34.203 +    // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
  34.204 +
  34.205 +    // unofficial modifier flags, used by HotSpot:
  34.206 +    static final int BRIDGE    = 0x00000040;
  34.207 +    static final int VARARGS   = 0x00000080;
  34.208 +    static final int SYNTHETIC = 0x00001000;
  34.209 +    static final int ANNOTATION= 0x00002000;
  34.210 +    static final int ENUM      = 0x00004000;
  34.211 +    public boolean isBridge() {
  34.212 +        return testAllFlags(IS_METHOD | BRIDGE);
  34.213 +    }
  34.214 +    public boolean isVarargs() {
  34.215 +        return testAllFlags(VARARGS) && isInvocable();
  34.216 +    }
  34.217 +    public boolean isSynthetic() {
  34.218 +        return testAllFlags(SYNTHETIC);
  34.219 +    }
  34.220 +
  34.221 +    static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
  34.222 +
  34.223 +    // modifiers exported by the JVM:
  34.224 +    static final int RECOGNIZED_MODIFIERS = 0xFFFF;
  34.225 +
  34.226 +    // private flags, not part of RECOGNIZED_MODIFIERS:
  34.227 +    static final int
  34.228 +            IS_METHOD      = MN_IS_METHOD,      // method (not constructor)
  34.229 +            IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
  34.230 +            IS_FIELD       = MN_IS_FIELD,       // field
  34.231 +            IS_TYPE        = MN_IS_TYPE;        // nested type
  34.232 +    static final int  // for MethodHandleNatives.getMembers
  34.233 +            SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
  34.234 +            SEARCH_INTERFACES   = MN_SEARCH_INTERFACES;
  34.235 +
  34.236 +    static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
  34.237 +    static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
  34.238 +    static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
  34.239 +    static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
  34.240 +    static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
  34.241 +
  34.242 +    public boolean isInvocable() {
  34.243 +        return testAnyFlags(IS_INVOCABLE);
  34.244 +    }
  34.245 +    public boolean isFieldOrMethod() {
  34.246 +        return testAnyFlags(IS_FIELD_OR_METHOD);
  34.247 +    }
  34.248 +    public boolean isMethod() {
  34.249 +        return testAllFlags(IS_METHOD);
  34.250 +    }
  34.251 +    public boolean isConstructor() {
  34.252 +        return testAllFlags(IS_CONSTRUCTOR);
  34.253 +    }
  34.254 +    public boolean isField() {
  34.255 +        return testAllFlags(IS_FIELD);
  34.256 +    }
  34.257 +    public boolean isType() {
  34.258 +        return testAllFlags(IS_TYPE);
  34.259 +    }
  34.260 +    public boolean isPackage() {
  34.261 +        return !testAnyFlags(ALL_ACCESS);
  34.262 +    }
  34.263 +
  34.264 +    /** Initialize a query.   It is not resolved. */
  34.265 +    private void init(Class<?> defClass, String name, Object type, int flags) {
  34.266 +        // defining class is allowed to be null (for a naked name/type pair)
  34.267 +        name.toString();  // null check
  34.268 +        type.equals(type);  // null check
  34.269 +        // fill in fields:
  34.270 +        this.clazz = defClass;
  34.271 +        this.name = name;
  34.272 +        this.type = type;
  34.273 +        setFlags(flags);
  34.274 +        assert(!isResolved());
  34.275 +    }
  34.276 +
  34.277 +    private void expandFromVM() {
  34.278 +        if (!isResolved())  return;
  34.279 +        if (type instanceof Object[])
  34.280 +            type = null;  // don't saddle JVM w/ typeInfo
  34.281 +        MethodHandleNatives.expand(this);
  34.282 +    }
  34.283 +
  34.284 +    // Capturing information from the Core Reflection API:
  34.285 +    private static int flagsMods(int flags, int mods) {
  34.286 +        assert((flags & RECOGNIZED_MODIFIERS) == 0);
  34.287 +        assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
  34.288 +        return flags | mods;
  34.289 +    }
  34.290 +    public MemberName(Method m) {
  34.291 +        Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
  34.292 +        init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
  34.293 +        // fill in vmtarget, vmindex while we have m in hand:
  34.294 +        MethodHandleNatives.init(this, m);
  34.295 +        assert(isResolved());
  34.296 +    }
  34.297 +    public MemberName(Constructor ctor) {
  34.298 +        Object[] typeInfo = { void.class, ctor.getParameterTypes() };
  34.299 +        init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
  34.300 +        // fill in vmtarget, vmindex while we have ctor in hand:
  34.301 +        MethodHandleNatives.init(this, ctor);
  34.302 +        assert(isResolved());
  34.303 +    }
  34.304 +    public MemberName(Field fld) {
  34.305 +        init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
  34.306 +        // fill in vmtarget, vmindex while we have fld in hand:
  34.307 +        MethodHandleNatives.init(this, fld);
  34.308 +        assert(isResolved());
  34.309 +    }
  34.310 +    public MemberName(Class<?> type) {
  34.311 +        init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
  34.312 +        vmindex = 0;  // isResolved
  34.313 +        assert(isResolved());
  34.314 +    }
  34.315 +
  34.316 +    // bare-bones constructor; the JVM will fill it in
  34.317 +    MemberName() { }
  34.318 +
  34.319 +    // locally useful cloner
  34.320 +    @Override protected MemberName clone() {
  34.321 +        try {
  34.322 +            return (MemberName) super.clone();
  34.323 +        } catch (CloneNotSupportedException ex) {
  34.324 +            throw new InternalError();
  34.325 +        }
  34.326 +     }
  34.327 +
  34.328 +    // %%% define equals/hashcode?
  34.329 +
  34.330 +    // Construction from symbolic parts, for queries:
  34.331 +    public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
  34.332 +        init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
  34.333 +    }
  34.334 +    public MemberName(Class<?> defClass, String name, Class<?> type) {
  34.335 +        this(defClass, name, type, 0);
  34.336 +    }
  34.337 +    public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
  34.338 +        int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
  34.339 +        init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
  34.340 +    }
  34.341 +    public MemberName(Class<?> defClass, String name, MethodType type) {
  34.342 +        this(defClass, name, type, 0);
  34.343 +    }
  34.344 +
  34.345 +    boolean isResolved() {
  34.346 +        return (vmindex != VM_INDEX_UNINITIALIZED);
  34.347 +    }
  34.348 +
  34.349 +    public boolean hasReceiverTypeDispatch() {
  34.350 +        return (isMethod() && getVMIndex(Access.TOKEN) >= 0);
  34.351 +    }
  34.352 +
  34.353 +    @Override
  34.354 +    public String toString() {
  34.355 +        if (isType())
  34.356 +            return type.toString();  // class java.lang.String
  34.357 +        // else it is a field, method, or constructor
  34.358 +        StringBuilder buf = new StringBuilder();
  34.359 +        if (getDeclaringClass() != null) {
  34.360 +            buf.append(getName(clazz));
  34.361 +            buf.append('.');
  34.362 +        }
  34.363 +        buf.append(getName());
  34.364 +        if (!isInvocable())  buf.append('/');
  34.365 +        buf.append(getName(getType()));
  34.366 +        /*
  34.367 +        buf.append('/');
  34.368 +        // key: Public, private, pRotected, sTatic, Final, sYnchronized,
  34.369 +        // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
  34.370 +        // (annotation), Enum, (unused)
  34.371 +        final String FIELD_MOD_CHARS  = "PprTF?vt????Y?E?";
  34.372 +        final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
  34.373 +        String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
  34.374 +        for (int i = 0; i < modChars.length(); i++) {
  34.375 +            if ((flags & (1 << i)) != 0) {
  34.376 +                char mc = modChars.charAt(i);
  34.377 +                if (mc != '.')
  34.378 +                    buf.append(mc);
  34.379 +            }
  34.380 +        }
  34.381 +         */
  34.382 +        return buf.toString();
  34.383 +    }
  34.384 +    private static String getName(Object obj) {
  34.385 +        if (obj instanceof Class<?>)
  34.386 +            return ((Class<?>)obj).getName();
  34.387 +        return obj.toString();
  34.388 +    }
  34.389 +
  34.390 +    // Queries to the JVM:
  34.391 +    public int getVMIndex(Access token) {
  34.392 +        Access.check(token);
  34.393 +        if (!isResolved())
  34.394 +            throw newIllegalStateException("not resolved");
  34.395 +        return vmindex;
  34.396 +    }
  34.397 +//    public Object getVMTarget(Access token) {
  34.398 +//        Access.check(token);
  34.399 +//        if (!isResolved())
  34.400 +//            throw newIllegalStateException("not resolved");
  34.401 +//        return vmtarget;
  34.402 +//    }
  34.403 +    private RuntimeException newIllegalStateException(String message) {
  34.404 +        return new IllegalStateException(message+": "+this);
  34.405 +    }
  34.406 +
  34.407 +    // handy shared exception makers (they simplify the common case code)
  34.408 +    public static RuntimeException newIllegalArgumentException(String message) {
  34.409 +        return new IllegalArgumentException(message);
  34.410 +    }
  34.411 +    public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) {
  34.412 +        return newNoAccessException("cannot access", name, lookupClass);
  34.413 +    }
  34.414 +    public static NoAccessException newNoAccessException(String message,
  34.415 +            MemberName name, Class<?> lookupClass) {
  34.416 +        message += ": " + name;
  34.417 +        if (lookupClass != null)  message += ", from " + lookupClass.getName();
  34.418 +        return new NoAccessException(message);
  34.419 +    }
  34.420 +
  34.421 +    /** Actually making a query requires an access check. */
  34.422 +    public static Factory getFactory(Access token) {
  34.423 +        Access.check(token);
  34.424 +        return Factory.INSTANCE;
  34.425 +    }
  34.426 +    public static Factory getFactory() {
  34.427 +        return getFactory(Access.getToken());
  34.428 +    }
  34.429 +    public static class Factory {
  34.430 +        private Factory() { } // singleton pattern
  34.431 +        static Factory INSTANCE = new Factory();
  34.432 +
  34.433 +        private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
  34.434 +
  34.435 +        /// Queries
  34.436 +        List<MemberName> getMembers(Class<?> defc,
  34.437 +                String matchName, Object matchType,
  34.438 +                int matchFlags, Class<?> lookupClass) {
  34.439 +            matchFlags &= ALLOWED_FLAGS;
  34.440 +            String matchSig = null;
  34.441 +            if (matchType != null) {
  34.442 +                matchSig = BytecodeSignature.unparse(matchType);
  34.443 +                if (matchSig.startsWith("("))
  34.444 +                    matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
  34.445 +                else
  34.446 +                    matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
  34.447 +            }
  34.448 +            final int BUF_MAX = 0x2000;
  34.449 +            int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
  34.450 +            MemberName[] buf = newMemberBuffer(len1);
  34.451 +            int totalCount = 0;
  34.452 +            ArrayList<MemberName[]> bufs = null;
  34.453 +            for (;;) {
  34.454 +                int bufCount = MethodHandleNatives.getMembers(defc,
  34.455 +                        matchName, matchSig, matchFlags,
  34.456 +                        MethodHandleNatives.asNativeCaller(lookupClass),
  34.457 +                        totalCount, buf);
  34.458 +                if (bufCount <= buf.length) {
  34.459 +                    if (bufCount >= 0)
  34.460 +                        totalCount += bufCount;
  34.461 +                    break;
  34.462 +                }
  34.463 +                // JVM returned tp us with an intentional overflow!
  34.464 +                totalCount += buf.length;
  34.465 +                int excess = bufCount - buf.length;
  34.466 +                if (bufs == null)  bufs = new ArrayList<MemberName[]>(1);
  34.467 +                bufs.add(buf);
  34.468 +                int len2 = buf.length;
  34.469 +                len2 = Math.max(len2, excess);
  34.470 +                len2 = Math.max(len2, totalCount / 4);
  34.471 +                buf = newMemberBuffer(Math.min(BUF_MAX, len2));
  34.472 +            }
  34.473 +            ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
  34.474 +            if (bufs != null) {
  34.475 +                for (MemberName[] buf0 : bufs) {
  34.476 +                    Collections.addAll(result, buf0);
  34.477 +                }
  34.478 +            }
  34.479 +            Collections.addAll(result, buf);
  34.480 +            // Signature matching is not the same as type matching, since
  34.481 +            // one signature might correspond to several types.
  34.482 +            // So if matchType is a Class or MethodType, refilter the results.
  34.483 +            if (matchType != null && matchType != matchSig) {
  34.484 +                for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
  34.485 +                    MemberName m = it.next();
  34.486 +                    if (!matchType.equals(m.getType()))
  34.487 +                        it.remove();
  34.488 +                }
  34.489 +            }
  34.490 +            return result;
  34.491 +        }
  34.492 +        boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
  34.493 +            Class<?> caller = MethodHandleNatives.asNativeCaller(lookupClass);
  34.494 +            MethodHandleNatives.resolve(m, caller);
  34.495 +            if (m.isResolved())  return true;
  34.496 +            int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  34.497 +            String matchSig = m.getSignature();
  34.498 +            MemberName[] buf = { m };
  34.499 +            int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
  34.500 +                    m.getName(), matchSig, matchFlags, caller, 0, buf);
  34.501 +            if (n != 1)  return false;
  34.502 +            return m.isResolved();
  34.503 +        }
  34.504 +        public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
  34.505 +            MemberName result = m.clone();
  34.506 +            if (resolveInPlace(result, searchSupers, lookupClass))
  34.507 +                return result;
  34.508 +            return null;
  34.509 +        }
  34.510 +        public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) {
  34.511 +            MemberName result = resolveOrNull(m, searchSupers, lookupClass);
  34.512 +            if (result != null)
  34.513 +                return result;
  34.514 +            throw newNoAccessException(m, lookupClass);
  34.515 +        }
  34.516 +        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
  34.517 +                Class<?> lookupClass) {
  34.518 +            return getMethods(defc, searchSupers, null, null, lookupClass);
  34.519 +        }
  34.520 +        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
  34.521 +                String name, MethodType type, Class<?> lookupClass) {
  34.522 +            int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  34.523 +            return getMembers(defc, name, type, matchFlags, lookupClass);
  34.524 +        }
  34.525 +        public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
  34.526 +            return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
  34.527 +        }
  34.528 +        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
  34.529 +                Class<?> lookupClass) {
  34.530 +            return getFields(defc, searchSupers, null, null, lookupClass);
  34.531 +        }
  34.532 +        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
  34.533 +                String name, Class<?> type, Class<?> lookupClass) {
  34.534 +            int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  34.535 +            return getMembers(defc, name, type, matchFlags, lookupClass);
  34.536 +        }
  34.537 +        public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
  34.538 +                Class<?> lookupClass) {
  34.539 +            int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
  34.540 +            return getMembers(defc, null, null, matchFlags, lookupClass);
  34.541 +        }
  34.542 +        private static MemberName[] newMemberBuffer(int length) {
  34.543 +            MemberName[] buf = new MemberName[length];
  34.544 +            // fill the buffer with dummy structs for the JVM to fill in
  34.545 +            for (int i = 0; i < length; i++)
  34.546 +                buf[i] = new MemberName();
  34.547 +            return buf;
  34.548 +        }
  34.549 +    }
  34.550 +
  34.551 +//    static {
  34.552 +//        System.out.println("Hello world!  My methods are:");
  34.553 +//        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
  34.554 +//    }
  34.555 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/share/classes/sun/dyn/MethodHandleImpl.java	Thu May 07 12:26:22 2009 -0700
    35.3 @@ -0,0 +1,355 @@
    35.4 +/*
    35.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.  Sun designates this
   35.11 + * particular file as subject to the "Classpath" exception as provided
   35.12 + * by Sun in the LICENSE file that accompanied this code.
   35.13 + *
   35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.17 + * version 2 for more details (a copy is included in the LICENSE file that
   35.18 + * accompanied this code).
   35.19 + *
   35.20 + * You should have received a copy of the GNU General Public License version
   35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.23 + *
   35.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   35.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   35.26 + * have any questions.
   35.27 + */
   35.28 +
   35.29 +package sun.dyn;
   35.30 +
   35.31 +import java.dyn.MethodHandle;
   35.32 +import java.dyn.MethodHandles;
   35.33 +import java.dyn.MethodHandles.Lookup;
   35.34 +import java.dyn.MethodType;
   35.35 +import sun.dyn.util.VerifyType;
   35.36 +import java.dyn.NoAccessException;
   35.37 +import static sun.dyn.MemberName.newIllegalArgumentException;
   35.38 +import static sun.dyn.MemberName.newNoAccessException;
   35.39 +
   35.40 +/**
   35.41 + * Base class for method handles, containing JVM-specific fields and logic.
   35.42 + * TO DO:  It should not be a base class.
   35.43 + * @author jrose
   35.44 + */
   35.45 +public abstract class MethodHandleImpl {
   35.46 +
   35.47 +    // Fields which really belong in MethodHandle:
   35.48 +    private byte       vmentry;    // adapter stub or method entry point
   35.49 +    //private int      vmslots;    // optionally, hoist type.form.vmslots
   35.50 +    protected Object   vmtarget;   // VM-specific, class-specific target value
   35.51 +    //MethodType       type;       // defined in MethodHandle
   35.52 +
   35.53 +    // TO DO:  vmtarget should be invisible to Java, since the JVM puts internal
   35.54 +    // managed pointers into it.  Making it visible exposes it to debuggers,
   35.55 +    // which can cause errors when they treat the pointer as an Object.
   35.56 +
   35.57 +    // These two dummy fields are present to force 'I' and 'J' signatures
   35.58 +    // into this class's constant pool, so they can be transferred
   35.59 +    // to vmentry when this class is loaded.
   35.60 +    static final int  INT_FIELD = 0;
   35.61 +    static final long LONG_FIELD = 0;
   35.62 +
   35.63 +    // type is defined in java.dyn.MethodHandle, which is platform-independent
   35.64 +
   35.65 +    // vmentry (a void* field) is used *only* by by the JVM.
   35.66 +    // The JVM adjusts its type to int or long depending on system wordsize.
   35.67 +    // Since it is statically typed as neither int nor long, it is impossible
   35.68 +    // to use this field from Java bytecode.  (Please don't try to, either.)
   35.69 +
   35.70 +    // The vmentry is an assembly-language stub which is jumped to
   35.71 +    // immediately after the method type is verified.
   35.72 +    // For a direct MH, this stub loads the vmtarget's entry point
   35.73 +    // and jumps to it.
   35.74 +
   35.75 +    /**
   35.76 +     * VM-based method handles must have a security token.
   35.77 +     * This security token can only be obtained by trusted code.
   35.78 +     * Do not create method handles directly; use factory methods.
   35.79 +     */
   35.80 +    public MethodHandleImpl(Access token) {
   35.81 +        Access.check(token);
   35.82 +    }
   35.83 +
   35.84 +    /** Initialize the method type form to participate in JVM calls.
   35.85 +     *  This is done once for each erased type.
   35.86 +     */
   35.87 +    public static void init(Access token, MethodType self) {
   35.88 +        Access.check(token);
   35.89 +        if (MethodHandleNatives.JVM_SUPPORT)
   35.90 +            MethodHandleNatives.init(self);
   35.91 +    }
   35.92 +
   35.93 +    /// Factory methods to create method handles:
   35.94 +
   35.95 +    private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
   35.96 +
   35.97 +    static private Lookup IMPL_LOOKUP_INIT;
   35.98 +
   35.99 +    public static void initLookup(Access token, Lookup lookup) {
  35.100 +        Access.check(token);
  35.101 +        if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != Access.class)
  35.102 +            throw new InternalError();
  35.103 +        IMPL_LOOKUP_INIT = lookup;
  35.104 +    }
  35.105 +
  35.106 +    public static Lookup getLookup(Access token) {
  35.107 +        Access.check(token);
  35.108 +        return IMPL_LOOKUP;
  35.109 +    }
  35.110 +
  35.111 +    static {
  35.112 +        // Force initialization:
  35.113 +        Lookup.PUBLIC_LOOKUP.lookupClass();
  35.114 +        if (IMPL_LOOKUP_INIT == null)
  35.115 +            throw new InternalError();
  35.116 +    }
  35.117 +
  35.118 +    public static void initStatics() {
  35.119 +        // Trigger preceding sequence.
  35.120 +    }
  35.121 +
  35.122 +    /** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */
  35.123 +    static final Lookup IMPL_LOOKUP = IMPL_LOOKUP_INIT;
  35.124 +
  35.125 +
  35.126 +    /** Look up a given method.
  35.127 +     * Callable only from java.dyn and related packages.
  35.128 +     * <p>
  35.129 +     * The resulting method handle type will be of the given type,
  35.130 +     * with a receiver type {@code rcvc} prepended if the member is not static.
  35.131 +     * <p>
  35.132 +     * Access checks are made as of the given lookup class.
  35.133 +     * In particular, if the method is protected and {@code defc} is in a
  35.134 +     * different package from the lookup class, then {@code rcvc} must be
  35.135 +     * the lookup class or a subclass.
  35.136 +     * @param token Proof that the lookup class has access to this package.
  35.137 +     * @param member Resolved method or constructor to call.
  35.138 +     * @param name Name of the desired method.
  35.139 +     * @param rcvc Receiver type of desired non-static method (else null)
  35.140 +     * @param doDispatch whether the method handle will test the receiver type
  35.141 +     * @param lookupClass access-check relative to this class
  35.142 +     * @return a direct handle to the matching method
  35.143 +     * @throws NoAccessException if the given method cannot be accessed by the lookup class
  35.144 +     */
  35.145 +    public static
  35.146 +    MethodHandle findMethod(Access token, MemberName method,
  35.147 +            boolean doDispatch, Class<?> lookupClass) {
  35.148 +        Access.check(token);  // only trusted calls
  35.149 +        MethodType mtype = method.getMethodType();
  35.150 +        if (method.isStatic()) {
  35.151 +            doDispatch = false;
  35.152 +        } else {
  35.153 +            // adjust the advertised receiver type to be exactly the one requested
  35.154 +            // (in the case of invokespecial, this will be the calling class)
  35.155 +            mtype = mtype.insertParameterType(0, method.getDeclaringClass());
  35.156 +            if (method.isConstructor())
  35.157 +                doDispatch = true;
  35.158 +        }
  35.159 +        DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
  35.160 +        if (!mh.isValid())
  35.161 +            throw newNoAccessException(method, lookupClass);
  35.162 +        return mh;
  35.163 +    }
  35.164 +
  35.165 +    public static
  35.166 +    MethodHandle accessField(Access token,
  35.167 +                           MemberName member, boolean isSetter,
  35.168 +                           Class<?> lookupClass) {
  35.169 +        Access.check(token);
  35.170 +        // FIXME: Use sun.misc.Unsafe to dig up the dirt on the field.
  35.171 +        throw new UnsupportedOperationException("Not yet implemented");
  35.172 +    }
  35.173 +
  35.174 +    public static
  35.175 +    MethodHandle accessArrayElement(Access token,
  35.176 +                           Class<?> arrayClass, boolean isSetter) {
  35.177 +        Access.check(token);
  35.178 +        if (!arrayClass.isArray())
  35.179 +            throw newIllegalArgumentException("not an array: "+arrayClass);
  35.180 +        // FIXME: Use sun.misc.Unsafe to dig up the dirt on the array.
  35.181 +        throw new UnsupportedOperationException("Not yet implemented");
  35.182 +    }
  35.183 +
  35.184 +    /** Bind a predetermined first argument to the given direct method handle.
  35.185 +     * Callable only from MethodHandles.
  35.186 +     * @param token Proof that the caller has access to this package.
  35.187 +     * @param target Any direct method handle.
  35.188 +     * @param receiver Receiver (or first static method argument) to pre-bind.
  35.189 +     * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
  35.190 +     */
  35.191 +    public static
  35.192 +    MethodHandle bindReceiver(Access token,
  35.193 +                              MethodHandle target, Object receiver) {
  35.194 +        Access.check(token);
  35.195 +        if (target instanceof DirectMethodHandle)
  35.196 +            return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
  35.197 +        return null;   // let caller try something else
  35.198 +    }
  35.199 +
  35.200 +    /** Bind a predetermined argument to the given arbitrary method handle.
  35.201 +     * Callable only from MethodHandles.
  35.202 +     * @param token Proof that the caller has access to this package.
  35.203 +     * @param target Any method handle.
  35.204 +     * @param receiver Argument (which can be a boxed primitive) to pre-bind.
  35.205 +     * @return a suitable BoundMethodHandle
  35.206 +     */
  35.207 +    public static
  35.208 +    MethodHandle bindArgument(Access token,
  35.209 +                              MethodHandle target, int argnum, Object receiver) {
  35.210 +        Access.check(token);
  35.211 +        throw new UnsupportedOperationException("NYI");
  35.212 +    }
  35.213 +
  35.214 +    public static MethodHandle convertArguments(Access token,
  35.215 +                                                MethodHandle target,
  35.216 +                                                MethodType newType,
  35.217 +                                                MethodType oldType,
  35.218 +                                                int[] permutationOrNull) {
  35.219 +        Access.check(token);
  35.220 +        MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target);
  35.221 +        if (res != null)
  35.222 +            return res;
  35.223 +        int argc = oldType.parameterCount();
  35.224 +        // The JVM can't do it directly, so fill in the gap with a Java adapter.
  35.225 +        // TO DO: figure out what to put here from case-by-case experience
  35.226 +        // Use a heavier method:  Convert all the arguments to Object,
  35.227 +        // then back to the desired types.  We might have to use Java-based
  35.228 +        // method handles to do this.
  35.229 +        MethodType objType = MethodType.makeGeneric(argc);
  35.230 +        MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
  35.231 +        if (objTarget == null)
  35.232 +            objTarget = FromGeneric.make(target);
  35.233 +        res = AdapterMethodHandle.makePairwiseConvert(token, newType, objTarget);
  35.234 +        if (res != null)
  35.235 +            return res;
  35.236 +        return ToGeneric.make(newType, objTarget);
  35.237 +    }
  35.238 +
  35.239 +    public static MethodHandle spreadArguments(Access token,
  35.240 +                                               MethodHandle target,
  35.241 +                                               MethodType newType,
  35.242 +                                               int spreadArg) {
  35.243 +        Access.check(token);
  35.244 +        // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
  35.245 +        MethodType oldType = target.type();
  35.246 +        // spread the last argument of newType to oldType
  35.247 +        int spreadCount = oldType.parameterCount() - spreadArg;
  35.248 +        Class<Object[]> spreadArgType = Object[].class;
  35.249 +        MethodHandle res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
  35.250 +        if (res != null)
  35.251 +            return res;
  35.252 +        // try an intermediate adapter
  35.253 +        Class<?> spreadType = null;
  35.254 +        if (spreadArg < 0 || spreadArg >= newType.parameterCount()
  35.255 +            || !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg)))
  35.256 +            throw newIllegalArgumentException("no restarg in "+newType);
  35.257 +        Class<?>[] ptypes = oldType.parameterArray();
  35.258 +        for (int i = 0; i < spreadCount; i++)
  35.259 +            ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
  35.260 +        MethodType midType = MethodType.make(newType.returnType(), ptypes);
  35.261 +        // after spreading, some arguments may need further conversion
  35.262 +        target = convertArguments(token, target, midType, oldType, null);
  35.263 +        if (target == null)
  35.264 +            throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
  35.265 +        res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
  35.266 +        return res;
  35.267 +    }
  35.268 +
  35.269 +    public static MethodHandle collectArguments(Access token,
  35.270 +                                                MethodHandle target,
  35.271 +                                                MethodType newType,
  35.272 +                                                int collectArg) {
  35.273 +        if (collectArg > 0)
  35.274 +            throw new UnsupportedOperationException("NYI");
  35.275 +        throw new UnsupportedOperationException("NYI");
  35.276 +    }
  35.277 +    public static
  35.278 +    MethodHandle dropArguments(Access token, MethodHandle target,
  35.279 +                               MethodType newType, int argnum) {
  35.280 +        Access.check(token);
  35.281 +        throw new UnsupportedOperationException("NYI");
  35.282 +    }
  35.283 +
  35.284 +    public static
  35.285 +    MethodHandle makeGuardWithTest(Access token,
  35.286 +                                   final MethodHandle test,
  35.287 +                                   final MethodHandle target,
  35.288 +                                   final MethodHandle fallback) {
  35.289 +        Access.check(token);
  35.290 +        // %%% This is just a sketch.  It needs to be de-boxed.
  35.291 +        // Adjust the handles to accept varargs lists.
  35.292 +        MethodType type = target.type();
  35.293 +        Class<?>  rtype = type.returnType();
  35.294 +        if (type.parameterCount() != 1 || type.parameterType(0).isPrimitive()) {
  35.295 +            MethodType vatestType   = MethodType.make(boolean.class, Object[].class);
  35.296 +            MethodType vatargetType = MethodType.make(rtype, Object[].class);
  35.297 +            MethodHandle vaguard = makeGuardWithTest(token,
  35.298 +                    MethodHandles.spreadArguments(test, vatestType),
  35.299 +                    MethodHandles.spreadArguments(target, vatargetType),
  35.300 +                    MethodHandles.spreadArguments(fallback, vatargetType));
  35.301 +            return MethodHandles.collectArguments(vaguard, type);
  35.302 +        }
  35.303 +        if (rtype.isPrimitive()) {
  35.304 +            MethodType boxtype = type.changeReturnType(Object.class);
  35.305 +            MethodHandle boxguard = makeGuardWithTest(token,
  35.306 +                    test,
  35.307 +                    MethodHandles.convertArguments(target, boxtype),
  35.308 +                    MethodHandles.convertArguments(fallback, boxtype));
  35.309 +            return MethodHandles.convertArguments(boxguard, type);
  35.310 +        }
  35.311 +        // Got here?  Reduced calling sequence to Object(Object).
  35.312 +        class Guarder {
  35.313 +            Object invoke(Object x) {
  35.314 +                // If javac supports MethodHandle.invoke directly:
  35.315 +                //z = vatest.invoke<boolean>(arguments);
  35.316 +                // If javac does not support direct MH.invoke calls:
  35.317 +                boolean z = (Boolean) MethodHandles.invoke_1(test, x);
  35.318 +                MethodHandle mh = (z ? target : fallback);
  35.319 +                return MethodHandles.invoke_1(mh, x);
  35.320 +            }
  35.321 +            MethodHandle handle() {
  35.322 +                MethodType invokeType = MethodType.makeGeneric(0, true);
  35.323 +                MethodHandle vh = IMPL_LOOKUP.bind(this, "invoke", invokeType);
  35.324 +                return MethodHandles.collectArguments(vh, target.type());
  35.325 +            }
  35.326 +        }
  35.327 +        return new Guarder().handle();
  35.328 +    }
  35.329 +
  35.330 +    public static
  35.331 +    MethodHandle combineArguments(Access token, MethodHandle target, MethodHandle checker, int pos) {
  35.332 +        Access.check(token);
  35.333 +        throw new UnsupportedOperationException("Not yet implemented");
  35.334 +    }
  35.335 +
  35.336 +    protected static String basicToString(MethodHandle target) {
  35.337 +        MemberName name = null;
  35.338 +        if (target != null)
  35.339 +            name = MethodHandleNatives.getMethodName(target);
  35.340 +        if (name == null)
  35.341 +            return "<unknown>";
  35.342 +        return name.getName();
  35.343 +    }
  35.344 +
  35.345 +    protected static String addTypeString(MethodHandle target, String name) {
  35.346 +        if (target == null)  return name;
  35.347 +        return name+target.type();
  35.348 +    }
  35.349 +    static RuntimeException newIllegalArgumentException(String string) {
  35.350 +        return new IllegalArgumentException(string);
  35.351 +    }
  35.352 +
  35.353 +    @Override
  35.354 +    public String toString() {
  35.355 +        MethodHandle self = (MethodHandle) this;
  35.356 +        return addTypeString(self, basicToString(self));
  35.357 +    }
  35.358 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/src/share/classes/sun/dyn/MethodHandleNatives.java	Thu May 07 12:26:22 2009 -0700
    36.3 @@ -0,0 +1,271 @@
    36.4 +/*
    36.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.7 + *
    36.8 + * This code is free software; you can redistribute it and/or modify it
    36.9 + * under the terms of the GNU General Public License version 2 only, as
   36.10 + * published by the Free Software Foundation.  Sun designates this
   36.11 + * particular file as subject to the "Classpath" exception as provided
   36.12 + * by Sun in the LICENSE file that accompanied this code.
   36.13 + *
   36.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.17 + * version 2 for more details (a copy is included in the LICENSE file that
   36.18 + * accompanied this code).
   36.19 + *
   36.20 + * You should have received a copy of the GNU General Public License version
   36.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.23 + *
   36.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   36.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   36.26 + * have any questions.
   36.27 + */
   36.28 +
   36.29 +package sun.dyn;
   36.30 +
   36.31 +import java.dyn.MethodHandle;
   36.32 +import java.dyn.MethodType;
   36.33 +import java.lang.reflect.AccessibleObject;
   36.34 +import java.lang.reflect.Field;
   36.35 +import static sun.dyn.MethodHandleNatives.Constants.*;
   36.36 +
   36.37 +/**
   36.38 + * The JVM interface for the method handles package is all here.
   36.39 + * @author jrose
   36.40 + */
   36.41 +class MethodHandleNatives {
   36.42 +
   36.43 +    private MethodHandleNatives() { } // static only
   36.44 +
   36.45 +    /// MethodName support
   36.46 +
   36.47 +    static native void init(MemberName self, Object ref);
   36.48 +    static native void expand(MemberName self);
   36.49 +    static native void resolve(MemberName self, Class<?> caller);
   36.50 +    static native int getMembers(Class<?> defc, String matchName, String matchSig,
   36.51 +            int matchFlags, Class<?> caller, int skip, MemberName[] results);
   36.52 +
   36.53 +    static Class<?> asNativeCaller(Class<?> lookupClass) {
   36.54 +        if (lookupClass == null)  // means "public only, non-privileged"
   36.55 +            return sun.dyn.empty.Empty.class;
   36.56 +        if (lookupClass == Access.class)  // means "internal, privileged"
   36.57 +            return null;    // to the JVM, null means completely privileged
   36.58 +        return lookupClass;
   36.59 +    }
   36.60 +
   36.61 +    /// MethodHandle support
   36.62 +
   36.63 +    /** Initialize the method handle to adapt the call. */
   36.64 +    static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
   36.65 +    /** Initialize the method handle to call the correct method, directly. */
   36.66 +    static native void init(BoundMethodHandle self, Object target, int argnum);
   36.67 +    /** Initialize the method handle to call as if by an invoke* instruction. */
   36.68 +    static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
   36.69 +
   36.70 +    /** Initialize a method type, once per form. */
   36.71 +    static native void init(MethodType self);
   36.72 +
   36.73 +    /** Tell the JVM that we need to change the target of an invokedynamic. */
   36.74 +    static native void linkCallSite(CallSiteImpl site, MethodHandle target);
   36.75 +
   36.76 +    /** Fetch the vmtarget field.
   36.77 +     *  It will be sanitized as necessary to avoid exposing non-Java references.
   36.78 +     *  This routine is for debugging and reflection.
   36.79 +     */
   36.80 +    static native Object getTarget(MethodHandle self, int format);
   36.81 +
   36.82 +    /** Fetch the name of the handled method, if available.
   36.83 +     *  This routine is for debugging and reflection.
   36.84 +     */
   36.85 +    static MemberName getMethodName(MethodHandle self) {
   36.86 +        if (!JVM_SUPPORT)  return null;
   36.87 +        return (MemberName) getTarget(self, ETF_METHOD_NAME);
   36.88 +    }
   36.89 +
   36.90 +    /** Fetch the reflective version of the handled method, if available.
   36.91 +     */
   36.92 +    static AccessibleObject getTargetMethod(MethodHandle self) {
   36.93 +        if (!JVM_SUPPORT)  return null;
   36.94 +        return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
   36.95 +    }
   36.96 +
   36.97 +    /** Fetch the target of this method handle.
   36.98 +     *  If it directly targets a method, return a tuple of method info.
   36.99 +     *  The info is of the form new Object[]{defclass, name, sig, refclass}.
  36.100 +     *  If it is chained to another method handle, return that handle.
  36.101 +     */
  36.102 +    static Object getTargetInfo(MethodHandle self) {
  36.103 +        if (!JVM_SUPPORT)  return null;
  36.104 +        return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
  36.105 +    }
  36.106 +
  36.107 +    static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
  36.108 +        return new Object[] { defc, name, sig, mods, refc };
  36.109 +    }
  36.110 +
  36.111 +    /** Fetch MH-related JVM parameter.
  36.112 +     *  which=0 retrieves MethodHandlePushLimit
  36.113 +     *  which=1 retrieves stack slot push size (in address units)
  36.114 +     */
  36.115 +    static native int getConstant(int which);
  36.116 +
  36.117 +    /** True iff this HotSpot JVM has built-in support for method handles.
  36.118 +     * If false, some test cases might run, but functionality will be missing.
  36.119 +     */
  36.120 +    public static final boolean JVM_SUPPORT;
  36.121 +
  36.122 +    /** Java copy of MethodHandlePushLimit in range 2..255. */
  36.123 +    static final int JVM_PUSH_LIMIT;
  36.124 +    /** JVM stack motion (in words) after one slot is pushed, usually -1.
  36.125 +     */
  36.126 +    static final int JVM_STACK_MOVE_UNIT;
  36.127 +
  36.128 +    private static native void registerNatives();
  36.129 +    static {
  36.130 +        boolean JVM_SUPPORT_;
  36.131 +        int     JVM_PUSH_LIMIT_;
  36.132 +        int     JVM_STACK_MOVE_UNIT_;
  36.133 +        try {
  36.134 +            registerNatives();
  36.135 +            JVM_SUPPORT_ = true;
  36.136 +            JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
  36.137 +            JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_LIMIT);
  36.138 +            //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
  36.139 +        } catch (UnsatisfiedLinkError ee) {
  36.140 +            // ignore; if we use init() methods later we'll see linkage errors
  36.141 +            JVM_SUPPORT_ = false;
  36.142 +            JVM_PUSH_LIMIT_ = 3;  // arbitrary
  36.143 +            JVM_STACK_MOVE_UNIT_ = -1;  // arbitrary
  36.144 +            //System.out.println("Warning: Running with JVM_SUPPORT=false");
  36.145 +            //System.out.println(ee);
  36.146 +            JVM_SUPPORT = JVM_SUPPORT_;
  36.147 +            JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
  36.148 +            JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
  36.149 +            throw ee;  // just die; hopeless to try to run with an older JVM
  36.150 +        }
  36.151 +        JVM_SUPPORT = JVM_SUPPORT_;
  36.152 +        JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
  36.153 +        JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
  36.154 +    }
  36.155 +
  36.156 +    // All compile-time constants go here.
  36.157 +    // There is an opportunity to check them against the JVM's idea of them.
  36.158 +    static class Constants {
  36.159 +        Constants() { } // static only
  36.160 +        // MethodHandleImpl
  36.161 +        static final int // for getConstant
  36.162 +                GC_JVM_PUSH_LIMIT = 0,
  36.163 +                GC_JVM_STACK_MOVE_LIMIT = 1;
  36.164 +        static final int
  36.165 +                ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
  36.166 +                ETF_DIRECT_HANDLE         = 1, // ultimate method handle (will be a DMH, may be self)
  36.167 +                ETF_METHOD_NAME           = 2, // ultimate method as MemberName
  36.168 +                ETF_REFLECT_METHOD        = 3; // ultimate method as java.lang.reflect object (sans refClass)
  36.169 +
  36.170 +        // MemberName
  36.171 +        // The JVM uses values of -2 and above for vtable indexes.
  36.172 +        // Field values are simple positive offsets.
  36.173 +        // Ref: src/share/vm/oops/methodOop.hpp
  36.174 +        // This value is negative enough to avoid such numbers,
  36.175 +        // but not too negative.
  36.176 +        static final int
  36.177 +                MN_IS_METHOD           = 0x00010000, // method (not constructor)
  36.178 +                MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
  36.179 +                MN_IS_FIELD            = 0x00040000, // field
  36.180 +                MN_IS_TYPE             = 0x00080000, // nested type
  36.181 +                MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
  36.182 +                MN_SEARCH_INTERFACES   = 0x00200000, // for MHN.getMembers
  36.183 +                VM_INDEX_UNINITIALIZED = -99;
  36.184 +
  36.185 +        // AdapterMethodHandle
  36.186 +        /** Conversions recognized by the JVM.
  36.187 +         *  They must align with the constants in sun.dyn_AdapterMethodHandle,
  36.188 +         *  in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
  36.189 +         */
  36.190 +        static final int
  36.191 +            OP_RETYPE_ONLY   = 0x0, // no argument changes; straight retype
  36.192 +            OP_CHECK_CAST    = 0x1, // ref-to-ref conversion; requires a Class argument
  36.193 +            OP_PRIM_TO_PRIM  = 0x2, // converts from one primitive to another
  36.194 +            OP_REF_TO_PRIM   = 0x3, // unboxes a wrapper to produce a primitive
  36.195 +            OP_PRIM_TO_REF   = 0x4, // boxes a primitive into a wrapper (NYI)
  36.196 +            OP_SWAP_ARGS     = 0x5, // swap arguments (vminfo is 2nd arg)
  36.197 +            OP_ROT_ARGS      = 0x6, // rotate arguments (vminfo is displaced arg)
  36.198 +            OP_DUP_ARGS      = 0x7, // duplicates one or more arguments (at TOS)
  36.199 +            OP_DROP_ARGS     = 0x8, // remove one or more argument slots
  36.200 +            OP_COLLECT_ARGS  = 0x9, // combine one or more arguments into a varargs (NYI)
  36.201 +            OP_SPREAD_ARGS   = 0xA, // expand in place a varargs array (of known size)
  36.202 +            OP_FLYBY         = 0xB, // operate first on reified argument list (NYI)
  36.203 +            OP_RICOCHET      = 0xC, // run an adapter chain on the return value (NYI)
  36.204 +            CONV_OP_LIMIT    = 0xD; // limit of CONV_OP enumeration
  36.205 +        /** Shift and mask values for decoding the AMH.conversion field.
  36.206 +         *  These numbers are shared with the JVM for creating AMHs.
  36.207 +         */
  36.208 +        static final int
  36.209 +            CONV_OP_MASK     = 0xF00, // this nybble contains the conversion op field
  36.210 +            CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
  36.211 +            CONV_VMINFO_SHIFT     =  0, // position of bits in CONV_VMINFO_MASK
  36.212 +            CONV_OP_SHIFT         =  8, // position of bits in CONV_OP_MASK
  36.213 +            CONV_DEST_TYPE_SHIFT  = 12, // byte 2 has the adapter BasicType (if needed)
  36.214 +            CONV_SRC_TYPE_SHIFT   = 16, // byte 2 has the source BasicType (if needed)
  36.215 +            CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
  36.216 +            CONV_STACK_MOVE_MASK  = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
  36.217 +
  36.218 +        /** Which conv-ops are implemented by the JVM? */
  36.219 +        static final int CONV_OP_IMPLEMENTED_MASK =
  36.220 +                // TODO: The following expression should be replaced by
  36.221 +                // a JVM query.
  36.222 +                ((1<<OP_RETYPE_ONLY)
  36.223 +                |(1<<OP_CHECK_CAST)
  36.224 +                |(1<<OP_PRIM_TO_PRIM)
  36.225 +                |(1<<OP_REF_TO_PRIM)
  36.226 +                |(1<<OP_SWAP_ARGS)
  36.227 +                |(1<<OP_ROT_ARGS)
  36.228 +                |(1<<OP_DUP_ARGS)
  36.229 +                |(1<<OP_DROP_ARGS)
  36.230 +                );
  36.231 +
  36.232 +        /**
  36.233 +         * Basic types as encoded in the JVM.  These code values are not
  36.234 +         * intended for use outside this class.  They are used as part of
  36.235 +         * a private interface between the JVM and this class.
  36.236 +         */
  36.237 +        static final int
  36.238 +            T_BOOLEAN  =  4,
  36.239 +            T_CHAR     =  5,
  36.240 +            T_FLOAT    =  6,
  36.241 +            T_DOUBLE   =  7,
  36.242 +            T_BYTE     =  8,
  36.243 +            T_SHORT    =  9,
  36.244 +            T_INT      = 10,
  36.245 +            T_LONG     = 11,
  36.246 +            T_OBJECT   = 12,
  36.247 +            //T_ARRAY    = 13
  36.248 +            T_VOID     = 14;
  36.249 +            //T_ADDRESS  = 15
  36.250 +    }
  36.251 +
  36.252 +    private static native int getNamedCon(int which, Object[] name);
  36.253 +    static boolean verifyConstants() {
  36.254 +        Object[] box = { null };
  36.255 +        for (int i = 0; ; i++) {
  36.256 +            box[0] = null;
  36.257 +            int vmval = getNamedCon(i, box);
  36.258 +            if (box[0] == null)  break;
  36.259 +            String name = (String) box[0];
  36.260 +            try {
  36.261 +                Field con = Constants.class.getDeclaredField(name);
  36.262 +                int jval = con.getInt(null);
  36.263 +                if (jval != vmval)
  36.264 +                    throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
  36.265 +            } catch (Exception ex) {
  36.266 +                throw new InternalError(name+": access failed, got "+ex);
  36.267 +            }
  36.268 +        }
  36.269 +        return true;
  36.270 +    }
  36.271 +    static {
  36.272 +        if (JVM_SUPPORT)  verifyConstants();
  36.273 +    }
  36.274 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/src/share/classes/sun/dyn/MethodTypeImpl.java	Thu May 07 12:26:22 2009 -0700
    37.3 @@ -0,0 +1,502 @@
    37.4 +/*
    37.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    37.7 + *
    37.8 + * This code is free software; you can redistribute it and/or modify it
    37.9 + * under the terms of the GNU General Public License version 2 only, as
   37.10 + * published by the Free Software Foundation.  Sun designates this
   37.11 + * particular file as subject to the "Classpath" exception as provided
   37.12 + * by Sun in the LICENSE file that accompanied this code.
   37.13 + *
   37.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   37.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   37.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   37.17 + * version 2 for more details (a copy is included in the LICENSE file that
   37.18 + * accompanied this code).
   37.19 + *
   37.20 + * You should have received a copy of the GNU General Public License version
   37.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   37.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   37.23 + *
   37.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   37.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   37.26 + * have any questions.
   37.27 + */
   37.28 +
   37.29 +package sun.dyn;
   37.30 +
   37.31 +import java.dyn.*;
   37.32 +import sun.dyn.util.Wrapper;
   37.33 +
   37.34 +/**
   37.35 + * Shared information for a group of method types, which differ
   37.36 + * only by reference types, and therefore share a common erasure
   37.37 + * and wrapping.
   37.38 + * <p>
   37.39 + * For an empirical discussion of the structure of method types,
   37.40 + * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
   37.41 + * the thread "Avoiding Boxing" on jvm-languages</a>.
   37.42 + * There are approximately 2000 distinct erased method types in the JDK.
   37.43 + * There are a little over 10 times that number of unerased types.
   37.44 + * No more than half of these are likely to be loaded at once.
   37.45 + * @author John Rose
   37.46 + */
   37.47 +public class MethodTypeImpl {
   37.48 +    final int[] argToSlotTable, slotToArgTable;
   37.49 +    final long argCounts;               // packed slot & value counts
   37.50 +    final long primCounts;              // packed prim & double counts
   37.51 +    final int vmslots;                  // total number of parameter slots
   37.52 +    final MethodType erasedType;        // the canonical erasure
   37.53 +    /*lazy*/ MethodType primsAsBoxes;   // replace prims by wrappers
   37.54 +    /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return
   37.55 +    /*lazy*/ MethodType primsAsInts;    // replace prims by int/long
   37.56 +    /*lazy*/ MethodType primsAsLongs;   // replace prims by long
   37.57 +    /*lazy*/ MethodType primsAtEnd;     // reorder primitives to the end
   37.58 +
   37.59 +    // Cached adapter information:
   37.60 +    /*lazy*/ ToGeneric   toGeneric;     // convert cs. with prims to w/o
   37.61 +    /*lazy*/ FromGeneric fromGeneric;   // convert cs. w/o prims to with
   37.62 +    /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
   37.63 +    ///*lazy*/ Invokers    invokers;    // cache of handy higher-order adapters
   37.64 +
   37.65 +    public MethodType erasedType() {
   37.66 +        return erasedType;
   37.67 +    }
   37.68 +
   37.69 +    public static MethodTypeImpl of(MethodType type) {
   37.70 +        return METHOD_TYPE_FRIEND.form(type);
   37.71 +    }
   37.72 +
   37.73 +    /** Access methods for the internals of MethodType, supplied to
   37.74 +     *  MethodTypeForm as a trusted agent.
   37.75 +     */
   37.76 +    static public interface MethodTypeFriend {
   37.77 +        Class<?>[]     ptypes(MethodType mt);
   37.78 +        MethodTypeImpl form(MethodType mt);
   37.79 +        void           setForm(MethodType mt, MethodTypeImpl form);
   37.80 +        MethodType     makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted);
   37.81 +        MethodTypeImpl newMethodTypeForm(MethodType mt);
   37.82 +        Invokers       getInvokers(MethodType mt);
   37.83 +        void           setInvokers(MethodType mt, Invokers inv);
   37.84 +    }
   37.85 +    public static void setMethodTypeFriend(Access token, MethodTypeFriend am) {
   37.86 +        Access.check(token);
   37.87 +        if (METHOD_TYPE_FRIEND != null)
   37.88 +            throw new InternalError();  // just once
   37.89 +        METHOD_TYPE_FRIEND = am;
   37.90 +    }
   37.91 +    static private MethodTypeFriend METHOD_TYPE_FRIEND;
   37.92 +
   37.93 +    protected MethodTypeImpl(MethodType erasedType) {
   37.94 +        this.erasedType = erasedType;
   37.95 +
   37.96 +        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(erasedType);
   37.97 +        int ptypeCount = ptypes.length;
   37.98 +        int pslotCount = ptypeCount;            // temp. estimate
   37.99 +        int rtypeCount = 1;                     // temp. estimate
  37.100 +        int rslotCount = 1;                     // temp. estimate
  37.101 +
  37.102 +        int[] argToSlotTab = null, slotToArgTab = null;
  37.103 +
  37.104 +        // Walk the argument types, looking for primitives.
  37.105 +        int pac = 0, lac = 0, prc = 0, lrc = 0;
  37.106 +        Class<?> epts[] = ptypes;
  37.107 +        for (int i = 0; i < epts.length; i++) {
  37.108 +            Class<?> pt = epts[i];
  37.109 +            if (pt != Object.class) {
  37.110 +                assert(pt.isPrimitive());
  37.111 +                ++pac;
  37.112 +                if (hasTwoArgSlots(pt))  ++lac;
  37.113 +            }
  37.114 +        }
  37.115 +        pslotCount += lac;                  // #slots = #args + #longs
  37.116 +        Class<?> rt = erasedType.returnType();
  37.117 +        if (rt != Object.class) {
  37.118 +            ++prc;          // even void.class counts as a prim here
  37.119 +            if (hasTwoArgSlots(rt))  ++lrc;
  37.120 +            // adjust #slots, #args
  37.121 +            if (rt == void.class)
  37.122 +                rtypeCount = rslotCount = 0;
  37.123 +            else
  37.124 +                rslotCount += lrc;
  37.125 +        }
  37.126 +        if (lac != 0) {
  37.127 +            int slot = ptypeCount + lac;
  37.128 +            slotToArgTab = new int[slot+1];
  37.129 +            argToSlotTab = new int[1+ptypeCount];
  37.130 +            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
  37.131 +            for (int i = 0; i < epts.length; i++) {
  37.132 +                Class<?> pt = epts[i];
  37.133 +                if (hasTwoArgSlots(pt))  --slot;
  37.134 +                --slot;
  37.135 +                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
  37.136 +                argToSlotTab[1+i]  = slot;
  37.137 +            }
  37.138 +            assert(slot == 0);  // filled the table
  37.139 +        }
  37.140 +        this.primCounts = pack(lrc, prc, lac, pac);
  37.141 +        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
  37.142 +        if (slotToArgTab == null) {
  37.143 +            int slot = ptypeCount; // first arg is deepest in stack
  37.144 +            slotToArgTab = new int[slot+1];
  37.145 +            argToSlotTab = new int[1+ptypeCount];
  37.146 +            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
  37.147 +            for (int i = 0; i < ptypeCount; i++) {
  37.148 +                --slot;
  37.149 +                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
  37.150 +                argToSlotTab[1+i]  = slot;
  37.151 +            }
  37.152 +        }
  37.153 +        this.argToSlotTable = argToSlotTab;
  37.154 +        this.slotToArgTable = slotToArgTab;
  37.155 +
  37.156 +        if (pslotCount >= 256)  throw new IllegalArgumentException("too many arguments");
  37.157 +
  37.158 +        // send a few bits down to the JVM:
  37.159 +        this.vmslots = parameterSlotCount();
  37.160 +
  37.161 +        // short circuit some no-op canonicalizations:
  37.162 +        if (!hasPrimitives()) {
  37.163 +            primsAsBoxes = erasedType;
  37.164 +            primArgsAsBoxes = erasedType;
  37.165 +            primsAsInts  = erasedType;
  37.166 +            primsAsLongs = erasedType;
  37.167 +            primsAtEnd   = erasedType;
  37.168 +        }
  37.169 +    }
  37.170 +
  37.171 +    /** Turn all primitive types to corresponding wrapper types.
  37.172 +     */
  37.173 +    public MethodType primsAsBoxes() {
  37.174 +        MethodType ct = primsAsBoxes;
  37.175 +        if (ct != null)  return ct;
  37.176 +        MethodType t = erasedType;
  37.177 +        ct = canonicalize(erasedType, WRAP, WRAP);
  37.178 +        if (ct == null)  ct = t;  // no prims to box
  37.179 +        return primsAsBoxes = ct;
  37.180 +    }
  37.181 +
  37.182 +    /** Turn all primitive argument types to corresponding wrapper types.
  37.183 +     *  Subword and void return types are promoted to int.
  37.184 +     */
  37.185 +    public MethodType primArgsAsBoxes() {
  37.186 +        MethodType ct = primArgsAsBoxes;
  37.187 +        if (ct != null)  return ct;
  37.188 +        MethodType t = erasedType;
  37.189 +        ct = canonicalize(erasedType, RAW_RETURN, WRAP);
  37.190 +        if (ct == null)  ct = t;  // no prims to box
  37.191 +        return primArgsAsBoxes = ct;
  37.192 +    }
  37.193 +
  37.194 +    /** Turn all primitive types to either int or long.
  37.195 +     *  Floating point return types are not changed, because
  37.196 +     *  they may require special calling sequences.
  37.197 +     *  A void return value is turned to int.
  37.198 +     */
  37.199 +    public MethodType primsAsInts() {
  37.200 +        MethodType ct = primsAsInts;
  37.201 +        if (ct != null)  return ct;
  37.202 +        MethodType t = erasedType;
  37.203 +        ct = canonicalize(t, RAW_RETURN, INTS);
  37.204 +        if (ct == null)  ct = t;  // no prims to int-ify
  37.205 +        return primsAsInts = ct;
  37.206 +    }
  37.207 +
  37.208 +    /** Turn all primitive types to either int or long.
  37.209 +     *  Floating point return types are not changed, because
  37.210 +     *  they may require special calling sequences.
  37.211 +     *  A void return value is turned to int.
  37.212 +     */
  37.213 +    public MethodType primsAsLongs() {
  37.214 +        MethodType ct = primsAsLongs;
  37.215 +        if (ct != null)  return ct;
  37.216 +        MethodType t = erasedType;
  37.217 +        ct = canonicalize(t, RAW_RETURN, LONGS);
  37.218 +        if (ct == null)  ct = t;  // no prims to int-ify
  37.219 +        return primsAsLongs = ct;
  37.220 +    }
  37.221 +
  37.222 +    /** Stably sort parameters into 3 buckets: ref, int, long. */
  37.223 +    public MethodType primsAtEnd() {
  37.224 +        MethodType ct = primsAtEnd;
  37.225 +        if (ct != null)  return ct;
  37.226 +        MethodType t = erasedType;
  37.227 +
  37.228 +        int pac = primitiveParameterCount();
  37.229 +        if (pac == 0)
  37.230 +            return primsAtEnd = t;
  37.231 +
  37.232 +        int argc = parameterCount();
  37.233 +        int lac = longPrimitiveParameterCount();
  37.234 +        if (pac == argc && (lac == 0 || lac == argc))
  37.235 +            return primsAtEnd = t;
  37.236 +
  37.237 +        // known to have a mix of 2 or 3 of ref, int, long
  37.238 +        return primsAtEnd = reorderParameters(t, primsAtEndOrder(t), null);
  37.239 +
  37.240 +    }
  37.241 +
  37.242 +    /** Compute a new ordering of parameters so that all references
  37.243 +     *  are before all ints or longs, and all ints are before all longs.
  37.244 +     *  For this ordering, doubles count as longs, and all other primitive
  37.245 +     *  values count as ints.
  37.246 +     *  As a special case, if the parameters are already in the specified
  37.247 +     *  order, this method returns a null reference, rather than an array
  37.248 +     *  specifying a null permutation.
  37.249 +     *  <p>
  37.250 +     *  For example, the type {@code (int,boolean,int,Object,String)void}
  37.251 +     *  produces the order {@code {3,4,0,1,2}}, the type
  37.252 +     *  {@code (long,int,String)void} produces {@code {2,1,2}}, and
  37.253 +     *  the type {@code (Object,int)Object} produces {@code null}.
  37.254 +     */
  37.255 +    public static int[] primsAtEndOrder(MethodType mt) {
  37.256 +        MethodTypeImpl form = METHOD_TYPE_FRIEND.form(mt);
  37.257 +        if (form.primsAtEnd == form.erasedType)
  37.258 +            // quick check shows no reordering is necessary
  37.259 +            return null;
  37.260 +
  37.261 +        int argc = form.parameterCount();
  37.262 +        int[] paramOrder = new int[argc];
  37.263 +
  37.264 +        // 3-way bucket sort:
  37.265 +        int pac = form.primitiveParameterCount();
  37.266 +        int lac = form.longPrimitiveParameterCount();
  37.267 +        int rfill = 0, ifill = argc - pac, lfill = argc - lac;
  37.268 +
  37.269 +        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
  37.270 +        boolean changed = false;
  37.271 +        for (int i = 0; i < ptypes.length; i++) {
  37.272 +            Class<?> pt = ptypes[i];
  37.273 +            int ord;
  37.274 +            if (!pt.isPrimitive())             ord = rfill++;
  37.275 +            else if (!hasTwoArgSlots(pt))      ord = ifill++;
  37.276 +            else                               ord = lfill++;
  37.277 +            if (ord != i)  changed = true;
  37.278 +            paramOrder[i] = ord;
  37.279 +        }
  37.280 +        assert(rfill == argc - pac && ifill == argc - lac && lfill == argc);
  37.281 +        if (!changed) {
  37.282 +            form.primsAtEnd = form.erasedType;
  37.283 +            return null;
  37.284 +        }
  37.285 +        return paramOrder;
  37.286 +    }
  37.287 +
  37.288 +    /** Put the existing parameters of mt into a new order, given by newParamOrder.
  37.289 +     *  The third argument is logically appended to mt.parameterArray,
  37.290 +     *  so that elements of newParamOrder can index either pre-existing or
  37.291 +     *  new parameter types.
  37.292 +     */
  37.293 +    public static MethodType reorderParameters(MethodType mt, int[] newParamOrder, Class<?>[] moreParams) {
  37.294 +        if (newParamOrder == null)  return mt;  // no-op reordering
  37.295 +        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
  37.296 +        Class<?>[] ntypes = new Class<?>[newParamOrder.length];
  37.297 +        int ordMax = ptypes.length + (moreParams == null ? 0 : moreParams.length);
  37.298 +        boolean changed = (ntypes.length != ptypes.length);
  37.299 +        for (int i = 0; i < newParamOrder.length; i++) {
  37.300 +            int ord = newParamOrder[i];
  37.301 +            if (ord != i)  changed = true;
  37.302 +            Class<?> nt;
  37.303 +            if (ord < ptypes.length)   nt = ptypes[ord];
  37.304 +            else if (ord == ordMax)    nt = mt.returnType();
  37.305 +            else                       nt = moreParams[ord - ptypes.length];
  37.306 +            ntypes[i] = nt;
  37.307 +        }
  37.308 +        if (!changed)  return mt;
  37.309 +        return METHOD_TYPE_FRIEND.makeImpl(mt.returnType(), ntypes, true);
  37.310 +    }
  37.311 +
  37.312 +    private static boolean hasTwoArgSlots(Class<?> type) {
  37.313 +        return type == long.class || type == double.class;
  37.314 +    }
  37.315 +
  37.316 +    private static long pack(int a, int b, int c, int d) {
  37.317 +        assert(((a|b|c|d) & ~0xFFFF) == 0);
  37.318 +        long hw = ((a << 16) | b), lw = ((c << 16) | d);
  37.319 +        return (hw << 32) | lw;
  37.320 +    }
  37.321 +    private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
  37.322 +        assert(word <= 3);
  37.323 +        return (char)(packed >> ((3-word) * 16));
  37.324 +    }
  37.325 +
  37.326 +    public int parameterCount() {                      // # outgoing values
  37.327 +        return unpack(argCounts, 3);
  37.328 +    }
  37.329 +    public int parameterSlotCount() {                  // # outgoing interpreter slots
  37.330 +        return unpack(argCounts, 2);
  37.331 +    }
  37.332 +    public int returnCount() {                         // = 0 (V), or 1
  37.333 +        return unpack(argCounts, 1);
  37.334 +    }
  37.335 +    public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
  37.336 +        return unpack(argCounts, 0);
  37.337 +    }
  37.338 +    public int primitiveParameterCount() {
  37.339 +        return unpack(primCounts, 3);
  37.340 +    }
  37.341 +    public int longPrimitiveParameterCount() {
  37.342 +        return unpack(primCounts, 2);
  37.343 +    }
  37.344 +    public int primitiveReturnCount() {                // = 0 (obj), or 1
  37.345 +        return unpack(primCounts, 1);
  37.346 +    }
  37.347 +    public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
  37.348 +        return unpack(primCounts, 0);
  37.349 +    }
  37.350 +    public boolean hasPrimitives() {
  37.351 +        return primCounts != 0;
  37.352 +    }
  37.353 +//    public boolean hasNonVoidPrimitives() {
  37.354 +//        if (primCounts == 0)  return false;
  37.355 +//        if (primitiveParameterCount() != 0)  return true;
  37.356 +//        return (primitiveReturnCount() != 0 && returnCount() != 0);
  37.357 +//    }
  37.358 +    public boolean hasLongPrimitives() {
  37.359 +        return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
  37.360 +    }
  37.361 +    public int parameterToArgSlot(int i) {
  37.362 +        return argToSlotTable[1+i];
  37.363 +    }
  37.364 +    public int argSlotToParameter(int argSlot) {
  37.365 +        // Note:  Empty slots are represented by zero in this table.
  37.366 +        // Valid arguments slots contain incremented entries, so as to be non-zero.
  37.367 +        // We return -1 the caller to mean an empty slot.
  37.368 +        return slotToArgTable[argSlot] - 1;
  37.369 +    }
  37.370 +
  37.371 +    public static void initForm(Access token, MethodType mt) {
  37.372 +        Access.check(token);
  37.373 +        MethodTypeImpl form = findForm(mt);
  37.374 +        METHOD_TYPE_FRIEND.setForm(mt, form);
  37.375 +        if (form.erasedType == mt) {
  37.376 +            // This is a principal (erased) type; show it to the JVM.
  37.377 +            MethodHandleImpl.init(token, mt);
  37.378 +        }
  37.379 +    }
  37.380 +
  37.381 +    static MethodTypeImpl findForm(MethodType mt) {
  37.382 +        MethodType erased = canonicalize(mt, ERASE, ERASE);
  37.383 +        if (erased == null) {
  37.384 +            // It is already erased.  Make a new MethodTypeForm.
  37.385 +            return METHOD_TYPE_FRIEND.newMethodTypeForm(mt);
  37.386 +        } else {
  37.387 +            // Share the MethodTypeForm with the erased version.
  37.388 +            return METHOD_TYPE_FRIEND.form(erased);
  37.389 +        }
  37.390 +    }
  37.391 +
  37.392 +    /** Codes for {@link #canonicalize(java.lang.Class, int).
  37.393 +     * ERASE means change every reference to {@code Object}.
  37.394 +     * WRAP means convert primitives (including {@code void} to their
  37.395 +     * corresponding wrapper types.  UNWRAP means the reverse of WRAP.
  37.396 +     * INTS means convert all non-void primitive types to int or long,
  37.397 +     * according to size.  LONGS means convert all non-void primitives
  37.398 +     * to long, regardless of size.  RAW_RETURN means convert a type
  37.399 +     * (assumed to be a return type) to int if it is smaller than an int,
  37.400 +     * or if it is void.
  37.401 +     */
  37.402 +    public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
  37.403 +
  37.404 +    /** Canonicalize the types in the given method type.
  37.405 +     * If any types change, intern the new type, and return it.
  37.406 +     * Otherwise return null.
  37.407 +     */
  37.408 +    public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
  37.409 +        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
  37.410 +        Class<?>[] ptc = MethodTypeImpl.canonicalizes(ptypes, howArgs);
  37.411 +        Class<?> rtype = mt.returnType();
  37.412 +        Class<?> rtc = MethodTypeImpl.canonicalize(rtype, howRet);
  37.413 +        if (ptc == null && rtc == null) {
  37.414 +            // It is already canonical.
  37.415 +            return null;
  37.416 +        }
  37.417 +        // Find the erased version of the method type:
  37.418 +        if (rtc == null)  rtc = rtype;
  37.419 +        if (ptc == null)  ptc = ptypes;
  37.420 +        return METHOD_TYPE_FRIEND.makeImpl(rtc, ptc, true);
  37.421 +    }
  37.422 +
  37.423 +    /** Canonicalize the given return or param type.
  37.424 +     *  Return null if the type is already canonicalized.
  37.425 +     */
  37.426 +    static Class<?> canonicalize(Class<?> t, int how) {
  37.427 +        Class<?> ct;
  37.428 +        if (t == Object.class) {
  37.429 +            // no change, ever
  37.430 +        } else if (!t.isPrimitive()) {
  37.431 +            switch (how) {
  37.432 +                case UNWRAP:
  37.433 +                    ct = Wrapper.asPrimitiveType(t);
  37.434 +                    if (ct != t)  return ct;
  37.435 +                    break;
  37.436 +                case RAW_RETURN:
  37.437 +                case ERASE:
  37.438 +                    return Object.class;
  37.439 +            }
  37.440 +        } else if (t == void.class) {
  37.441 +            // no change, usually
  37.442 +            switch (how) {
  37.443 +                case RAW_RETURN:
  37.444 +                    return int.class;
  37.445 +                case WRAP:
  37.446 +                    return Void.class;
  37.447 +            }
  37.448 +        } else {
  37.449 +            // non-void primitive
  37.450 +            switch (how) {
  37.451 +                case WRAP:
  37.452 +                    return Wrapper.asWrapperType(t);
  37.453 +                case INTS:
  37.454 +                    if (t == int.class || t == long.class)
  37.455 +                        return null;  // no change
  37.456 +                    if (t == double.class)
  37.457 +                        return long.class;
  37.458 +                    return int.class;
  37.459 +                case LONGS:
  37.460 +                    if (t == long.class)
  37.461 +                        return null;  // no change
  37.462 +                    return long.class;
  37.463 +                case RAW_RETURN:
  37.464 +                    if (t == int.class || t == long.class ||
  37.465 +                        t == float.class || t == double.class)
  37.466 +                        return null;  // no change
  37.467 +                    // everything else returns as an int
  37.468 +                    return int.class;
  37.469 +            }
  37.470 +        }
  37.471 +        // no change; return null to signify
  37.472 +        return null;
  37.473 +    }
  37.474 +
  37.475 +    /** Canonicalize each param type in the given array.
  37.476 +     *  Return null if all types are already canonicalized.
  37.477 +     */
  37.478 +    static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
  37.479 +        Class<?>[] cs = null;
  37.480 +        for (int imax = ts.length, i = 0; i < imax; i++) {
  37.481 +            Class<?> c = canonicalize(ts[i], how);
  37.482 +            if (c != null) {
  37.483 +                if (cs == null)
  37.484 +                    cs = ts.clone();
  37.485 +                cs[i] = c;
  37.486 +            }
  37.487 +        }
  37.488 +        return cs;
  37.489 +    }
  37.490 +
  37.491 +    public static Invokers invokers(Access token, MethodType type) {
  37.492 +        Access.check(token);
  37.493 +        Invokers inv = METHOD_TYPE_FRIEND.getInvokers(type);
  37.494 +        if (inv != null)  return inv;
  37.495 +        inv = new Invokers(token, type);
  37.496 +        METHOD_TYPE_FRIEND.setInvokers(type, inv);
  37.497 +        return inv;
  37.498 +    }
  37.499 +
  37.500 +    @Override
  37.501 +    public String toString() {
  37.502 +        return "Form"+erasedType;
  37.503 +    }
  37.504 +
  37.505 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/src/share/classes/sun/dyn/ToGeneric.java	Thu May 07 12:26:22 2009 -0700
    38.3 @@ -0,0 +1,1018 @@
    38.4 +/*
    38.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    38.7 + *
    38.8 + * This code is free software; you can redistribute it and/or modify it
    38.9 + * under the terms of the GNU General Public License version 2 only, as
   38.10 + * published by the Free Software Foundation.  Sun designates this
   38.11 + * particular file as subject to the "Classpath" exception as provided
   38.12 + * by Sun in the LICENSE file that accompanied this code.
   38.13 + *
   38.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   38.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   38.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   38.17 + * version 2 for more details (a copy is included in the LICENSE file that
   38.18 + * accompanied this code).
   38.19 + *
   38.20 + * You should have received a copy of the GNU General Public License version
   38.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   38.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   38.23 + *
   38.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   38.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   38.26 + * have any questions.
   38.27 + */
   38.28 +
   38.29 +package sun.dyn;
   38.30 +
   38.31 +import java.dyn.JavaMethodHandle;
   38.32 +import java.dyn.MethodHandle;
   38.33 +import java.dyn.MethodHandles;
   38.34 +import java.dyn.MethodType;
   38.35 +import java.dyn.NoAccessException;
   38.36 +import java.lang.reflect.Constructor;
   38.37 +import java.lang.reflect.InvocationTargetException;
   38.38 +import sun.dyn.util.ValueConversions;
   38.39 +import sun.dyn.util.Wrapper;
   38.40 +
   38.41 +/**
   38.42 + * Adapters which mediate between incoming calls which are not generic
   38.43 + * and outgoing calls which are.  Any call can be represented generically
   38.44 + * boxing up its arguments, and (on return) unboxing the return value.
   38.45 + * <p>
   38.46 + * A call is "generic" (in MethodHandle terms) if its MethodType features
   38.47 + * only Object arguments.  A non-generic call therefore features
   38.48 + * primitives and/or reference types other than Object.
   38.49 + * An adapter has types for its incoming and outgoing calls.
   38.50 + * The incoming call type is simply determined by the adapter's type
   38.51 + * (the MethodType it presents to callers).  The outgoing call type
   38.52 + * is determined by the adapter's target (a MethodHandle that the adapter
   38.53 + * either binds internally or else takes as a leading argument).
   38.54 + * (To stretch the term, adapter-like method handles may have multiple
   38.55 + * targets or be polymorphic across multiple call types.)
   38.56 + * @author jrose
   38.57 + */
   38.58 +class ToGeneric {
   38.59 +    // type for the incoming call (may be erased)
   38.60 +    private final MethodType entryType;
   38.61 +    // incoming type with primitives moved to the end and turned to int/long
   38.62 +    private final MethodType rawEntryType;
   38.63 +    // adapter for the erased type
   38.64 +    private final Adapter adapter;
   38.65 +    // entry point for adapter (Adapter mh, a...) => ...
   38.66 +    private final MethodHandle entryPoint;
   38.67 +    // permutation of arguments for primsAtEndType
   38.68 +    private final int[] primsAtEndOrder;
   38.69 +    // optional final argument list conversions (at least, invokes the target)
   38.70 +    private final MethodHandle invoker;
   38.71 +    // conversion which unboxes a primitive return value
   38.72 +    private final MethodHandle returnConversion;
   38.73 +
   38.74 +    /** Compute and cache information common to all collecting adapters
   38.75 +     *  that implement members of the erasure-family of the given erased type.
   38.76 +     */
   38.77 +    private ToGeneric(MethodType entryType) {
   38.78 +        assert(entryType.erase() == entryType); // for now
   38.79 +        // incoming call will first "forget" all reference types except Object
   38.80 +        this.entryType = entryType;
   38.81 +        MethodHandle invoker0 = MethodHandles.exactInvoker(entryType.generic());
   38.82 +        MethodType rawEntryTypeInit;
   38.83 +        Adapter ad = findAdapter(rawEntryTypeInit = entryType);
   38.84 +        if (ad != null) {
   38.85 +            // Immediate hit to exactly the adapter we want,
   38.86 +            // with no monkeying around with primitive types.
   38.87 +            this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
   38.88 +            this.rawEntryType = rawEntryTypeInit;
   38.89 +            this.adapter = ad;
   38.90 +            this.entryPoint = ad.prototypeEntryPoint();
   38.91 +            this.primsAtEndOrder = null;
   38.92 +            this.invoker = invoker0;
   38.93 +            return;
   38.94 +        }
   38.95 +
   38.96 +        // next, it will reorder primitives after references
   38.97 +        MethodType primsAtEnd = MethodTypeImpl.of(entryType).primsAtEnd();
   38.98 +        // at the same time, it will "forget" all primitive types except int/long
   38.99 +        this.primsAtEndOrder = MethodTypeImpl.primsAtEndOrder(entryType);
  38.100 +        if (primsAtEndOrder != null) {
  38.101 +            // reordering is required; build on top of a simpler ToGeneric
  38.102 +            ToGeneric va2 = ToGeneric.of(primsAtEnd);
  38.103 +            this.adapter = va2.adapter;
  38.104 +            this.entryPoint = MethodHandleImpl.convertArguments(Access.TOKEN,
  38.105 +                    va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
  38.106 +            // example: for entryType of (int,Object,Object), the reordered
  38.107 +            // type is (Object,Object,int) and the order is {1,2,0},
  38.108 +            // and putPAE is (mh,int0,obj1,obj2) => mh.invoke(obj1,obj2,int0)
  38.109 +            if (true) throw new UnsupportedOperationException("NYI");
  38.110 +            return;
  38.111 +        }
  38.112 +
  38.113 +        // after any needed argument reordering, it will reinterpret
  38.114 +        // primitive arguments according to their "raw" types int/long
  38.115 +        MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts();
  38.116 +        ad = findAdapter(rawEntryTypeInit = intsAtEnd);
  38.117 +        if (ad == null) {
  38.118 +            // Perhaps the adapter is available only for longs.
  38.119 +            // If so, we can use it, but there will have to be a little
  38.120 +            // more stack motion on each call.
  38.121 +            MethodType longsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsLongs();
  38.122 +            ad = findAdapter(rawEntryTypeInit = longsAtEnd);
  38.123 +            if (ad == null) {
  38.124 +                // If there is no statically compiled adapter,
  38.125 +                // build one by means of dynamic bytecode generation.
  38.126 +                ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd);
  38.127 +            }
  38.128 +        }
  38.129 +        MethodHandle rawEntryPoint = ad.prototypeEntryPoint();
  38.130 +        MethodType tepType = entryType.insertParameterType(0, ad.getClass());
  38.131 +        this.entryPoint =
  38.132 +            AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, rawEntryPoint);
  38.133 +        if (this.entryPoint == null)
  38.134 +            throw new UnsupportedOperationException("cannot retype to "+entryType
  38.135 +                    +" from "+rawEntryPoint.type().dropParameterType(0));
  38.136 +        this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
  38.137 +        this.rawEntryType = rawEntryTypeInit;
  38.138 +        this.adapter = ad;
  38.139 +        this.invoker = makeRawArgumentFilter(invoker0,
  38.140 +                rawEntryPoint.type().dropParameterType(0), entryType);
  38.141 +    }
  38.142 +
  38.143 +    /** A generic argument list will be created by a call of type 'raw'.
  38.144 +     *  The values need to be reboxed for to match 'cooked'.
  38.145 +     *  Do this on the fly.
  38.146 +     */
  38.147 +    // TO DO: Use a generic argument converter in a different file
  38.148 +    static MethodHandle makeRawArgumentFilter(MethodHandle invoker,
  38.149 +            MethodType raw, MethodType cooked) {
  38.150 +        MethodHandle filteredInvoker = null;
  38.151 +        for (int i = 0, nargs = raw.parameterCount(); i < nargs; i++) {
  38.152 +            Class<?> src = raw.parameterType(i);
  38.153 +            Class<?> dst = cooked.parameterType(i);
  38.154 +            if (src == dst)  continue;
  38.155 +            assert(src.isPrimitive() && dst.isPrimitive());
  38.156 +            if (filteredInvoker == null) {
  38.157 +                filteredInvoker =
  38.158 +                        AdapterMethodHandle.makeCheckCast(Access.TOKEN,
  38.159 +                            invoker.type().generic(), invoker, 0, MethodHandle.class);
  38.160 +                if (filteredInvoker == null)  throw new UnsupportedOperationException("NYI");
  38.161 +            }
  38.162 +            MethodHandle reboxer = ValueConversions.rebox(dst, false);
  38.163 +            FilterGeneric gen = new FilterGeneric(filteredInvoker.type(), (short)(1+i), (short)1, 'R');
  38.164 +            filteredInvoker = gen.makeInstance(reboxer, filteredInvoker);
  38.165 +        }
  38.166 +        if (filteredInvoker == null)  return invoker;
  38.167 +        return AdapterMethodHandle.makeRetypeOnly(Access.TOKEN, invoker.type(), filteredInvoker);
  38.168 +    }
  38.169 +
  38.170 +    /**
  38.171 +     * Caller will be expecting a result from a call to {@code type},
  38.172 +     * while the internal adapter entry point is rawEntryType.
  38.173 +     * Also, the internal target method will be returning a boxed value,
  38.174 +     * as an untyped object.
  38.175 +     * <p>
  38.176 +     * Produce a value converter which will be typed to convert from
  38.177 +     * {@code Object} to the return value of {@code rawEntryType}, and will
  38.178 +     * in fact ensure that the value is compatible with the return type of
  38.179 +     * {@code type}.
  38.180 +     */
  38.181 +    private static MethodHandle computeReturnConversion(
  38.182 +            MethodType type, MethodType rawEntryType, boolean mustCast) {
  38.183 +        Class<?> tret = type.returnType();
  38.184 +        Class<?> rret = rawEntryType.returnType();
  38.185 +        if (mustCast || !tret.isPrimitive()) {
  38.186 +            assert(!tret.isPrimitive());
  38.187 +            assert(!rret.isPrimitive());
  38.188 +            if (rret == Object.class && !mustCast)
  38.189 +                return null;
  38.190 +            return ValueConversions.cast(tret, false);
  38.191 +        } else if (tret == rret) {
  38.192 +            return ValueConversions.unbox(tret, false);
  38.193 +        } else {
  38.194 +            assert(rret.isPrimitive());
  38.195 +            assert(tret == double.class ? rret == long.class : rret == int.class);
  38.196 +            return ValueConversions.unboxRaw(tret, false);
  38.197 +        }
  38.198 +    }
  38.199 +
  38.200 +    Adapter makeInstance(MethodType type, MethodHandle genericTarget) {
  38.201 +        genericTarget.getClass();  // check for NPE
  38.202 +        MethodHandle convert = returnConversion;
  38.203 +        if (primsAtEndOrder != null)
  38.204 +            // reorder arguments passed to genericTarget, if primsAtEndOrder
  38.205 +            throw new UnsupportedOperationException("NYI");
  38.206 +        if (type == entryType) {
  38.207 +            if (convert == null)  convert = ValueConversions.identity();
  38.208 +            return adapter.makeInstance(entryPoint, invoker, convert, genericTarget);
  38.209 +        }
  38.210 +        // my erased-type is not exactly the same as the desired type
  38.211 +        assert(type.erase() == entryType);  // else we are busted
  38.212 +        if (convert == null)
  38.213 +            convert = computeReturnConversion(type, rawEntryType, true);
  38.214 +        // retype erased reference arguments (the cast makes it safe to do this)
  38.215 +        MethodType tepType = type.insertParameterType(0, adapter.getClass());
  38.216 +        MethodHandle typedEntryPoint =
  38.217 +            AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, entryPoint);
  38.218 +        return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
  38.219 +    }
  38.220 +
  38.221 +    /** Build an adapter of the given type, which invokes genericTarget
  38.222 +     *  on the incoming arguments, after boxing as necessary.
  38.223 +     *  The return value is unboxed if necessary.
  38.224 +     * @param type  the required type of the
  38.225 +     * @param genericTarget the target, which must accept and return only Object values
  38.226 +     * @return an adapter method handle
  38.227 +     */
  38.228 +    public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
  38.229 +        MethodType gtype = genericTarget.type();
  38.230 +        if (type.generic() != gtype)
  38.231 +            throw new IllegalArgumentException();
  38.232 +        if (type == gtype)  return genericTarget;
  38.233 +        return ToGeneric.of(type).makeInstance(type, genericTarget);
  38.234 +    }
  38.235 +
  38.236 +    /** Return the adapter information for this type's erasure. */
  38.237 +    static ToGeneric of(MethodType type) {
  38.238 +        MethodTypeImpl form = MethodTypeImpl.of(type);
  38.239 +        ToGeneric toGen = form.toGeneric;
  38.240 +        if (toGen == null)
  38.241 +            form.toGeneric = toGen = new ToGeneric(form.erasedType());
  38.242 +        return toGen;
  38.243 +    }
  38.244 +
  38.245 +    public String toString() {
  38.246 +        return "ToGeneric"+entryType
  38.247 +                +(primsAtEndOrder!=null?"[reorder]":"");
  38.248 +    }
  38.249 +
  38.250 +    /* Create an adapter for the given incoming call type. */
  38.251 +    static Adapter findAdapter(MethodType entryPointType) {
  38.252 +        MethodTypeImpl form = MethodTypeImpl.of(entryPointType);
  38.253 +        Class<?> rtype = entryPointType.returnType();
  38.254 +        int argc = form.parameterCount();
  38.255 +        int lac = form.longPrimitiveParameterCount();
  38.256 +        int iac = form.primitiveParameterCount() - lac;
  38.257 +        String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
  38.258 +        String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
  38.259 +        String iname0 = "invoke_"+rawReturn;
  38.260 +        String iname1 = "invoke";
  38.261 +        String[] inames = { iname0, iname1 };
  38.262 +        String cname0 = rawReturn + argc;
  38.263 +        String cname1 = "A"       + argc;
  38.264 +        String[] cnames = { cname1, cname1+intsAndLongs, cname0, cname0+intsAndLongs };
  38.265 +        // e.g., D5I2, D5, L5I2, L5
  38.266 +        for (String cname : cnames) {
  38.267 +            Class<? extends Adapter> acls = Adapter.findSubClass(cname);
  38.268 +            if (acls == null)  continue;
  38.269 +            // see if it has the required invoke method
  38.270 +            for (String iname : inames) {
  38.271 +                MethodHandle entryPoint = null;
  38.272 +                try {
  38.273 +                    entryPoint = MethodHandleImpl.IMPL_LOOKUP.
  38.274 +                                    findSpecial(acls, iname, entryPointType, acls);
  38.275 +                } catch (NoAccessException ex) {
  38.276 +                }
  38.277 +                if (entryPoint == null)  continue;
  38.278 +                Constructor<? extends Adapter> ctor = null;
  38.279 +                try {
  38.280 +                    // Prototype builder:
  38.281 +                    ctor = acls.getDeclaredConstructor(MethodHandle.class);
  38.282 +                } catch (NoSuchMethodException ex) {
  38.283 +                } catch (SecurityException ex) {
  38.284 +                }
  38.285 +                if (ctor == null)  continue;
  38.286 +                try {
  38.287 +                    return ctor.newInstance(entryPoint);
  38.288 +                } catch (IllegalArgumentException ex) {
  38.289 +                } catch (InvocationTargetException ex) {
  38.290 +                } catch (InstantiationException ex) {
  38.291 +                } catch (IllegalAccessException ex) {
  38.292 +                }
  38.293 +            }
  38.294 +        }
  38.295 +        return null;
  38.296 +    }
  38.297 +
  38.298 +    static Adapter buildAdapterFromBytecodes(MethodType entryPointType) {
  38.299 +        throw new UnsupportedOperationException("NYI");
  38.300 +    }
  38.301 +
  38.302 +    /**
  38.303 +     * The invoke method takes some particular but unconstrained spread
  38.304 +     * of raw argument types, and returns a raw return type (in L/I/J/F/D).
  38.305 +     * Internally, it converts the incoming arguments uniformly into objects.
  38.306 +     * This series of objects is then passed to the {@code target} method,
  38.307 +     * which returns a result object.  This result is finally converted,
  38.308 +     * via another method handle {@code convert}, which is responsible for
  38.309 +     * converting the object result into the raw return value.
  38.310 +     */
  38.311 +    static abstract class Adapter extends JavaMethodHandle {
  38.312 +        /*
  38.313 +         * class X<<R,A...>> extends Adapter {
  38.314 +         *   Object...=>Object target;
  38.315 +         *   Object=>R convert;
  38.316 +         *   R invoke(A... a...) = convert(invoker(target, a...)))
  38.317 +         * }
  38.318 +         */
  38.319 +        protected final MethodHandle invoker;  // (MH, Object...) -> Object
  38.320 +        protected final MethodHandle target;   // Object... -> Object
  38.321 +        protected final MethodHandle convert;  // Object -> R
  38.322 +
  38.323 +        protected boolean isPrototype() { return target == null; }
  38.324 +        /* Prototype constructor. */
  38.325 +        protected Adapter(MethodHandle entryPoint) {
  38.326 +            super(entryPoint);
  38.327 +            this.invoker = null;
  38.328 +            this.convert = entryPoint;
  38.329 +            this.target = null;
  38.330 +            assert(isPrototype());
  38.331 +        }
  38.332 +        protected MethodHandle prototypeEntryPoint() {
  38.333 +            if (!isPrototype())  throw new InternalError();
  38.334 +            return convert;
  38.335 +        }
  38.336 +
  38.337 +        protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
  38.338 +            super(entryPoint);
  38.339 +            this.invoker = invoker;
  38.340 +            this.convert = convert;
  38.341 +            this.target = target;
  38.342 +        }
  38.343 +
  38.344 +        /** Make a copy of self, with new fields. */
  38.345 +        protected abstract Adapter makeInstance(MethodHandle entryPoint,
  38.346 +                MethodHandle invoker, MethodHandle convert, MethodHandle target);
  38.347 +        // { return new ThisType(entryPoint, convert, target); }
  38.348 +
  38.349 +        // Code to run when the arguments (<= 4) have all been boxed.
  38.350 +        protected Object target()               { return invoker.<Object>invoke(target); }
  38.351 +        protected Object target(Object a0)      { return invoker.<Object>invoke(target, a0); }
  38.352 +        protected Object target(Object a0, Object a1)
  38.353 +                                                { return invoker.<Object>invoke(target, a0, a1); }
  38.354 +        protected Object target(Object a0, Object a1, Object a2)
  38.355 +                                                { return invoker.<Object>invoke(target, a0, a1, a2); }
  38.356 +        protected Object target(Object a0, Object a1, Object a2, Object a3)
  38.357 +                                                { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
  38.358 +        /*
  38.359 +        protected Object target_0(Object... av) { return invoker.<Object>invoke(target, av); }
  38.360 +        protected Object target_1(Object a0, Object... av)
  38.361 +                                                { return invoker.<Object>invoke(target, a0, (Object)av); }
  38.362 +        protected Object target_2(Object a0, Object a1, Object... av)
  38.363 +                                                { return invoker.<Object>invoke(target, a0, a1, (Object)av); }
  38.364 +        protected Object target_3(Object a0, Object a1, Object a2, Object... av)
  38.365 +                                                { return invoker.<Object>invoke(target, a0, a1, a2, (Object)av); }
  38.366 +        protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
  38.367 +                                                { return invoker.<Object>invoke(target, a0, a1, a2, a3, (Object)av); }
  38.368 +        // */
  38.369 +        // (For more than 4 arguments, generate the code in the adapter itself.)
  38.370 +
  38.371 +        // Code to run when the generic target has finished and produced a value.
  38.372 +        protected Object return_L(Object res) { return convert.<Object>invoke(res); }
  38.373 +        protected int    return_I(Object res) { return convert.<int   >invoke(res); }
  38.374 +        protected long   return_J(Object res) { return convert.<long  >invoke(res); }
  38.375 +        protected float  return_F(Object res) { return convert.<float >invoke(res); }
  38.376 +        protected double return_D(Object res) { return convert.<double>invoke(res); }
  38.377 +
  38.378 +        static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$"
  38.379 +        static {
  38.380 +            String aname = Adapter.class.getName();
  38.381 +            String sname = Adapter.class.getSimpleName();
  38.382 +            if (!aname.endsWith(sname))  throw new InternalError();
  38.383 +            CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
  38.384 +        }
  38.385 +        /** Find a sibing class of Adapter. */
  38.386 +        static Class<? extends Adapter> findSubClass(String name) {
  38.387 +            String cname = Adapter.CLASS_PREFIX + name;
  38.388 +            try {
  38.389 +                return Class.forName(cname).asSubclass(Adapter.class);
  38.390 +            } catch (ClassNotFoundException ex) {
  38.391 +                return null;
  38.392 +            } catch (ClassCastException ex) {
  38.393 +                return null;
  38.394 +            }
  38.395 +        }
  38.396 +    }
  38.397 +
  38.398 +    /* generated classes follow this pattern:
  38.399 +    static class A1 extends Adapter {
  38.400 +        protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.401 +        protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.402 +        protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
  38.403 +        protected Object target(Object a0)    { return invoker.<Object>invoke(target, a0); }
  38.404 +        protected Object targetA1(Object a0) { return target(a0); }
  38.405 +        protected Object targetA1(int    a0) { return target(a0); }
  38.406 +        protected Object targetA1(long   a0) { return target(a0); }
  38.407 +        protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); }
  38.408 +        protected int    invoke_I(Object a0) { return return_I(targetA1(a0)); }
  38.409 +        protected long   invoke_J(Object a0) { return return_J(targetA1(a0)); }
  38.410 +        protected float  invoke_F(Object a0) { return return_F(targetA1(a0)); }
  38.411 +        protected double invoke_D(Object a0) { return return_D(targetA1(a0)); }
  38.412 +        protected Object invoke_L(int    a0) { return return_L(targetA1(a0)); }
  38.413 +        protected int    invoke_I(int    a0) { return return_I(targetA1(a0)); }
  38.414 +        protected long   invoke_J(int    a0) { return return_J(targetA1(a0)); }
  38.415 +        protected float  invoke_F(int    a0) { return return_F(targetA1(a0)); }
  38.416 +        protected double invoke_D(int    a0) { return return_D(targetA1(a0)); }
  38.417 +        protected Object invoke_L(long   a0) { return return_L(targetA1(a0)); }
  38.418 +        protected int    invoke_I(long   a0) { return return_I(targetA1(a0)); }
  38.419 +        protected long   invoke_J(long   a0) { return return_J(targetA1(a0)); }
  38.420 +        protected float  invoke_F(long   a0) { return return_F(targetA1(a0)); }
  38.421 +        protected double invoke_D(long   a0) { return return_D(targetA1(a0)); }
  38.422 +    }
  38.423 +    // */
  38.424 +
  38.425 +/*
  38.426 +: SHELL; n=ToGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
  38.427 +//{{{
  38.428 +import java.util.*;
  38.429 +class genclasses {
  38.430 +    static String[] TYPES = { "Object", "int   ", "long  ", "float ", "double" };
  38.431 +    static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
  38.432 +    static String[][] TEMPLATES = { {
  38.433 +        "@for@ arity=0..3   rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
  38.434 +        "@for@ arity=4..5   rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
  38.435 +        "@for@ arity=6..10  rcat<=2 nrefs<=99 nints=0   nlongs<=99",
  38.436 +        "    //@each-cat@",
  38.437 +        "    static class @cat@ extends Adapter {",
  38.438 +        "        protected @cat@(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype",
  38.439 +        "        protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
  38.440 +        "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
  38.441 +        "        protected Object target(@Ovav@)   { return invoker.<Object>invoke(target, @av@); }",
  38.442 +        "        //@each-Tv@",
  38.443 +        "        protected Object target@cat@(@Tvav@) { return target(@av@); }",
  38.444 +        "        //@end-Tv@",
  38.445 +        "        //@each-Tv@",
  38.446 +        "        //@each-R@",
  38.447 +        "        protected @R@ invoke_@Rc@(@Tvav@) { return return_@Rc@(target@cat@(@av@)); }",
  38.448 +        "        //@end-R@",
  38.449 +        "        //@end-Tv@",
  38.450 +        "    }",
  38.451 +    } };
  38.452 +    enum VAR {
  38.453 +        cat, R, Rc, Tv, av, Tvav, Ovav;
  38.454 +        public final String pattern = "@"+toString().replace('_','.')+"@";
  38.455 +        public String binding;
  38.456 +        static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
  38.457 +            int nargs = nrefs + nints + nlongs;
  38.458 +            if (topLevel)
  38.459 +                VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
  38.460 +            VAR.R.binding = TYPES[rcat];
  38.461 +            VAR.Rc.binding = TCHARS[rcat];
  38.462 +            String[] Tv = new String[nargs];
  38.463 +            String[] av = new String[nargs];
  38.464 +            String[] Tvav = new String[nargs];
  38.465 +            String[] Ovav = new String[nargs];
  38.466 +            for (int i = 0; i < nargs; i++) {
  38.467 +                int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
  38.468 +                Tv[i] = TYPES[tcat];
  38.469 +                av[i] = arg(i);
  38.470 +                Tvav[i] = param(Tv[i], av[i]);
  38.471 +                Ovav[i] = param("Object", av[i]);
  38.472 +            }
  38.473 +            VAR.Tv.binding = comma(Tv);
  38.474 +            VAR.av.binding = comma(av);
  38.475 +            VAR.Tvav.binding = comma(Tvav);
  38.476 +            VAR.Ovav.binding = comma(Ovav);
  38.477 +        }
  38.478 +        static String arg(int i) { return "a"+i; }
  38.479 +        static String param(String t, String a) { return t+" "+a; }
  38.480 +        static String comma(String[] v) { return comma(v, ""); }
  38.481 +        static String comma(String sep, String[] v) {
  38.482 +            if (v.length == 0)  return "";
  38.483 +            String res = sep+v[0];
  38.484 +            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
  38.485 +            return res;
  38.486 +        }
  38.487 +        static String transform(String string) {
  38.488 +            for (VAR var : values())
  38.489 +                string = string.replaceAll(var.pattern, var.binding);
  38.490 +            return string;
  38.491 +        }
  38.492 +    }
  38.493 +    static String[] stringsIn(String[] strings, int beg, int end) {
  38.494 +        return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
  38.495 +    }
  38.496 +    static String[] stringsBefore(String[] strings, int pos) {
  38.497 +        return stringsIn(strings, 0, pos);
  38.498 +    }
  38.499 +    static String[] stringsAfter(String[] strings, int pos) {
  38.500 +        return stringsIn(strings, pos, strings.length);
  38.501 +    }
  38.502 +    static int indexAfter(String[] strings, int pos, String tag) {
  38.503 +        return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
  38.504 +    }
  38.505 +    static int indexBefore(String[] strings, int pos, String tag) {
  38.506 +        for (int i = pos, end = strings.length; ; i++) {
  38.507 +            if (i == end || strings[i].endsWith(tag))  return i;
  38.508 +        }
  38.509 +    }
  38.510 +    static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
  38.511 +    static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
  38.512 +    static HashSet<String> done = new HashSet<String>();
  38.513 +    public static void main(String... av) {
  38.514 +        for (String[] template : TEMPLATES) {
  38.515 +            int forLinesLimit = indexBefore(template, 0, "@each-cat@");
  38.516 +            String[] forLines = stringsBefore(template, forLinesLimit);
  38.517 +            template = stringsAfter(template, forLinesLimit);
  38.518 +            for (String forLine : forLines)
  38.519 +                expandTemplate(forLine, template);
  38.520 +        }
  38.521 +    }
  38.522 +    static void expandTemplate(String forLine, String[] template) {
  38.523 +        String[] params = forLine.split("[^0-9]+");
  38.524 +        if (params[0].length() == 0)  params = stringsAfter(params, 1);
  38.525 +        System.out.println("//params="+Arrays.asList(params));
  38.526 +        int pcur = 0;
  38.527 +        MIN_ARITY = Integer.valueOf(params[pcur++]);
  38.528 +        MAX_ARITY = Integer.valueOf(params[pcur++]);
  38.529 +        MAX_RCAT  = Integer.valueOf(params[pcur++]);
  38.530 +        MAX_REFS  = Integer.valueOf(params[pcur++]);
  38.531 +        MAX_INTS  = Integer.valueOf(params[pcur++]);
  38.532 +        MAX_LONGS = Integer.valueOf(params[pcur++]);
  38.533 +        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
  38.534 +        if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
  38.535 +        ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
  38.536 +        ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
  38.537 +        for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
  38.538 +            for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
  38.539 +                expandTemplate(template, true, rcat, nargs, 0, 0);
  38.540 +                if (ALL_ARG_TYPES)  break;
  38.541 +                expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
  38.542 +                if (ALL_RETURN_TYPES)  break;
  38.543 +            }
  38.544 +        }
  38.545 +    }
  38.546 +    static String catstr(int rcat, int nrefs, int nints, int nlongs) {
  38.547 +        int nargs = nrefs + nints + nlongs;
  38.548 +        String cat = TCHARS[rcat] + nargs;
  38.549 +        if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
  38.550 +        return cat;
  38.551 +    }
  38.552 +    static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
  38.553 +        for (int isLong = 0; isLong <= 1; isLong++) {
  38.554 +            for (int nprims = 1; nprims <= nargs; nprims++) {
  38.555 +                int nrefs = nargs - nprims;
  38.556 +                int nints = ((1-isLong) * nprims);
  38.557 +                int nlongs = (isLong * nprims);
  38.558 +                expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
  38.559 +            }
  38.560 +        }
  38.561 +    }
  38.562 +    static void expandTemplate(String[] template, boolean topLevel,
  38.563 +                               int rcat, int nrefs, int nints, int nlongs) {
  38.564 +        int nargs = nrefs + nints + nlongs;
  38.565 +        if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
  38.566 +        VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
  38.567 +        if (topLevel && !done.add(VAR.cat.binding)) {
  38.568 +            System.out.println("    //repeat "+VAR.cat.binding);
  38.569 +            return;
  38.570 +        }
  38.571 +        for (int i = 0; i < template.length; i++) {
  38.572 +            String line = template[i];
  38.573 +            if (line.endsWith("@each-cat@")) {
  38.574 +                // ignore
  38.575 +            } else if (line.endsWith("@each-R@")) {
  38.576 +                int blockEnd = indexAfter(template, i, "@end-R@");
  38.577 +                String[] block = stringsIn(template, i+1, blockEnd-1);
  38.578 +                for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
  38.579 +                    expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
  38.580 +                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
  38.581 +                i = blockEnd-1; continue;
  38.582 +            } else if (line.endsWith("@each-Tv@")) {
  38.583 +                int blockEnd = indexAfter(template, i, "@end-Tv@");
  38.584 +                String[] block = stringsIn(template, i+1, blockEnd-1);
  38.585 +                expandTemplate(block, false, rcat, nrefs, nints, nlongs);
  38.586 +                expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
  38.587 +                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
  38.588 +                i = blockEnd-1; continue;
  38.589 +            } else {
  38.590 +                System.out.println(VAR.transform(line));
  38.591 +            }
  38.592 +        }
  38.593 +    }
  38.594 +}
  38.595 +//}}} */
  38.596 +//params=[0, 3, 4, 99, 99, 99]
  38.597 +    static class A0 extends Adapter {
  38.598 +        protected A0(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.599 +        protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.600 +        protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); }
  38.601 +        protected Object target()   { return invoker.<Object>invoke(target); }
  38.602 +        protected Object targetA0() { return target(); }
  38.603 +        protected Object invoke_L() { return return_L(targetA0()); }
  38.604 +        protected int    invoke_I() { return return_I(targetA0()); }
  38.605 +        protected long   invoke_J() { return return_J(targetA0()); }
  38.606 +        protected float  invoke_F() { return return_F(targetA0()); }
  38.607 +        protected double invoke_D() { return return_D(targetA0()); }
  38.608 +    }
  38.609 +    static class A1 extends Adapter {
  38.610 +        protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.611 +        protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.612 +        protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
  38.613 +        protected Object target(Object a0)   { return invoker.<Object>invoke(target, a0); }
  38.614 +        protected Object targetA1(Object a0) { return target(a0); }
  38.615 +        protected Object targetA1(int    a0) { return target(a0); }
  38.616 +        protected Object targetA1(long   a0) { return target(a0); }
  38.617 +        protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); }
  38.618 +        protected int    invoke_I(Object a0) { return return_I(targetA1(a0)); }
  38.619 +        protected long   invoke_J(Object a0) { return return_J(targetA1(a0)); }
  38.620 +        protected float  invoke_F(Object a0) { return return_F(targetA1(a0)); }
  38.621 +        protected double invoke_D(Object a0) { return return_D(targetA1(a0)); }
  38.622 +        protected Object invoke_L(int    a0) { return return_L(targetA1(a0)); }
  38.623 +        protected int    invoke_I(int    a0) { return return_I(targetA1(a0)); }
  38.624 +        protected long   invoke_J(int    a0) { return return_J(targetA1(a0)); }
  38.625 +        protected float  invoke_F(int    a0) { return return_F(targetA1(a0)); }
  38.626 +        protected double invoke_D(int    a0) { return return_D(targetA1(a0)); }
  38.627 +        protected Object invoke_L(long   a0) { return return_L(targetA1(a0)); }
  38.628 +        protected int    invoke_I(long   a0) { return return_I(targetA1(a0)); }
  38.629 +        protected long   invoke_J(long   a0) { return return_J(targetA1(a0)); }
  38.630 +        protected float  invoke_F(long   a0) { return return_F(targetA1(a0)); }
  38.631 +        protected double invoke_D(long   a0) { return return_D(targetA1(a0)); }
  38.632 +    }
  38.633 +    static class A2 extends Adapter {
  38.634 +        protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.635 +        protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.636 +        protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); }
  38.637 +        protected Object target(Object a0, Object a1)   { return invoker.<Object>invoke(target, a0, a1); }
  38.638 +        protected Object targetA2(Object a0, Object a1) { return target(a0, a1); }
  38.639 +        protected Object targetA2(Object a0, int    a1) { return target(a0, a1); }
  38.640 +        protected Object targetA2(int    a0, int    a1) { return target(a0, a1); }
  38.641 +        protected Object targetA2(Object a0, long   a1) { return target(a0, a1); }
  38.642 +        protected Object targetA2(long   a0, long   a1) { return target(a0, a1); }
  38.643 +        protected Object invoke_L(Object a0, Object a1) { return return_L(targetA2(a0, a1)); }
  38.644 +        protected int    invoke_I(Object a0, Object a1) { return return_I(targetA2(a0, a1)); }
  38.645 +        protected long   invoke_J(Object a0, Object a1) { return return_J(targetA2(a0, a1)); }
  38.646 +        protected float  invoke_F(Object a0, Object a1) { return return_F(targetA2(a0, a1)); }
  38.647 +        protected double invoke_D(Object a0, Object a1) { return return_D(targetA2(a0, a1)); }
  38.648 +        protected Object invoke_L(Object a0, int    a1) { return return_L(targetA2(a0, a1)); }
  38.649 +        protected int    invoke_I(Object a0, int    a1) { return return_I(targetA2(a0, a1)); }
  38.650 +        protected long   invoke_J(Object a0, int    a1) { return return_J(targetA2(a0, a1)); }
  38.651 +        protected float  invoke_F(Object a0, int    a1) { return return_F(targetA2(a0, a1)); }
  38.652 +        protected double invoke_D(Object a0, int    a1) { return return_D(targetA2(a0, a1)); }
  38.653 +        protected Object invoke_L(int    a0, int    a1) { return return_L(targetA2(a0, a1)); }
  38.654 +        protected int    invoke_I(int    a0, int    a1) { return return_I(targetA2(a0, a1)); }
  38.655 +        protected long   invoke_J(int    a0, int    a1) { return return_J(targetA2(a0, a1)); }
  38.656 +        protected float  invoke_F(int    a0, int    a1) { return return_F(targetA2(a0, a1)); }
  38.657 +        protected double invoke_D(int    a0, int    a1) { return return_D(targetA2(a0, a1)); }
  38.658 +        protected Object invoke_L(Object a0, long   a1) { return return_L(targetA2(a0, a1)); }
  38.659 +        protected int    invoke_I(Object a0, long   a1) { return return_I(targetA2(a0, a1)); }
  38.660 +        protected long   invoke_J(Object a0, long   a1) { return return_J(targetA2(a0, a1)); }
  38.661 +        protected float  invoke_F(Object a0, long   a1) { return return_F(targetA2(a0, a1)); }
  38.662 +        protected double invoke_D(Object a0, long   a1) { return return_D(targetA2(a0, a1)); }
  38.663 +        protected Object invoke_L(long   a0, long   a1) { return return_L(targetA2(a0, a1)); }
  38.664 +        protected int    invoke_I(long   a0, long   a1) { return return_I(targetA2(a0, a1)); }
  38.665 +        protected long   invoke_J(long   a0, long   a1) { return return_J(targetA2(a0, a1)); }
  38.666 +        protected float  invoke_F(long   a0, long   a1) { return return_F(targetA2(a0, a1)); }
  38.667 +        protected double invoke_D(long   a0, long   a1) { return return_D(targetA2(a0, a1)); }
  38.668 +    }
  38.669 +    static class A3 extends Adapter {
  38.670 +        protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.671 +        protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.672 +        protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); }
  38.673 +        protected Object target(Object a0, Object a1, Object a2)   { return invoker.<Object>invoke(target, a0, a1, a2); }
  38.674 +        protected Object targetA3(Object a0, Object a1, Object a2) { return target(a0, a1, a2); }
  38.675 +        protected Object targetA3(Object a0, Object a1, int    a2) { return target(a0, a1, a2); }
  38.676 +        protected Object targetA3(Object a0, int    a1, int    a2) { return target(a0, a1, a2); }
  38.677 +        protected Object targetA3(int    a0, int    a1, int    a2) { return target(a0, a1, a2); }
  38.678 +        protected Object targetA3(Object a0, Object a1, long   a2) { return target(a0, a1, a2); }
  38.679 +        protected Object targetA3(Object a0, long   a1, long   a2) { return target(a0, a1, a2); }
  38.680 +        protected Object targetA3(long   a0, long   a1, long   a2) { return target(a0, a1, a2); }
  38.681 +        protected Object invoke_L(Object a0, Object a1, Object a2) { return return_L(targetA3(a0, a1, a2)); }
  38.682 +        protected int    invoke_I(Object a0, Object a1, Object a2) { return return_I(targetA3(a0, a1, a2)); }
  38.683 +        protected long   invoke_J(Object a0, Object a1, Object a2) { return return_J(targetA3(a0, a1, a2)); }
  38.684 +        protected float  invoke_F(Object a0, Object a1, Object a2) { return return_F(targetA3(a0, a1, a2)); }
  38.685 +        protected double invoke_D(Object a0, Object a1, Object a2) { return return_D(targetA3(a0, a1, a2)); }
  38.686 +        protected Object invoke_L(Object a0, Object a1, int    a2) { return return_L(targetA3(a0, a1, a2)); }
  38.687 +        protected int    invoke_I(Object a0, Object a1, int    a2) { return return_I(targetA3(a0, a1, a2)); }
  38.688 +        protected long   invoke_J(Object a0, Object a1, int    a2) { return return_J(targetA3(a0, a1, a2)); }
  38.689 +        protected float  invoke_F(Object a0, Object a1, int    a2) { return return_F(targetA3(a0, a1, a2)); }
  38.690 +        protected double invoke_D(Object a0, Object a1, int    a2) { return return_D(targetA3(a0, a1, a2)); }
  38.691 +        protected Object invoke_L(Object a0, int    a1, int    a2) { return return_L(targetA3(a0, a1, a2)); }
  38.692 +        protected int    invoke_I(Object a0, int    a1, int    a2) { return return_I(targetA3(a0, a1, a2)); }
  38.693 +        protected long   invoke_J(Object a0, int    a1, int    a2) { return return_J(targetA3(a0, a1, a2)); }
  38.694 +        protected float  invoke_F(Object a0, int    a1, int    a2) { return return_F(targetA3(a0, a1, a2)); }
  38.695 +        protected double invoke_D(Object a0, int    a1, int    a2) { return return_D(targetA3(a0, a1, a2)); }
  38.696 +        protected Object invoke_L(int    a0, int    a1, int    a2) { return return_L(targetA3(a0, a1, a2)); }
  38.697 +        protected int    invoke_I(int    a0, int    a1, int    a2) { return return_I(targetA3(a0, a1, a2)); }
  38.698 +        protected long   invoke_J(int    a0, int    a1, int    a2) { return return_J(targetA3(a0, a1, a2)); }
  38.699 +        protected float  invoke_F(int    a0, int    a1, int    a2) { return return_F(targetA3(a0, a1, a2)); }
  38.700 +        protected double invoke_D(int    a0, int    a1, int    a2) { return return_D(targetA3(a0, a1, a2)); }
  38.701 +        protected Object invoke_L(Object a0, Object a1, long   a2) { return return_L(targetA3(a0, a1, a2)); }
  38.702 +        protected int    invoke_I(Object a0, Object a1, long   a2) { return return_I(targetA3(a0, a1, a2)); }
  38.703 +        protected long   invoke_J(Object a0, Object a1, long   a2) { return return_J(targetA3(a0, a1, a2)); }
  38.704 +        protected float  invoke_F(Object a0, Object a1, long   a2) { return return_F(targetA3(a0, a1, a2)); }
  38.705 +        protected double invoke_D(Object a0, Object a1, long   a2) { return return_D(targetA3(a0, a1, a2)); }
  38.706 +        protected Object invoke_L(Object a0, long   a1, long   a2) { return return_L(targetA3(a0, a1, a2)); }
  38.707 +        protected int    invoke_I(Object a0, long   a1, long   a2) { return return_I(targetA3(a0, a1, a2)); }
  38.708 +        protected long   invoke_J(Object a0, long   a1, long   a2) { return return_J(targetA3(a0, a1, a2)); }
  38.709 +        protected float  invoke_F(Object a0, long   a1, long   a2) { return return_F(targetA3(a0, a1, a2)); }
  38.710 +        protected double invoke_D(Object a0, long   a1, long   a2) { return return_D(targetA3(a0, a1, a2)); }
  38.711 +        protected Object invoke_L(long   a0, long   a1, long   a2) { return return_L(targetA3(a0, a1, a2)); }
  38.712 +        protected int    invoke_I(long   a0, long   a1, long   a2) { return return_I(targetA3(a0, a1, a2)); }
  38.713 +        protected long   invoke_J(long   a0, long   a1, long   a2) { return return_J(targetA3(a0, a1, a2)); }
  38.714 +        protected float  invoke_F(long   a0, long   a1, long   a2) { return return_F(targetA3(a0, a1, a2)); }
  38.715 +        protected double invoke_D(long   a0, long   a1, long   a2) { return return_D(targetA3(a0, a1, a2)); }
  38.716 +    }
  38.717 +//params=[4, 5, 2, 99, 99, 99]
  38.718 +    static class A4 extends Adapter {
  38.719 +        protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.720 +        protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.721 +        protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); }
  38.722 +        protected Object target(Object a0, Object a1, Object a2, Object a3)   { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
  38.723 +        protected Object targetA4(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, a3); }
  38.724 +        protected Object targetA4(Object a0, Object a1, Object a2, int    a3) { return target(a0, a1, a2, a3); }
  38.725 +        protected Object targetA4(Object a0, Object a1, int    a2, int    a3) { return target(a0, a1, a2, a3); }
  38.726 +        protected Object targetA4(Object a0, int    a1, int    a2, int    a3) { return target(a0, a1, a2, a3); }
  38.727 +        protected Object targetA4(int    a0, int    a1, int    a2, int    a3) { return target(a0, a1, a2, a3); }
  38.728 +        protected Object targetA4(Object a0, Object a1, Object a2, long   a3) { return target(a0, a1, a2, a3); }
  38.729 +        protected Object targetA4(Object a0, Object a1, long   a2, long   a3) { return target(a0, a1, a2, a3); }
  38.730 +        protected Object targetA4(Object a0, long   a1, long   a2, long   a3) { return target(a0, a1, a2, a3); }
  38.731 +        protected Object targetA4(long   a0, long   a1, long   a2, long   a3) { return target(a0, a1, a2, a3); }
  38.732 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.733 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.734 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.735 +        protected Object invoke_L(Object a0, Object a1, Object a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.736 +        protected int    invoke_I(Object a0, Object a1, Object a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.737 +        protected long   invoke_J(Object a0, Object a1, Object a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.738 +        protected Object invoke_L(Object a0, Object a1, int    a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.739 +        protected int    invoke_I(Object a0, Object a1, int    a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.740 +        protected long   invoke_J(Object a0, Object a1, int    a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.741 +        protected Object invoke_L(Object a0, int    a1, int    a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.742 +        protected int    invoke_I(Object a0, int    a1, int    a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.743 +        protected long   invoke_J(Object a0, int    a1, int    a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.744 +        protected Object invoke_L(int    a0, int    a1, int    a2, int    a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.745 +        protected int    invoke_I(int    a0, int    a1, int    a2, int    a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.746 +        protected long   invoke_J(int    a0, int    a1, int    a2, int    a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.747 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.748 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.749 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.750 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.751 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.752 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.753 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.754 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.755 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.756 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3) { return return_L(targetA4(a0, a1, a2, a3)); }
  38.757 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3) { return return_I(targetA4(a0, a1, a2, a3)); }
  38.758 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3) { return return_J(targetA4(a0, a1, a2, a3)); }
  38.759 +    }
  38.760 +    static class A5 extends Adapter {
  38.761 +        protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.762 +        protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.763 +        protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); }
  38.764 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4); }
  38.765 +        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) { return target(a0, a1, a2, a3, a4); }
  38.766 +        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int    a4) { return target(a0, a1, a2, a3, a4); }
  38.767 +        protected Object targetA5(Object a0, Object a1, Object a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
  38.768 +        protected Object targetA5(Object a0, Object a1, int    a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
  38.769 +        protected Object targetA5(Object a0, int    a1, int    a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
  38.770 +        protected Object targetA5(int    a0, int    a1, int    a2, int    a3, int    a4) { return target(a0, a1, a2, a3, a4); }
  38.771 +        protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long   a4) { return target(a0, a1, a2, a3, a4); }
  38.772 +        protected Object targetA5(Object a0, Object a1, Object a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
  38.773 +        protected Object targetA5(Object a0, Object a1, long   a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
  38.774 +        protected Object targetA5(Object a0, long   a1, long   a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
  38.775 +        protected Object targetA5(long   a0, long   a1, long   a2, long   a3, long   a4) { return target(a0, a1, a2, a3, a4); }
  38.776 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.777 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.778 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.779 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.780 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.781 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.782 +        protected Object invoke_L(Object a0, Object a1, Object a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.783 +        protected int    invoke_I(Object a0, Object a1, Object a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.784 +        protected long   invoke_J(Object a0, Object a1, Object a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.785 +        protected Object invoke_L(Object a0, Object a1, int    a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.786 +        protected int    invoke_I(Object a0, Object a1, int    a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.787 +        protected long   invoke_J(Object a0, Object a1, int    a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.788 +        protected Object invoke_L(Object a0, int    a1, int    a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.789 +        protected int    invoke_I(Object a0, int    a1, int    a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.790 +        protected long   invoke_J(Object a0, int    a1, int    a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.791 +        protected Object invoke_L(int    a0, int    a1, int    a2, int    a3, int    a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.792 +        protected int    invoke_I(int    a0, int    a1, int    a2, int    a3, int    a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.793 +        protected long   invoke_J(int    a0, int    a1, int    a2, int    a3, int    a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.794 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.795 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.796 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.797 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.798 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.799 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.800 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.801 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.802 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.803 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.804 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.805 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.806 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); }
  38.807 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); }
  38.808 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); }
  38.809 +    }
  38.810 +//params=[6, 10, 2, 99, 0, 99]
  38.811 +    static class A6 extends Adapter {
  38.812 +        protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.813 +        protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.814 +        protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); }
  38.815 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5); }
  38.816 +        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.817 +        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.818 +        protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.819 +        protected Object targetA6(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.820 +        protected Object targetA6(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.821 +        protected Object targetA6(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.822 +        protected Object targetA6(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return target(a0, a1, a2, a3, a4, a5); }
  38.823 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.824 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.825 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.826 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.827 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.828 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.829 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.830 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.831 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.832 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.833 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.834 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.835 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.836 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.837 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.838 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.839 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.840 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.841 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.842 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.843 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
  38.844 +    }
  38.845 +    static class A7 extends Adapter {
  38.846 +        protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.847 +        protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.848 +        protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); }
  38.849 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6); }
  38.850 +        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.851 +        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.852 +        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.853 +        protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.854 +        protected Object targetA7(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.855 +        protected Object targetA7(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.856 +        protected Object targetA7(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.857 +        protected Object targetA7(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return target(a0, a1, a2, a3, a4, a5, a6); }
  38.858 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.859 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.860 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.861 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.862 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.863 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.864 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.865 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.866 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.867 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.868 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.869 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.870 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.871 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.872 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.873 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.874 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.875 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.876 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.877 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.878 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.879 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.880 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.881 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
  38.882 +    }
  38.883 +    static class A8 extends Adapter {
  38.884 +        protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.885 +        protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.886 +        protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); }
  38.887 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); }
  38.888 +        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.889 +        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.890 +        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.891 +        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.892 +        protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.893 +        protected Object targetA8(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.894 +        protected Object targetA8(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.895 +        protected Object targetA8(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.896 +        protected Object targetA8(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
  38.897 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.898 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.899 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.900 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.901 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.902 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.903 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.904 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.905 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.906 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.907 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.908 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.909 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.910 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.911 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.912 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.913 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.914 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.915 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.916 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.917 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.918 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.919 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.920 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.921 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.922 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.923 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
  38.924 +    }
  38.925 +    static class A9 extends Adapter {
  38.926 +        protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.927 +        protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.928 +        protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); }
  38.929 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.930 +        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.931 +        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.932 +        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.933 +        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.934 +        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.935 +        protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.936 +        protected Object targetA9(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.937 +        protected Object targetA9(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.938 +        protected Object targetA9(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.939 +        protected Object targetA9(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  38.940 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.941 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.942 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.943 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.944 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.945 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.946 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.947 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.948 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.949 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.950 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.951 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.952 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.953 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.954 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.955 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.956 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.957 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.958 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.959 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.960 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.961 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.962 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.963 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.964 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.965 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.966 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.967 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.968 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.969 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
  38.970 +    }
  38.971 +    static class A10 extends Adapter {
  38.972 +        protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
  38.973 +        protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
  38.974 +        protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); }
  38.975 +        protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9)   { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.976 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.977 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.978 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.979 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.980 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.981 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.982 +        protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.983 +        protected Object targetA10(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.984 +        protected Object targetA10(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.985 +        protected Object targetA10(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.986 +        protected Object targetA10(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  38.987 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.988 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.989 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.990 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.991 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.992 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.993 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.994 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.995 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.996 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.997 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.998 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
  38.999 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1000 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1001 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1002 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1003 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1004 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1005 +        protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1006 +        protected int    invoke_I(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1007 +        protected long   invoke_J(Object a0, Object a1, Object a2, Object a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1008 +        protected Object invoke_L(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1009 +        protected int    invoke_I(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1010 +        protected long   invoke_J(Object a0, Object a1, Object a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1011 +        protected Object invoke_L(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1012 +        protected int    invoke_I(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1013 +        protected long   invoke_J(Object a0, Object a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1014 +        protected Object invoke_L(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1015 +        protected int    invoke_I(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1016 +        protected long   invoke_J(Object a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1017 +        protected Object invoke_L(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1018 +        protected int    invoke_I(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1019 +        protected long   invoke_J(long   a0, long   a1, long   a2, long   a3, long   a4, long   a5, long   a6, long   a7, long   a8, long   a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
 38.1020 +    }
 38.1021 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java	Thu May 07 12:26:22 2009 -0700
    39.3 @@ -0,0 +1,297 @@
    39.4 +/*
    39.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    39.7 + *
    39.8 + * This code is free software; you can redistribute it and/or modify it
    39.9 + * under the terms of the GNU General Public License version 2 only, as
   39.10 + * published by the Free Software Foundation.  Sun designates this
   39.11 + * particular file as subject to the "Classpath" exception as provided
   39.12 + * by Sun in the LICENSE file that accompanied this code.
   39.13 + *
   39.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   39.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   39.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   39.17 + * version 2 for more details (a copy is included in the LICENSE file that
   39.18 + * accompanied this code).
   39.19 + *
   39.20 + * You should have received a copy of the GNU General Public License version
   39.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   39.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   39.23 + *
   39.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   39.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   39.26 + * have any questions.
   39.27 + */
   39.28 +
   39.29 +package sun.dyn.anon;
   39.30 +
   39.31 +import java.io.IOException;
   39.32 +import java.io.InputStream;
   39.33 +import java.lang.reflect.InvocationTargetException;
   39.34 +import java.lang.reflect.Method;
   39.35 +
   39.36 +/**
   39.37 + * Anonymous class loader.  Will load any valid classfile, producing
   39.38 + * a {@link Class} metaobject, without installing that class in the
   39.39 + * system dictionary.  Therefore, {@link Class#forName(String)} will never
   39.40 + * produce a reference to an anonymous class.
   39.41 + * <p>
   39.42 + * The access permissions of the anonymous class are borrowed from
   39.43 + * a <em>host class</em>.  The new class behaves as if it were an
   39.44 + * inner class of the host class.  It can access the host's private
   39.45 + * members, if the creator of the class loader has permission to
   39.46 + * do so (or to create accessible reflective objects).
   39.47 + * <p>
   39.48 + * When the anonymous class is loaded, elements of its constant pool
   39.49 + * can be patched to new values.  This provides a hook to pre-resolve
   39.50 + * named classes in the constant pool to other classes, including
   39.51 + * anonymous ones.  Also, string constants can be pre-resolved to
   39.52 + * any reference.  (The verifier treats non-string, non-class reference
   39.53 + * constants as plain objects.)
   39.54 + *  <p>
   39.55 + * Why include the patching function?  It makes some use cases much easier.
   39.56 + * Second, the constant pool needed some internal patching anyway,
   39.57 + * to anonymize the loaded class itself.  Finally, if you are going
   39.58 + * to use this seriously, you'll want to build anonymous classes
   39.59 + * on top of pre-existing anonymous classes, and that requires patching.
   39.60 + *
   39.61 + * <p>%%% TO-DO:
   39.62 + * <ul>
   39.63 + * <li>needs better documentation</li>
   39.64 + * <li>needs more security work (for safe delegation)</li>
   39.65 + * <li>needs a clearer story about error processing</li>
   39.66 + * <li>patch member references also (use ';' as delimiter char)</li>
   39.67 + * <li>patch method references to (conforming) method handles</li>
   39.68 + * </ul>
   39.69 + *
   39.70 + * @author jrose
   39.71 + * @author Remi Forax
   39.72 + * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
   39.73 + *      http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
   39.74 + */
   39.75 +
   39.76 +public class AnonymousClassLoader {
   39.77 +    final Class<?> hostClass;
   39.78 +
   39.79 +    // Note: Do not refactor the calls to checkHostClass unless you
   39.80 +    //       also adjust this constant:
   39.81 +    private static int CHC_CALLERS = 3;
   39.82 +
   39.83 +    public AnonymousClassLoader() {
   39.84 +        this.hostClass = checkHostClass(null);
   39.85 +    }
   39.86 +    public AnonymousClassLoader(Class<?> hostClass) {
   39.87 +        this.hostClass = checkHostClass(hostClass);
   39.88 +    }
   39.89 +
   39.90 +    private static Class<?> getTopLevelClass(Class<?> clazz) {
   39.91 +      for(Class<?> outer = clazz.getDeclaringClass(); outer != null;
   39.92 +          outer = outer.getDeclaringClass()) {
   39.93 +        clazz = outer;
   39.94 +      }
   39.95 +      return clazz;
   39.96 +    }
   39.97 +
   39.98 +    private static Class<?> checkHostClass(Class<?> hostClass) {
   39.99 +        // called only from the constructor
  39.100 +        // does a context-sensitive check on caller class
  39.101 +        // CC[0..3] = {Reflection, this.checkHostClass, this.<init>, caller}
  39.102 +        Class<?> caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS);
  39.103 +
  39.104 +        if (caller == null) {
  39.105 +            // called from the JVM directly
  39.106 +            if (hostClass == null)
  39.107 +                return AnonymousClassLoader.class; // anything central will do
  39.108 +            return hostClass;
  39.109 +        }
  39.110 +
  39.111 +        if (hostClass == null)
  39.112 +            hostClass = caller; // default value is caller itself
  39.113 +
  39.114 +        // anonymous class will access hostClass on behalf of caller
  39.115 +        Class<?> callee = hostClass;
  39.116 +
  39.117 +        if (caller == callee)
  39.118 +            // caller can always nominate itself to grant caller's own access rights
  39.119 +            return hostClass;
  39.120 +
  39.121 +        // normalize caller and callee to their top-level classes:
  39.122 +        caller = getTopLevelClass(caller);
  39.123 +        callee = getTopLevelClass(callee);
  39.124 +        if (caller == callee)
  39.125 +            return caller;
  39.126 +
  39.127 +        ClassLoader callerCL = caller.getClassLoader();
  39.128 +        if (callerCL == null) {
  39.129 +            // caller is trusted code, so accept the proposed hostClass
  39.130 +            return hostClass;
  39.131 +        }
  39.132 +
  39.133 +        // %%% should do something with doPrivileged, because trusted
  39.134 +        // code should have a way to execute on behalf of
  39.135 +        // partially-trusted clients
  39.136 +
  39.137 +        // Does the caller have the right to access the private
  39.138 +        // members of the callee?  If not, raise an error.
  39.139 +        final int ACC_PRIVATE = 2;
  39.140 +        try {
  39.141 +            sun.reflect.Reflection.ensureMemberAccess(caller, callee, null, ACC_PRIVATE);
  39.142 +        } catch (IllegalAccessException ee) {
  39.143 +            throw new IllegalArgumentException(ee);
  39.144 +        }
  39.145 +
  39.146 +        return hostClass;
  39.147 +    }
  39.148 +
  39.149 +    public Class<?> loadClass(byte[] classFile) {
  39.150 +        if (defineAnonymousClass == null) {
  39.151 +            // no JVM support; try to fake an approximation
  39.152 +            try {
  39.153 +                return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
  39.154 +            } catch (InvalidConstantPoolFormatException ee) {
  39.155 +                throw new IllegalArgumentException(ee);
  39.156 +            }
  39.157 +        }
  39.158 +        return loadClass(classFile, null);
  39.159 +    }
  39.160 +
  39.161 +    public Class<?> loadClass(ConstantPoolPatch classPatch) {
  39.162 +        if (defineAnonymousClass == null) {
  39.163 +            // no JVM support; try to fake an approximation
  39.164 +            return fakeLoadClass(classPatch);
  39.165 +        }
  39.166 +        Object[] patches = classPatch.patchArray;
  39.167 +        // Convert class names (this late in the game)
  39.168 +        // to use slash '/' instead of dot '.'.
  39.169 +        // Java likes dots, but the JVM likes slashes.
  39.170 +        for (int i = 0; i < patches.length; i++) {
  39.171 +            Object value = patches[i];
  39.172 +            if (value != null) {
  39.173 +                byte tag = classPatch.getTag(i);
  39.174 +                switch (tag) {
  39.175 +                case ConstantPoolVisitor.CONSTANT_Class:
  39.176 +                    if (value instanceof String) {
  39.177 +                        if (patches == classPatch.patchArray)
  39.178 +                            patches = patches.clone();
  39.179 +                        patches[i] = ((String)value).replace('.', '/');
  39.180 +                    }
  39.181 +                    break;
  39.182 +                case ConstantPoolVisitor.CONSTANT_Fieldref:
  39.183 +                case ConstantPoolVisitor.CONSTANT_Methodref:
  39.184 +                case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
  39.185 +                case ConstantPoolVisitor.CONSTANT_NameAndType:
  39.186 +                    // When/if the JVM supports these patches,
  39.187 +                    // we'll probably need to reformat them also.
  39.188 +                    // Meanwhile, let the class loader create the error.
  39.189 +                    break;
  39.190 +                }
  39.191 +            }
  39.192 +        }
  39.193 +        return loadClass(classPatch.outer.classFile, classPatch.patchArray);
  39.194 +    }
  39.195 +
  39.196 +    private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
  39.197 +        try {
  39.198 +            return (Class<?>)
  39.199 +                defineAnonymousClass.invoke(unsafe,
  39.200 +                                            hostClass, classFile, patchArray);
  39.201 +        } catch (Exception ex) {
  39.202 +            throwReflectedException(ex);
  39.203 +            throw new RuntimeException("error loading into "+hostClass, ex);
  39.204 +        }
  39.205 +    }
  39.206 +
  39.207 +    private static void throwReflectedException(Exception ex) {
  39.208 +        if (ex instanceof InvocationTargetException) {
  39.209 +            Throwable tex = ((InvocationTargetException)ex).getTargetException();
  39.210 +            if (tex instanceof Error)
  39.211 +                throw (Error) tex;
  39.212 +            ex = (Exception) tex;
  39.213 +        }
  39.214 +        if (ex instanceof RuntimeException) {
  39.215 +            throw (RuntimeException) ex;
  39.216 +        }
  39.217 +    }
  39.218 +
  39.219 +    private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
  39.220 +        // Implementation:
  39.221 +        // 1. Make up a new name nobody has used yet.
  39.222 +        // 2. Inspect the tail-header of the class to find the this_class index.
  39.223 +        // 3. Patch the CONSTANT_Class for this_class to the new name.
  39.224 +        // 4. Add other CP entries required by (e.g.) string patches.
  39.225 +        // 5. Flatten Class constants down to their names, making sure that
  39.226 +        //    the host class loader can pick them up again accurately.
  39.227 +        // 6. Generate the edited class file bytes.
  39.228 +        //
  39.229 +        // Potential limitations:
  39.230 +        // * The class won't be truly anonymous, and may interfere with others.
  39.231 +        // * Flattened class constants might not work, because of loader issues.
  39.232 +        // * Pseudo-string constants will not flatten down to real strings.
  39.233 +        // * Method handles will (of course) fail to flatten to linkage strings.
  39.234 +        if (true)  throw new UnsupportedOperationException("NYI");
  39.235 +        Object[] cpArray;
  39.236 +        try {
  39.237 +            cpArray = classPatch.getOriginalCP();
  39.238 +        } catch (InvalidConstantPoolFormatException ex) {
  39.239 +            throw new RuntimeException(ex);
  39.240 +        }
  39.241 +        int thisClassIndex = classPatch.getParser().getThisClassIndex();
  39.242 +        String thisClassName = (String) cpArray[thisClassIndex];
  39.243 +        synchronized (AnonymousClassLoader.class) {
  39.244 +            thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
  39.245 +        }
  39.246 +        classPatch.putUTF8(thisClassIndex, thisClassName);
  39.247 +        byte[] classFile = null;
  39.248 +        return unsafe.defineClass(null, classFile, 0, classFile.length,
  39.249 +                                  hostClass.getClassLoader(),
  39.250 +                                  hostClass.getProtectionDomain());
  39.251 +    }
  39.252 +    private static int fakeNameCounter = 99999;
  39.253 +
  39.254 +    // ignore two warnings on this line:
  39.255 +    static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
  39.256 +    // preceding line requires that this class be on the boot class path
  39.257 +
  39.258 +    static private final Method defineAnonymousClass;
  39.259 +    static {
  39.260 +        Method dac = null;
  39.261 +        Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
  39.262 +        try {
  39.263 +            dac = unsafeClass.getMethod("defineAnonymousClass",
  39.264 +                                        Class.class,
  39.265 +                                        byte[].class,
  39.266 +                                        Object[].class);
  39.267 +        } catch (Exception ee) {
  39.268 +            dac = null;
  39.269 +        }
  39.270 +        defineAnonymousClass = dac;
  39.271 +    }
  39.272 +
  39.273 +    private static void noJVMSupport() {
  39.274 +        throw new UnsupportedOperationException("no JVM support for anonymous classes");
  39.275 +    }
  39.276 +
  39.277 +
  39.278 +    private static native Class<?> loadClassInternal(Class<?> hostClass,
  39.279 +                                                     byte[] classFile,
  39.280 +                                                     Object[] patchArray);
  39.281 +
  39.282 +    public static byte[] readClassFile(Class<?> templateClass) throws IOException {
  39.283 +        String templateName = templateClass.getName();
  39.284 +        int lastDot = templateName.lastIndexOf('.');
  39.285 +        java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
  39.286 +        java.net.URLConnection connection = url.openConnection();
  39.287 +        int contentLength = connection.getContentLength();
  39.288 +        if (contentLength < 0)
  39.289 +            throw new IOException("invalid content length "+contentLength);
  39.290 +
  39.291 +        byte[] classFile = new byte[contentLength];
  39.292 +        InputStream tcs = connection.getInputStream();
  39.293 +        for (int fill = 0, nr; fill < classFile.length; fill += nr) {
  39.294 +            nr = tcs.read(classFile, fill, classFile.length - fill);
  39.295 +            if (nr < 0)
  39.296 +                throw new IOException("premature end of file");
  39.297 +        }
  39.298 +        return classFile;
  39.299 +    }
  39.300 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/src/share/classes/sun/dyn/anon/ConstantPoolParser.java	Thu May 07 12:26:22 2009 -0700
    40.3 @@ -0,0 +1,368 @@
    40.4 +/*
    40.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    40.7 + *
    40.8 + * This code is free software; you can redistribute it and/or modify it
    40.9 + * under the terms of the GNU General Public License version 2 only, as
   40.10 + * published by the Free Software Foundation.  Sun designates this
   40.11 + * particular file as subject to the "Classpath" exception as provided
   40.12 + * by Sun in the LICENSE file that accompanied this code.
   40.13 + *
   40.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   40.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   40.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   40.17 + * version 2 for more details (a copy is included in the LICENSE file that
   40.18 + * accompanied this code).
   40.19 + *
   40.20 + * You should have received a copy of the GNU General Public License version
   40.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   40.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   40.23 + *
   40.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   40.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   40.26 + * have any questions.
   40.27 + */
   40.28 +
   40.29 +package sun.dyn.anon;
   40.30 +
   40.31 +import java.io.IOException;
   40.32 +import java.io.OutputStream;
   40.33 +import java.nio.BufferUnderflowException;
   40.34 +import java.nio.ByteBuffer;
   40.35 +
   40.36 +import static sun.dyn.anon.ConstantPoolVisitor.*;
   40.37 +
   40.38 +/** A constant pool parser.
   40.39 + */
   40.40 +public class ConstantPoolParser {
   40.41 +    final byte[] classFile;
   40.42 +    final byte[] tags;
   40.43 +    final char[] firstHeader;  // maghi, maglo, minor, major, cplen
   40.44 +
   40.45 +    // these are filled in on first parse:
   40.46 +    int endOffset;
   40.47 +    char[] secondHeader;       // flags, this_class, super_class, intlen
   40.48 +
   40.49 +    // used to decode UTF8 array
   40.50 +    private char[] charArray = new char[80];
   40.51 +
   40.52 +    /** Creates a constant pool parser.
   40.53 +     * @param classFile an array of bytes containing a class.
   40.54 +     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
   40.55 +     */
   40.56 +    public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
   40.57 +        this.classFile = classFile;
   40.58 +        this.firstHeader = parseHeader(classFile);
   40.59 +        this.tags = new byte[firstHeader[4]];
   40.60 +    }
   40.61 +
   40.62 +    /** Create a constant pool parser by loading the bytecodes of the
   40.63 +     *  class taken as argument.
   40.64 +     *
   40.65 +     * @param templateClass the class to parse.
   40.66 +     *
   40.67 +     * @throws IOException raised if an I/O occurs when loading
   40.68 +     *  the bytecode of the template class.
   40.69 +     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
   40.70 +     *
   40.71 +     * @see #ConstantPoolParser(byte[])
   40.72 +     * @see AnonymousClassLoader#readClassFile(Class)
   40.73 +     */
   40.74 +    public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
   40.75 +        this(AnonymousClassLoader.readClassFile(templateClass));
   40.76 +    }
   40.77 +
   40.78 +    /** Creates an empty patch to patch the class file
   40.79 +     *  used by the current parser.
   40.80 +     * @return a new class patch.
   40.81 +     */
   40.82 +    public ConstantPoolPatch createPatch() {
   40.83 +        return new ConstantPoolPatch(this);
   40.84 +    }
   40.85 +
   40.86 +    /** Report the tag of the indicated CP entry.
   40.87 +     * @param index
   40.88 +     * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
   40.89 +     */
   40.90 +    public byte getTag(int index) {
   40.91 +        getEndOffset();  // trigger an exception if we haven't parsed yet
   40.92 +        return tags[index];
   40.93 +    }
   40.94 +
   40.95 +    /** Report the length of the constant pool. */
   40.96 +    public int getLength() {
   40.97 +        return firstHeader[4];
   40.98 +    }
   40.99 +
  40.100 +    /** Report the offset, within the class file, of the start of the constant pool. */
  40.101 +    public int getStartOffset() {
  40.102 +        return firstHeader.length * 2;
  40.103 +    }
  40.104 +
  40.105 +    /** Report the offset, within the class file, of the end of the constant pool. */
  40.106 +    public int getEndOffset() {
  40.107 +        if (endOffset == 0)
  40.108 +            throw new IllegalStateException("class file has not yet been parsed");
  40.109 +        return endOffset;
  40.110 +    }
  40.111 +
  40.112 +    /** Report the CP index of this class's own name. */
  40.113 +    public int getThisClassIndex() {
  40.114 +        getEndOffset();   // provoke exception if not yet parsed
  40.115 +        return secondHeader[1];
  40.116 +    }
  40.117 +
  40.118 +    /** Report the total size of the class file. */
  40.119 +    public int getTailLength() {
  40.120 +        return classFile.length - getEndOffset();
  40.121 +    }
  40.122 +
  40.123 +    /** Write the head (header plus constant pool)
  40.124 +     *  of the class file to the indicated stream.
  40.125 +     */
  40.126 +    public void writeHead(OutputStream out) throws IOException {
  40.127 +        out.write(classFile, 0, getEndOffset());
  40.128 +    }
  40.129 +
  40.130 +    /** Write the head (header plus constant pool)
  40.131 +     *  of the class file to the indicated stream,
  40.132 +     *  incorporating the non-null entries of the given array
  40.133 +     *  as patches.
  40.134 +     */
  40.135 +    void writePatchedHead(OutputStream out, Object[] patchArray) {
  40.136 +        // this will be useful to partially emulate the class loader on old JVMs
  40.137 +        throw new UnsupportedOperationException("Not yet implemented");
  40.138 +    }
  40.139 +
  40.140 +    /** Write the tail (everything after the constant pool)
  40.141 +     *  of the class file to the indicated stream.
  40.142 +     */
  40.143 +    public void writeTail(OutputStream out) throws IOException {
  40.144 +        out.write(classFile, getEndOffset(), getTailLength());
  40.145 +    }
  40.146 +
  40.147 +    private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
  40.148 +        char[] result = new char[5];
  40.149 +        ByteBuffer buffer = ByteBuffer.wrap(classFile);
  40.150 +        for (int i = 0; i < result.length; i++)
  40.151 +            result[i] = (char) getUnsignedShort(buffer);
  40.152 +        int magic = result[0] << 16 | result[1] << 0;
  40.153 +        if (magic != 0xCAFEBABE)
  40.154 +            throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
  40.155 +        // skip major, minor version
  40.156 +        int len = result[4];
  40.157 +        if (len < 1)
  40.158 +            throw new InvalidConstantPoolFormatException("constant pool length < 1");
  40.159 +        return result;
  40.160 +    }
  40.161 +
  40.162 +    /** Parse the constant pool of the class
  40.163 +     *  calling a method visit* each time a constant pool entry is parsed.
  40.164 +     *
  40.165 +     *  The order of the calls to visit* is not guaranteed to be the same
  40.166 +     *  than the order of the constant pool entry in the bytecode array.
  40.167 +     *
  40.168 +     * @param visitor
  40.169 +     * @throws InvalidConstantPoolFormatException
  40.170 +     */
  40.171 +    public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
  40.172 +        ByteBuffer buffer = ByteBuffer.wrap(classFile);
  40.173 +        buffer.position(getStartOffset()); //skip header
  40.174 +
  40.175 +        Object[] values = new Object[getLength()];
  40.176 +        try {
  40.177 +            parseConstantPool(buffer, values, visitor);
  40.178 +        } catch(BufferUnderflowException e) {
  40.179 +            throw new InvalidConstantPoolFormatException(e);
  40.180 +        }
  40.181 +        if (endOffset == 0) {
  40.182 +            endOffset = buffer.position();
  40.183 +            secondHeader = new char[4];
  40.184 +            for (int i = 0; i < secondHeader.length; i++) {
  40.185 +                secondHeader[i] = (char) getUnsignedShort(buffer);
  40.186 +            }
  40.187 +        }
  40.188 +        resolveConstantPool(values, visitor);
  40.189 +    }
  40.190 +
  40.191 +    private char[] getCharArray(int utfLength) {
  40.192 +        if (utfLength <= charArray.length)
  40.193 +            return charArray;
  40.194 +        return charArray = new char[utfLength];
  40.195 +    }
  40.196 +
  40.197 +    private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
  40.198 +        for (int i = 1; i < tags.length; ) {
  40.199 +            byte tag = (byte) getUnsignedByte(buffer);
  40.200 +            assert(tags[i] == 0 || tags[i] == tag);
  40.201 +            tags[i] = tag;
  40.202 +            switch (tag) {
  40.203 +                case CONSTANT_Utf8:
  40.204 +                    int utfLen = getUnsignedShort(buffer);
  40.205 +                    String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
  40.206 +                    visitor.visitUTF8(i, CONSTANT_Utf8, value);
  40.207 +                    tags[i] = tag;
  40.208 +                    values[i++] = value;
  40.209 +                    break;
  40.210 +                case CONSTANT_Integer:
  40.211 +                    visitor.visitConstantValue(i, tag, buffer.getInt());
  40.212 +                    i++;
  40.213 +                    break;
  40.214 +                case CONSTANT_Float:
  40.215 +                    visitor.visitConstantValue(i, tag, buffer.getFloat());
  40.216 +                    i++;
  40.217 +                    break;
  40.218 +                case CONSTANT_Long:
  40.219 +                    visitor.visitConstantValue(i, tag, buffer.getLong());
  40.220 +                    i+=2;
  40.221 +                    break;
  40.222 +                case CONSTANT_Double:
  40.223 +                    visitor.visitConstantValue(i, tag, buffer.getDouble());
  40.224 +                    i+=2;
  40.225 +                    break;
  40.226 +
  40.227 +                case CONSTANT_Class:    // fall through:
  40.228 +                case CONSTANT_String:
  40.229 +                    tags[i] = tag;
  40.230 +                    values[i++] = new int[] { getUnsignedShort(buffer) };
  40.231 +                    break;
  40.232 +
  40.233 +                case CONSTANT_Fieldref:           // fall through:
  40.234 +                case CONSTANT_Methodref:          // fall through:
  40.235 +                case CONSTANT_InterfaceMethodref: // fall through:
  40.236 +                case CONSTANT_NameAndType:
  40.237 +                    tags[i] = tag;
  40.238 +                    values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
  40.239 +                    break;
  40.240 +                default:
  40.241 +                    throw new AssertionError("invalid constant "+tag);
  40.242 +            }
  40.243 +        }
  40.244 +    }
  40.245 +
  40.246 +    private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
  40.247 +        // clean out the int[] values, which are temporary
  40.248 +        for (int beg = 1, end = values.length-1, beg2, end2;
  40.249 +             beg <= end;
  40.250 +             beg = beg2, end = end2) {
  40.251 +             beg2 = end; end2 = beg-1;
  40.252 +             //System.out.println("CP resolve pass: "+beg+".."+end);
  40.253 +             for (int i = beg; i <= end; i++) {
  40.254 +                  Object value = values[i];
  40.255 +                  if (!(value instanceof int[]))
  40.256 +                      continue;
  40.257 +                  int[] array = (int[]) value;
  40.258 +                  byte tag = tags[i];
  40.259 +                  switch (tag) {
  40.260 +                      case CONSTANT_String:
  40.261 +                          String stringBody = (String) values[array[0]];
  40.262 +                          visitor.visitConstantString(i, tag, stringBody, array[0]);
  40.263 +                          values[i] = null;
  40.264 +                          break;
  40.265 +                      case CONSTANT_Class: {
  40.266 +                          String className = (String) values[array[0]];
  40.267 +                          // use the external form favored by Class.forName:
  40.268 +                          className = className.replace('/', '.');
  40.269 +                          visitor.visitConstantString(i, tag, className, array[0]);
  40.270 +                          values[i] = className;
  40.271 +                          break;
  40.272 +                      }
  40.273 +                      case CONSTANT_NameAndType: {
  40.274 +                          String memberName = (String) values[array[0]];
  40.275 +                          String signature  = (String) values[array[1]];
  40.276 +                          visitor.visitDescriptor(i, tag, memberName, signature,
  40.277 +                                                  array[0], array[1]);
  40.278 +                          values[i] = new String[] {memberName, signature};
  40.279 +                          break;
  40.280 +                      }
  40.281 +                      case CONSTANT_Fieldref:           // fall through:
  40.282 +                      case CONSTANT_Methodref:          // fall through:
  40.283 +                      case CONSTANT_InterfaceMethodref: {
  40.284 +                              Object className   = values[array[0]];
  40.285 +                              Object nameAndType = values[array[1]];
  40.286 +                              if (!(className instanceof String) ||
  40.287 +                                  !(nameAndType instanceof String[])) {
  40.288 +                                   // one more pass is needed
  40.289 +                                   if (beg2 > i)  beg2 = i;
  40.290 +                                   if (end2 < i)  end2 = i;
  40.291 +                                   continue;
  40.292 +                              }
  40.293 +                              String[] nameAndTypeArray = (String[]) nameAndType;
  40.294 +                              visitor.visitMemberRef(i, tag,
  40.295 +                                  (String)className,
  40.296 +                                  nameAndTypeArray[0],
  40.297 +                                  nameAndTypeArray[1],
  40.298 +                                  array[0], array[1]);
  40.299 +                              values[i] = null;
  40.300 +                          }
  40.301 +                          break;
  40.302 +                      default:
  40.303 +                          continue;
  40.304 +                }
  40.305 +            }
  40.306 +        }
  40.307 +    }
  40.308 +
  40.309 +    private static int getUnsignedByte(ByteBuffer buffer) {
  40.310 +        return buffer.get() & 0xFF;
  40.311 +    }
  40.312 +
  40.313 +    private static int getUnsignedShort(ByteBuffer buffer) {
  40.314 +        int b1 = getUnsignedByte(buffer);
  40.315 +        int b2 = getUnsignedByte(buffer);
  40.316 +        return (b1 << 8) + (b2 << 0);
  40.317 +    }
  40.318 +
  40.319 +    private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
  40.320 +      int utfLimit = buffer.position() + utfLen;
  40.321 +      int index = 0;
  40.322 +      while (buffer.position() < utfLimit) {
  40.323 +          int c = buffer.get() & 0xff;
  40.324 +          if (c > 127) {
  40.325 +              buffer.position(buffer.position() - 1);
  40.326 +              return getUTF8Extended(buffer, utfLimit, charArray, index);
  40.327 +          }
  40.328 +          charArray[index++] = (char)c;
  40.329 +      }
  40.330 +      return new String(charArray, 0, index);
  40.331 +    }
  40.332 +
  40.333 +    private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
  40.334 +        int c, c2, c3;
  40.335 +        while (buffer.position() < utfLimit) {
  40.336 +            c = buffer.get() & 0xff;
  40.337 +            switch (c >> 4) {
  40.338 +                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
  40.339 +                    /* 0xxxxxxx*/
  40.340 +                    charArray[index++] = (char)c;
  40.341 +                    break;
  40.342 +                case 12: case 13:
  40.343 +                    /* 110x xxxx   10xx xxxx*/
  40.344 +                    c2 = buffer.get();
  40.345 +                    if ((c2 & 0xC0) != 0x80)
  40.346 +                        throw new InvalidConstantPoolFormatException(
  40.347 +                            "malformed input around byte " + buffer.position());
  40.348 +                     charArray[index++] = (char)(((c  & 0x1F) << 6) |
  40.349 +                                                  (c2 & 0x3F));
  40.350 +                    break;
  40.351 +                case 14:
  40.352 +                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
  40.353 +                    c2 = buffer.get();
  40.354 +                    c3 = buffer.get();
  40.355 +                    if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
  40.356 +                       throw new InvalidConstantPoolFormatException(
  40.357 +                          "malformed input around byte " + (buffer.position()));
  40.358 +                    charArray[index++] = (char)(((c  & 0x0F) << 12) |
  40.359 +                                                ((c2 & 0x3F) << 6)  |
  40.360 +                                                ((c3 & 0x3F) << 0));
  40.361 +                    break;
  40.362 +                default:
  40.363 +                    /* 10xx xxxx,  1111 xxxx */
  40.364 +                    throw new InvalidConstantPoolFormatException(
  40.365 +                        "malformed input around byte " + buffer.position());
  40.366 +            }
  40.367 +        }
  40.368 +        // The number of chars produced may be less than utflen
  40.369 +        return new String(charArray, 0, index);
  40.370 +    }
  40.371 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java	Thu May 07 12:26:22 2009 -0700
    41.3 @@ -0,0 +1,503 @@
    41.4 +/*
    41.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    41.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.7 + *
    41.8 + * This code is free software; you can redistribute it and/or modify it
    41.9 + * under the terms of the GNU General Public License version 2 only, as
   41.10 + * published by the Free Software Foundation.  Sun designates this
   41.11 + * particular file as subject to the "Classpath" exception as provided
   41.12 + * by Sun in the LICENSE file that accompanied this code.
   41.13 + *
   41.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   41.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.17 + * version 2 for more details (a copy is included in the LICENSE file that
   41.18 + * accompanied this code).
   41.19 + *
   41.20 + * You should have received a copy of the GNU General Public License version
   41.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   41.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.23 + *
   41.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   41.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   41.26 + * have any questions.
   41.27 + */
   41.28 +
   41.29 +package sun.dyn.anon;
   41.30 +
   41.31 +import java.io.IOException;
   41.32 +import java.io.OutputStream;
   41.33 +import java.util.Arrays;
   41.34 +import java.util.HashSet;
   41.35 +import java.util.IdentityHashMap;
   41.36 +import java.util.Map;
   41.37 +
   41.38 +import static sun.dyn.anon.ConstantPoolVisitor.*;
   41.39 +
   41.40 +/** A class and its patched constant pool.
   41.41 + *
   41.42 + *  This class allow to modify (patch) a constant pool
   41.43 + *  by changing the value of its entry.
   41.44 + *  Entry are referenced using index that can be get
   41.45 + *  by parsing the constant pool using
   41.46 + *  {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
   41.47 + *
   41.48 + * @see ConstantPoolVisitor
   41.49 + * @see ConstantPoolParser#createPatch()
   41.50 + */
   41.51 +public class ConstantPoolPatch {
   41.52 +    final ConstantPoolParser outer;
   41.53 +    final Object[] patchArray;
   41.54 +
   41.55 +    ConstantPoolPatch(ConstantPoolParser outer) {
   41.56 +        this.outer      = outer;
   41.57 +        this.patchArray = new Object[outer.getLength()];
   41.58 +    }
   41.59 +
   41.60 +    /** Create a {@link ConstantPoolParser} and
   41.61 +     *  a {@link ConstantPoolPatch} in one step.
   41.62 +     *  Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
   41.63 +     *
   41.64 +     * @param classFile an array of bytes containing a class.
   41.65 +     * @see #ConstantPoolParser(Class)
   41.66 +     */
   41.67 +    public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
   41.68 +        this(new ConstantPoolParser(classFile));
   41.69 +    }
   41.70 +
   41.71 +    /** Create a {@link ConstantPoolParser} and
   41.72 +     *  a {@link ConstantPoolPatch} in one step.
   41.73 +     *  Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
   41.74 +     *
   41.75 +     * @param templateClass the class to parse.
   41.76 +     * @see #ConstantPoolParser(Class)
   41.77 +     */
   41.78 +    public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
   41.79 +        this(new ConstantPoolParser(templateClass));
   41.80 +    }
   41.81 +
   41.82 +
   41.83 +    /** Creates a patch from an existing patch.
   41.84 +     *  All changes are copied from that patch.
   41.85 +     * @param patch a patch
   41.86 +     *
   41.87 +     * @see ConstantPoolParser#createPatch()
   41.88 +     */
   41.89 +    public ConstantPoolPatch(ConstantPoolPatch patch) {
   41.90 +        outer      = patch.outer;
   41.91 +        patchArray = patch.patchArray.clone();
   41.92 +    }
   41.93 +
   41.94 +    /** Which parser built this patch? */
   41.95 +    public ConstantPoolParser getParser() {
   41.96 +        return outer;
   41.97 +    }
   41.98 +
   41.99 +    /** Report the tag at the given index in the constant pool. */
  41.100 +    public byte getTag(int index) {
  41.101 +        return outer.getTag(index);
  41.102 +    }
  41.103 +
  41.104 +    /** Report the current patch at the given index of the constant pool.
  41.105 +     *  Null means no patch will be made.
  41.106 +     *  To observe the unpatched entry at the given index, use
  41.107 +     *  {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
  41.108 +     */
  41.109 +    public Object getPatch(int index) {
  41.110 +        Object value = patchArray[index];
  41.111 +        if (value == null)  return null;
  41.112 +        switch (getTag(index)) {
  41.113 +        case CONSTANT_Fieldref:
  41.114 +        case CONSTANT_Methodref:
  41.115 +        case CONSTANT_InterfaceMethodref:
  41.116 +            if (value instanceof String)
  41.117 +                value = stripSemis(2, (String) value);
  41.118 +            break;
  41.119 +        case CONSTANT_NameAndType:
  41.120 +            if (value instanceof String)
  41.121 +                value = stripSemis(1, (String) value);
  41.122 +            break;
  41.123 +        }
  41.124 +        return value;
  41.125 +    }
  41.126 +
  41.127 +    /** Clear all patches. */
  41.128 +    public void clear() {
  41.129 +        Arrays.fill(patchArray, null);
  41.130 +    }
  41.131 +
  41.132 +    /** Clear one patch. */
  41.133 +    public void clear(int index) {
  41.134 +        patchArray[index] = null;
  41.135 +    }
  41.136 +
  41.137 +    /** Produce the patches as an array. */
  41.138 +    public Object[] getPatches() {
  41.139 +        return patchArray.clone();
  41.140 +    }
  41.141 +
  41.142 +    /** Produce the original constant pool as an array. */
  41.143 +    public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
  41.144 +        return getOriginalCP(0, patchArray.length, -1);
  41.145 +    }
  41.146 +
  41.147 +    /** Walk the constant pool, applying patches using the given map.
  41.148 +     *
  41.149 +     * @param utf8Map Utf8 strings to modify, if encountered
  41.150 +     * @param classMap Classes (or their names) to modify, if encountered
  41.151 +     * @param valueMap Constant values to modify, if encountered
  41.152 +     * @param deleteUsedEntries if true, delete map entries that are used
  41.153 +     */
  41.154 +    public void putPatches(final Map<String,String> utf8Map,
  41.155 +                           final Map<String,Object> classMap,
  41.156 +                           final Map<Object,Object> valueMap,
  41.157 +                           boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
  41.158 +        final HashSet<String> usedUtf8Keys;
  41.159 +        final HashSet<String> usedClassKeys;
  41.160 +        final HashSet<Object> usedValueKeys;
  41.161 +        if (deleteUsedEntries) {
  41.162 +            usedUtf8Keys  = (utf8Map  == null) ? null : new HashSet<String>();
  41.163 +            usedClassKeys = (classMap == null) ? null : new HashSet<String>();
  41.164 +            usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
  41.165 +        } else {
  41.166 +            usedUtf8Keys = null;
  41.167 +            usedClassKeys = null;
  41.168 +            usedValueKeys = null;
  41.169 +        }
  41.170 +
  41.171 +        outer.parse(new ConstantPoolVisitor() {
  41.172 +
  41.173 +            @Override
  41.174 +            public void visitUTF8(int index, byte tag, String utf8) {
  41.175 +                putUTF8(index, utf8Map.get(utf8));
  41.176 +                if (usedUtf8Keys != null)  usedUtf8Keys.add(utf8);
  41.177 +            }
  41.178 +
  41.179 +            @Override
  41.180 +            public void visitConstantValue(int index, byte tag, Object value) {
  41.181 +                putConstantValue(index, tag, valueMap.get(value));
  41.182 +                if (usedValueKeys != null)  usedValueKeys.add(value);
  41.183 +            }
  41.184 +
  41.185 +            @Override
  41.186 +            public void visitConstantString(int index, byte tag, String name, int nameIndex) {
  41.187 +                if (tag == CONSTANT_Class) {
  41.188 +                    putConstantValue(index, tag, classMap.get(name));
  41.189 +                    if (usedClassKeys != null)  usedClassKeys.add(name);
  41.190 +                } else {
  41.191 +                    assert(tag == CONSTANT_String);
  41.192 +                    visitConstantValue(index, tag, name);
  41.193 +                }
  41.194 +            }
  41.195 +        });
  41.196 +        if (usedUtf8Keys != null)   utf8Map.keySet().removeAll(usedUtf8Keys);
  41.197 +        if (usedClassKeys != null)  classMap.keySet().removeAll(usedClassKeys);
  41.198 +        if (usedValueKeys != null)  valueMap.keySet().removeAll(usedValueKeys);
  41.199 +    }
  41.200 +
  41.201 +    Object[] getOriginalCP(final int startIndex,
  41.202 +                           final int endIndex,
  41.203 +                           final int tagMask) throws InvalidConstantPoolFormatException {
  41.204 +        final Object[] cpArray = new Object[endIndex - startIndex];
  41.205 +        outer.parse(new ConstantPoolVisitor() {
  41.206 +
  41.207 +            void show(int index, byte tag, Object value) {
  41.208 +                if (index < startIndex || index >= endIndex)  return;
  41.209 +                if (((1 << tag) & tagMask) == 0)  return;
  41.210 +                cpArray[index - startIndex] = value;
  41.211 +            }
  41.212 +
  41.213 +            @Override
  41.214 +            public void visitUTF8(int index, byte tag, String utf8) {
  41.215 +                show(index, tag, utf8);
  41.216 +            }
  41.217 +
  41.218 +            @Override
  41.219 +            public void visitConstantValue(int index, byte tag, Object value) {
  41.220 +                assert(tag != CONSTANT_String);
  41.221 +                show(index, tag, value);
  41.222 +            }
  41.223 +
  41.224 +            @Override
  41.225 +            public void visitConstantString(int index, byte tag,
  41.226 +                                            String value, int j) {
  41.227 +                show(index, tag, value);
  41.228 +            }
  41.229 +
  41.230 +            @Override
  41.231 +            public void visitMemberRef(int index, byte tag,
  41.232 +                    String className, String memberName,
  41.233 +                    String signature,
  41.234 +                    int j, int k) {
  41.235 +                show(index, tag, new String[]{ className, memberName, signature });
  41.236 +            }
  41.237 +
  41.238 +            @Override
  41.239 +            public void visitDescriptor(int index, byte tag,
  41.240 +                    String memberName, String signature,
  41.241 +                    int j, int k) {
  41.242 +                show(index, tag, new String[]{ memberName, signature });
  41.243 +            }
  41.244 +        });
  41.245 +        return cpArray;
  41.246 +    }
  41.247 +
  41.248 +    /** Write the head (header plus constant pool)
  41.249 +     *  of the patched class file to the indicated stream.
  41.250 +     */
  41.251 +    void writeHead(OutputStream out) throws IOException {
  41.252 +        outer.writePatchedHead(out, patchArray);
  41.253 +    }
  41.254 +
  41.255 +    /** Write the tail (everything after the constant pool)
  41.256 +     *  of the patched class file to the indicated stream.
  41.257 +     */
  41.258 +    void writeTail(OutputStream out) throws IOException {
  41.259 +        outer.writeTail(out);
  41.260 +    }
  41.261 +
  41.262 +    private void checkConstantTag(byte tag, Object value) {
  41.263 +        if (value == null)
  41.264 +            throw new IllegalArgumentException(
  41.265 +                    "invalid null constant value");
  41.266 +        if (classForTag(tag) != value.getClass())
  41.267 +            throw new IllegalArgumentException(
  41.268 +                    "invalid constant value"
  41.269 +                    + (tag == CONSTANT_None ? ""
  41.270 +                        : " for tag "+tagName(tag))
  41.271 +                    + " of class "+value.getClass());
  41.272 +    }
  41.273 +
  41.274 +    private void checkTag(int index, byte putTag) {
  41.275 +        byte tag = outer.tags[index];
  41.276 +        if (tag != putTag)
  41.277 +            throw new IllegalArgumentException(
  41.278 +                "invalid put operation"
  41.279 +                + " for " + tagName(putTag)
  41.280 +                + " at index " + index + " found " + tagName(tag));
  41.281 +    }
  41.282 +
  41.283 +    private void checkTagMask(int index, int tagBitMask) {
  41.284 +        byte tag = outer.tags[index];
  41.285 +        int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
  41.286 +        if ((tagBit & tagBitMask) == 0)
  41.287 +            throw new IllegalArgumentException(
  41.288 +                "invalid put operation"
  41.289 +                + " at index " + index + " found " + tagName(tag));
  41.290 +    }
  41.291 +
  41.292 +    private static void checkMemberName(String memberName) {
  41.293 +        if (memberName.indexOf(';') >= 0)
  41.294 +            throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
  41.295 +    }
  41.296 +
  41.297 +    /** Set the entry of the constant pool indexed by index to
  41.298 +     *  a new string.
  41.299 +     *
  41.300 +     * @param index an index to a constant pool entry containing a
  41.301 +     *        {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
  41.302 +     * @param utf8 a string
  41.303 +     *
  41.304 +     * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
  41.305 +     */
  41.306 +    public void putUTF8(int index, String utf8) {
  41.307 +        if (utf8 == null) { clear(index); return; }
  41.308 +        checkTag(index, CONSTANT_Utf8);
  41.309 +        patchArray[index] = utf8;
  41.310 +    }
  41.311 +
  41.312 +    /** Set the entry of the constant pool indexed by index to
  41.313 +     *  a new value, depending on its dynamic type.
  41.314 +     *
  41.315 +     * @param index an index to a constant pool entry containing a
  41.316 +     *        one of the following structures:
  41.317 +     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
  41.318 +     *        {@link ConstantPoolVisitor#CONSTANT_Float},
  41.319 +     *        {@link ConstantPoolVisitor#CONSTANT_Long},
  41.320 +     *        {@link ConstantPoolVisitor#CONSTANT_Double},
  41.321 +     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
  41.322 +     *        {@link ConstantPoolVisitor#CONSTANT_Class}
  41.323 +     * @param value a boxed int, float, long or double; or a string or class object
  41.324 +     * @throws IllegalArgumentException if the type of the constant does not
  41.325 +     *         match the constant pool entry type,
  41.326 +     *         as reported by {@link #getTag(int)}
  41.327 +     *
  41.328 +     * @see #putConstantValue(int, byte, Object)
  41.329 +     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
  41.330 +     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
  41.331 +     */
  41.332 +    public void putConstantValue(int index, Object value) {
  41.333 +        if (value == null) { clear(index); return; }
  41.334 +        byte tag = tagForConstant(value.getClass());
  41.335 +        checkConstantTag(tag, value);
  41.336 +        checkTag(index, tag);
  41.337 +        patchArray[index] = value;
  41.338 +    }
  41.339 +
  41.340 +    /** Set the entry of the constant pool indexed by index to
  41.341 +     *  a new value.
  41.342 +     *
  41.343 +     * @param index an index to a constant pool entry matching the given tag
  41.344 +     * @param tag one of the following values:
  41.345 +     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
  41.346 +     *        {@link ConstantPoolVisitor#CONSTANT_Float},
  41.347 +     *        {@link ConstantPoolVisitor#CONSTANT_Long},
  41.348 +     *        {@link ConstantPoolVisitor#CONSTANT_Double},
  41.349 +     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
  41.350 +     *        {@link ConstantPoolVisitor#CONSTANT_Class}
  41.351 +     * @param value a boxed number, string, or class object
  41.352 +     * @throws IllegalArgumentException if the type of the constant does not
  41.353 +     *         match the constant pool entry type, or if a class name contains
  41.354 +     *         '/' or ';'
  41.355 +     *
  41.356 +     * @see #putConstantValue(int, Object)
  41.357 +     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
  41.358 +     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
  41.359 +     */
  41.360 +    public void putConstantValue(int index, byte tag, Object value) {
  41.361 +        if (value == null) { clear(index); return; }
  41.362 +        checkTag(index, tag);
  41.363 +        if (tag == CONSTANT_Class && value instanceof String) {
  41.364 +            checkClassName((String) value);
  41.365 +        } else if (tag == CONSTANT_String) {
  41.366 +            // the JVM accepts any object as a patch for a string
  41.367 +        } else {
  41.368 +            // make sure the incoming value is the right type
  41.369 +            checkConstantTag(tag, value);
  41.370 +        }
  41.371 +        checkTag(index, tag);
  41.372 +        patchArray[index] = value;
  41.373 +    }
  41.374 +
  41.375 +    /** Set the entry of the constant pool indexed by index to
  41.376 +     *  a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
  41.377 +     *
  41.378 +     * @param index an index to a constant pool entry containing a
  41.379 +     *        {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
  41.380 +     * @param memberName a memberName
  41.381 +     * @param signature a signature
  41.382 +     * @throws IllegalArgumentException if memberName contains the character ';'
  41.383 +     *
  41.384 +     * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
  41.385 +     */
  41.386 +    public void putDescriptor(int index, String memberName, String signature) {
  41.387 +        checkTag(index, CONSTANT_NameAndType);
  41.388 +        checkMemberName(memberName);
  41.389 +        patchArray[index] = addSemis(memberName, signature);
  41.390 +    }
  41.391 +
  41.392 +    /** Set the entry of the constant pool indexed by index to
  41.393 +     *  a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
  41.394 +     *  {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
  41.395 +     *  {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
  41.396 +     *
  41.397 +     * @param index an index to a constant pool entry containing a member reference
  41.398 +     * @param className a class name
  41.399 +     * @param memberName a field or method name
  41.400 +     * @param signature a field or method signature
  41.401 +     * @throws IllegalArgumentException if memberName contains the character ';'
  41.402 +     *             or signature is not a correct signature
  41.403 +     *
  41.404 +     * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
  41.405 +     */
  41.406 +    public void putMemberRef(int index, byte tag,
  41.407 +                    String className, String memberName, String signature) {
  41.408 +        checkTagMask(tag, CONSTANT_MemberRef_MASK);
  41.409 +        checkTag(index, tag);
  41.410 +        checkClassName(className);
  41.411 +        checkMemberName(memberName);
  41.412 +        if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
  41.413 +            throw new IllegalArgumentException("bad signature: "+signature);
  41.414 +        patchArray[index] = addSemis(className, memberName, signature);
  41.415 +    }
  41.416 +
  41.417 +    static private final int CONSTANT_MemberRef_MASK =
  41.418 +              CONSTANT_Fieldref
  41.419 +            | CONSTANT_Methodref
  41.420 +            | CONSTANT_InterfaceMethodref;
  41.421 +
  41.422 +    private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
  41.423 +        = new IdentityHashMap<Class<?>, Byte>();
  41.424 +    private static final Class[] CONSTANT_VALUE_CLASS = new Class[16];
  41.425 +    static {
  41.426 +        Object[][] values = {
  41.427 +            {Integer.class, CONSTANT_Integer},
  41.428 +            {Long.class, CONSTANT_Long},
  41.429 +            {Float.class, CONSTANT_Float},
  41.430 +            {Double.class, CONSTANT_Double},
  41.431 +            {String.class, CONSTANT_String},
  41.432 +            {Class.class, CONSTANT_Class}
  41.433 +        };
  41.434 +        for (Object[] value : values) {
  41.435 +            Class<?> cls = (Class<?>)value[0];
  41.436 +            Byte     tag = (Byte) value[1];
  41.437 +            CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
  41.438 +            CONSTANT_VALUE_CLASS[(byte)tag] = cls;
  41.439 +        }
  41.440 +    }
  41.441 +
  41.442 +    static Class<?> classForTag(byte tag) {
  41.443 +        if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
  41.444 +            return null;
  41.445 +        return CONSTANT_VALUE_CLASS[tag];
  41.446 +    }
  41.447 +
  41.448 +    static byte tagForConstant(Class<?> cls) {
  41.449 +        Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
  41.450 +        return (tag == null) ? CONSTANT_None : (byte)tag;
  41.451 +    }
  41.452 +
  41.453 +    private static void checkClassName(String className) {
  41.454 +        if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
  41.455 +            throw new IllegalArgumentException("invalid class name " + className);
  41.456 +    }
  41.457 +
  41.458 +    static String addSemis(String name, String... names) {
  41.459 +        StringBuilder buf = new StringBuilder(name.length() * 5);
  41.460 +        buf.append(name);
  41.461 +        for (String name2 : names) {
  41.462 +            buf.append(';').append(name2);
  41.463 +        }
  41.464 +        String res = buf.toString();
  41.465 +        assert(stripSemis(names.length, res)[0].equals(name));
  41.466 +        assert(stripSemis(names.length, res)[1].equals(names[0]));
  41.467 +        assert(names.length == 1 ||
  41.468 +               stripSemis(names.length, res)[2].equals(names[1]));
  41.469 +        return res;
  41.470 +    }
  41.471 +
  41.472 +    static String[] stripSemis(int count, String string) {
  41.473 +        String[] res = new String[count+1];
  41.474 +        int pos = 0;
  41.475 +        for (int i = 0; i < count; i++) {
  41.476 +            int pos2 = string.indexOf(';', pos);
  41.477 +            if (pos2 < 0)  pos2 = string.length();  // yuck
  41.478 +            res[i] = string.substring(pos, pos2);
  41.479 +            pos = pos2;
  41.480 +        }
  41.481 +        res[count] = string.substring(pos);
  41.482 +        return res;
  41.483 +    }
  41.484 +
  41.485 +    public String toString() {
  41.486 +        StringBuilder buf = new StringBuilder(this.getClass().getName());
  41.487 +        buf.append("{");
  41.488 +        Object[] origCP = null;
  41.489 +        for (int i = 0; i < patchArray.length; i++) {
  41.490 +            if (patchArray[i] == null)  continue;
  41.491 +            if (origCP != null) {
  41.492 +                buf.append(", ");
  41.493 +            } else {
  41.494 +                try {
  41.495 +                    origCP = getOriginalCP();
  41.496 +                } catch (InvalidConstantPoolFormatException ee) {
  41.497 +                    origCP = new Object[0];
  41.498 +                }
  41.499 +            }
  41.500 +            Object orig = (i < origCP.length) ? origCP[i] : "?";
  41.501 +            buf.append(orig).append("=").append(patchArray[i]);
  41.502 +        }
  41.503 +        buf.append("}");
  41.504 +        return buf.toString();
  41.505 +    }
  41.506 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java	Thu May 07 12:26:22 2009 -0700
    42.3 @@ -0,0 +1,192 @@
    42.4 +/*
    42.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    42.7 + *
    42.8 + * This code is free software; you can redistribute it and/or modify it
    42.9 + * under the terms of the GNU General Public License version 2 only, as
   42.10 + * published by the Free Software Foundation.  Sun designates this
   42.11 + * particular file as subject to the "Classpath" exception as provided
   42.12 + * by Sun in the LICENSE file that accompanied this code.
   42.13 + *
   42.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   42.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   42.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   42.17 + * version 2 for more details (a copy is included in the LICENSE file that
   42.18 + * accompanied this code).
   42.19 + *
   42.20 + * You should have received a copy of the GNU General Public License version
   42.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   42.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   42.23 + *
   42.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   42.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   42.26 + * have any questions.
   42.27 + */
   42.28 +
   42.29 +package sun.dyn.anon;
   42.30 +
   42.31 +/**
   42.32 + * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
   42.33 + * when a constant pool entry is parsed.
   42.34 + * <p>
   42.35 + * A visit* method is called when a constant pool entry is parsed.
   42.36 + * The first argument is always the constant pool index.
   42.37 + * The second argument is always the constant pool tag,
   42.38 + * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
   42.39 + * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
   42.40 + * and are always accompanied by the indexes of those entries.
   42.41 + * <p>
   42.42 + * The order of the calls to the visit* methods is not necessarily related
   42.43 + * to the order of the entries in the constant pool.
   42.44 + * If one entry has a reference to another entry, the latter (lower-level)
   42.45 + * entry will be visited first.
   42.46 + * <p>
   42.47 + * The following table shows the relation between constant pool entry
   42.48 + * types and the corresponding visit* methods:
   42.49 + *
   42.50 + * <table border=1 cellpadding=5 summary="constant pool visitor methods">
   42.51 + * <tr><th>Tag(s)</th><th>Method</th></tr>
   42.52 + * <tr>
   42.53 + *   <td>{@link #CONSTANT_Utf8}</td>
   42.54 + *   <td>{@link #visitUTF8(int, byte, String)}</td>
   42.55 + * </tr><tr>
   42.56 + *   <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
   42.57 + *       {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
   42.58 + *   <td>{@link #visitConstantValue(int, byte, Object)}</td>
   42.59 + * </tr><tr>
   42.60 + *   <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
   42.61 + *   <td>{@link #visitConstantString(int, byte, String, int)}</td>
   42.62 + * </tr><tr>
   42.63 + *   <td>{@link #CONSTANT_NameAndType}</td>
   42.64 + *   <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
   42.65 + * </tr><tr>
   42.66 + *   <td>{@link #CONSTANT_Fieldref},
   42.67 + *       {@link #CONSTANT_Methodref},
   42.68 + *       {@link #CONSTANT_InterfaceMethodref}</td>
   42.69 + *   <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
   42.70 + * </tr>
   42.71 + * </table>
   42.72 + *
   42.73 + * @see ConstantPoolPatch
   42.74 + * @author Remi Forax
   42.75 + * @author jrose
   42.76 + */
   42.77 +public class ConstantPoolVisitor {
   42.78 +  /** Called each time an UTF8 constant pool entry is found.
   42.79 +   * @param index the constant pool index
   42.80 +   * @param tag always {@link #CONSTANT_Utf8}
   42.81 +   * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
   42.82 +   *
   42.83 +   * @see ConstantPoolPatch#putUTF8(int, String)
   42.84 +   */
   42.85 +  public void visitUTF8(int index, byte tag, String utf8) {
   42.86 +    // do nothing
   42.87 +  }
   42.88 +
   42.89 +  /** Called for each constant pool entry that encodes an integer,
   42.90 +   *  a float, a long, or a double.
   42.91 +   *  Constant strings and classes are not managed by this method but
   42.92 +   *  by {@link #visitConstantString(int, byte, String, int)}.
   42.93 +   *
   42.94 +   * @param index the constant pool index
   42.95 +   * @param tag one of {@link #CONSTANT_Integer},
   42.96 +   *            {@link #CONSTANT_Float},
   42.97 +   *            {@link #CONSTANT_Long},
   42.98 +   *            or {@link #CONSTANT_Double}
   42.99 +   * @param value encoded value
  42.100 +   *
  42.101 +   * @see ConstantPoolPatch#putConstantValue(int, Object)
  42.102 +   */
  42.103 +  public void visitConstantValue(int index, byte tag, Object value) {
  42.104 +    // do nothing
  42.105 +  }
  42.106 +
  42.107 +  /** Called for each constant pool entry that encodes a string or a class.
  42.108 +   * @param index the constant pool index
  42.109 +   * @param tag one of {@link #CONSTANT_String},
  42.110 +   *            {@link #CONSTANT_Class},
  42.111 +   * @param name string body or class name (using dot separator)
  42.112 +   * @param nameIndex the index of the Utf8 string for the name
  42.113 +   *
  42.114 +   * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
  42.115 +   */
  42.116 +  public void visitConstantString(int index, byte tag,
  42.117 +                                  String name, int nameIndex) {
  42.118 +    // do nothing
  42.119 +  }
  42.120 +
  42.121 +  /** Called for each constant pool entry that encodes a name and type.
  42.122 +   * @param index the constant pool index
  42.123 +   * @param tag always {@link #CONSTANT_NameAndType}
  42.124 +   * @param memberName a field or method name
  42.125 +   * @param signature the member signature
  42.126 +   * @param memberNameIndex index of the Utf8 string for the member name
  42.127 +   * @param signatureIndex index of the Utf8 string for the signature
  42.128 +   *
  42.129 +   * @see ConstantPoolPatch#putDescriptor(int, String, String)
  42.130 +   */
  42.131 +  public void visitDescriptor(int index, byte tag,
  42.132 +                              String memberName, String signature,
  42.133 +                              int memberNameIndex, int signatureIndex) {
  42.134 +    // do nothing
  42.135 +  }
  42.136 +
  42.137 +  /** Called for each constant pool entry that encodes a field or method.
  42.138 +   * @param index the constant pool index
  42.139 +   * @param tag one of {@link #CONSTANT_Fieldref},
  42.140 +   *            or {@link #CONSTANT_Methodref},
  42.141 +   *            or {@link #CONSTANT_InterfaceMethodref}
  42.142 +   * @param className the class name (using dot separator)
  42.143 +   * @param memberName name of the field or method
  42.144 +   * @param signature the field or method signature
  42.145 +   * @param classNameIndex index of the Utf8 string for the class name
  42.146 +   * @param descriptorIndex index of the NameAndType descriptor constant
  42.147 +   *
  42.148 +   * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
  42.149 +   */
  42.150 +  public void visitMemberRef(int index, byte tag,
  42.151 +                             String className, String memberName, String signature,
  42.152 +                             int classNameIndex, int descriptorIndex) {
  42.153 +    // do nothing
  42.154 +  }
  42.155 +
  42.156 +    public static final byte
  42.157 +      CONSTANT_None = 0,
  42.158 +      CONSTANT_Utf8 = 1,
  42.159 +      //CONSTANT_Unicode = 2,               /* unused */
  42.160 +      CONSTANT_Integer = 3,
  42.161 +      CONSTANT_Float = 4,
  42.162 +      CONSTANT_Long = 5,
  42.163 +      CONSTANT_Double = 6,
  42.164 +      CONSTANT_Class = 7,
  42.165 +      CONSTANT_String = 8,
  42.166 +      CONSTANT_Fieldref = 9,
  42.167 +      CONSTANT_Methodref = 10,
  42.168 +      CONSTANT_InterfaceMethodref = 11,
  42.169 +      CONSTANT_NameAndType = 12;
  42.170 +
  42.171 +    private static String[] TAG_NAMES = {
  42.172 +        "Empty",
  42.173 +        "Utf8",
  42.174 +        null, //"Unicode",
  42.175 +        "Integer",
  42.176 +        "Float",
  42.177 +        "Long",
  42.178 +        "Double",
  42.179 +        "Class",
  42.180 +        "String",
  42.181 +        "Fieldref",
  42.182 +        "Methodref",
  42.183 +        "InterfaceMethodref",
  42.184 +        "NameAndType"
  42.185 +    };
  42.186 +
  42.187 +    public static String tagName(byte tag) {
  42.188 +        String name = null;
  42.189 +        if ((tag & 0xFF) < TAG_NAMES.length)
  42.190 +            name = TAG_NAMES[tag];
  42.191 +        if (name == null)
  42.192 +            name = "Unknown#"+(tag&0xFF);
  42.193 +        return name;
  42.194 +    }
  42.195 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java	Thu May 07 12:26:22 2009 -0700
    43.3 @@ -0,0 +1,45 @@
    43.4 +/*
    43.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    43.7 + *
    43.8 + * This code is free software; you can redistribute it and/or modify it
    43.9 + * under the terms of the GNU General Public License version 2 only, as
   43.10 + * published by the Free Software Foundation.  Sun designates this
   43.11 + * particular file as subject to the "Classpath" exception as provided
   43.12 + * by Sun in the LICENSE file that accompanied this code.
   43.13 + *
   43.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   43.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   43.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   43.17 + * version 2 for more details (a copy is included in the LICENSE file that
   43.18 + * accompanied this code).
   43.19 + *
   43.20 + * You should have received a copy of the GNU General Public License version
   43.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   43.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   43.23 + *
   43.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   43.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   43.26 + * have any questions.
   43.27 + */
   43.28 +
   43.29 +package sun.dyn.anon;
   43.30 +
   43.31 +/** Exception used when there is an error in the constant pool
   43.32 + *  format.
   43.33 + */
   43.34 +public class InvalidConstantPoolFormatException extends Exception {
   43.35 +    private static final long serialVersionUID=-6103888330523770949L;
   43.36 +
   43.37 +    public InvalidConstantPoolFormatException(String message,Throwable cause) {
   43.38 +        super(message,cause);
   43.39 +    }
   43.40 +
   43.41 +    public InvalidConstantPoolFormatException(String message) {
   43.42 +        super(message);
   43.43 +    }
   43.44 +
   43.45 +    public InvalidConstantPoolFormatException(Throwable cause) {
   43.46 +        super(cause);
   43.47 +    }
   43.48 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/src/share/classes/sun/dyn/empty/Empty.java	Thu May 07 12:26:22 2009 -0700
    44.3 @@ -0,0 +1,36 @@
    44.4 +/*
    44.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    44.7 + *
    44.8 + * This code is free software; you can redistribute it and/or modify it
    44.9 + * under the terms of the GNU General Public License version 2 only, as
   44.10 + * published by the Free Software Foundation.  Sun designates this
   44.11 + * particular file as subject to the "Classpath" exception as provided
   44.12 + * by Sun in the LICENSE file that accompanied this code.
   44.13 + *
   44.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   44.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   44.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   44.17 + * version 2 for more details (a copy is included in the LICENSE file that
   44.18 + * accompanied this code).
   44.19 + *
   44.20 + * You should have received a copy of the GNU General Public License version
   44.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   44.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   44.23 + *
   44.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   44.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   44.26 + * have any questions.
   44.27 + */
   44.28 +
   44.29 +package sun.dyn.empty;
   44.30 +
   44.31 +/**
   44.32 + * An empty class in an empty package.
   44.33 + * Used as a proxy for unprivileged code, since making access checks
   44.34 + * against it will only succeed against public methods in public types.
   44.35 + * @author jrose
   44.36 + */
   44.37 +public class Empty {
   44.38 +    private Empty() { throw new InternalError(); }
   44.39 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/src/share/classes/sun/dyn/package-info.java	Thu May 07 12:26:22 2009 -0700
    45.3 @@ -0,0 +1,35 @@
    45.4 +/*
    45.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    45.7 + *
    45.8 + * This code is free software; you can redistribute it and/or modify it
    45.9 + * under the terms of the GNU General Public License version 2 only, as
   45.10 + * published by the Free Software Foundation.  Sun designates this
   45.11 + * particular file as subject to the "Classpath" exception as provided
   45.12 + * by Sun in the LICENSE file that accompanied this code.
   45.13 + *
   45.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   45.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   45.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   45.17 + * version 2 for more details (a copy is included in the LICENSE file that
   45.18 + * accompanied this code).
   45.19 + *
   45.20 + * You should have received a copy of the GNU General Public License version
   45.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   45.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   45.23 + *
   45.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   45.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   45.26 + * have any questions.
   45.27 + */
   45.28 +
   45.29 +/**
   45.30 + * Implementation details for JSR 292 RI, package java.dyn.
   45.31 + * This particular version is specific to Hotspot.
   45.32 + * There is also a backport version of this sub-package which uses reflection,
   45.33 + * and can therefore run (slowly) on older versions of Java.
   45.34 + * Other JVM vendors may create their own versions of this sub-package.
   45.35 + * @author jrose
   45.36 + */
   45.37 +
   45.38 +package sun.dyn;
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/src/share/classes/sun/dyn/util/BytecodeName.java	Thu May 07 12:26:22 2009 -0700
    46.3 @@ -0,0 +1,711 @@
    46.4 +/*
    46.5 + * Copyright 2007-2009 Sun Microsystems, Inc.  All Rights Reserved.
    46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    46.7 + *
    46.8 + * This code is free software; you can redistribute it and/or modify it
    46.9 + * under the terms of the GNU General Public License version 2 only, as
   46.10 + * published by the Free Software Foundation.  Sun designates this
   46.11 + * particular file as subject to the "Classpath" exception as provided
   46.12 + * by Sun in the LICENSE file that accompanied this code.
   46.13 + *
   46.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   46.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   46.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   46.17 + * version 2 for more details (a copy is included in the LICENSE file that
   46.18 + * accompanied this code).
   46.19 + *
   46.20 + * You should have received a copy of the GNU General Public License version
   46.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   46.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   46.23 + *
   46.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   46.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   46.26 + * have any questions.
   46.27 + */
   46.28 +
   46.29 +package sun.dyn.util;
   46.30 +
   46.31 +/**
   46.32 + * Utility routines for dealing with bytecode-level names.
   46.33 + * Includes universal mangling rules for the JVM.
   46.34 + *
   46.35 + * <h3>Avoiding Dangerous Characters </h3>
   46.36 + *
   46.37 + * <p>
   46.38 + * The JVM defines a very small set of characters which are illegal
   46.39 + * in name spellings.  We will slightly extend and regularize this set
   46.40 + * into a group of <cite>dangerous characters</cite>.
   46.41 + * These characters will then be replaced, in mangled names, by escape sequences.
   46.42 + * In addition, accidental escape sequences must be further escaped.
   46.43 + * Finally, a special prefix will be applied if and only if
   46.44 + * the mangling would otherwise fail to begin with the escape character.
   46.45 + * This happens to cover the corner case of the null string,
   46.46 + * and also clearly marks symbols which need demangling.
   46.47 + * </p>
   46.48 + * <p>
   46.49 + * Dangerous characters are the union of all characters forbidden
   46.50 + * or otherwise restricted by the JVM specification,
   46.51 + * plus their mates, if they are brackets
   46.52 + * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
   46.53 + * <code><big><b>&lt;</b></big></code> and <code><big><b>&gt;</b></big></code>),
   46.54 + * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
   46.55 + * There is no distinction between type, method, and field names.
   46.56 + * This makes it easier to convert between mangled names of different
   46.57 + * types, since they do not need to be decoded (demangled).
   46.58 + * </p>
   46.59 + * <p>
   46.60 + * The escape character is backslash <code><big><b>\</b></big></code>
   46.61 + * (also known as reverse solidus).
   46.62 + * This character is, until now, unheard of in bytecode names,
   46.63 + * but traditional in the proposed role.
   46.64 + *
   46.65 + * </p>
   46.66 + * <h3> Replacement Characters </h3>
   46.67 + *
   46.68 + *
   46.69 + * <p>
   46.70 + * Every escape sequence is two characters
   46.71 + * (in fact, two UTF8 bytes) beginning with
   46.72 + * the escape character and followed by a
   46.73 + * <cite>replacement character</cite>.
   46.74 + * (Since the replacement character is never a backslash,
   46.75 + * iterated manglings do not double in size.)
   46.76 + * </p>
   46.77 + * <p>
   46.78 + * Each dangerous character has some rough visual similarity
   46.79 + * to its corresponding replacement character.
   46.80 + * This makes mangled symbols easier to recognize by sight.
   46.81 + * </p>
   46.82 + * <p>
   46.83 + * The dangerous characters are
   46.84 + * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
   46.85 + * <code><big><b>.</b></big></code> (dot, also a package delimiter),
   46.86 + * <code><big><b>;</b></big></code> (semicolon, used in signatures),
   46.87 + * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
   46.88 + * <code><big><b>&lt;</b></big></code> (left angle),
   46.89 + * <code><big><b>&gt;</b></big></code> (right angle),
   46.90 + * <code><big><b>[</b></big></code> (left square bracket, used in array types),
   46.91 + * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
   46.92 + * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
   46.93 + * Their replacements are, respectively,
   46.94 + * <code><big><b>|</b></big></code> (vertical bar),
   46.95 + * <code><big><b>,</b></big></code> (comma),
   46.96 + * <code><big><b>?</b></big></code> (question mark),
   46.97 + * <code><big><b>%</b></big></code> (percent),
   46.98 + * <code><big><b>^</b></big></code> (caret),
   46.99 + * <code><big><b>_</b></big></code> (underscore), and
  46.100 + * <code><big><b>{</b></big></code> (left curly bracket),
  46.101 + * <code><big><b>}</b></big></code> (right curly bracket),
  46.102 + * <code><big><b>!</b></big></code> (exclamation mark).
  46.103 + * In addition, the replacement character for the escape character itself is
  46.104 + * <code><big><b>-</b></big></code> (hyphen),
  46.105 + * and the replacement character for the null prefix is
  46.106 + * <code><big><b>=</b></big></code> (equal sign).
  46.107 + * </p>
  46.108 + * <p>
  46.109 + * An escape character <code><big><b>\</b></big></code>
  46.110 + * followed by any of these replacement characters
  46.111 + * is an escape sequence, and there are no other escape sequences.
  46.112 + * An equal sign is only part of an escape sequence
  46.113 + * if it is the second character in the whole string, following a backslash.
  46.114 + * Two consecutive backslashes do <em>not</em> form an escape sequence.
  46.115 + * </p>
  46.116 + * <p>
  46.117 + * Each escape sequence replaces a so-called <cite>original character</cite>
  46.118 + * which is either one of the dangerous characters or the escape character.
  46.119 + * A null prefix replaces an initial null string, not a character.
  46.120 + * </p>
  46.121 + * <p>
  46.122 + * All this implies that escape sequences cannot overlap and may be
  46.123 + * determined all at once for a whole string.  Note that a spelling
  46.124 + * string can contain <cite>accidental escapes</cite>, apparent escape
  46.125 + * sequences which must not be interpreted as manglings.
  46.126 + * These are disabled by replacing their leading backslash with an
  46.127 + * escape sequence (<code><big><b>\-</b></big></code>).  To mangle a string, three logical steps
  46.128 + * are required, though they may be carried out in one pass:
  46.129 + * </p>
  46.130 + * <ol>
  46.131 + *   <li>In each accidental escape, replace the backslash with an escape sequence
  46.132 + * (<code><big><b>\-</b></big></code>).</li>
  46.133 + *   <li>Replace each dangerous character with an escape sequence
  46.134 + * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
  46.135 + *   <li>If the first two steps introduced any change, <em>and</em>
  46.136 + * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
  46.137 + * </ol>
  46.138 + *
  46.139 + * To demangle a mangled string that begins with an escape,
  46.140 + * remove any null prefix, and then replace (in parallel)
  46.141 + * each escape sequence by its original character.
  46.142 + * <p>Spelling strings which contain accidental
  46.143 + * escapes <em>must</em> have them replaced, even if those
  46.144 + * strings do not contain dangerous characters.
  46.145 + * This restriction means that mangling a string always
  46.146 + * requires a scan of the string for escapes.
  46.147 + * But then, a scan would be required anyway,
  46.148 + * to check for dangerous characters.
  46.149 + *
  46.150 + * </p>
  46.151 + * <h3> Nice Properties </h3>
  46.152 + *
  46.153 + * <p>
  46.154 + * If a bytecode name does not contain any escape sequence,
  46.155 + * demangling is a no-op:  The string demangles to itself.
  46.156 + * Such a string is called <cite>self-mangling</cite>.
  46.157 + * Almost all strings are self-mangling.
  46.158 + * In practice, to demangle almost any name &ldquo;found in nature&rdquo;,
  46.159 + * simply verify that it does not begin with a backslash.
  46.160 + * </p>
  46.161 + * <p>
  46.162 + * Mangling is a one-to-one function, while demangling
  46.163 + * is a many-to-one function.
  46.164 + * A mangled string is defined as <cite>validly mangled</cite> if
  46.165 + * it is in fact the unique mangling of its spelling string.
  46.166 + * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
  46.167 + * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
  46.168 + * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
  46.169 + * If a language back-end or runtime is using mangled names,
  46.170 + * it should never present an invalidly mangled bytecode
  46.171 + * name to the JVM.  If the runtime encounters one,
  46.172 + * it should also report an error, since such an occurrence
  46.173 + * probably indicates a bug in name encoding which
  46.174 + * will lead to errors in linkage.
  46.175 + * However, this note does not propose that the JVM verifier
  46.176 + * detect invalidly mangled names.
  46.177 + * </p>
  46.178 + * <p>
  46.179 + * As a result of these rules, it is a simple matter to
  46.180 + * compute validly mangled substrings and concatenations
  46.181 + * of validly mangled strings, and (with a little care)
  46.182 + * these correspond to corresponding operations on their
  46.183 + * spelling strings.
  46.184 + * </p>
  46.185 + * <ul>
  46.186 + *   <li>Any prefix of a validly mangled string is also validly mangled,
  46.187 + * although a null prefix may need to be removed.</li>
  46.188 + *   <li>Any suffix of a validly mangled string is also validly mangled,
  46.189 + * although a null prefix may need to be added.</li>
  46.190 + *   <li>Two validly mangled strings, when concatenated,
  46.191 + * are also validly mangled, although any null prefix
  46.192 + * must be removed from the second string,
  46.193 + * and a trailing backslash on the first string may need escaping,
  46.194 + * if it would participate in an accidental escape when followed
  46.195 + * by the first character of the second string.</li>
  46.196 + * </ul>
  46.197 + * <p>If languages that include non-Java symbol spellings use this
  46.198 + * mangling convention, they will enjoy the following advantages:
  46.199 + * </p>
  46.200 + * <ul>
  46.201 + *   <li>They can interoperate via symbols they share in common.</li>
  46.202 + *   <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
  46.203 + *   <li>Future JVM and language extensions can safely use the dangerous characters
  46.204 + * for structuring symbols, but will never interfere with valid spellings.</li>
  46.205 + *   <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
  46.206 + *   <li>Occasional transliterations and name composition will be simple and regular,
  46.207 + * for classes, methods, and fields.</li>
  46.208 + *   <li>Bytecode names will continue to be compact.
  46.209 + * When mangled, spellings will at most double in length, either in
  46.210 + * UTF8 or UTF16 format, and most will not change at all.</li>
  46.211 + * </ul>
  46.212 + *
  46.213 + *
  46.214 + * <h3> Suggestions for Human Readable Presentations </h3>
  46.215 + *
  46.216 + *
  46.217 + * <p>
  46.218 + * For human readable displays of symbols,
  46.219 + * it will be better to present a string-like quoted
  46.220 + * representation of the spelling, because JVM users
  46.221 + * are generally familiar with such tokens.
  46.222 + * We suggest using single or double quotes before and after
  46.223 + * mangled symbols which are not valid Java identifiers,
  46.224 + * with quotes, backslashes, and non-printing characters
  46.225 + * escaped as if for literals in the Java language.
  46.226 + * </p>
  46.227 + * <p>
  46.228 + * For example, an HTML-like spelling
  46.229 + * <code><big><b>&lt;pre&gt;</b></big></code> mangles to
  46.230 + * <code><big><b>\^pre\_</b></big></code> and could
  46.231 + * display more cleanly as
  46.232 + * <code><big><b>'&lt;pre&gt;'</b></big></code>,
  46.233 + * with the quotes included.
  46.234 + * Such string-like conventions are <em>not</em> suitable
  46.235 + * for mangled bytecode names, in part because
  46.236 + * dangerous characters must be eliminated, rather
  46.237 + * than just quoted.  Otherwise internally structured
  46.238 + * strings like package prefixes and method signatures
  46.239 + * could not be reliably parsed.
  46.240 + * </p>
  46.241 + * <p>
  46.242 + * In such human-readable displays, invalidly mangled
  46.243 + * names should <em>not</em> be demangled and quoted,
  46.244 + * for this would be misleading.  Likewise, JVM symbols
  46.245 + * which contain dangerous characters (like dots in field
  46.246 + * names or brackets in method names) should not be
  46.247 + * simply quoted.  The bytecode names
  46.248 + * <code><big><b>\=phase\,1</b></big></code> and
  46.249 + * <code><big><b>phase.1</b></big></code> are distinct,
  46.250 + * and in demangled displays they should be presented as
  46.251 + * <code><big><b>'phase.1'</b></big></code> and something like
  46.252 + * <code><big><b>'phase'.1</b></big></code>, respectively.
  46.253 + * </p>
  46.254 + *
  46.255 + * @author John Rose
  46.256 + * @version 1.2, 02/06/2008
  46.257 + * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
  46.258 + */
  46.259 +public class BytecodeName {
  46.260 +    private BytecodeName() { }  // static only class
  46.261 +
  46.262 +    /** Given a source name, produce the corresponding bytecode name.
  46.263 +     * The source name should not be qualified, because any syntactic
  46.264 +     * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
  46.265 +     * @param s the source name
  46.266 +     * @return a valid bytecode name which represents the source name
  46.267 +     */
  46.268 +    public static String toBytecodeName(String s) {
  46.269 +        String bn = mangle(s);
  46.270 +        assert((Object)bn == s || looksMangled(bn)) : bn;
  46.271 +        assert(s.equals(toSourceName(bn))) : s;
  46.272 +        return bn;
  46.273 +    }
  46.274 +
  46.275 +    /** Given an unqualified bytecode name, produce the corresponding source name.
  46.276 +     * The bytecode name must not contain dangerous characters.
  46.277 +     * In particular, it must not be qualified or segmented by colon {@code ':'}.
  46.278 +     * @param s the bytecode name
  46.279 +     * @return the source name, which may possibly have unsafe characters
  46.280 +     * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
  46.281 +     * @see #isSafeBytecodeName(java.lang.String)
  46.282 +     */
  46.283 +    public static String toSourceName(String s) {
  46.284 +        checkSafeBytecodeName(s);
  46.285 +        String sn = s;
  46.286 +        if (looksMangled(s)) {
  46.287 +            sn = demangle(s);
  46.288 +            assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
  46.289 +        }
  46.290 +        return sn;
  46.291 +    }
  46.292 +
  46.293 +    /**
  46.294 +     * Given a bytecode name from a classfile, separate it into
  46.295 +     * components delimited by dangerous characters.
  46.296 +     * Each resulting array element will be either a dangerous character,
  46.297 +     * or else a safe bytecode name.
  46.298 +     * (The safe name might possibly be mangled to hide further dangerous characters.)
  46.299 +     * For example, the qualified class name {@code java/lang/String}
  46.300 +     * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
  46.301 +     * The name {@code &lt;init&gt;} will be parsed into { '&lt;', "init", '&gt;'}}
  46.302 +     * The name {@code foo/bar$:baz} will be parsed into
  46.303 +     * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
  46.304 +     */
  46.305 +    public static Object[] parseBytecodeName(String s) {
  46.306 +        int slen = s.length();
  46.307 +        Object[] res = null;
  46.308 +        for (int pass = 0; pass <= 1; pass++) {
  46.309 +            int fillp = 0;
  46.310 +            int lasti = 0;
  46.311 +            for (int i = 0; i <= slen; i++) {
  46.312 +                int whichDC = -1;
  46.313 +                if (i < slen) {
  46.314 +                    whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
  46.315 +                    if (whichDC < DANGEROUS_CHAR_FIRST_INDEX)  continue;
  46.316 +                }
  46.317 +                // got to end of string or next dangerous char
  46.318 +                if (lasti < i) {
  46.319 +                    // normal component
  46.320 +                    if (pass != 0)
  46.321 +                        res[fillp] = s.substring(lasti, i);
  46.322 +                    fillp++;
  46.323 +                    lasti = i+1;
  46.324 +                }
  46.325 +                if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
  46.326 +                    if (pass != 0)
  46.327 +                        res[fillp] = DANGEROUS_CHARS_CA[whichDC];
  46.328 +                    fillp++;
  46.329 +                }
  46.330 +            }
  46.331 +            if (pass != 0)  break;
  46.332 +            // between passes, build the result array
  46.333 +            res = new String[fillp];
  46.334 +            if (fillp <= 1) {
  46.335 +                if (fillp != 0)  res[0] = s;
  46.336 +                break;
  46.337 +            }
  46.338 +        }
  46.339 +        return res;
  46.340 +    }
  46.341 +
  46.342 +    /**
  46.343 +     * Given a series of components, create a bytecode name for a classfile.
  46.344 +     * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
  46.345 +     * Each component must either be an interned one-character string of
  46.346 +     * a dangerous character, or else a safe bytecode name.
  46.347 +     * @param components a series of name components
  46.348 +     * @return the concatenation of all components
  46.349 +     * @throws IllegalArgumentException if any component contains an unsafe
  46.350 +     *          character, and is not an interned one-character string
  46.351 +     * @throws NullPointerException if any component is null
  46.352 +     */
  46.353 +    public static String unparseBytecodeName(Object[] components) {
  46.354 +        for (Object c : components) {
  46.355 +            if (c instanceof String)
  46.356 +                checkSafeBytecodeName((String) c);  // may fail
  46.357 +        }
  46.358 +        return appendAll(components);
  46.359 +    }
  46.360 +    private static String appendAll(Object[] components) {
  46.361 +        if (components.length <= 1) {
  46.362 +            if (components.length == 1) {
  46.363 +                return String.valueOf(components[0]);
  46.364 +            }
  46.365 +            return "";
  46.366 +        }
  46.367 +        int slen = 0;
  46.368 +        for (Object c : components) {
  46.369 +            if (c instanceof String)
  46.370 +                slen += String.valueOf(c).length();
  46.371 +            else
  46.372 +                slen += 1;
  46.373 +        }
  46.374 +        StringBuilder sb = new StringBuilder(slen);
  46.375 +        for (Object c : components) {
  46.376 +            sb.append(c);
  46.377 +        }
  46.378 +        return sb.toString();
  46.379 +    }
  46.380 +
  46.381 +    /**
  46.382 +     * Given a bytecode name, produce the corresponding display name.
  46.383 +     * This is the source name, plus quotes if needed.
  46.384 +     * If the bytecode name contains dangerous characters,
  46.385 +     * assume that they are being used as punctuation,
  46.386 +     * and pass them through unchanged.
  46.387 +     * @param s the original bytecode name (which may be qualified)
  46.388 +     * @return a human-readable presentation
  46.389 +     */
  46.390 +    public static String toDisplayName(String s) {
  46.391 +        Object[] components = parseBytecodeName(s);
  46.392 +        for (int i = 0; i < components.length; i++) {
  46.393 +            if (!(components[i] instanceof String))
  46.394 +                continue;
  46.395 +            String c = (String) components[i];
  46.396 +            // pretty up the name by demangling it
  46.397 +            String sn = toSourceName(c);
  46.398 +            if ((Object)sn != c || !isJavaIdent(sn)) {
  46.399 +                components[i] = quoteDisplay(sn);
  46.400 +            }
  46.401 +        }
  46.402 +        return appendAll(components);
  46.403 +    }
  46.404 +    private static boolean isJavaIdent(String s) {
  46.405 +        int slen = s.length();
  46.406 +        if (slen == 0)  return false;
  46.407 +        if (!Character.isUnicodeIdentifierStart(s.charAt(0)))
  46.408 +            return false;
  46.409 +        for (int i = 1; i < slen; i++) {
  46.410 +            if (!Character.isUnicodeIdentifierPart(s.charAt(0)))
  46.411 +                return false;
  46.412 +        }
  46.413 +        return true;
  46.414 +    }
  46.415 +    private static String quoteDisplay(String s) {
  46.416 +        // TO DO:  Replace wierd characters in s by C-style escapes.
  46.417 +        return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
  46.418 +    }
  46.419 +
  46.420 +    private static void checkSafeBytecodeName(String s)
  46.421 +            throws IllegalArgumentException {
  46.422 +        if (!isSafeBytecodeName(s)) {
  46.423 +            throw new IllegalArgumentException(s);
  46.424 +        }
  46.425 +    }
  46.426 +
  46.427 +    /**
  46.428 +     * Report whether a simple name is safe as a bytecode name.
  46.429 +     * Such names are acceptable in class files as class, method, and field names.
  46.430 +     * Additionally, they are free of "dangerous" characters, even if those
  46.431 +     * characters are legal in some (or all) names in class files.
  46.432 +     * @param s the proposed bytecode name
  46.433 +     * @return true if the name is non-empty and all of its characters are safe
  46.434 +     */
  46.435 +    public static boolean isSafeBytecodeName(String s) {
  46.436 +        if (s.length() == 0)  return false;
  46.437 +        // check occurrences of each DANGEROUS char
  46.438 +        for (char xc : DANGEROUS_CHARS_A) {
  46.439 +            if (xc == ESCAPE_C)  continue;  // not really that dangerous
  46.440 +            if (s.indexOf(xc) >= 0)  return false;
  46.441 +        }
  46.442 +        return true;
  46.443 +    }
  46.444 +
  46.445 +    /**
  46.446 +     * Report whether a character is safe in a bytecode name.
  46.447 +     * This is true of any unicode character except the following
  46.448 +     * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
  46.449 +     * @param s the proposed character
  46.450 +     * @return true if the character is safe to use in classfiles
  46.451 +     */
  46.452 +    public static boolean isSafeBytecodeChar(char c) {
  46.453 +        return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
  46.454 +    }
  46.455 +
  46.456 +    private static boolean looksMangled(String s) {
  46.457 +        return s.charAt(0) == ESCAPE_C;
  46.458 +    }
  46.459 +
  46.460 +    private static String mangle(String s) {
  46.461 +        if (s.length() == 0)
  46.462 +            return NULL_ESCAPE;
  46.463 +
  46.464 +        // build this lazily, when we first need an escape:
  46.465 +        StringBuilder sb = null;
  46.466 +
  46.467 +        for (int i = 0, slen = s.length(); i < slen; i++) {
  46.468 +            char c = s.charAt(i);
  46.469 +
  46.470 +            boolean needEscape = false;
  46.471 +            if (c == ESCAPE_C) {
  46.472 +                if (i+1 < slen) {
  46.473 +                    char c1 = s.charAt(i+1);
  46.474 +                    if ((i == 0 && c1 == NULL_ESCAPE_C)
  46.475 +                        || c1 != originalOfReplacement(c1)) {
  46.476 +                        // an accidental escape
  46.477 +                        needEscape = true;
  46.478 +                    }
  46.479 +                }
  46.480 +            } else {
  46.481 +                needEscape = isDangerous(c);
  46.482 +            }
  46.483 +
  46.484 +            if (!needEscape) {
  46.485 +                if (sb != null)  sb.append(c);
  46.486 +                continue;
  46.487 +            }
  46.488 +
  46.489 +            // build sb if this is the first escape
  46.490 +            if (sb == null) {
  46.491 +                sb = new StringBuilder(s.length()+10);
  46.492 +                // mangled names must begin with a backslash:
  46.493 +                if (s.charAt(0) != ESCAPE_C && i > 0)
  46.494 +                    sb.append(NULL_ESCAPE);
  46.495 +                // append the string so far, which is unremarkable:
  46.496 +                sb.append(s.substring(0, i));
  46.497 +            }
  46.498 +
  46.499 +            // rewrite \ to \-, / to \|, etc.
  46.500 +            sb.append(ESCAPE_C);
  46.501 +            sb.append(replacementOf(c));
  46.502 +        }
  46.503 +
  46.504 +        if (sb != null)   return sb.toString();
  46.505 +
  46.506 +        return s;
  46.507 +    }
  46.508 +
  46.509 +    private static String demangle(String s) {
  46.510 +        // build this lazily, when we first meet an escape:
  46.511 +        StringBuilder sb = null;
  46.512 +
  46.513 +        int stringStart = 0;
  46.514 +        if (s.startsWith(NULL_ESCAPE))
  46.515 +            stringStart = 2;
  46.516 +
  46.517 +        for (int i = stringStart, slen = s.length(); i < slen; i++) {
  46.518 +            char c = s.charAt(i);
  46.519 +
  46.520 +            if (c == ESCAPE_C && i+1 < slen) {
  46.521 +                // might be an escape sequence
  46.522 +                char rc = s.charAt(i+1);
  46.523 +                char oc = originalOfReplacement(rc);
  46.524 +                if (oc != rc) {
  46.525 +                    // build sb if this is the first escape
  46.526 +                    if (sb == null) {
  46.527 +                        sb = new StringBuilder(s.length());
  46.528 +                        // append the string so far, which is unremarkable:
  46.529 +                        sb.append(s.substring(stringStart, i));
  46.530 +                    }
  46.531 +                    ++i;  // skip both characters
  46.532 +                    c = oc;
  46.533 +                }
  46.534 +            }
  46.535 +
  46.536 +            if (sb != null)
  46.537 +                sb.append(c);
  46.538 +        }
  46.539 +
  46.540 +        if (sb != null)   return sb.toString();
  46.541 +
  46.542 +        return s.substring(stringStart);
  46.543 +    }
  46.544 +
  46.545 +    static char ESCAPE_C = '\\';
  46.546 +    // empty escape sequence to avoid a null name or illegal prefix
  46.547 +    static char NULL_ESCAPE_C = '=';
  46.548 +    static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
  46.549 +
  46.550 +    static final String DANGEROUS_CHARS   = "\\/.;:$[]<>"; // \\ must be first
  46.551 +    static final String REPLACEMENT_CHARS =  "-|,?!%{}^_";
  46.552 +    static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
  46.553 +    static char[] DANGEROUS_CHARS_A   = DANGEROUS_CHARS.toCharArray();
  46.554 +    static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
  46.555 +    static final Character[] DANGEROUS_CHARS_CA;
  46.556 +    static {
  46.557 +        Character[] dcca = new Character[DANGEROUS_CHARS.length()];
  46.558 +        for (int i = 0; i < dcca.length; i++)
  46.559 +            dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
  46.560 +        DANGEROUS_CHARS_CA = dcca;
  46.561 +    }
  46.562 +
  46.563 +    static final long[] SPECIAL_BITMAP = new long[2];  // 128 bits
  46.564 +    static {
  46.565 +        String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
  46.566 +        //System.out.println("SPECIAL = "+SPECIAL);
  46.567 +        for (char c : SPECIAL.toCharArray()) {
  46.568 +            SPECIAL_BITMAP[c >>> 6] |= 1L << c;
  46.569 +        }
  46.570 +    }
  46.571 +    static boolean isSpecial(char c) {
  46.572 +        if ((c >>> 6) < SPECIAL_BITMAP.length)
  46.573 +            return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
  46.574 +        else
  46.575 +            return false;
  46.576 +    }
  46.577 +    static char replacementOf(char c) {
  46.578 +        if (!isSpecial(c))  return c;
  46.579 +        int i = DANGEROUS_CHARS.indexOf(c);
  46.580 +        if (i < 0)  return c;
  46.581 +        return REPLACEMENT_CHARS.charAt(i);
  46.582 +    }
  46.583 +    static char originalOfReplacement(char c) {
  46.584 +        if (!isSpecial(c))  return c;
  46.585 +        int i = REPLACEMENT_CHARS.indexOf(c);
  46.586 +        if (i < 0)  return c;
  46.587 +        return DANGEROUS_CHARS.charAt(i);
  46.588 +    }
  46.589 +    static boolean isDangerous(char c) {
  46.590 +        if (!isSpecial(c))  return false;
  46.591 +        return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
  46.592 +    }
  46.593 +    static int indexOfDangerousChar(String s, int from) {
  46.594 +        for (int i = from, slen = s.length(); i < slen; i++) {
  46.595 +            if (isDangerous(s.charAt(i)))
  46.596 +                return i;
  46.597 +        }
  46.598 +        return -1;
  46.599 +    }
  46.600 +    static int lastIndexOfDangerousChar(String s, int from) {
  46.601 +        for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
  46.602 +            if (isDangerous(s.charAt(i)))
  46.603 +                return i;
  46.604 +        }
  46.605 +        return -1;
  46.606 +    }
  46.607 +
  46.608 +    // test driver
  46.609 +    static void main(String[] av) {
  46.610 +        // If verbose is enabled, quietly check everything.
  46.611 +        // Otherwise, print the output for the user to check.
  46.612 +        boolean verbose = false;
  46.613 +
  46.614 +        int maxlen = 0;
  46.615 +
  46.616 +        while (av.length > 0 && av[0].startsWith("-")) {
  46.617 +            String flag = av[0].intern();
  46.618 +            av = java.util.Arrays.copyOfRange(av, 1, av.length); // Java 1.6 or later
  46.619 +            if (flag == "-" || flag == "--")  break;
  46.620 +            else if (flag == "-q")
  46.621 +                verbose = false;
  46.622 +            else if (flag == "-v")
  46.623 +                verbose = true;
  46.624 +            else if (flag.startsWith("-l"))
  46.625 +                maxlen = Integer.valueOf(flag.substring(2));
  46.626 +            else
  46.627 +                throw new Error("Illegal flag argument: "+flag);
  46.628 +        }
  46.629 +
  46.630 +        if (maxlen == 0)
  46.631 +            maxlen = (verbose ? 2 : 4);
  46.632 +        if (verbose)  System.out.println("Note: maxlen = "+maxlen);
  46.633 +
  46.634 +        switch (av.length) {
  46.635 +        case 0: av = new String[] {
  46.636 +                    DANGEROUS_CHARS.substring(0) +
  46.637 +                    REPLACEMENT_CHARS.substring(0, 1) +
  46.638 +                    NULL_ESCAPE + "x"
  46.639 +                }; // and fall through:
  46.640 +        case 1:
  46.641 +            char[] cv = av[0].toCharArray();
  46.642 +            av = new String[cv.length];
  46.643 +            int avp = 0;
  46.644 +            for (char c : cv) {
  46.645 +                String s = String.valueOf(c);
  46.646 +                if (c == 'x')  s = "foo";  // tradition...
  46.647 +                av[avp++] = s;
  46.648 +            }
  46.649 +        }
  46.650 +        if (verbose)
  46.651 +            System.out.println("Note: Verbose output mode enabled.  Use '-q' to suppress.");
  46.652 +        Tester t = new Tester();
  46.653 +        t.maxlen = maxlen;
  46.654 +        t.verbose = verbose;
  46.655 +        t.tokens = av;
  46.656 +        t.test("", 0);
  46.657 +    }
  46.658 +
  46.659 +    static class Tester {
  46.660 +        boolean verbose;
  46.661 +        int maxlen;
  46.662 +        java.util.Map<String,String> map = new java.util.HashMap<String,String>();
  46.663 +        String[] tokens;
  46.664 +
  46.665 +        void test(String stringSoFar, int tokensSoFar) {
  46.666 +            test(stringSoFar);
  46.667 +            if (tokensSoFar <= maxlen) {
  46.668 +                for (String token : tokens) {
  46.669 +                    if (token.length() == 0)  continue;  // skip empty tokens
  46.670 +                    if (stringSoFar.indexOf(token) != stringSoFar.lastIndexOf(token))
  46.671 +                        continue;   // there are already two occs. of this token
  46.672 +                    if (token.charAt(0) == ESCAPE_C && token.length() == 1 && maxlen < 4)
  46.673 +                        test(stringSoFar+token, tokensSoFar);  // want lots of \'s
  46.674 +                    else if (tokensSoFar < maxlen)
  46.675 +                        test(stringSoFar+token, tokensSoFar+1);
  46.676 +                }
  46.677 +            }
  46.678 +        }
  46.679 +
  46.680 +        void test(String s) {
  46.681 +            // for small batches, do not test the null string
  46.682 +            if (s.length() == 0 && maxlen >=1 && maxlen <= 2)  return;
  46.683 +            String bn = testSourceName(s);
  46.684 +            if (bn == null)  return;
  46.685 +            if (bn == s) {
  46.686 +                //if (verbose)  System.out.println(s+" == id");
  46.687 +            } else {
  46.688 +                if (verbose)  System.out.println(s+" => "+bn+" "+toDisplayName(bn));
  46.689 +                String bnbn = testSourceName(bn);
  46.690 +                if (bnbn == null)  return;
  46.691 +                if (verbose)  System.out.println(bn+" => "+bnbn+" "+toDisplayName(bnbn));
  46.692 +                /*
  46.693 +                String bn3 = testSourceName(bnbn);
  46.694 +                if (bn3 == null)  return;
  46.695 +                if (verbose)  System.out.println(bnbn+" => "+bn3);
  46.696 +                */
  46.697 +            }
  46.698 +        }
  46.699 +
  46.700 +        String testSourceName(String s) {
  46.701 +            if (map.containsKey(s))  return null;
  46.702 +            String bn = toBytecodeName(s);
  46.703 +            map.put(s, bn);
  46.704 +            String sn = toSourceName(bn);
  46.705 +            if (!sn.equals(s)) {
  46.706 +                String bad = (s+" => "+bn+" != "+sn);
  46.707 +                if (!verbose)  throw new Error("Bad mangling: "+bad);
  46.708 +                System.out.println("*** "+bad);
  46.709 +                return null;
  46.710 +            }
  46.711 +            return bn;
  46.712 +        }
  46.713 +    }
  46.714 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/src/share/classes/sun/dyn/util/BytecodeSignature.java	Thu May 07 12:26:22 2009 -0700
    47.3 @@ -0,0 +1,137 @@
    47.4 +/*
    47.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    47.7 + *
    47.8 + * This code is free software; you can redistribute it and/or modify it
    47.9 + * under the terms of the GNU General Public License version 2 only, as
   47.10 + * published by the Free Software Foundation.  Sun designates this
   47.11 + * particular file as subject to the "Classpath" exception as provided
   47.12 + * by Sun in the LICENSE file that accompanied this code.
   47.13 + *
   47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   47.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   47.17 + * version 2 for more details (a copy is included in the LICENSE file that
   47.18 + * accompanied this code).
   47.19 + *
   47.20 + * You should have received a copy of the GNU General Public License version
   47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   47.23 + *
   47.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   47.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   47.26 + * have any questions.
   47.27 + */
   47.28 +
   47.29 +package sun.dyn.util;
   47.30 +
   47.31 +import java.dyn.MethodType;
   47.32 +import java.util.ArrayList;
   47.33 +import java.util.List;
   47.34 +
   47.35 +/**
   47.36 + * Utility routines for dealing with bytecode-level signatures.
   47.37 + * @author jrose
   47.38 + */
   47.39 +public class BytecodeSignature {
   47.40 +
   47.41 +    private BytecodeSignature() { }  // cannot instantiate
   47.42 +
   47.43 +    public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
   47.44 +        return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
   47.45 +    }
   47.46 +
   47.47 +    static List<Class<?>> parseMethod(String bytecodeSignature,
   47.48 +            int start, int end, ClassLoader loader) {
   47.49 +        if (loader == null)
   47.50 +            loader = ClassLoader.getSystemClassLoader();
   47.51 +        String str = bytecodeSignature;
   47.52 +        int[] i = {start};
   47.53 +        ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
   47.54 +        if (i[0] < end && str.charAt(i[0]) == '(') {
   47.55 +            ++i[0];  // skip '('
   47.56 +            while (i[0] < end && str.charAt(i[0]) != ')') {
   47.57 +                Class<?> pt = parseSig(str, i, end, loader);
   47.58 +                if (pt == null || pt == void.class)
   47.59 +                    parseError(str, "bad argument type");
   47.60 +                ptypes.add(pt);
   47.61 +            }
   47.62 +            ++i[0];  // skip ')'
   47.63 +        } else {
   47.64 +            parseError(str, "not a method type");
   47.65 +        }
   47.66 +        Class<?> rtype = parseSig(str, i, end, loader);
   47.67 +        if (rtype == null || i[0] != end)
   47.68 +            parseError(str, "bad return type");
   47.69 +        ptypes.add(rtype);
   47.70 +        return ptypes;
   47.71 +    }
   47.72 +
   47.73 +    static private void parseError(String str, String msg) {
   47.74 +        throw new IllegalArgumentException("bad signature: "+str+": "+msg);
   47.75 +    }
   47.76 +
   47.77 +    static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
   47.78 +        if (i[0] == end)  return null;
   47.79 +        char c = str.charAt(i[0]++);
   47.80 +        if (c == 'L') {
   47.81 +            int begc = i[0], endc = str.indexOf(';', begc);
   47.82 +            if (endc < 0)  return null;
   47.83 +            i[0] = endc+1;
   47.84 +            String name = str.substring(begc, endc).replace('/', '.');
   47.85 +            try {
   47.86 +                return loader.loadClass(name);
   47.87 +            } catch (ClassNotFoundException ex) {
   47.88 +                throw new TypeNotPresentException(name, ex);
   47.89 +            }
   47.90 +        } else if (c == '[') {
   47.91 +            Class<?> t = parseSig(str, i, end, loader);
   47.92 +            if (t != null)
   47.93 +                t = java.lang.reflect.Array.newInstance(t, 0).getClass();
   47.94 +            return t;
   47.95 +        } else {
   47.96 +            return Wrapper.forBasicType(c).primitiveType();
   47.97 +        }
   47.98 +    }
   47.99 +
  47.100 +    public static String unparse(Class<?> type) {
  47.101 +        StringBuilder sb = new StringBuilder();
  47.102 +        unparseSig(type, sb);
  47.103 +        return sb.toString();
  47.104 +    }
  47.105 +
  47.106 +    public static String unparse(MethodType type) {
  47.107 +        return unparseMethod(type.returnType(), type.parameterList());
  47.108 +    }
  47.109 +
  47.110 +    public static String unparse(Object type) {
  47.111 +        if (type instanceof Class<?>)
  47.112 +            return unparse((Class<?>) type);
  47.113 +        if (type instanceof MethodType)
  47.114 +            return unparse((MethodType) type);
  47.115 +        return (String) type;
  47.116 +    }
  47.117 +
  47.118 +    public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
  47.119 +        StringBuilder sb = new StringBuilder();
  47.120 +        sb.append('(');
  47.121 +        for (Class<?> pt : ptypes)
  47.122 +            unparseSig(pt, sb);
  47.123 +        sb.append(')');
  47.124 +        unparseSig(rtype, sb);
  47.125 +        return sb.toString();
  47.126 +    }
  47.127 +
  47.128 +    static private void unparseSig(Class<?> t, StringBuilder sb) {
  47.129 +        char c = Wrapper.forBasicType(t).basicTypeChar();
  47.130 +        if (c != 'L') {
  47.131 +            sb.append(c);
  47.132 +        } else {
  47.133 +            boolean lsemi = (!t.isArray());
  47.134 +            if (lsemi)  sb.append('L');
  47.135 +            sb.append(t.getName().replace('.', '/'));
  47.136 +            if (lsemi)  sb.append(';');
  47.137 +        }
  47.138 +    }
  47.139 +
  47.140 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/src/share/classes/sun/dyn/util/ValueConversions.java	Thu May 07 12:26:22 2009 -0700
    48.3 @@ -0,0 +1,563 @@
    48.4 +/*
    48.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    48.7 + *
    48.8 + * This code is free software; you can redistribute it and/or modify it
    48.9 + * under the terms of the GNU General Public License version 2 only, as
   48.10 + * published by the Free Software Foundation.  Sun designates this
   48.11 + * particular file as subject to the "Classpath" exception as provided
   48.12 + * by Sun in the LICENSE file that accompanied this code.
   48.13 + *
   48.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   48.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   48.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   48.17 + * version 2 for more details (a copy is included in the LICENSE file that
   48.18 + * accompanied this code).
   48.19 + *
   48.20 + * You should have received a copy of the GNU General Public License version
   48.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   48.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   48.23 + *
   48.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   48.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   48.26 + * have any questions.
   48.27 + */
   48.28 +
   48.29 +package sun.dyn.util;
   48.30 +
   48.31 +import java.dyn.*;
   48.32 +import java.dyn.MethodHandles.Lookup;
   48.33 +import java.util.EnumMap;
   48.34 +import sun.dyn.Access;
   48.35 +import sun.dyn.AdapterMethodHandle;
   48.36 +import sun.dyn.MethodHandleImpl;
   48.37 +
   48.38 +public class ValueConversions {
   48.39 +    private static final Access IMPL_TOKEN = Access.getToken();
   48.40 +    private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN);
   48.41 +
   48.42 +    private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
   48.43 +        EnumMap<Wrapper, MethodHandle>[] caches
   48.44 +                = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n];  // unchecked warning expected here
   48.45 +        for (int i = 0; i < n; i++)
   48.46 +            caches[i] = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
   48.47 +        return caches;
   48.48 +    }
   48.49 +
   48.50 +    /// Converting references to values.
   48.51 +
   48.52 +    static int unboxInteger(Object x) {
   48.53 +        if (x == null)  return 0;  // never NPE
   48.54 +        return ((Integer) x).intValue();
   48.55 +    }
   48.56 +
   48.57 +    static byte unboxByte(Object x) {
   48.58 +        if (x == null)  return 0;  // never NPE
   48.59 +        return ((Byte) x).byteValue();
   48.60 +    }
   48.61 +
   48.62 +    static short unboxShort(Object x) {
   48.63 +        if (x == null)  return 0;  // never NPE
   48.64 +        return ((Short) x).shortValue();
   48.65 +    }
   48.66 +
   48.67 +    static boolean unboxBoolean(Object x) {
   48.68 +        if (x == null)  return false;  // never NPE
   48.69 +        return ((Boolean) x).booleanValue();
   48.70 +    }
   48.71 +
   48.72 +    static char unboxCharacter(Object x) {
   48.73 +        if (x == null)  return 0;  // never NPE
   48.74 +        return ((Character) x).charValue();
   48.75 +    }
   48.76 +
   48.77 +    static long unboxLong(Object x) {
   48.78 +        if (x == null)  return 0;  // never NPE
   48.79 +        return ((Long) x).longValue();
   48.80 +    }
   48.81 +
   48.82 +    static float unboxFloat(Object x) {
   48.83 +        if (x == null)  return 0;  // never NPE
   48.84 +        return ((Float) x).floatValue();
   48.85 +    }
   48.86 +
   48.87 +    static double unboxDouble(Object x) {
   48.88 +        if (x == null)  return 0;  // never NPE
   48.89 +        return ((Double) x).doubleValue();
   48.90 +    }
   48.91 +
   48.92 +    /// Converting references to "raw" values.
   48.93 +    /// A raw primitive value is always an int or long.
   48.94 +
   48.95 +    static int unboxByteRaw(Object x) {
   48.96 +        return unboxByte(x);
   48.97 +    }
   48.98 +
   48.99 +    static int unboxShortRaw(Object x) {
  48.100 +        return unboxShort(x);
  48.101 +    }
  48.102 +
  48.103 +    static int unboxBooleanRaw(Object x) {
  48.104 +        return unboxBoolean(x) ? 1 : 0;
  48.105 +    }
  48.106 +
  48.107 +    static int unboxCharacterRaw(Object x) {
  48.108 +        return unboxCharacter(x);
  48.109 +    }
  48.110 +
  48.111 +    static int unboxFloatRaw(Object x) {
  48.112 +        return Float.floatToIntBits(unboxFloat(x));
  48.113 +    }
  48.114 +
  48.115 +    static long unboxDoubleRaw(Object x) {
  48.116 +        return Double.doubleToRawLongBits(unboxDouble(x));
  48.117 +    }
  48.118 +
  48.119 +    private static MethodType unboxType(Wrapper wrap, boolean raw) {
  48.120 +        return MethodType.make(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
  48.121 +    }
  48.122 +
  48.123 +    private static final EnumMap<Wrapper, MethodHandle>[]
  48.124 +            UNBOX_CONVERSIONS = newWrapperCaches(4);
  48.125 +
  48.126 +    private static MethodHandle unbox(Wrapper wrap, boolean exact, boolean raw) {
  48.127 +        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
  48.128 +        MethodHandle mh = cache.get(wrap);
  48.129 +        if (mh != null) {
  48.130 +            return mh;
  48.131 +        }
  48.132 +        // slow path
  48.133 +        switch (wrap) {
  48.134 +            case OBJECT:
  48.135 +                mh = IDENTITY; break;
  48.136 +            case VOID:
  48.137 +                mh = raw ? ALWAYS_ZERO : IGNORE; break;
  48.138 +            case INT: case LONG:
  48.139 +                // these guys don't need separate raw channels
  48.140 +                if (raw)  mh = unbox(wrap, exact, false);
  48.141 +                break;
  48.142 +        }
  48.143 +        if (mh != null) {
  48.144 +            cache.put(wrap, mh);
  48.145 +            return mh;
  48.146 +        }
  48.147 +        // look up the method
  48.148 +        String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
  48.149 +        MethodType type = unboxType(wrap, raw);
  48.150 +        if (!exact)
  48.151 +            // actually, type is wrong; the Java method takes Object
  48.152 +            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
  48.153 +        else
  48.154 +            mh = retype(type, unbox(wrap, !exact, raw));
  48.155 +        if (mh != null) {
  48.156 +            cache.put(wrap, mh);
  48.157 +            return mh;
  48.158 +        }
  48.159 +        throw new IllegalArgumentException("cannot find unbox adapter for " + wrap + (raw ? " (raw)" : ""));
  48.160 +    }
  48.161 +
  48.162 +    public static MethodHandle unbox(Wrapper type, boolean exact) {
  48.163 +        return unbox(type, exact, false);
  48.164 +    }
  48.165 +
  48.166 +    public static MethodHandle unboxRaw(Wrapper type, boolean exact) {
  48.167 +        return unbox(type, exact, true);
  48.168 +    }
  48.169 +
  48.170 +    public static MethodHandle unbox(Class<?> type, boolean exact) {
  48.171 +        return unbox(Wrapper.forPrimitiveType(type), exact, false);
  48.172 +    }
  48.173 +
  48.174 +    public static MethodHandle unboxRaw(Class<?> type, boolean exact) {
  48.175 +        return unbox(Wrapper.forPrimitiveType(type), exact, true);
  48.176 +    }
  48.177 +
  48.178 +    /// Converting primitives to references
  48.179 +
  48.180 +    static Integer boxInteger(int x) {
  48.181 +        return x;
  48.182 +    }
  48.183 +
  48.184 +    static Byte boxByte(byte x) {
  48.185 +        return x;
  48.186 +    }
  48.187 +
  48.188 +    static Short boxShort(short x) {
  48.189 +        return x;
  48.190 +    }
  48.191 +
  48.192 +    static Boolean boxBoolean(boolean x) {
  48.193 +        return x;
  48.194 +    }
  48.195 +
  48.196 +    static Character boxCharacter(char x) {
  48.197 +        return x;
  48.198 +    }
  48.199 +
  48.200 +    static Long boxLong(long x) {
  48.201 +        return x;
  48.202 +    }
  48.203 +
  48.204 +    static Float boxFloat(float x) {
  48.205 +        return x;
  48.206 +    }
  48.207 +
  48.208 +    static Double boxDouble(double x) {
  48.209 +        return x;
  48.210 +    }
  48.211 +
  48.212 +    /// Converting raw primitives to references
  48.213 +
  48.214 +    static Byte boxByteRaw(int x) {
  48.215 +        return boxByte((byte)x);
  48.216 +    }
  48.217 +
  48.218 +    static Short boxShortRaw(int x) {
  48.219 +        return boxShort((short)x);
  48.220 +    }
  48.221 +
  48.222 +    static Boolean boxBooleanRaw(int x) {
  48.223 +        return boxBoolean(x != 0);
  48.224 +    }
  48.225 +
  48.226 +    static Character boxCharacterRaw(int x) {
  48.227 +        return boxCharacter((char)x);
  48.228 +    }
  48.229 +
  48.230 +    static Float boxFloatRaw(int x) {
  48.231 +        return boxFloat(Float.intBitsToFloat(x));
  48.232 +    }
  48.233 +
  48.234 +    static Double boxDoubleRaw(long x) {
  48.235 +        return boxDouble(Double.longBitsToDouble(x));
  48.236 +    }
  48.237 +
  48.238 +    // a raw void value is (arbitrarily) a garbage int
  48.239 +    static Void boxVoidRaw(int x) {
  48.240 +        return null;
  48.241 +    }
  48.242 +
  48.243 +    private static MethodType boxType(Wrapper wrap, boolean raw) {
  48.244 +        // be exact, since return casts are hard to compose
  48.245 +        Class<?> boxType = wrap.wrapperType();
  48.246 +        return MethodType.make(boxType, rawWrapper(wrap, raw).primitiveType());
  48.247 +    }
  48.248 +
  48.249 +    private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
  48.250 +        if (raw)  return wrap.isDoubleWord() ? Wrapper.LONG : Wrapper.INT;
  48.251 +        return wrap;
  48.252 +    }
  48.253 +
  48.254 +    private static final EnumMap<Wrapper, MethodHandle>[]
  48.255 +            BOX_CONVERSIONS = newWrapperCaches(4);
  48.256 +
  48.257 +    private static MethodHandle box(Wrapper wrap, boolean exact, boolean raw) {
  48.258 +        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
  48.259 +        MethodHandle mh = cache.get(wrap);
  48.260 +        if (mh != null) {
  48.261 +            return mh;
  48.262 +        }
  48.263 +        // slow path
  48.264 +        switch (wrap) {
  48.265 +            case OBJECT:
  48.266 +                mh = IDENTITY; break;
  48.267 +            case VOID:
  48.268 +                if (!raw)  mh = ZERO_OBJECT;
  48.269 +                break;
  48.270 +            case INT: case LONG:
  48.271 +                // these guys don't need separate raw channels
  48.272 +                if (raw)  mh = box(wrap, exact, false);
  48.273 +                break;
  48.274 +        }
  48.275 +        if (mh != null) {
  48.276 +            cache.put(wrap, mh);
  48.277 +            return mh;
  48.278 +        }
  48.279 +        // look up the method
  48.280 +        String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
  48.281 +        MethodType type = boxType(wrap, raw);
  48.282 +        if (exact)
  48.283 +            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
  48.284 +        else
  48.285 +            mh = retype(type.erase(), box(wrap, !exact, raw));
  48.286 +        if (mh != null) {
  48.287 +            cache.put(wrap, mh);
  48.288 +            return mh;
  48.289 +        }
  48.290 +        throw new IllegalArgumentException("cannot find box adapter for " + wrap + (raw ? " (raw)" : ""));
  48.291 +    }
  48.292 +
  48.293 +    public static MethodHandle box(Class<?> type, boolean exact) {
  48.294 +        return box(Wrapper.forPrimitiveType(type), exact, false);
  48.295 +    }
  48.296 +
  48.297 +    public static MethodHandle boxRaw(Class<?> type, boolean exact) {
  48.298 +        return box(Wrapper.forPrimitiveType(type), exact, true);
  48.299 +    }
  48.300 +
  48.301 +    public static MethodHandle box(Wrapper type, boolean exact) {
  48.302 +        return box(type, exact, false);
  48.303 +    }
  48.304 +
  48.305 +    public static MethodHandle boxRaw(Wrapper type, boolean exact) {
  48.306 +        return box(type, exact, true);
  48.307 +    }
  48.308 +
  48.309 +    /// Kludges for when raw values get accidentally boxed.
  48.310 +
  48.311 +    static Byte reboxRawByte(Object x) {
  48.312 +        if (x instanceof Byte)  return (Byte) x;
  48.313 +        return boxByteRaw(unboxInteger(x));
  48.314 +    }
  48.315 +
  48.316 +    static Short reboxRawShort(Object x) {
  48.317 +        if (x instanceof Short)  return (Short) x;
  48.318 +        return boxShortRaw(unboxInteger(x));
  48.319 +    }
  48.320 +
  48.321 +    static Boolean reboxRawBoolean(Object x) {
  48.322 +        if (x instanceof Boolean)  return (Boolean) x;
  48.323 +        return boxBooleanRaw(unboxInteger(x));
  48.324 +    }
  48.325 +
  48.326 +    static Character reboxRawCharacter(Object x) {
  48.327 +        if (x instanceof Character)  return (Character) x;
  48.328 +        return boxCharacterRaw(unboxInteger(x));
  48.329 +    }
  48.330 +
  48.331 +    static Float reboxRawFloat(Object x) {
  48.332 +        if (x instanceof Float)  return (Float) x;
  48.333 +        return boxFloatRaw(unboxInteger(x));
  48.334 +    }
  48.335 +
  48.336 +    static Double reboxRawDouble(Object x) {
  48.337 +        if (x instanceof Double)  return (Double) x;
  48.338 +        return boxDoubleRaw(unboxLong(x));
  48.339 +    }
  48.340 +
  48.341 +    private static MethodType reboxType(Wrapper wrap) {
  48.342 +        Class<?> boxType = wrap.wrapperType();
  48.343 +        return MethodType.make(boxType, Object.class);
  48.344 +    }
  48.345 +
  48.346 +    private static final EnumMap<Wrapper, MethodHandle>[]
  48.347 +            REBOX_CONVERSIONS = newWrapperCaches(2);
  48.348 +
  48.349 +    public static MethodHandle rebox(Wrapper wrap, boolean exact) {
  48.350 +        EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[exact?1:0];
  48.351 +        MethodHandle mh = cache.get(wrap);
  48.352 +        if (mh != null) {
  48.353 +            return mh;
  48.354 +        }
  48.355 +        // slow path
  48.356 +        switch (wrap) {
  48.357 +            case OBJECT:
  48.358 +                mh = IDENTITY; break;
  48.359 +            case VOID:
  48.360 +                throw new IllegalArgumentException("cannot rebox a void");
  48.361 +            case INT: case LONG:
  48.362 +                mh = cast(wrap.wrapperType(), exact);
  48.363 +                break;
  48.364 +        }
  48.365 +        if (mh != null) {
  48.366 +            cache.put(wrap, mh);
  48.367 +            return mh;
  48.368 +        }
  48.369 +        // look up the method
  48.370 +        String name = "reboxRaw" + wrap.simpleName();
  48.371 +        MethodType type = reboxType(wrap);
  48.372 +        if (exact)
  48.373 +            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
  48.374 +        else
  48.375 +            mh = retype(IDENTITY.type(), rebox(wrap, !exact));
  48.376 +        if (mh != null) {
  48.377 +            cache.put(wrap, mh);
  48.378 +            return mh;
  48.379 +        }
  48.380 +        throw new IllegalArgumentException("cannot find rebox adapter for " + wrap);
  48.381 +    }
  48.382 +
  48.383 +    public static MethodHandle rebox(Class<?> type, boolean exact) {
  48.384 +        return rebox(Wrapper.forPrimitiveType(type), exact);
  48.385 +    }
  48.386 +
  48.387 +    /// Width-changing conversions between int and long.
  48.388 +
  48.389 +    static long widenInt(int x) {
  48.390 +        return x;
  48.391 +    }
  48.392 +
  48.393 +    static int narrowLong(long x) {
  48.394 +        return (int) x;
  48.395 +    }
  48.396 +
  48.397 +    /// Constant functions
  48.398 +
  48.399 +    static void ignore(Object x) {
  48.400 +        // no value to return; this is an unbox of null
  48.401 +        return;
  48.402 +    }
  48.403 +
  48.404 +    static void empty() {
  48.405 +        return;
  48.406 +    }
  48.407 +
  48.408 +    static Object zeroObject() {
  48.409 +        return null;
  48.410 +    }
  48.411 +
  48.412 +    static int zeroInteger() {
  48.413 +        return 0;
  48.414 +    }
  48.415 +
  48.416 +    static long zeroLong() {
  48.417 +        return 0;
  48.418 +    }
  48.419 +
  48.420 +    static float zeroFloat() {
  48.421 +        return 0;
  48.422 +    }
  48.423 +
  48.424 +    static double zeroDouble() {
  48.425 +        return 0;
  48.426 +    }
  48.427 +
  48.428 +    private static final EnumMap<Wrapper, MethodHandle>[]
  48.429 +            ZERO_CONSTANT_FUNCTIONS = newWrapperCaches(1);
  48.430 +
  48.431 +    public static MethodHandle zeroConstantFunction(Wrapper wrap) {
  48.432 +        EnumMap<Wrapper, MethodHandle> cache = ZERO_CONSTANT_FUNCTIONS[0];
  48.433 +        MethodHandle mh = cache.get(wrap);
  48.434 +        if (mh != null) {
  48.435 +            return mh;
  48.436 +        }
  48.437 +        // slow path
  48.438 +        MethodType type = MethodType.make(wrap.primitiveType());
  48.439 +        switch (wrap) {
  48.440 +            case VOID:
  48.441 +                mh = EMPTY;
  48.442 +                break;
  48.443 +            case INT: case LONG: case FLOAT: case DOUBLE:
  48.444 +                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
  48.445 +                break;
  48.446 +        }
  48.447 +        if (mh != null) {
  48.448 +            cache.put(wrap, mh);
  48.449 +            return mh;
  48.450 +        }
  48.451 +
  48.452 +        // use the raw method
  48.453 +        Wrapper rawWrap = wrap.rawPrimitive();
  48.454 +        if (rawWrap != wrap) {
  48.455 +            mh = retype(type, zeroConstantFunction(rawWrap));
  48.456 +        }
  48.457 +        if (mh != null) {
  48.458 +            cache.put(wrap, mh);
  48.459 +            return mh;
  48.460 +        }
  48.461 +        throw new IllegalArgumentException("cannot find zero constant for " + wrap);
  48.462 +    }
  48.463 +
  48.464 +    /// Converting references to references.
  48.465 +
  48.466 +    /**
  48.467 +     * Value-killing function.
  48.468 +     * @param x an arbitrary reference value
  48.469 +     * @return a null
  48.470 +     */
  48.471 +    static Object alwaysNull(Object x) {
  48.472 +        return null;
  48.473 +    }
  48.474 +
  48.475 +    /**
  48.476 +     * Value-killing function.
  48.477 +     * @param x an arbitrary reference value
  48.478 +     * @return a zero
  48.479 +     */
  48.480 +    static int alwaysZero(Object x) {
  48.481 +        return 0;
  48.482 +    }
  48.483 +
  48.484 +    /**
  48.485 +     * Identity function.
  48.486 +     * @param x an arbitrary reference value
  48.487 +     * @return the same value x
  48.488 +     */
  48.489 +    static <T> T identity(T x) {
  48.490 +        return x;
  48.491 +    }
  48.492 +
  48.493 +    /**
  48.494 +     * Identity function, with reference cast.
  48.495 +     * @param t an arbitrary reference type
  48.496 +     * @param x an arbitrary reference value
  48.497 +     * @return the same value x
  48.498 +     */
  48.499 +    static <T,U> T castReference(Class<? extends T> t, U x) {
  48.500 +        return t.cast(x);
  48.501 +    }
  48.502 +
  48.503 +    private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
  48.504 +    static {
  48.505 +        try {
  48.506 +            MethodType idType = MethodType.makeGeneric(1);
  48.507 +            MethodType castType = idType.insertParameterType(0, Class.class);
  48.508 +            MethodType alwaysZeroType = idType.changeReturnType(int.class);
  48.509 +            MethodType ignoreType = idType.changeReturnType(void.class);
  48.510 +            MethodType zeroObjectType = MethodType.makeGeneric(0);
  48.511 +            IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
  48.512 +            //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
  48.513 +            CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
  48.514 +            ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType);
  48.515 +            ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType);
  48.516 +            ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
  48.517 +            IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
  48.518 +            EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterType(0));
  48.519 +        } catch (RuntimeException ex) {
  48.520 +            throw ex;
  48.521 +        }
  48.522 +    }
  48.523 +
  48.524 +    private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS
  48.525 +            = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
  48.526 +
  48.527 +    private static final EnumMap<Wrapper, MethodHandle> EXACT_WRAPPER_CASTS
  48.528 +            = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
  48.529 +
  48.530 +    /** Return a method that casts its sole argument (an Object) to the given type
  48.531 +     *  and returns it as the given type (if exact is true), or as plain Object (if erase is true).
  48.532 +     */
  48.533 +    public static MethodHandle cast(Class<?> type, boolean exact) {
  48.534 +        if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
  48.535 +        MethodHandle mh = null;
  48.536 +        Wrapper wrap = null;
  48.537 +        EnumMap<Wrapper, MethodHandle> cache = null;
  48.538 +        if (Wrapper.isWrapperType(type)) {
  48.539 +            wrap = Wrapper.forWrapperType(type);
  48.540 +            cache = (exact ? EXACT_WRAPPER_CASTS : WRAPPER_CASTS);
  48.541 +            mh = cache.get(wrap);
  48.542 +            if (mh != null)  return mh;
  48.543 +        }
  48.544 +        if (VerifyType.isNullReferenceConversion(Object.class, type))
  48.545 +            mh = IDENTITY;
  48.546 +        else if (VerifyType.isNullType(type))
  48.547 +            mh = ALWAYS_NULL;
  48.548 +        else
  48.549 +            mh = MethodHandles.insertArgument(CAST_REFERENCE, 0, type);
  48.550 +        if (exact) {
  48.551 +            MethodType xmt = MethodType.make(type, Object.class);
  48.552 +            mh = AdapterMethodHandle.makeRawRetypeOnly(IMPL_TOKEN, xmt, mh);
  48.553 +        }
  48.554 +        if (cache != null)
  48.555 +            cache.put(wrap, mh);
  48.556 +        return mh;
  48.557 +    }
  48.558 +
  48.559 +    public static MethodHandle identity() {
  48.560 +        return IDENTITY;
  48.561 +    }
  48.562 +
  48.563 +    private static MethodHandle retype(MethodType type, MethodHandle mh) {
  48.564 +        return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh);
  48.565 +    }
  48.566 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/src/share/classes/sun/dyn/util/VerifyAccess.java	Thu May 07 12:26:22 2009 -0700
    49.3 @@ -0,0 +1,169 @@
    49.4 +/*
    49.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    49.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    49.7 + *
    49.8 + * This code is free software; you can redistribute it and/or modify it
    49.9 + * under the terms of the GNU General Public License version 2 only, as
   49.10 + * published by the Free Software Foundation.  Sun designates this
   49.11 + * particular file as subject to the "Classpath" exception as provided
   49.12 + * by Sun in the LICENSE file that accompanied this code.
   49.13 + *
   49.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   49.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   49.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   49.17 + * version 2 for more details (a copy is included in the LICENSE file that
   49.18 + * accompanied this code).
   49.19 + *
   49.20 + * You should have received a copy of the GNU General Public License version
   49.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   49.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   49.23 + *
   49.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   49.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   49.26 + * have any questions.
   49.27 + */
   49.28 +
   49.29 +package sun.dyn.util;
   49.30 +
   49.31 +import java.dyn.LinkagePermission;
   49.32 +import java.lang.reflect.Modifier;
   49.33 +import sun.dyn.Access;
   49.34 +
   49.35 +/**
   49.36 + * This class centralizes information about the JVM's linkage access control.
   49.37 + * @author jrose
   49.38 + */
   49.39 +public class VerifyAccess {
   49.40 +
   49.41 +    private VerifyAccess() { }  // cannot instantiate
   49.42 +
   49.43 +    /**
   49.44 +     * Evaluate the JVM linkage rules for access to the given method on behalf of caller.
   49.45 +     * Return non-null if and only if the given accessing class has at least partial
   49.46 +     * privileges to invoke the given method.  The return value {@code Object.class}
   49.47 +     * denotes unlimited privileges.
   49.48 +     * <p>
   49.49 +     * Some circumstances require an additional check on the
   49.50 +     * leading parameter (the receiver) of the method, if it is non-static.
   49.51 +     * In the case of {@code invokespecial} ({@code doDispatch} is false),
   49.52 +     * the leading parameter must be the accessing class or a subclass.
   49.53 +     * In the case of a call to a {@code protected} method outside the same
   49.54 +     * package, the same constraint applies.
   49.55 +     * @param m the proposed callee
   49.56 +     * @param doDispatch if false, a non-static m will be invoked as if by {@code invokespecial}
   49.57 +     * @param lookupClass the class for which the access check is being made
   49.58 +     * @return null if the method is not accessible, else a receiver type constraint, else {@code Object.class}
   49.59 +     */
   49.60 +    public static Class<?> isAccessible(Class<?> defc, int mods,
   49.61 +            boolean doDispatch, Class<?> lookupClass) {
   49.62 +        if (!isAccessible(defc, lookupClass))
   49.63 +            return null;
   49.64 +        Class<?> constraint = Object.class;
   49.65 +        if (!doDispatch && !Modifier.isStatic(mods)) {
   49.66 +            constraint = lookupClass;
   49.67 +        }
   49.68 +        if (Modifier.isPublic(mods))
   49.69 +            return constraint;
   49.70 +        if (Modifier.isPrivate(mods))
   49.71 +            return isSamePackageMember(defc, lookupClass) ? constraint : null;
   49.72 +        if (isSamePackage(defc, lookupClass))
   49.73 +            return constraint;
   49.74 +        if (Modifier.isProtected(mods) && defc.isAssignableFrom(lookupClass))
   49.75 +            return constraint;
   49.76 +        // else it is private or package scoped, and not close enough
   49.77 +        return null;
   49.78 +    }
   49.79 +
   49.80 +    /**
   49.81 +     * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
   49.82 +     */
   49.83 +    public static boolean isAccessible(Class<?> refc, Class<?> lookupClass) {
   49.84 +        int mods = refc.getModifiers();
   49.85 +        if (Modifier.isPublic(mods))
   49.86 +            return true;
   49.87 +        if (isSamePackage(lookupClass, refc))
   49.88 +            return true;
   49.89 +        return false;
   49.90 +    }
   49.91 +
   49.92 +    /**
   49.93 +     * Test if two classes have the same class loader and package qualifier.
   49.94 +     * @param class1
   49.95 +     * @param class2
   49.96 +     * @return whether they are in the same package
   49.97 +     */
   49.98 +    public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
   49.99 +        if (class1 == class2)
  49.100 +            return true;
  49.101 +        if (loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
  49.102 +            return false;
  49.103 +        String name1 = class1.getName(), name2 = class2.getName();
  49.104 +        int dot = name1.lastIndexOf('.');
  49.105 +        if (dot != name2.lastIndexOf('.'))
  49.106 +            return false;
  49.107 +        for (int i = 0; i < dot; i++) {
  49.108 +            if (name1.charAt(i) != name2.charAt(i))
  49.109 +                return false;
  49.110 +        }
  49.111 +        return true;
  49.112 +    }
  49.113 +
  49.114 +    /**
  49.115 +     * Test if two classes are defined as part of the same package member (top-level class).
  49.116 +     * If this is true, they can share private access with each other.
  49.117 +     * @param class1
  49.118 +     * @param class2
  49.119 +     * @return whether they are identical or nested together
  49.120 +     */
  49.121 +    public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
  49.122 +        if (class1 == class2)
  49.123 +            return true;
  49.124 +        if (!isSamePackage(class1, class2))
  49.125 +            return false;
  49.126 +        if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
  49.127 +            return false;
  49.128 +        return true;
  49.129 +    }
  49.130 +
  49.131 +    private static Class<?> getOutermostEnclosingClass(Class<?> c) {
  49.132 +        Class<?> pkgmem = c;
  49.133 +        for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
  49.134 +            pkgmem = enc;
  49.135 +        return pkgmem;
  49.136 +    }
  49.137 +
  49.138 +    private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2) {
  49.139 +        if (loader1 == loader2 || loader1 == null || loader2 == null) {
  49.140 +            return true;
  49.141 +        }
  49.142 +        for (ClassLoader scan1 = loader1;
  49.143 +                scan1 != null; scan1 = scan1.getParent()) {
  49.144 +            if (scan1 == loader2)  return true;
  49.145 +        }
  49.146 +        for (ClassLoader scan2 = loader2;
  49.147 +                scan2 != null; scan2 = scan2.getParent()) {
  49.148 +            if (scan2 == loader1)  return true;
  49.149 +        }
  49.150 +        return false;
  49.151 +    }
  49.152 +
  49.153 +    /**
  49.154 +     * Ensure the requesting class have privileges to perform invokedynamic
  49.155 +     * linkage operations on subjectClass.  True if requestingClass is
  49.156 +     * Access.class (meaning the request originates from the JVM) or if the
  49.157 +     * classes are in the same package and have consistent class loaders.
  49.158 +     * (The subject class loader must be identical with or be a child of
  49.159 +     * the requesting class loader.)
  49.160 +     * @param requestingClass
  49.161 +     * @param subjectClass
  49.162 +     */
  49.163 +    public static void checkBootstrapPrivilege(Class requestingClass, Class subjectClass,
  49.164 +                                               String permissionName) {
  49.165 +        if (requestingClass == Access.class)  return;
  49.166 +        if (requestingClass == subjectClass)  return;
  49.167 +        SecurityManager security = System.getSecurityManager();
  49.168 +        if (security == null)  return;  // open season
  49.169 +        if (isSamePackage(requestingClass, subjectClass))  return;
  49.170 +        security.checkPermission(new LinkagePermission(permissionName, requestingClass));
  49.171 +    }
  49.172 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/src/share/classes/sun/dyn/util/VerifyType.java	Thu May 07 12:26:22 2009 -0700
    50.3 @@ -0,0 +1,219 @@
    50.4 +/*
    50.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    50.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    50.7 + *
    50.8 + * This code is free software; you can redistribute it and/or modify it
    50.9 + * under the terms of the GNU General Public License version 2 only, as
   50.10 + * published by the Free Software Foundation.  Sun designates this
   50.11 + * particular file as subject to the "Classpath" exception as provided
   50.12 + * by Sun in the LICENSE file that accompanied this code.
   50.13 + *
   50.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   50.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   50.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   50.17 + * version 2 for more details (a copy is included in the LICENSE file that
   50.18 + * accompanied this code).
   50.19 + *
   50.20 + * You should have received a copy of the GNU General Public License version
   50.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   50.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   50.23 + *
   50.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   50.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   50.26 + * have any questions.
   50.27 + */
   50.28 +
   50.29 +package sun.dyn.util;
   50.30 +
   50.31 +import java.dyn.MethodType;
   50.32 +
   50.33 +/**
   50.34 + * This class centralizes information about the JVM verifier
   50.35 + * and its requirements about type correctness.
   50.36 + * @author jrose
   50.37 + */
   50.38 +public class VerifyType {
   50.39 +
   50.40 +    private VerifyType() { }  // cannot instantiate
   50.41 +
   50.42 +    /**
   50.43 +     * True if a value can be stacked as the source type and unstacked as the
   50.44 +     * destination type, without violating the JVM's type consistency.
   50.45 +     *
   50.46 +     * @param call the type of a stacked value
   50.47 +     * @param recv the type by which we'd like to treat it
   50.48 +     * @return whether the retyping can be done without motion or reformatting
   50.49 +     */
   50.50 +    public static boolean isNullConversion(Class<?> src, Class<?> dst) {
   50.51 +        if (src == dst)            return true;
   50.52 +        // Verifier allows any interface to be treated as Object:
   50.53 +        if (dst.isInterface())     dst = Object.class;
   50.54 +        if (src.isInterface())     src = Object.class;
   50.55 +        if (src == dst)            return true;  // check again
   50.56 +        if (dst == void.class)     return true;  // drop any return value
   50.57 +        if (isNullType(src))       return !dst.isPrimitive();
   50.58 +        if (!src.isPrimitive())    return dst.isAssignableFrom(src);
   50.59 +        // Verifier allows an int to carry byte, short, char, or even boolean:
   50.60 +        if (dst == int.class)      return Wrapper.forPrimitiveType(src).isSubwordOrInt();
   50.61 +        return false;
   50.62 +    }
   50.63 +
   50.64 +    /**
   50.65 +     * Specialization of isNullConversion to reference types.
   50.66 +
   50.67 +     * @param call the type of a stacked value
   50.68 +     * @param recv the reference type by which we'd like to treat it
   50.69 +     * @return whether the retyping can be done without a cast
   50.70 +     */
   50.71 +    public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
   50.72 +        assert(!dst.isPrimitive());
   50.73 +        if (dst.isInterface())  return true;   // verifier allows this
   50.74 +        if (isNullType(src))    return true;
   50.75 +        return dst.isAssignableFrom(src);
   50.76 +    }
   50.77 +
   50.78 +    /**
   50.79 +     * Is the given type either java.lang.Void or java.lang.Null?
   50.80 +     * These types serve as markers for bare nulls and therefore
   50.81 +     * may be promoted to any type.  This is secure, since
   50.82 +     */
   50.83 +    public static boolean isNullType(Class<?> type) {
   50.84 +        if (type == null)  return false;
   50.85 +        return type == NULL_CLASS_1 || type == NULL_CLASS_2;
   50.86 +    }
   50.87 +    private static final Class<?> NULL_CLASS_1, NULL_CLASS_2;
   50.88 +    static {
   50.89 +        Class<?> nullClass1 = null, nullClass2 = null;
   50.90 +        try {
   50.91 +            nullClass1 = Class.forName("java.lang.Null");
   50.92 +        } catch (ClassNotFoundException ex) {
   50.93 +            // OK, we'll cope
   50.94 +        }
   50.95 +        NULL_CLASS_1 = nullClass1;
   50.96 +
   50.97 +        // This one may also be used as a null type.
   50.98 +        // TO DO: Decide if we really want to legitimize it here.
   50.99 +        // Probably we do, unless java.lang.Null really makes it into Java 7
  50.100 +        nullClass2 = Void.class;
  50.101 +        NULL_CLASS_2 = nullClass2;
  50.102 +    }
  50.103 +
  50.104 +    /**
  50.105 +     * True if a method handle can receive a call under a slightly different
  50.106 +     * method type, without moving or reformatting any stack elements.
  50.107 +     *
  50.108 +     * @param call the type of call being made
  50.109 +     * @param recv the type of the method handle receiving the call
  50.110 +     * @return whether the retyping can be done without motion or reformatting
  50.111 +     */
  50.112 +    public static boolean isNullConversion(MethodType call, MethodType recv) {
  50.113 +        if (call == recv)  return true;
  50.114 +        int len = call.parameterCount();
  50.115 +        if (len != recv.parameterCount())  return false;
  50.116 +        for (int i = 0; i < len; i++)
  50.117 +            if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
  50.118 +                return false;
  50.119 +        return isNullConversion(recv.returnType(), call.returnType());
  50.120 +    }
  50.121 +
  50.122 +    //TO DO: isRawConversion
  50.123 +
  50.124 +    /**
  50.125 +     * Determine if the JVM verifier allows a value of type call to be
  50.126 +     * passed to a formal parameter (or return variable) of type recv.
  50.127 +     * Returns 1 if the verifier allows the types to match without conversion.
  50.128 +     * Returns -1 if the types can be made to match by a JVM-supported adapter.
  50.129 +     * Cases supported are:
  50.130 +     * <ul><li>checkcast
  50.131 +     * </li><li>conversion between any two integral types (but not floats)
  50.132 +     * </li><li>unboxing from a wrapper to its corresponding primitive type
  50.133 +     * </li><li>conversion in either direction between float and double
  50.134 +     * </li></ul>
  50.135 +     * (Autoboxing is not supported here; it must be done via Java code.)
  50.136 +     * Returns 0 otherwise.
  50.137 +     */
  50.138 +    public static int canPassUnchecked(Class<?> src, Class<?> dst) {
  50.139 +        if (src == dst)
  50.140 +            return 1;
  50.141 +
  50.142 +        if (dst.isPrimitive()) {
  50.143 +            if (dst == void.class)
  50.144 +                // Return anything to a caller expecting void.
  50.145 +                // This is a property of the implementation, which links
  50.146 +                // return values via a register rather than via a stack push.
  50.147 +                // This makes it possible to ignore cleanly.
  50.148 +                return 1;
  50.149 +            if (src == void.class)
  50.150 +                return 0;  // void-to-something?
  50.151 +            if (!src.isPrimitive())
  50.152 +                // Cannot pass a reference to any primitive type (exc. void).
  50.153 +                return 0;
  50.154 +            Wrapper sw = Wrapper.forPrimitiveType(src);
  50.155 +            Wrapper dw = Wrapper.forPrimitiveType(dst);
  50.156 +            if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
  50.157 +                if (sw.bitWidth() >= dw.bitWidth())
  50.158 +                    return -1;   // truncation may be required
  50.159 +                if (!dw.isSigned() && sw.isSigned())
  50.160 +                    return -1;   // sign elimination may be required
  50.161 +            }
  50.162 +            if (src == float.class || dst == float.class) {
  50.163 +                if (src == double.class || dst == double.class)
  50.164 +                    return -1;   // floating conversion may be required
  50.165 +                else
  50.166 +                    return 0;    // other primitive conversions NYI
  50.167 +            } else {
  50.168 +                // all fixed-point conversions are supported
  50.169 +                return 0;
  50.170 +            }
  50.171 +        } else if (src.isPrimitive()) {
  50.172 +            // Cannot pass a primitive to any reference type.
  50.173 +            // (Maybe allow null.class?)
  50.174 +            return 0;
  50.175 +        }
  50.176 +
  50.177 +        // Handle reference types in the rest of the block:
  50.178 +
  50.179 +        // The verifier treats interfaces exactly like Object.
  50.180 +        if (isNullReferenceConversion(src, dst))
  50.181 +            // pass any reference to object or an arb. interface
  50.182 +            return 1;
  50.183 +        // else it's a definite "maybe" (cast is required)
  50.184 +        return -1;
  50.185 +    }
  50.186 +
  50.187 +    public static int canPassRaw(Class<?> src, Class<?> dst) {
  50.188 +        if (dst.isPrimitive()) {
  50.189 +            if (dst == void.class)
  50.190 +                // As above, return anything to a caller expecting void.
  50.191 +                return 1;
  50.192 +            if (src == void.class)
  50.193 +                // Special permission for raw conversions: allow a void
  50.194 +                // to be captured as a garbage int.
  50.195 +                // Caller promises that the actual value will be disregarded.
  50.196 +                return dst == int.class ? 1 : 0;
  50.197 +            if (!src.isPrimitive())
  50.198 +                return 0;
  50.199 +            Wrapper sw = Wrapper.forPrimitiveType(src);
  50.200 +            Wrapper dw = Wrapper.forPrimitiveType(dst);
  50.201 +            if (sw.stackSlots() == dw.stackSlots())
  50.202 +                return 1;  // can do a reinterpret-cast on a stacked primitive
  50.203 +            if (sw.isSubwordOrInt() && dw == Wrapper.VOID)
  50.204 +                return 1;  // can drop an outgoing int value
  50.205 +            return 0;
  50.206 +        } else if (src.isPrimitive()) {
  50.207 +            return 0;
  50.208 +        }
  50.209 +
  50.210 +        // Both references.
  50.211 +        if (isNullReferenceConversion(src, dst))
  50.212 +            return 1;
  50.213 +        return -1;
  50.214 +    }
  50.215 +
  50.216 +    public static boolean isSpreadArgType(Class<?> spreadArg) {
  50.217 +        return spreadArg.isArray();
  50.218 +    }
  50.219 +    public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
  50.220 +        return spreadArg.getComponentType();
  50.221 +    }
  50.222 +}
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/src/share/classes/sun/dyn/util/Wrapper.java	Thu May 07 12:26:22 2009 -0700
    51.3 @@ -0,0 +1,467 @@
    51.4 +/*
    51.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    51.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    51.7 + *
    51.8 + * This code is free software; you can redistribute it and/or modify it
    51.9 + * under the terms of the GNU General Public License version 2 only, as
   51.10 + * published by the Free Software Foundation.  Sun designates this
   51.11 + * particular file as subject to the "Classpath" exception as provided
   51.12 + * by Sun in the LICENSE file that accompanied this code.
   51.13 + *
   51.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   51.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   51.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   51.17 + * version 2 for more details (a copy is included in the LICENSE file that
   51.18 + * accompanied this code).
   51.19 + *
   51.20 + * You should have received a copy of the GNU General Public License version
   51.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   51.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   51.23 + *
   51.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   51.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   51.26 + * have any questions.
   51.27 + */
   51.28 +
   51.29 +package sun.dyn.util;
   51.30 +
   51.31 +public enum Wrapper {
   51.32 +    INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
   51.33 +    LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
   51.34 +    BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)),
   51.35 +    SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)),
   51.36 +    CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)),
   51.37 +    BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
   51.38 +    FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)),
   51.39 +    DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)),
   51.40 +    VOID(Void.class, void.class, 'V', null, Format.other(0)),
   51.41 +    //NULL(Null.class, null.class, 'N', null, Format.other(1)),
   51.42 +    OBJECT(Object.class, Object.class, 'L', null, Format.other(1)),
   51.43 +    ;
   51.44 +
   51.45 +    private final Class<?> wrapperType;
   51.46 +    private final Class<?> primitiveType;
   51.47 +    private final char     basicTypeChar;
   51.48 +    private final Object   zero;
   51.49 +    private final int      format;
   51.50 +    private final String   simpleName;
   51.51 +
   51.52 +    private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, int format) {
   51.53 +        this.wrapperType = wtype;
   51.54 +        this.primitiveType = ptype;
   51.55 +        this.basicTypeChar = tchar;
   51.56 +        this.zero = zero;
   51.57 +        this.format = format;
   51.58 +        this.simpleName = wtype.getSimpleName();
   51.59 +    }
   51.60 +
   51.61 +    private static abstract class Format {
   51.62 +        static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
   51.63 +        static final int
   51.64 +                SIGNED   = (-1) << KIND_SHIFT,
   51.65 +                UNSIGNED = 0    << KIND_SHIFT,
   51.66 +                FLOATING = 1    << KIND_SHIFT;
   51.67 +        static final int
   51.68 +                SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
   51.69 +                SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
   51.70 +        static int format(int kind, int size, int slots) {
   51.71 +            assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
   51.72 +            assert((size & (size-1)) == 0); // power of two
   51.73 +            assert((kind == SIGNED)   ? (size > 0) :
   51.74 +                   (kind == UNSIGNED) ? (size > 0) :
   51.75 +                   (kind == FLOATING) ? (size == 32 || size == 64)  :
   51.76 +                   false);
   51.77 +            assert((slots == 2) ? (size == 64) :
   51.78 +                   (slots == 1) ? (size <= 32) :
   51.79 +                   false);
   51.80 +            return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
   51.81 +        }
   51.82 +        static int
   51.83 +                INT      = SIGNED   | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   51.84 +                BOOLEAN  = UNSIGNED | (1  << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   51.85 +                FLOAT    = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   51.86 +                VOID     = UNSIGNED | (0  << SIZE_SHIFT) | (0 << SLOT_SHIFT),
   51.87 +                NUM_MASK = (-1) << SIZE_SHIFT;
   51.88 +        static int signed(int size)   { return format(SIGNED,   size, (size > 32 ? 2 : 1)); }
   51.89 +        static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
   51.90 +        static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
   51.91 +        static int other(int slots)   { return slots << SLOT_SHIFT; }
   51.92 +    }
   51.93 +
   51.94 +    /// format queries:
   51.95 +
   51.96 +    /** How many bits are in the wrapped value?  Returns 0 for OBJECT or VOID. */
   51.97 +    public int     bitWidth()      { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
   51.98 +    /** How many JVM stack slots occupied by the wrapped value?  Returns 0 for VOID. */
   51.99 +    public int     stackSlots()    { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
  51.100 +    /** Does the wrapped value occupy a single JVM stack slot? */
  51.101 +    public boolean isSingleWord()  { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
  51.102 +    /** Does the wrapped value occupy two JVM stack slots? */
  51.103 +    public boolean isDoubleWord()  { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
  51.104 +    /** Is the wrapped type numeric (not void or object)? */
  51.105 +    public boolean isNumeric()     { return (format & Format.NUM_MASK) != 0; }
  51.106 +    /** Is the wrapped type a primitive other than float, double, or void? */
  51.107 +    public boolean isIntegral()    { return isNumeric() && format < Format.FLOAT; }
  51.108 +    /** Is the wrapped type one of int, boolean, byte, char, or short? */
  51.109 +    public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
  51.110 +    /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
  51.111 +    public boolean isSigned()      { return format < Format.VOID; }
  51.112 +    /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
  51.113 +    public boolean isUnsigned()    { return format >= Format.BOOLEAN && format < Format.FLOAT; }
  51.114 +    /** Is the wrapped type either float or double? */
  51.115 +    public boolean isFloating()    { return format >= Format.FLOAT; }
  51.116 +
  51.117 +    /** Produce a zero value for the given wrapper type.
  51.118 +     *  This will be a numeric zero for a number or character,
  51.119 +     *  false for a boolean, and null for a reference or void.
  51.120 +     *  The common thread is that this is what is contained
  51.121 +     *  in a default-initialized variable of the given primitive
  51.122 +     *  type.  (For void, it is what a reflective method returns
  51.123 +     *  instead of no value at all.)
  51.124 +     */
  51.125 +    public Object zero() { return zero; }
  51.126 +
  51.127 +    /** Produce a zero value for the given wrapper type T.
  51.128 +     *  The optinoal argument must a type compatible with this wrapper.
  51.129 +     *  Equivalent to {@code this.cast(this.zero(), type)}.
  51.130 +     */
  51.131 +    public <T> T zero(Class<T> type) { return cast(zero, type); }
  51.132 +
  51.133 +//    /** Produce a wrapper for the given wrapper or primitive type. */
  51.134 +//    public static Wrapper valueOf(Class<?> type) {
  51.135 +//        if (isPrimitiveType(type))
  51.136 +//            return forPrimitiveType(type);
  51.137 +//        else
  51.138 +//            return forWrapperType(type);
  51.139 +//    }
  51.140 +
  51.141 +    /** Return the wrapper that wraps values of the given type.
  51.142 +     *  The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
  51.143 +     *  Otherwise, the type must be a primitive.
  51.144 +     *  @throws IllegalArgumentException for unexpected types
  51.145 +     */
  51.146 +    public static Wrapper forPrimitiveType(Class<?> type) {
  51.147 +        Wrapper w = FROM_PRIM[hashPrim(type)];
  51.148 +        if (w != null && w.primitiveType == type) {
  51.149 +            return w;
  51.150 +        }
  51.151 +        if (type.isPrimitive())
  51.152 +            throw new InternalError(); // redo hash function
  51.153 +        throw newIllegalArgumentException("not primitive: "+type);
  51.154 +    }
  51.155 +
  51.156 +    /** Return the wrapper that wraps values into the given wrapper type.
  51.157 +     *  If it is {@code Object} or an interface, return {@code OBJECT}.
  51.158 +     *  Otherwise, it must be a wrapper type.
  51.159 +     *  The type must not be a primitive type.
  51.160 +     *  @throws IllegalArgumentException for unexpected types
  51.161 +     */
  51.162 +    public static Wrapper forWrapperType(Class<?> type) {
  51.163 +        Wrapper w = findWrapperType(type);
  51.164 +        if (w != null)  return w;
  51.165 +        for (Wrapper x : values())
  51.166 +            if (w.wrapperType == type)
  51.167 +                throw new InternalError(); // redo hash function
  51.168 +        throw newIllegalArgumentException("not wrapper: "+type);
  51.169 +    }
  51.170 +
  51.171 +    static Wrapper findWrapperType(Class<?> type) {
  51.172 +        Wrapper w = FROM_WRAP[hashWrap(type)];
  51.173 +        if (w != null && w.wrapperType == type) {
  51.174 +            return w;
  51.175 +        }
  51.176 +        if (type.isInterface())
  51.177 +            return OBJECT;
  51.178 +        return null;
  51.179 +    }
  51.180 +
  51.181 +    /** Return the wrapper that corresponds to the given bytecode
  51.182 +     *  signature character.  Return {@code OBJECT} for the character 'L'.
  51.183 +     *  @throws IllegalArgumentException for any non-signature character or {@code '['}.
  51.184 +     */
  51.185 +    public static Wrapper forBasicType(char type) {
  51.186 +        Wrapper w = FROM_CHAR[hashChar(type)];
  51.187 +        if (w != null && w.basicTypeChar == type) {
  51.188 +            return w;
  51.189 +        }
  51.190 +        for (Wrapper x : values())
  51.191 +            if (w.basicTypeChar == type)
  51.192 +                throw new InternalError(); // redo hash function
  51.193 +        throw newIllegalArgumentException("not basic type char: "+type);
  51.194 +    }
  51.195 +
  51.196 +    /** Return the wrapper for the given type, if it is
  51.197 +     *  a primitive type, else return {@code OBJECT}.
  51.198 +     */
  51.199 +    public static Wrapper forBasicType(Class<?> type) {
  51.200 +        if (type.isPrimitive())
  51.201 +            return forPrimitiveType(type);
  51.202 +        return OBJECT;  // any reference, including wrappers or arrays
  51.203 +    }
  51.204 +
  51.205 +    // Note on perfect hashes:
  51.206 +    //   for signature chars c, do (c + (c >> 1)) % 16
  51.207 +    //   for primitive type names n, do (n[0] + n[2]) % 16
  51.208 +    // The type name hash works for both primitive and wrapper names.
  51.209 +    // You can add "java/lang/Object" to the primitive names.
  51.210 +    // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
  51.211 +    private static final Wrapper[] FROM_PRIM = new Wrapper[16];
  51.212 +    private static final Wrapper[] FROM_WRAP = new Wrapper[16];
  51.213 +    private static final Wrapper[] FROM_CHAR = new Wrapper[16];
  51.214 +    private static int hashPrim(Class<?> x) {
  51.215 +        String xn = x.getName();
  51.216 +        if (xn.length() < 3)  return 0;
  51.217 +        return (xn.charAt(0) + xn.charAt(2)) % 16;
  51.218 +    }
  51.219 +    private static int hashWrap(Class<?> x) {
  51.220 +        String xn = x.getName();
  51.221 +        final int offset = 10; assert(offset == "java.lang.".length());
  51.222 +        if (xn.length() < offset+3)  return 0;
  51.223 +        return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
  51.224 +    }
  51.225 +    private static int hashChar(char x) {
  51.226 +        return (x + (x >> 1)) % 16;
  51.227 +    }
  51.228 +    static {
  51.229 +        for (Wrapper w : values()) {
  51.230 +            int pi = hashPrim(w.primitiveType);
  51.231 +            int wi = hashWrap(w.wrapperType);
  51.232 +            int ci = hashChar(w.basicTypeChar);
  51.233 +            assert(FROM_PRIM[pi] == null);
  51.234 +            assert(FROM_WRAP[wi] == null);
  51.235 +            assert(FROM_CHAR[ci] == null);
  51.236 +            FROM_PRIM[pi] = w;
  51.237 +            FROM_WRAP[wi] = w;
  51.238 +            FROM_CHAR[ci] = w;
  51.239 +        }
  51.240 +        //assert(jdk.sun.dyn.util.WrapperTest.test(false));
  51.241 +    }
  51.242 +
  51.243 +    /** What is the primitive type wrapped by this wrapper? */
  51.244 +    public Class<?> primitiveType() { return primitiveType; }
  51.245 +
  51.246 +    /** What is the wrapper type for this wrapper? */
  51.247 +    public Class<?> wrapperType() { return wrapperType; }
  51.248 +
  51.249 +    /** What is the wrapper type for this wrapper?
  51.250 +     * The example type must be the wrapper type,
  51.251 +     * or the corresponding primitive type.
  51.252 +     * The resulting class type has the same type parameter.
  51.253 +     */
  51.254 +    public <T> Class<T> wrapperType(Class<T> exampleType) {
  51.255 +        if (exampleType == wrapperType) {
  51.256 +            return exampleType;
  51.257 +        } else if (exampleType == primitiveType ||
  51.258 +                   wrapperType == Object.class ||
  51.259 +                   exampleType.isInterface()) {
  51.260 +            return forceType(wrapperType, exampleType);
  51.261 +        }
  51.262 +        throw new ClassCastException(exampleType + " not <:" + wrapperType);
  51.263 +    }
  51.264 +
  51.265 +    /** If {@code type} is a primitive type, return the corresponding
  51.266 +     *  wrapper type, else return {@code type} unchanged.
  51.267 +     */
  51.268 +    public static <T> Class<T> asWrapperType(Class<T> type) {
  51.269 +        if (type.isPrimitive()) {
  51.270 +            return forPrimitiveType(type).wrapperType(type);
  51.271 +        }
  51.272 +        return type;
  51.273 +    }
  51.274 +
  51.275 +    /** If {@code type} is a wrapper type, return the corresponding
  51.276 +     *  primitive type, else return {@code type} unchanged.
  51.277 +     */
  51.278 +    public static <T> Class<T> asPrimitiveType(Class<T> type) {
  51.279 +        Wrapper w = findWrapperType(type);
  51.280 +        if (w != null) {
  51.281 +            return forceType(w.primitiveType(), type);
  51.282 +        }
  51.283 +        return type;
  51.284 +    }
  51.285 +
  51.286 +    /** Query:  Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
  51.287 +    public static boolean isWrapperType(Class<?> type) {
  51.288 +        return findWrapperType(type) != null;
  51.289 +    }
  51.290 +
  51.291 +    /** Query:  Is the given type a primitive, such as {@code int} or {@code void}? */
  51.292 +    public static boolean isPrimitiveType(Class<?> type) {
  51.293 +        return type.isPrimitive();
  51.294 +    }
  51.295 +
  51.296 +    /** What is the bytecode signature character for this wrapper's
  51.297 +     *  primitive type?
  51.298 +     */
  51.299 +    public char basicTypeChar() { return basicTypeChar; }
  51.300 +
  51.301 +    /** What is the simple name of the wrapper type?
  51.302 +     */
  51.303 +    public String simpleName() { return simpleName; }
  51.304 +
  51.305 +//    /** Wrap a value in the given type, which may be either a primitive or wrapper type.
  51.306 +//     *  Performs standard primitive conversions, including truncation and float conversions.
  51.307 +//     */
  51.308 +//    public static <T> T wrap(Object x, Class<T> type) {
  51.309 +//        return Wrapper.valueOf(type).cast(x, type);
  51.310 +//    }
  51.311 +
  51.312 +    /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
  51.313 +     *  Performs standard primitive conversions, including truncation and float conversions.
  51.314 +     *  The given type must be compatible with this wrapper.  That is, it must either
  51.315 +     *  be the wrapper type (or a subtype, in the case of {@code OBJECT} or else
  51.316 +     *  it must be the wrapper's primitive type.
  51.317 +     *  @throws ClassCastException if the given type is not compatible with this wrapper
  51.318 +     */
  51.319 +    public <T> T cast(Object x, Class<T> type) {
  51.320 +        Class<T> wtype = wrapperType(type);
  51.321 +        if (wtype.isInstance(x))
  51.322 +            return wtype.cast(x);
  51.323 +        return wtype.cast(wrap(x));
  51.324 +    }
  51.325 +
  51.326 +    /** Cast a reference type to another reference type.
  51.327 +     * If the target type is an interface, perform no runtime check.
  51.328 +     * (This loophole is safe, and is allowed by the JVM verifier.)
  51.329 +     * If the target type is a primitive, change it to a wrapper.
  51.330 +     */
  51.331 +    static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
  51.332 +        assert(type == exampleType ||
  51.333 +               type == asWrapperType(exampleType) ||
  51.334 +               type == Object.class && exampleType.isInterface());
  51.335 +        Class<T> result = (Class<T>) type;  // unchecked warning is expected here
  51.336 +        return result;
  51.337 +    }
  51.338 +
  51.339 +    /** Wrap a value in this wrapper's type.
  51.340 +     * Performs standard primitive conversions, including truncation and float conversions.
  51.341 +     * Performs returns the unchanged reference for {@code OBJECT}.
  51.342 +     * Returns null for {@code VOID}.
  51.343 +     * Returns a zero value for a null input.
  51.344 +     * @throws ClassCastException if this wrapper is numeric and the operand
  51.345 +     *                            is not a number, character, boolean, or null
  51.346 +     */
  51.347 +    public Object wrap(Object x) {
  51.348 +        // do non-numeric wrappers first
  51.349 +        switch (basicTypeChar) {
  51.350 +            case 'L': return x;
  51.351 +            case 'V': return null;
  51.352 +        }
  51.353 +        Number xn = numberValue(x);
  51.354 +        switch (basicTypeChar) {
  51.355 +            case 'I': return Integer.valueOf(xn.intValue());
  51.356 +            case 'J': return Long.valueOf(xn.longValue());
  51.357 +            case 'F': return Float.valueOf(xn.floatValue());
  51.358 +            case 'D': return Double.valueOf(xn.doubleValue());
  51.359 +            case 'S': return Short.valueOf((short) xn.intValue());
  51.360 +            case 'B': return Byte.valueOf((byte) xn.intValue());
  51.361 +            case 'C': return Character.valueOf((char) xn.intValue());
  51.362 +            case 'Z': return Boolean.valueOf(boolValue(xn.longValue()));
  51.363 +        }
  51.364 +        throw new InternalError("bad wrapper");
  51.365 +    }
  51.366 +
  51.367 +    /** Wrap a value (an int or smaller value) in this wrapper's type.
  51.368 +     * Performs standard primitive conversions, including truncation and float conversions.
  51.369 +     * Produces an {@code Integer} for {@code OBJECT}, although the exact type
  51.370 +     * of the operand is not known.
  51.371 +     * Returns null for {@code VOID}.
  51.372 +     */
  51.373 +    public Object wrap(int x) {
  51.374 +        if (basicTypeChar == 'L')  return (Integer)x;
  51.375 +        switch (basicTypeChar) {
  51.376 +            case 'L': throw newIllegalArgumentException("cannot wrap to object type");
  51.377 +            case 'V': return null;
  51.378 +            case 'I': return Integer.valueOf((int)x);
  51.379 +            case 'J': return Long.valueOf(x);
  51.380 +            case 'F': return Float.valueOf(x);
  51.381 +            case 'D': return Double.valueOf(x);
  51.382 +            case 'S': return Short.valueOf((short) x);
  51.383 +            case 'B': return Byte.valueOf((byte) x);
  51.384 +            case 'C': return Character.valueOf((char) x);
  51.385 +            case 'Z': return Boolean.valueOf(boolValue(x));
  51.386 +        }
  51.387 +        throw new InternalError("bad wrapper");
  51.388 +    }
  51.389 +
  51.390 +    /** Wrap a value (a long or smaller value) in this wrapper's type.
  51.391 +     * Does not perform floating point conversion.
  51.392 +     * Produces a {@code Long} for {@code OBJECT}, although the exact type
  51.393 +     * of the operand is not known.
  51.394 +     * Returns null for {@code VOID}.
  51.395 +     */
  51.396 +    public Object wrapRaw(long x) {
  51.397 +        switch (basicTypeChar) {
  51.398 +            case 'F':  return Float.valueOf(Float.intBitsToFloat((int)x));
  51.399 +            case 'D':  return Double.valueOf(Double.longBitsToDouble(x));
  51.400 +            case 'L':  // same as 'J':
  51.401 +            case 'J':  return (Long) x;
  51.402 +        }
  51.403 +        // Other wrapping operations are just the same, given that the
  51.404 +        // operand is already promoted to an int.
  51.405 +        return wrap((int)x);
  51.406 +    }
  51.407 +
  51.408 +    /** Produce bitwise value which encodes the given wrapped value.
  51.409 +     * Does not perform floating point conversion.
  51.410 +     * Returns zero for {@code VOID}.
  51.411 +     */
  51.412 +    public long unwrapRaw(Object x) {
  51.413 +        switch (basicTypeChar) {
  51.414 +            case 'F':  return Float.floatToRawIntBits((Float) x);
  51.415 +            case 'D':  return Double.doubleToRawLongBits((Double) x);
  51.416 +
  51.417 +            case 'L': throw newIllegalArgumentException("cannot unwrap from sobject type");
  51.418 +            case 'V': return 0;
  51.419 +            case 'I': return (int)(Integer) x;
  51.420 +            case 'J': return (long)(Long) x;
  51.421 +            case 'S': return (short)(Short) x;
  51.422 +            case 'B': return (byte)(Byte) x;
  51.423 +            case 'C': return (char)(Character) x;
  51.424 +            case 'Z': return (boolean)(Boolean) x ? 1 : 0;
  51.425 +        }
  51.426 +        throw new InternalError("bad wrapper");
  51.427 +    }
  51.428 +
  51.429 +    /** Report what primitive type holds this guy's raw value. */
  51.430 +    public Class<?> rawPrimitiveType() {
  51.431 +        return rawPrimitive().primitiveType();
  51.432 +    }
  51.433 +
  51.434 +    /** Report, as a wrapper, what primitive type holds this guy's raw value.
  51.435 +     *  Returns self for INT, LONG, OBJECT; returns LONG for DOUBLE,
  51.436 +     *  else returns INT.
  51.437 +     */
  51.438 +    public Wrapper rawPrimitive() {
  51.439 +        switch (basicTypeChar) {
  51.440 +            case 'S': case 'B':
  51.441 +            case 'C': case 'Z':
  51.442 +            case 'V':
  51.443 +            case 'F':
  51.444 +                return INT;
  51.445 +            case 'D':
  51.446 +                return LONG;
  51.447 +        }
  51.448 +        return this;
  51.449 +    }
  51.450 +
  51.451 +    private static Number numberValue(Object x) {
  51.452 +        if (x instanceof Number)     return (Number)x;
  51.453 +        if (x instanceof Character)  return (int)(Character)x;
  51.454 +        if (x instanceof Boolean)    return (Boolean)x ? 1 : 0;
  51.455 +        // Remaining allowed case of void:  Must be a null reference.
  51.456 +        return (Number)x;
  51.457 +    }
  51.458 +
  51.459 +    private static boolean boolValue(long bits) {
  51.460 +        //bits &= 1;  // simple 31-bit zero extension
  51.461 +        return (bits != 0);
  51.462 +    }
  51.463 +
  51.464 +    private static RuntimeException newIllegalArgumentException(String message, Object x) {
  51.465 +        return newIllegalArgumentException(message + x);
  51.466 +    }
  51.467 +    private static RuntimeException newIllegalArgumentException(String message) {
  51.468 +        return new IllegalArgumentException(message);
  51.469 +    }
  51.470 +}
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/src/share/classes/sun/dyn/util/package-info.java	Thu May 07 12:26:22 2009 -0700
    52.3 @@ -0,0 +1,31 @@
    52.4 +/*
    52.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    52.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    52.7 + *
    52.8 + * This code is free software; you can redistribute it and/or modify it
    52.9 + * under the terms of the GNU General Public License version 2 only, as
   52.10 + * published by the Free Software Foundation.  Sun designates this
   52.11 + * particular file as subject to the "Classpath" exception as provided
   52.12 + * by Sun in the LICENSE file that accompanied this code.
   52.13 + *
   52.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   52.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   52.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   52.17 + * version 2 for more details (a copy is included in the LICENSE file that
   52.18 + * accompanied this code).
   52.19 + *
   52.20 + * You should have received a copy of the GNU General Public License version
   52.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   52.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   52.23 + *
   52.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   52.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
   52.26 + * have any questions.
   52.27 + */
   52.28 +
   52.29 +/**
   52.30 + * Extra support for using JSR 292 RI, package java.dyn.
   52.31 + * @author jrose
   52.32 + */
   52.33 +
   52.34 +package sun.dyn.util;
    53.1 --- a/src/share/classes/sun/misc/JavaLangAccess.java	Thu May 07 10:31:32 2009 -0700
    53.2 +++ b/src/share/classes/sun/misc/JavaLangAccess.java	Thu May 07 12:26:22 2009 -0700
    53.3 @@ -55,6 +55,22 @@
    53.4      /** Set thread's blocker field. */
    53.5      void blockedOn(Thread t, Interruptible b);
    53.6  
    53.7 -    /** register shutdown hook */
    53.8 -    void registerShutdownHook(int slot, Runnable r);
    53.9 +    /**
   53.10 +     * Registers a shutdown hook.
   53.11 +     *
   53.12 +     * It is expected that this method with registerShutdownInProgress=true
   53.13 +     * is only used to register DeleteOnExitHook since the first file
   53.14 +     * may be added to the delete on exit list by the application shutdown
   53.15 +     * hooks.
   53.16 +     *
   53.17 +     * @params slot  the slot in the shutdown hook array, whose element
   53.18 +     *               will be invoked in order during shutdown
   53.19 +     * @params registerShutdownInProgress true to allow the hook
   53.20 +     *               to be registered even if the shutdown is in progress.
   53.21 +     * @params hook  the hook to be registered
   53.22 +     *
   53.23 +     * @throw IllegalStateException if shutdown is in progress and
   53.24 +     *          the slot is not valid to register.
   53.25 +     */
   53.26 +    void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook);
   53.27  }
    54.1 --- a/src/share/classes/sun/misc/Unsafe.java	Thu May 07 10:31:32 2009 -0700
    54.2 +++ b/src/share/classes/sun/misc/Unsafe.java	Thu May 07 12:26:22 2009 -0700
    54.3 @@ -1,5 +1,5 @@
    54.4  /*
    54.5 - * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
    54.6 + * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
    54.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    54.8   *
    54.9   * This code is free software; you can redistribute it and/or modify it
   54.10 @@ -811,6 +811,25 @@
   54.11  
   54.12      public native Class defineClass(String name, byte[] b, int off, int len);
   54.13  
   54.14 +    /**
   54.15 +     * Define a class but do not make it known to the class loader or system dictionary.
   54.16 +     * <p>
   54.17 +     * For each CP entry, the corresponding CP patch must either be null or have
   54.18 +     * the a format that matches its tag:
   54.19 +     * <ul>
   54.20 +     * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang
   54.21 +     * <li>Utf8: a string (must have suitable syntax if used as signature or name)
   54.22 +     * <li>Class: any java.lang.Class object
   54.23 +     * <li>String: any object (not just a java.lang.String)
   54.24 +     * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments
   54.25 +     * </ul>
   54.26 +     * @params hostClass context for linkage, access control, protection domain, and class loader
   54.27 +     * @params data      bytes of a class file
   54.28 +     * @params cpPatches where non-null entries exist, they replace corresponding CP entries in data
   54.29 +     */
   54.30 +    public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches);
   54.31 +
   54.32 +
   54.33      /** Allocate an instance but do not run any constructor.
   54.34          Initializes the class if it has not yet been. */
   54.35      public native Object allocateInstance(Class cls)
    55.1 --- a/src/share/javavm/export/classfile_constants.h	Thu May 07 10:31:32 2009 -0700
    55.2 +++ b/src/share/javavm/export/classfile_constants.h	Thu May 07 12:26:22 2009 -0700
    55.3 @@ -1,5 +1,5 @@
    55.4  /*
    55.5 - * Copyright 2004-2005 Sun Microsystems, Inc.  All Rights Reserved.
    55.6 + * Copyright 2004-2009 Sun Microsystems, Inc.  All Rights Reserved.
    55.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    55.8   *
    55.9   * This code is free software; you can redistribute it and/or modify it
   55.10 @@ -306,7 +306,7 @@
   55.11      JVM_OPC_invokespecial       = 183,
   55.12      JVM_OPC_invokestatic        = 184,
   55.13      JVM_OPC_invokeinterface     = 185,
   55.14 -    JVM_OPC_xxxunusedxxx        = 186,
   55.15 +    JVM_OPC_invokedynamic       = 186,
   55.16      JVM_OPC_new                 = 187,
   55.17      JVM_OPC_newarray            = 188,
   55.18      JVM_OPC_anewarray           = 189,
   55.19 @@ -515,7 +515,7 @@
   55.20     3,   /* invokespecial */             \
   55.21     3,   /* invokestatic */              \
   55.22     5,   /* invokeinterface */           \
   55.23 -   0,   /* xxxunusedxxx */              \
   55.24 +   5,   /* invokedynamic */             \
   55.25     3,   /* new */                       \
   55.26     2,   /* newarray */                  \
   55.27     3,   /* anewarray */                 \
    56.1 --- a/src/share/native/common/check_code.c	Thu May 07 10:31:32 2009 -0700
    56.2 +++ b/src/share/native/common/check_code.c	Thu May 07 12:26:22 2009 -0700
    56.3 @@ -1,5 +1,5 @@
    56.4  /*
    56.5 - * Copyright 1994-2008 Sun Microsystems, Inc.  All Rights Reserved.
    56.6 + * Copyright 1994-2009 Sun Microsystems, Inc.  All Rights Reserved.
    56.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    56.8   *
    56.9   * This code is free software; you can redistribute it and/or modify it
   56.10 @@ -1223,16 +1223,20 @@
   56.11      case JVM_OPC_invokevirtual:
   56.12      case JVM_OPC_invokespecial:
   56.13      case JVM_OPC_invokestatic:
   56.14 +    case JVM_OPC_invokedynamic:
   56.15      case JVM_OPC_invokeinterface: {
   56.16          /* Make sure the constant pool item is the right type. */
   56.17          int key = (code[offset + 1] << 8) + code[offset + 2];
   56.18          const char *methodname;
   56.19          jclass cb = context->class;
   56.20          fullinfo_type clazz_info;
   56.21 -        int is_constructor, is_internal;
   56.22 +        int is_constructor, is_internal, is_invokedynamic;
   56.23          int kind = (opcode == JVM_OPC_invokeinterface
   56.24                              ? 1 << JVM_CONSTANT_InterfaceMethodref
   56.25 +                  : opcode == JVM_OPC_invokedynamic
   56.26 +                            ? 1 << JVM_CONSTANT_NameAndType
   56.27                              : 1 << JVM_CONSTANT_Methodref);
   56.28 +        is_invokedynamic = opcode == JVM_OPC_invokedynamic;
   56.29          /* Make sure the constant pool item is the right type. */
   56.30          verify_constant_pool_type(context, key, kind);
   56.31          methodname = JVM_GetCPMethodNameUTF(env, cb, key);
   56.32 @@ -1241,8 +1245,11 @@
   56.33          is_internal = methodname[0] == '<';
   56.34          pop_and_free(context);
   56.35  
   56.36 -        clazz_info = cp_index_to_class_fullinfo(context, key,
   56.37 -                                                JVM_CONSTANT_Methodref);
   56.38 +        if (is_invokedynamic)
   56.39 +          clazz_info = context->object_info;  // anything will do
   56.40 +        else
   56.41 +          clazz_info = cp_index_to_class_fullinfo(context, key,
   56.42 +                                                  JVM_CONSTANT_Methodref);
   56.43          this_idata->operand.i = key;
   56.44          this_idata->operand2.fi = clazz_info;
   56.45          if (is_constructor) {
   56.46 @@ -1304,6 +1311,11 @@
   56.47                          "Fourth operand byte of invokeinterface must be zero");
   56.48              }
   56.49              pop_and_free(context);
   56.50 +        } else if (opcode == JVM_OPC_invokedynamic) {
   56.51 +            if (code[offset + 3] != 0 || code[offset + 4] != 0) {
   56.52 +                CCerror(context,
   56.53 +                        "Third and fourth operand bytes of invokedynamic must be zero");
   56.54 +            }
   56.55          } else if (opcode == JVM_OPC_invokevirtual
   56.56                        || opcode == JVM_OPC_invokespecial)
   56.57              set_protected(context, inumber, key, opcode);
   56.58 @@ -1990,6 +2002,7 @@
   56.59  
   56.60          case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial:
   56.61          case JVM_OPC_invokeinit:    /* invokespecial call to <init> */
   56.62 +        case JVM_OPC_invokedynamic:
   56.63          case JVM_OPC_invokestatic: case JVM_OPC_invokeinterface: {
   56.64              /* The top stuff on the stack depends on the method signature */
   56.65              int operand = this_idata->operand.i;
   56.66 @@ -2005,7 +2018,8 @@
   56.67                  print_formatted_methodname(context, operand);
   56.68              }
   56.69  #endif
   56.70 -            if (opcode != JVM_OPC_invokestatic)
   56.71 +            if (opcode != JVM_OPC_invokestatic &&
   56.72 +                opcode != JVM_OPC_invokedynamic)
   56.73                  /* First, push the object */
   56.74                  *ip++ = (opcode == JVM_OPC_invokeinit ? '@' : 'A');
   56.75              for (p = signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) {
   56.76 @@ -2290,6 +2304,7 @@
   56.77  
   56.78          case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial:
   56.79          case JVM_OPC_invokeinit:
   56.80 +        case JVM_OPC_invokedynamic:
   56.81          case JVM_OPC_invokeinterface: case JVM_OPC_invokestatic: {
   56.82              int operand = this_idata->operand.i;
   56.83              const char *signature =
   56.84 @@ -2299,7 +2314,8 @@
   56.85              int item;
   56.86              const char *p;
   56.87              check_and_push(context, signature, VM_STRING_UTF);
   56.88 -            if (opcode == JVM_OPC_invokestatic) {
   56.89 +            if (opcode == JVM_OPC_invokestatic ||
   56.90 +                opcode == JVM_OPC_invokedynamic) {
   56.91                  item = 0;
   56.92              } else if (opcode == JVM_OPC_invokeinit) {
   56.93                  fullinfo_type init_type = this_idata->operand2.fi;
   56.94 @@ -2680,6 +2696,7 @@
   56.95  
   56.96          case JVM_OPC_invokevirtual: case JVM_OPC_invokespecial:
   56.97          case JVM_OPC_invokeinit:
   56.98 +        case JVM_OPC_invokedynamic:
   56.99          case JVM_OPC_invokestatic: case JVM_OPC_invokeinterface: {
  56.100              /* Look to signature to determine correct result. */
  56.101              int operand = this_idata->operand.i;
    57.1 --- a/src/share/native/common/opcodes.in_out	Thu May 07 10:31:32 2009 -0700
    57.2 +++ b/src/share/native/common/opcodes.in_out	Thu May 07 12:26:22 2009 -0700
    57.3 @@ -1,5 +1,5 @@
    57.4  /* 
    57.5 - * Copyright 1998 Sun Microsystems, Inc.  All Rights Reserved.
    57.6 + * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
    57.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    57.8   *
    57.9   * This code is free software; you can redistribute it and/or modify it
   57.10 @@ -210,7 +210,7 @@
   57.11     {"?", "?"}, 		/* invokespecial */
   57.12     {"?", "?"}, 		/* invokestatic */
   57.13     {"?", "?"}, 		/* invokeinterface */
   57.14 -   {"?", "?"}, 		/* xxxunusedxxx */
   57.15 +   {"?", "?"}, 		/* invokedynamic */
   57.16     {"", "A"}, 		/* new */
   57.17     {"I", "A"}, 		/* newarray */
   57.18     {"I", "A"}, 		/* anewarray */
    58.1 --- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Thu May 07 10:31:32 2009 -0700
    58.2 +++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Thu May 07 12:26:22 2009 -0700
    58.3 @@ -475,49 +475,40 @@
    58.4                  // get an OVERLAPPED structure (from the cache or allocate)
    58.5                  overlapped = ioCache.add(result);
    58.6  
    58.7 -                // synchronize on result to allow this thread handle the case
    58.8 -                // where the read completes immediately.
    58.9 -                synchronized (result) {
   58.10 -                    int n = read0(handle, numBufs, readBufferArray, overlapped);
   58.11 -                    if (n == IOStatus.UNAVAILABLE) {
   58.12 -                        // I/O is pending
   58.13 -                        pending = true;
   58.14 -                        return;
   58.15 +                // initiate read
   58.16 +                int n = read0(handle, numBufs, readBufferArray, overlapped);
   58.17 +                if (n == IOStatus.UNAVAILABLE) {
   58.18 +                    // I/O is pending
   58.19 +                    pending = true;
   58.20 +                    return;
   58.21 +                }
   58.22 +                if (n == IOStatus.EOF) {
   58.23 +                    // input shutdown
   58.24 +                    enableReading();
   58.25 +                    if (scatteringRead) {
   58.26 +                        result.setResult((V)Long.valueOf(-1L));
   58.27 +                    } else {
   58.28 +                        result.setResult((V)Integer.valueOf(-1));
   58.29                      }
   58.30 -                    // read completed immediately:
   58.31 -                    // 1. update buffer position
   58.32 -                    // 2. reset read flag
   58.33 -                    // 3. release waiters
   58.34 -                    if (n == 0) {
   58.35 -                        n = -1;
   58.36 -                    } else {
   58.37 -                        updateBuffers(n);
   58.38 -                    }
   58.39 -                    enableReading();
   58.40 -
   58.41 -                    if (scatteringRead) {
   58.42 -                        result.setResult((V)Long.valueOf(n));
   58.43 -                    } else {
   58.44 -                        result.setResult((V)Integer.valueOf(n));
   58.45 -                    }
   58.46 +                } else {
   58.47 +                    throw new InternalError("Read completed immediately");
   58.48                  }
   58.49              } catch (Throwable x) {
   58.50 -                // failed to initiate read:
   58.51 -                // 1. reset read flag
   58.52 -                // 2. free resources
   58.53 -                // 3. release waiters
   58.54 +                // failed to initiate read
   58.55 +                // reset read flag before releasing waiters
   58.56                  enableReading();
   58.57 -                if (overlapped != 0L)
   58.58 -                    ioCache.remove(overlapped);
   58.59                  if (x instanceof ClosedChannelException)
   58.60                      x = new AsynchronousCloseException();
   58.61                  if (!(x instanceof IOException))
   58.62                      x = new IOException(x);
   58.63                  result.setFailure(x);
   58.64              } finally {
   58.65 -                if (prepared && !pending) {
   58.66 -                    // return direct buffer(s) to cache if substituted
   58.67 -                    releaseBuffers();
   58.68 +                // release resources if I/O not pending
   58.69 +                if (!pending) {
   58.70 +                    if (overlapped != 0L)
   58.71 +                        ioCache.remove(overlapped);
   58.72 +                    if (prepared)
   58.73 +                        releaseBuffers();
   58.74                  }
   58.75                  end();
   58.76              }
   58.77 @@ -721,7 +712,6 @@
   58.78          @Override
   58.79          @SuppressWarnings("unchecked")
   58.80          public void run() {
   58.81 -            int n = -1;
   58.82              long overlapped = 0L;
   58.83              boolean prepared = false;
   58.84              boolean pending = false;
   58.85 @@ -736,56 +726,34 @@
   58.86  
   58.87                  // get an OVERLAPPED structure (from the cache or allocate)
   58.88                  overlapped = ioCache.add(result);
   58.89 -
   58.90 -                // synchronize on result to allow this thread handle the case
   58.91 -                // where the read completes immediately.
   58.92 -                synchronized (result) {
   58.93 -                    n = write0(handle, numBufs, writeBufferArray, overlapped);
   58.94 -                    if (n == IOStatus.UNAVAILABLE) {
   58.95 -                        // I/O is pending
   58.96 -                        pending = true;
   58.97 -                        return;
   58.98 -                    }
   58.99 -
  58.100 -                    enableWriting();
  58.101 -
  58.102 -                    if (n == IOStatus.EOF) {
  58.103 -                        // special case for shutdown output
  58.104 -                        shutdown = true;
  58.105 -                        throw new ClosedChannelException();
  58.106 -                    }
  58.107 -
  58.108 -                    // write completed immediately:
  58.109 -                    // 1. enable writing
  58.110 -                    // 2. update buffer position
  58.111 -                    // 3. release waiters
  58.112 -                    updateBuffers(n);
  58.113 -
  58.114 -                    // result is a Long or Integer
  58.115 -                    if (gatheringWrite) {
  58.116 -                        result.setResult((V)Long.valueOf(n));
  58.117 -                    } else {
  58.118 -                        result.setResult((V)Integer.valueOf(n));
  58.119 -                    }
  58.120 +                int n = write0(handle, numBufs, writeBufferArray, overlapped);
  58.121 +                if (n == IOStatus.UNAVAILABLE) {
  58.122 +                    // I/O is pending
  58.123 +                    pending = true;
  58.124 +                    return;
  58.125                  }
  58.126 +                if (n == IOStatus.EOF) {
  58.127 +                    // special case for shutdown output
  58.128 +                    shutdown = true;
  58.129 +                    throw new ClosedChannelException();
  58.130 +                }
  58.131 +                // write completed immediately
  58.132 +                throw new InternalError("Write completed immediately");
  58.133              } catch (Throwable x) {
  58.134 +                // write failed. Enable writing before releasing waiters.
  58.135                  enableWriting();
  58.136 -
  58.137 -                // failed to initiate read:
  58.138                  if (!shutdown && (x instanceof ClosedChannelException))
  58.139                      x = new AsynchronousCloseException();
  58.140                  if (!(x instanceof IOException))
  58.141                      x = new IOException(x);
  58.142                  result.setFailure(x);
  58.143 -
  58.144 -                // release resources
  58.145 -                if (overlapped != 0L)
  58.146 -                    ioCache.remove(overlapped);
  58.147 -
  58.148              } finally {
  58.149 -                if (prepared && !pending) {
  58.150 -                    // return direct buffer(s) to cache if substituted
  58.151 -                    releaseBuffers();
  58.152 +                // release resources if I/O not pending
  58.153 +                if (!pending) {
  58.154 +                    if (overlapped != 0L)
  58.155 +                        ioCache.remove(overlapped);
  58.156 +                    if (prepared)
  58.157 +                        releaseBuffers();
  58.158                  }
  58.159                  end();
  58.160              }
    59.1 --- a/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c	Thu May 07 10:31:32 2009 -0700
    59.2 +++ b/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c	Thu May 07 12:26:22 2009 -0700
    59.3 @@ -157,14 +157,13 @@
    59.4      WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address);
    59.5      OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
    59.6      BOOL res;
    59.7 -    DWORD nread = 0;
    59.8      DWORD flags = 0;
    59.9  
   59.10      ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
   59.11      res = WSARecv(s,
   59.12                    lpWsaBuf,
   59.13                    (DWORD)count,
   59.14 -                  &nread,
   59.15 +                  NULL,
   59.16                    &flags,
   59.17                    lpOverlapped,
   59.18                    NULL);
   59.19 @@ -175,17 +174,12 @@
   59.20              return IOS_UNAVAILABLE;
   59.21          }
   59.22          if (error == WSAESHUTDOWN) {
   59.23 -            return 0;       // input shutdown
   59.24 +            return IOS_EOF;       // input shutdown
   59.25          }
   59.26          JNU_ThrowIOExceptionWithLastError(env, "WSARecv failed");
   59.27          return IOS_THROWN;
   59.28      }
   59.29 -    if (nread == 0) {
   59.30 -        // Handle graceful close or bytes not yet available cases
   59.31 -        // via completion port notification.
   59.32 -        return IOS_UNAVAILABLE;
   59.33 -    }
   59.34 -    return (jint)nread;
   59.35 +    return IOS_UNAVAILABLE;
   59.36  }
   59.37  
   59.38  JNIEXPORT jint JNICALL
   59.39 @@ -196,13 +190,12 @@
   59.40      WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address);
   59.41      OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
   59.42      BOOL res;
   59.43 -    DWORD nwritten;
   59.44  
   59.45      ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
   59.46      res = WSASend(s,
   59.47                    lpWsaBuf,
   59.48                    (DWORD)count,
   59.49 -                  &nwritten,
   59.50 +                  NULL,
   59.51                    0,
   59.52                    lpOverlapped,
   59.53                    NULL);
   59.54 @@ -218,5 +211,5 @@
   59.55          JNU_ThrowIOExceptionWithLastError(env, "WSASend failed");
   59.56          return IOS_THROWN;
   59.57      }
   59.58 -    return (jint)nwritten;
   59.59 +    return IOS_UNAVAILABLE;
   59.60  }
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/test/java/lang/Runtime/shutdown/ShutdownHooks.java	Thu May 07 12:26:22 2009 -0700
    60.3 @@ -0,0 +1,69 @@
    60.4 +/*
    60.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    60.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    60.7 + *
    60.8 + * This code is free software; you can redistribute it and/or modify it
    60.9 + * under the terms of the GNU General Public License version 2 only, as
   60.10 + * published by the Free Software Foundation.
   60.11 + *
   60.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   60.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   60.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   60.15 + * version 2 for more details (a copy is included in the LICENSE file that
   60.16 + * accompanied this code).
   60.17 + *
   60.18 + * You should have received a copy of the GNU General Public License version
   60.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   60.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   60.21 + *
   60.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   60.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   60.24 + * have any questions.
   60.25 + */
   60.26 +
   60.27 +/*
   60.28 + * @bug      6829503
   60.29 + * @summary  1) Test Console and DeleteOnExitHook can be initialized
   60.30 + *              while shutdown is in progress
   60.31 + *           2) Test if files that are added by the application shutdown
   60.32 + *              hook are deleted on exit during shutdown
   60.33 + */
   60.34 +import java.io.*;
   60.35 +public class ShutdownHooks {
   60.36 +    private static File file;
   60.37 +    public static void main(String[] args) throws Exception {
   60.38 +        if (args.length != 2) {
   60.39 +            throw new IllegalArgumentException("Usage: ShutdownHooks <dir> <filename>");
   60.40 +        }
   60.41 +
   60.42 +        // Add a shutdown hook
   60.43 +        Runtime.getRuntime().addShutdownHook(new Cleaner());
   60.44 +
   60.45 +        File dir = new File(args[0]);
   60.46 +        file = new File(dir, args[1]);
   60.47 +        // write to file
   60.48 +        System.out.println("writing to "+ file);
   60.49 +        PrintWriter pw = new PrintWriter(file);
   60.50 +        pw.println("Shutdown begins");
   60.51 +        pw.close();
   60.52 +    }
   60.53 +
   60.54 +    public static class Cleaner extends Thread {
   60.55 +        public void run() {
   60.56 +            // register the Console's shutdown hook while the application
   60.57 +            // shutdown hook is running
   60.58 +            Console cons = System.console();
   60.59 +            // register the DeleteOnExitHook while the application
   60.60 +            // shutdown hook is running
   60.61 +            file.deleteOnExit();
   60.62 +            try {
   60.63 +                PrintWriter pw = new PrintWriter(file);
   60.64 +                pw.println("file is being deleted");
   60.65 +                pw.close();
   60.66 +            } catch (FileNotFoundException e) {
   60.67 +                throw new RuntimeException(e);
   60.68 +            }
   60.69 +        }
   60.70 +    }
   60.71 +
   60.72 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/test/java/lang/Runtime/shutdown/ShutdownHooks.sh	Thu May 07 12:26:22 2009 -0700
    61.3 @@ -0,0 +1,57 @@
    61.4 +#!/bin/sh
    61.5 +
    61.6 +#
    61.7 +# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    61.8 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    61.9 +#
   61.10 +# This code is free software; you can redistribute it and/or modify it
   61.11 +# under the terms of the GNU General Public License version 2 only, as
   61.12 +# published by the Free Software Foundation.
   61.13 +#
   61.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
   61.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   61.16 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   61.17 +# version 2 for more details (a copy is included in the LICENSE file that
   61.18 +# accompanied this code).
   61.19 +#
   61.20 +# You should have received a copy of the GNU General Public License version
   61.21 +# 2 along with this work; if not, write to the Free Software Foundation,
   61.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   61.23 +#
   61.24 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   61.25 +# CA 95054 USA or visit www.sun.com if you need additional information or
   61.26 +# have any questions.
   61.27 +#
   61.28 +
   61.29 +
   61.30 +# @test
   61.31 +# @bug 6829503
   61.32 +# @summary  1) Test Console and DeleteOnExitHook can be initialized
   61.33 +#              while shutdown is in progress
   61.34 +#           2) Test if files that are added by the application shutdown
   61.35 +#              hook are deleted on exit during shutdown
   61.36 +#
   61.37 +# @build ShutdownHooks 
   61.38 +# @run shell ShutdownHooks.sh
   61.39 +
   61.40 +if [ "${TESTJAVA}" = "" ]
   61.41 +then
   61.42 +  echo "TESTJAVA not set.  Test cannot execute.  Failed."
   61.43 +  exit 1
   61.44 +fi
   61.45 +
   61.46 +FILENAME=fileToBeDeleted
   61.47 +rm -f ${TESTCLASSES}/${FILENAME}
   61.48 +
   61.49 +# create the file to be deleted on exit
   61.50 +echo "testing shutdown" > ${TESTCLASSES}/${FILENAME}
   61.51 +
   61.52 +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} ShutdownHooks ${TESTCLASSES} $FILENAME 
   61.53 +if [ $? != 0 ] ; then
   61.54 +  echo "Test Failed"; exit 1
   61.55 +fi
   61.56 +
   61.57 +if [ -f ${TESTCLASSES}/${FILENAME} ]; then
   61.58 +  echo "Test Failed: ${TESTCLASSES}/${FILENAME} not deleted"; exit 2
   61.59 +fi
   61.60 +echo "ShutdownHooks test passed.";
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java	Thu May 07 12:26:22 2009 -0700
    62.3 @@ -0,0 +1,183 @@
    62.4 +/*
    62.5 + * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
    62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    62.7 + *
    62.8 + * This code is free software; you can redistribute it and/or modify it
    62.9 + * under the terms of the GNU General Public License version 2 only, as
   62.10 + * published by the Free Software Foundation.
   62.11 + *
   62.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   62.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   62.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   62.15 + * version 2 for more details (a copy is included in the LICENSE file that
   62.16 + * accompanied this code).
   62.17 + *
   62.18 + * You should have received a copy of the GNU General Public License version
   62.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   62.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   62.21 + *
   62.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   62.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   62.24 + * have any questions.
   62.25 + */
   62.26 +
   62.27 +/* @test
   62.28 + * @bug 6834246
   62.29 + * @summary Stress test connections through the loopback interface
   62.30 + */
   62.31 +
   62.32 +import java.nio.ByteBuffer;
   62.33 +import java.net.*;
   62.34 +import java.nio.channels.*;
   62.35 +import java.util.Random;
   62.36 +import java.io.IOException;
   62.37 +
   62.38 +public class StressLoopback {
   62.39 +    static final Random rand = new Random();
   62.40 +
   62.41 +    public static void main(String[] args) throws Exception {
   62.42 +        // setup listener
   62.43 +        AsynchronousServerSocketChannel listener =
   62.44 +            AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
   62.45 +        int port =((InetSocketAddress)(listener.getLocalAddress())).getPort();
   62.46 +        InetAddress lh = InetAddress.getLocalHost();
   62.47 +        SocketAddress remote = new InetSocketAddress(lh, port);
   62.48 +
   62.49 +        // create sources and sinks
   62.50 +        int count = 2 + rand.nextInt(9);
   62.51 +        Source[] source = new Source[count];
   62.52 +        Sink[] sink = new Sink[count];
   62.53 +        for (int i=0; i<count; i++) {
   62.54 +            AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
   62.55 +            ch.connect(remote).get();
   62.56 +            source[i] = new Source(ch);
   62.57 +            sink[i] = new Sink(listener.accept().get());
   62.58 +        }
   62.59 +
   62.60 +        // start the sinks and sources
   62.61 +        for (int i=0; i<count; i++) {
   62.62 +            sink[i].start();
   62.63 +            source[i].start();
   62.64 +        }
   62.65 +
   62.66 +        // let the test run for a while
   62.67 +        Thread.sleep(20*1000);
   62.68 +
   62.69 +        // wait until everyone is done
   62.70 +        boolean failed = false;
   62.71 +        long total = 0L;
   62.72 +        for (int i=0; i<count; i++) {
   62.73 +            long nwrote = source[i].finish();
   62.74 +            long nread = sink[i].finish();
   62.75 +            if (nread != nwrote)
   62.76 +                failed = true;
   62.77 +            System.out.format("%d -> %d (%s)\n",
   62.78 +                nwrote, nread, (failed) ? "FAIL" : "PASS");
   62.79 +            total += nwrote;
   62.80 +        }
   62.81 +        if (failed)
   62.82 +            throw new RuntimeException("Test failed - see log for details");
   62.83 +        System.out.format("Total sent %d MB\n", total / (1024L * 1024L));
   62.84 +    }
   62.85 +
   62.86 +    /**
   62.87 +     * Writes bytes to a channel until "done". When done the channel is closed.
   62.88 +     */
   62.89 +    static class Source {
   62.90 +        private final AsynchronousByteChannel channel;
   62.91 +        private final ByteBuffer sentBuffer;
   62.92 +        private volatile long bytesSent;
   62.93 +        private volatile boolean finished;
   62.94 +
   62.95 +        Source(AsynchronousByteChannel channel) {
   62.96 +            this.channel = channel;
   62.97 +            int size = 1024 + rand.nextInt(10000);
   62.98 +            this.sentBuffer = (rand.nextBoolean()) ?
   62.99 +                ByteBuffer.allocateDirect(size) : ByteBuffer.allocate(size);
  62.100 +        }
  62.101 +
  62.102 +        void start() {
  62.103 +            sentBuffer.position(0);
  62.104 +            sentBuffer.limit(sentBuffer.capacity());
  62.105 +            channel.write(sentBuffer, null, new CompletionHandler<Integer,Void> () {
  62.106 +                public void completed(Integer nwrote, Void att) {
  62.107 +                    bytesSent += nwrote;
  62.108 +                    if (finished) {
  62.109 +                        closeUnchecked(channel);
  62.110 +                    } else {
  62.111 +                        sentBuffer.position(0);
  62.112 +                        sentBuffer.limit(sentBuffer.capacity());
  62.113 +                        channel.write(sentBuffer, null, this);
  62.114 +                    }
  62.115 +                }
  62.116 +                public void failed(Throwable exc, Void att) {
  62.117 +                    exc.printStackTrace();
  62.118 +                    closeUnchecked(channel);
  62.119 +                }
  62.120 +                public void cancelled(Void att) {
  62.121 +                }
  62.122 +            });
  62.123 +        }
  62.124 +
  62.125 +        long finish() {
  62.126 +            finished = true;
  62.127 +            waitUntilClosed(channel);
  62.128 +            return bytesSent;
  62.129 +        }
  62.130 +    }
  62.131 +
  62.132 +    /**
  62.133 +     * Read bytes from a channel until EOF is received.
  62.134 +     */
  62.135 +    static class Sink {
  62.136 +        private final AsynchronousByteChannel channel;
  62.137 +        private final ByteBuffer readBuffer;
  62.138 +        private volatile long bytesRead;
  62.139 +
  62.140 +        Sink(AsynchronousByteChannel channel) {
  62.141 +            this.channel = channel;
  62.142 +            int size = 1024 + rand.nextInt(10000);
  62.143 +            this.readBuffer = (rand.nextBoolean()) ?
  62.144 +                ByteBuffer.allocateDirect(size) : ByteBuffer.allocate(size);
  62.145 +        }
  62.146 +
  62.147 +        void start() {
  62.148 +            channel.read(readBuffer, null, new CompletionHandler<Integer,Void> () {
  62.149 +                public void completed(Integer nread, Void att) {
  62.150 +                    if (nread < 0) {
  62.151 +                        closeUnchecked(channel);
  62.152 +                    } else {
  62.153 +                        bytesRead += nread;
  62.154 +                        readBuffer.clear();
  62.155 +                        channel.read(readBuffer, null, this);
  62.156 +                    }
  62.157 +                }
  62.158 +                public void failed(Throwable exc, Void att) {
  62.159 +                    exc.printStackTrace();
  62.160 +                    closeUnchecked(channel);
  62.161 +                }
  62.162 +                public void cancelled(Void att) {
  62.163 +                }
  62.164 +            });
  62.165 +        }
  62.166 +
  62.167 +        long finish() {
  62.168 +            waitUntilClosed(channel);
  62.169 +            return bytesRead;
  62.170 +        }
  62.171 +    }
  62.172 +
  62.173 +    static void waitUntilClosed(Channel c) {
  62.174 +        while (c.isOpen()) {
  62.175 +            try {
  62.176 +                Thread.sleep(100);
  62.177 +            } catch (InterruptedException ignore) { }
  62.178 +        }
  62.179 +    }
  62.180 +
  62.181 +    static void closeUnchecked(Channel c) {
  62.182 +        try {
  62.183 +            c.close();
  62.184 +        } catch (IOException ignore) { }
  62.185 +    }
  62.186 +}